From 8fbd60ff15728f377144163767437894b1af982f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 25 Aug 2024 13:05:59 -0700 Subject: [PATCH 001/586] wip: start updating to 24w34a A lot doesn't compile with some registries having changed. Some kinds have migrated to records, moving away from enums. This poses some slight problem with representing the kinds themselves for API usage. --- SpongeAPI | 2 +- .../vanilla/generator/GeneratorMain.java | 27 ++-- .../vanilla/generator/TagGenerator.java | 6 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 123 +++++++++++++++++- .../MushroomCow_MushroomTypeAccessor.java | 36 ----- .../entity/decoration/ArmorStandAccessor.java | 4 - .../world/level/biome/BiomeAccessor.java | 4 + .../resources/mixins.sponge.accessors.json | 1 - .../common/adventure/SpongeAdventure.java | 9 +- .../server/level/ServerPlayerBridge.java | 14 +- .../block/location/ServerLocationData.java | 5 +- .../data/provider/entity/ArmorStandData.java | 8 +- .../common/data/provider/entity/FoxData.java | 2 +- .../data/provider/entity/MooshroomData.java | 2 +- .../item/stack/TieredItemStackData.java | 31 +++-- .../data/provider/world/biome/BiomeData.java | 11 +- .../data/type/SpongeArtTypeTemplate.java | 3 +- .../effect/particle/SpongeParticleHelper.java | 4 +- .../common/entity/SpongeEntityArchetype.java | 3 +- .../entity/living/human/HumanEntity.java | 3 +- .../projectile/DispenserSourceLogic.java | 2 +- .../entity/projectile/ProjectileUtil.java | 13 +- .../event/SpongeCommonEventFactory.java | 4 +- .../common/event/tracking/TrackingUtil.java | 2 +- .../transaction/block/ChangeBlock.java | 2 +- .../effect/AddBlockLootDropsEffect.java | 6 +- .../transaction/effect/BlockAddedEffect.java | 2 +- .../CheckBlockPostPlacementIsSameEffect.java | 6 +- .../effect/ChunkChangeCompleteEffect.java | 2 +- .../effect/ExplodeBlockEffect.java | 4 +- .../effect/NotifyClientEffect.java | 2 +- .../effect/NotifyNeighborSideEffect.java | 4 +- .../effect/OldBlockOnReplaceEffect.java | 2 +- .../PerformBlockDropsFromDestruction.java | 2 +- .../RemoveTileEntityFromChunkEffect.java | 4 +- ...SetAndRegisterBlockEntityToLevelChunk.java | 4 +- .../effect/SetBlockToChunkSectionEffect.java | 6 +- .../effect/SpawnDestructBlocksEffect.java | 4 +- .../effect/UpdateChunkLightManagerEffect.java | 2 +- .../effect/UpdateConnectingBlocksEffect.java | 4 +- .../effect/UpdateHeightMapEffect.java | 6 +- .../effect/UpdateLightSideEffect.java | 25 ++-- ...reateNewTileEntityPostPlacementEffect.java | 4 +- .../effect/UpdateWorldRendererEffect.java | 4 +- .../WorldBlockChangeCompleteEffect.java | 4 +- .../effect/WorldDestroyBlockLevelEffect.java | 4 +- .../inventory/SetCarriedItemTransaction.java | 4 +- .../transaction/pipeline/ChunkPipeline.java | 8 +- .../transaction/pipeline/PipelineCursor.java | 61 ++------- .../pipeline/TileEntityPipeline.java | 15 +-- .../transaction/pipeline/WorldPipeline.java | 8 +- .../shapeless/SpongeShapelessRecipe.java | 34 ++--- .../recipe/ingredient/SpongeIngredient.java | 15 ++- .../recipe/ingredient/SpongeItemList.java | 72 +++++++++- .../recipe/smithing/SpongeSmithingRecipe.java | 2 +- .../SpongeSmithingRecipeRegistration.java | 3 +- .../SpongeStonecuttingRecipe.java | 2 +- .../loader/VanillaRegistryLoader.java | 9 +- .../common/util/TristateUtil.java | 51 -------- .../common/world/SpongeExplosionBuilder.java | 6 +- .../world/biome/SpongeBiomeTemplate.java | 6 +- .../SpongeStructurePlacementBuilder.java | 3 +- .../chunk/storage/SpongeEntityChunk.java | 4 +- .../world/server/SpongeWorldManager.java | 2 +- .../world/volume/VolumeStreamUtils.java | 3 +- src/main/resources/common.accesswidener | 5 +- ...xin_API.java => Fox_VariantMixin_API.java} | 4 +- .../MushroomCow_MushroomTypeMixin_API.java | 2 +- ...in_API.java => ToolMaterialMixin_API.java} | 20 ++- .../item/crafting/IngredientMixin_API.java | 11 +- .../GenerationStep_CarvingMixin_API.java | 34 ----- .../world/item/crafting/IngredientMixin.java | 35 +++-- .../level/ServerLevelMixin_Tracker.java | 4 +- src/mixins/resources/mixins.sponge.api.json | 5 +- 75 files changed, 455 insertions(+), 397 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MushroomCow_MushroomTypeAccessor.java delete mode 100644 src/main/java/org/spongepowered/common/util/TristateUtil.java rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{Fox_TypeMixin_API.java => Fox_VariantMixin_API.java} (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/{TiersMixin_API.java => ToolMaterialMixin_API.java} (65%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/GenerationStep_CarvingMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 42dc372340a..44857814d3c 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 42dc372340aa68a7ea28a5ffa90b68c25af09661 +Subproject commit 44857814d3ce80343bf5b1c4f59e315c0be96a07 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 2b19277298e..615845a9d49 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -66,7 +66,6 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; -import net.minecraft.world.item.Tiers; import net.minecraft.world.item.component.FireworkExplosion; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.WorldDataConfiguration; @@ -167,11 +166,11 @@ private static Pair loadVanill final LayeredRegistryAccess staticRegistries = RegistryLayer.createRegistryAccess(); final LayeredRegistryAccess withWorldgen = staticRegistries.replaceFrom( RegistryLayer.WORLDGEN, - RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN), RegistryDataLoader.WORLDGEN_REGISTRIES) + RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN).listRegistries().toList(), RegistryDataLoader.WORLDGEN_REGISTRIES) ); final LayeredRegistryAccess withDimensions = withWorldgen.replaceFrom( RegistryLayer.DIMENSIONS, - RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.DIMENSIONS), RegistryDataLoader.DIMENSION_REGISTRIES) + RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.DIMENSIONS).listRegistries().toList(), RegistryDataLoader.DIMENSION_REGISTRIES) ); @@ -179,6 +178,7 @@ private static Pair loadVanill final var resourcesFuture = ReloadableServerResources.loadResources( resourceManager, withDimensions, + List.of(), packRepository.getRequestedFeatureFlags(), CommandSelection.ALL, 2, // functionPermissionLevel @@ -189,7 +189,7 @@ private static Pair loadVanill resourceManager.close(); } }).thenApply(resources -> { - resources.updateRegistryTags(); + resources.updateStaticRegistryTags(); return resources; }); @@ -318,14 +318,14 @@ private static List generators(final Context context) { new EnumEntriesValidator<>( "data.type", "MooshroomTypes", - MushroomCow.MushroomType.class, + MushroomCow.Variant.class, "getSerializedName", "sponge" ), new EnumEntriesValidator<>( "data.type", "FoxTypes", - Fox.Type.class, + Fox.Variant.class, "getSerializedName", "sponge" ), @@ -789,13 +789,14 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), - new EnumEntriesValidator<>( - "data.type", - "ItemTiers", - Tiers.class, - "name", - "sponge" - ), +// TODO - Figure out this change since ToolMaterials aren't registered, nor an enum anymore. - Snapshot 24w34a +// new EnumEntriesValidator<>( +// "data.type", +// "ItemTiers", +// ToolMaterial.class, +// "name", +// "sponge" +// ), new EnumEntriesValidator<>( "entity.display", "BillboardTypes", diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java index 87955f21e49..0e72fb03ce7 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java @@ -29,6 +29,7 @@ import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -93,8 +94,9 @@ public void generate(final Context ctx) throws IOException { ).build(); - ctx.registries().registryOrThrow(this.taggedRegistry).getTagNames() - .map(TagKey::location) + ctx.registries().registryOrThrow(this.taggedRegistry).getTags() + .>map(HolderSet.Named::key) + .map(TagKey::location) .sorted(Comparator.naturalOrder()) .map(v -> this.makeField(this.targetClassSimpleName, fieldType, factoryMethod, v)) .forEachOrdered(clazz::addField); diff --git a/gradle.properties b/gradle.properties index db84133290e..c3b4e0178b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.1 +minecraftVersion=24w34a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9f191f07979..e897213b226 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -183,6 +183,11 @@ + + + + + @@ -213,6 +218,11 @@ + + + + + @@ -238,6 +248,11 @@ + + + + + @@ -253,6 +268,14 @@ + + + + + + + + @@ -272,6 +295,14 @@ + + + + + + + + @@ -280,6 +311,14 @@ + + + + + + + + @@ -404,6 +443,14 @@ + + + + + + + + @@ -994,6 +1041,14 @@ + + + + + + + + @@ -1016,6 +1071,14 @@ + + + + + + + + @@ -1114,6 +1177,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1876,12 +1971,12 @@ - - - - - - + + + + + + @@ -3104,6 +3199,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MushroomCow_MushroomTypeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MushroomCow_MushroomTypeAccessor.java deleted file mode 100644 index 0bcfb85fffd..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MushroomCow_MushroomTypeAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.entity.animal; - -import net.minecraft.world.entity.animal.MushroomCow; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(MushroomCow.MushroomType.class) -public interface MushroomCow_MushroomTypeAccessor { - - @Accessor("type") String accessor$type(); - -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java index f7793b8ce90..a44016eaaa9 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java @@ -50,10 +50,6 @@ public interface ArmorStandAccessor { @Invoker("setSmall") void invoker$setSmall(final boolean small); - @Invoker("setShowArms") void invoker$setShowArms(final boolean showArms); - - @Invoker("setNoBasePlate") void invoker$setNoBasePlate(final boolean noBasePlate); - @Invoker("setMarker") void invoker$setMarker(final boolean marker); @Invoker("hasPhysics") boolean invoker$hasPhysics(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/biome/BiomeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/biome/BiomeAccessor.java index 80b9378b46b..bfaea3db80f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/biome/BiomeAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/biome/BiomeAccessor.java @@ -24,13 +24,17 @@ */ package org.spongepowered.common.accessor.world.level.biome; +import net.minecraft.core.BlockPos; import net.minecraft.world.level.biome.Biome; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Biome.class) public interface BiomeAccessor { @Accessor("climateSettings") Biome.ClimateSettings accessor$climateSettings(); + @Invoker("getTemperature") float shadow$getTemperature(BlockPos pos, int seaLevel); + } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index fd01d3d6f7f..b7084dbaae1 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -73,7 +73,6 @@ "world.entity.animal.AnimalAccessor", "world.entity.animal.CatAccessor", "world.entity.animal.FoxAccessor", - "world.entity.animal.MushroomCow_MushroomTypeAccessor", "world.entity.animal.OcelotAccessor", "world.entity.animal.PandaAccessor", "world.entity.animal.PigAccessor", diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index ef073687f61..32a311d9c66 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -61,6 +61,7 @@ import net.kyori.adventure.util.Codec; import net.kyori.adventure.util.TriState; import net.minecraft.ChatFormatting; +import net.minecraft.commands.arguments.selector.SelectorPattern; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; @@ -264,7 +265,7 @@ private static MutableComponent asVanillaMutable0(final Component component) { return net.minecraft.network.chat.Component.score($this.name(), $this.objective()); } if (component instanceof final SelectorComponent $this) { - return net.minecraft.network.chat.Component.selector($this.pattern(), SpongeAdventure.asVanillaOpt($this.separator())); + return net.minecraft.network.chat.Component.selector($this, SpongeAdventure.asVanillaOpt($this.separator())); } if (component instanceof NBTComponent) { if (component instanceof final BlockNBTComponent $this) { @@ -320,11 +321,11 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c return Component.keybind().keybind(kc.getName()); } if (contents instanceof final ScoreContents sc) { - return Component.score().name(sc.getName()).objective(sc.getObjective()); + return Component.score().name(sc.name().mapLeft(SelectorPattern::pattern).orThrow()).objective(sc.objective()); } if (contents instanceof final SelectorContents sc) { - return Component.selector().pattern(sc.getPattern()) - .separator(SpongeAdventure.asAdventure(sc.getSeparator())); + return Component.selector().pattern(sc.selector().pattern()) + .separator(SpongeAdventure.asAdventure(sc.separator())); } if (contents instanceof final NbtContents nc) { NBTComponentBuilder nbtBuilder; diff --git a/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java index ac2c724af1a..89fa19c7ce8 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java @@ -92,8 +92,18 @@ public interface ServerPlayerBridge extends ServerPlayerEntityHealthScaleBridge default void bridge$sendChangeDimension(final Holder dimensionType, final ResourceKey key, final long hashedSeed, final GameType gameType, final GameType previousGameType, final boolean isDebug, final boolean isFlat, final byte dataToKeepMask) { - ((ServerPlayer) this).connection.send(new ClientboundRespawnPacket(new CommonPlayerSpawnInfo(dimensionType, key, hashedSeed, gameType, previousGameType, isDebug, - isFlat, ((ServerPlayer) this).getLastDeathLocation(), ((ServerPlayer) this).getPortalCooldown()), dataToKeepMask)); + ((ServerPlayer) this).connection.send(new ClientboundRespawnPacket(new CommonPlayerSpawnInfo( + dimensionType, + key, + hashedSeed, + gameType, + previousGameType, + isDebug, + isFlat, + ((ServerPlayer) this).getLastDeathLocation(), + ((ServerPlayer) this).getPortalCooldown(), + ((ServerPlayer) this).serverLevel().getSeaLevel() + ), dataToKeepMask)); } boolean bridge$kick(final Component message); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/location/ServerLocationData.java b/src/main/java/org/spongepowered/common/data/provider/block/location/ServerLocationData.java index ec9e9c2ae55..2f3915a3afd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/location/ServerLocationData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/location/ServerLocationData.java @@ -34,6 +34,7 @@ import org.spongepowered.api.block.entity.NameableBlockEntity; import org.spongepowered.api.data.Keys; import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.common.accessor.world.level.biome.BiomeAccessor; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.CustomNameableBridge; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; @@ -66,7 +67,7 @@ public static void register(final DataProviderRegistrator registrator) { final Level world = (Level) h.world(); final BlockPos pos = VecHelper.toBlockPos(h); final Biome biome = world.getBiome(pos).unwrap().right().get(); - return (double) biome.getTemperature(pos); + return (double) ((BiomeAccessor) (Object) biome).shadow$getTemperature(pos, world.getSeaLevel()); }) .create(Keys.SKY_LIGHT) .get(h -> { @@ -79,7 +80,7 @@ public static void register(final DataProviderRegistrator registrator) { final BlockState block = (BlockState) h.block(); final Level world = (Level) h.world(); final BlockPos pos = VecHelper.toBlockPos(h.position()); - return block.isSolidRender(world, pos); + return block.isSolidRender(); }) .create(Keys.IS_INDIRECTLY_POWERED) .get(h -> { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java index 2398a2d8aa3..03356948e4d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java @@ -78,11 +78,11 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> VecHelper.toVector3d(h.getBodyPose())) .set((h, v) -> h.setBodyPose(VecHelper.toRotation(v))) .create(Keys.HAS_ARMS) - .get(ArmorStand::isShowArms) - .set((h, v) -> ((ArmorStandAccessor) h).invoker$setShowArms(v)) + .get(ArmorStand::showArms) + .set(ArmorStand::setShowArms) .create(Keys.HAS_BASE_PLATE) - .get(h -> !h.isNoBasePlate()) - .set((h, v) -> ((ArmorStandAccessor) h).invoker$setNoBasePlate(!v)) + .get(h -> !h.showBasePlate()) + .set((h, v) -> h.setNoBasePlate(!v)) .create(Keys.HAS_MARKER) .get(ArmorStand::isMarker) .set((h, v) -> { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java index f13dc6efb5e..9ab53c3d8aa 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java @@ -46,7 +46,7 @@ public static void register(final DataProviderRegistrator registrator) { .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v))) .create(Keys.FOX_TYPE) .get(h -> (FoxType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((Fox.Type) (Object) v)) + .set((h, v) -> h.setVariant((Fox.Variant) (Object) v)) .create(Keys.IS_CROUCHING) .get(Fox::isCrouching) .set(Fox::setIsCrouching) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java index 73587f66a71..61fdd8ad81e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java @@ -40,7 +40,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(MushroomCow.class) .create(Keys.MOOSHROOM_TYPE) .get(h -> (MooshroomType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((MushroomCow.MushroomType) (Object) v)); + .set((h, v) -> h.setVariant((MushroomCow.Variant) (Object) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/TieredItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/TieredItemStackData.java index 63321580580..f6a67c892ee 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/TieredItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/TieredItemStackData.java @@ -24,12 +24,8 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Tier; -import net.minecraft.world.item.TieredItem; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.type.ItemTier; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class TieredItemStackData { @@ -41,18 +37,21 @@ private TieredItemStackData() { public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(ItemStack.class) - .create(Keys.TOOL_TYPE) - .get(h -> { - final Item item = h.getItem(); - if (item instanceof TieredItem) { - final Tier tier = ((TieredItem) item).getTier(); - if (tier instanceof ItemTier) { - return (ItemTier) tier; - } - } - return null; - }) - .supports(h -> h.getItem() instanceof TieredItem); + .create(Keys.TOOL_TYPE); + // TODO - snapshot 24w34a changes away from the enum to a record and data components +// .get(h -> { +// h.is(ItemTags.WOODEN_TOOL_MATERIALS) +// final Item item = h.getItem(); +// final Tool tool = h.get(DataComponents.TOOL); +// if (item instanceof ToolItem) { +// final Tier tier = ((TieredItem) item).getTier(); +// if (tier instanceof ItemTier) { +// return (ItemTier) tier; +// } +// } +// return null; +// }) +// .supports(h -> h.getItem() instanceof TieredItem); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index 4b5e92d46c8..e63a348dd9e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -41,7 +41,6 @@ import org.spongepowered.api.world.biome.spawner.NaturalSpawnCost; import org.spongepowered.api.world.biome.spawner.NaturalSpawner; import org.spongepowered.api.world.generation.carver.Carver; -import org.spongepowered.api.world.generation.carver.CarvingStep; import org.spongepowered.api.world.generation.feature.DecorationStep; import org.spongepowered.api.world.generation.feature.PlacedFeature; import org.spongepowered.common.accessor.world.level.biome.BiomeAccessor; @@ -116,15 +115,9 @@ public static void register(final DataProviderRegistrator registrator) { } // @formatter:on - private static Map> carvers(final Biome biome) { + public static List carvers(final Biome biome) { final var settings = biome.getGenerationSettings(); - return Arrays.stream(GenerationStep.Carving.values()) - .collect(Collectors.toMap(step -> (CarvingStep) (Object) step, - step -> BiomeData.carverList(settings, step))); - } - - private static List carverList(final BiomeGenerationSettings settings, final GenerationStep.Carving step) { - final var carvers = settings.getCarvers(step); + final var carvers = settings.getCarvers(); return StreamSupport.stream(carvers.spliterator(), false) .map(carver -> (Carver) (Object) carver.value()) .collect(Collectors.toList()); diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java index b97360fe3d6..1b184a83ef8 100644 --- a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java +++ b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java @@ -44,6 +44,7 @@ import java.io.IOException; import java.util.Objects; +import java.util.Optional; import java.util.function.Function; public record SpongeArtTypeTemplate(ResourceKey key, PaintingVariant representedType, DataPack pack) implements ArtTypeTemplate { @@ -130,7 +131,7 @@ protected ArtTypeTemplate build0() { Preconditions.checkArgument(this.width >= 0, "width must set"); Preconditions.checkArgument(this.height >= 0, "height must set"); Objects.requireNonNull(this.assetId, "assetId"); - return new SpongeArtTypeTemplate(this.key, new PaintingVariant(this.width, this.height, this.assetId), this.pack); + return new SpongeArtTypeTemplate(this.key, new PaintingVariant(this.width, this.height, this.assetId, Optional.empty(), Optional.empty()), this.pack); } } } diff --git a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java index 3e582e1edab..c9782b4f606 100644 --- a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java +++ b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java @@ -38,7 +38,7 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundBundlePacket; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; -import net.minecraft.util.FastColor; +import net.minecraft.util.ARGB; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.effect.particle.ParticleEffect; @@ -158,7 +158,7 @@ private static CachedParticlePacket getNamedPacket(final ParticleEffect effect, final double opacity = effect.optionOrDefault(ParticleOptions.OPACITY).get(); final ColorParticleOption particleData = ColorParticleOption.create( (net.minecraft.core.particles.ParticleType) internalType, - FastColor.ARGB32.color(FastColor.as8BitChannel((float) opacity), color.red(), color.green(), color.blue())); + ARGB.color(ARGB.as8BitChannel((float) opacity), color.red(), color.green(), color.blue())); return new NamedCachedPacket(particleData, offset, quantity, velocity); } diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java index 8b6e6d98173..bd111f30c4d 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java @@ -31,6 +31,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.Mob; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -146,7 +147,7 @@ public Optional apply(final ServerLocation compound.put(Constants.Entity.ENTITY_POSITION, pos); compound.remove(Constants.Entity.ENTITY_UUID); - final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, level, e -> { + final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, level, EntitySpawnReason.LOAD, e -> { e.moveTo(location.x(), location.y(), location.z()); if (e instanceof Mob mobentity) { mobentity.yHeadRot = mobentity.getYRot(); diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index a38c2d70259..f985c34e232 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -429,7 +429,8 @@ public void untrackFrom(final ServerPlayer player) { public ClientboundPlayerInfoUpdatePacket createPlayerListPacket(final EnumSet actions) { final ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, List.of()); - ((ClientboundPlayerInfoUpdatePacketAccessor) packet).accessor$entries(List.of(new ClientboundPlayerInfoUpdatePacket.Entry(this.uuid, this.fakeProfile.gameProfile(), false, 0, GameType.DEFAULT_MODE, this.getDisplayName(), null))); + ((ClientboundPlayerInfoUpdatePacketAccessor) packet).accessor$entries(List.of( + new ClientboundPlayerInfoUpdatePacket.Entry(this.uuid, this.fakeProfile.gameProfile(), false, 0, GameType.DEFAULT_MODE, this.getDisplayName(), 0, null))); return packet; } diff --git a/src/main/java/org/spongepowered/common/entity/projectile/DispenserSourceLogic.java b/src/main/java/org/spongepowered/common/entity/projectile/DispenserSourceLogic.java index 7aa7c741042..58e29308780 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/DispenserSourceLogic.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/DispenserSourceLogic.java @@ -57,7 +57,7 @@ public

Optional

launch(final ProjectileLogic

logic, if (projectile.isPresent()) { final Direction enumfacing = DispenserSourceLogic.getFacing((DispenserBlockEntity) source); final net.minecraft.world.entity.Entity projectileEntity = (net.minecraft.world.entity.Entity) projectile.get(); - final BlockPos adjustedPosition = projectileEntity.blockPosition().offset(enumfacing.getNormal()); + final BlockPos adjustedPosition = projectileEntity.blockPosition().offset(enumfacing.getUnitVec3i()); projectileEntity.setPos(adjustedPosition.getX(), adjustedPosition.getY(), adjustedPosition.getZ()); } return projectile; diff --git a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java index 8d73b2dde50..c7963bdab4d 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java @@ -197,7 +197,7 @@ protected Optional createProjectile(final LivingEntity source, fi @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final ThrownEgg egg = new ThrownEgg(source.level(), source); + final ThrownEgg egg = new ThrownEgg(source.level(), source, new ItemStack(Items.EGG)); egg.shoot(source.getXRot(), source.getYRot(), 0.0F, 1.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (Egg) egg); } @@ -226,7 +226,8 @@ protected Optional createProjectile(final LivingEntity source, f @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final net.minecraft.world.entity.projectile.Snowball snowball = new net.minecraft.world.entity.projectile.Snowball(source.level(), source); + final net.minecraft.world.entity.projectile.Snowball snowball = new net.minecraft.world.entity.projectile.Snowball( + source.level(), source, new ItemStack(Items.SNOWBALL)); snowball.shoot(source.getXRot(), source.getYRot(), 0.0F, 1.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (Snowball) snowball); } @@ -236,7 +237,7 @@ protected Optional createProjectile(final LivingEntity source, final S @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final ThrownExperienceBottle expBottle = new ThrownExperienceBottle(source.level(), source); + final ThrownExperienceBottle expBottle = new ThrownExperienceBottle(source.level(), source, new ItemStack(Items.EXPERIENCE_BOTTLE)); expBottle.shoot(source.getXRot(), source.getYRot(), -20.0F, 0.7F, 0); return ProjectileUtil.doLaunch(loc.world(), (ExperienceBottle) expBottle); } @@ -247,7 +248,7 @@ protected Optional createProjectile(final LivingEntity source, @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final ThrownEnderpearl pearl = new ThrownEnderpearl(source.level(), source); + final ThrownEnderpearl pearl = new ThrownEnderpearl(source.level(), source, new ItemStack(Items.ENDER_PEARL)); pearl.shoot(source.getXRot(), source.getYRot(), 0.0F, 1.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (EnderPearl) pearl); } @@ -295,7 +296,7 @@ protected Optional createProjectile(final LivingEntity source, fina @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { if (source instanceof Player) { - final FishingHook hook = new FishingHook((Player) source, source.level(), 0, 0); + final FishingHook hook = new FishingHook((Player) source, source.level(), 0, 0, new ItemStack(Items.FISHING_ROD)); hook.setPos(loc.x(), loc.y(), loc.z()); return ProjectileUtil.doLaunch(loc.world(), (FishingBobber) hook); } @@ -306,7 +307,7 @@ protected Optional createProjectile(final LivingEntity source, fi @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final ThrownPotion potion = new ThrownPotion(source.level(), source); + final ThrownPotion potion = new ThrownPotion(source.level(), source, new ItemStack(this.item)); potion.setItem(new ItemStack(Items.SPLASH_POTION, 1)); potion.shoot(source.getXRot(), source.getYRot(), -20.0F, 0.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (Potion) potion); diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index acb07d0647e..79a8f646077 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -527,7 +527,7 @@ public static boolean handleCollideBlockEvent(final Block block, final Level wor return false; } - if (world.isClientSide() || pos.getY() < world.getMinBuildHeight()) { + if (world.isClientSide() || pos.getY() < world.getMinY()) { return false; } @@ -591,7 +591,7 @@ public static boolean handleCollideImpactEvent(final net.minecraft.world.entity. if (movingObjectType == HitResult.Type.BLOCK) { final BlockHitResult blockMovingObjectPosition = (BlockHitResult) movingObjectPosition; final BlockPos blockPos = blockMovingObjectPosition.getBlockPos(); - if (blockPos.getY() < projectile.level().getMinBuildHeight()) { + if (blockPos.getY() < projectile.level().getMinY()) { return false; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java index 8ad0399038d..2f559132d4f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java @@ -258,7 +258,7 @@ public static void updateTickFluid( try (final PhaseContext context = phaseContext) { context.buildAndSwitch(); PhaseTracker.LOGGER.trace(TrackingUtil.FLUID_TICK, () -> "Wrapping Fluid Tick: " + fluidState.toString()); - fluidState.tick(world, pos); + fluidState.tick(world, pos, blockState); } catch (final Exception | NoClassDefFoundError e) { PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java index 527a30c23a0..7efa1a2dfa7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java @@ -71,7 +71,7 @@ public ChangeBlock( this.original = attachedSnapshot; this.newState = newState; this.blockChangeFlag = blockChange; - this.originalOpacity = this.originalState.getLightBlock(this.original.getServerWorld().get(), this.affectedPosition); + this.originalOpacity = this.originalState.getLightBlock(); } public BlockState getNewState() { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java index 51e1a40d109..05d963c3f60 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java @@ -60,8 +60,8 @@ public EffectResult processSideEffect( final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); final ServerLevel world = pipeline.getServerWorld(); - final @Nullable BlockEntity existingTile = oldState.tileEntity; - final BlockPos pos = oldState.pos; + final @Nullable BlockEntity existingTile = oldState.tileEntity(); + final BlockPos pos = oldState.pos(); final LootParams.Builder lootBuilder = new LootParams.Builder(world) .withParameter(LootContextParams.ORIGIN, VecHelper.toVanillaVector3d(pos)) @@ -70,6 +70,6 @@ public EffectResult processSideEffect( phaseContext.populateLootContext(lootBuilder); - return new EffectResult(newState, oldState.state.getDrops(lootBuilder), false); + return new EffectResult(newState, oldState.state().getDrops(lootBuilder), false); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java index bb2a8c66667..50b2977f8b2 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java @@ -53,7 +53,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli // so we wrap the onPlace with the flag check (also, we're always on the // server in this context). if (flag.performBlockPhysics()) { - newState.onPlace(pipeline.getServerWorld(), oldState.pos, oldState.state, flag.movingBlocks()); + newState.onPlace(pipeline.getServerWorld(), oldState.pos(), oldState.state(), flag.movingBlocks()); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java index f3693379738..951ba947beb 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java @@ -44,9 +44,9 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final SpongeBlockChangeFlag flag, final int limit ) { final LevelChunkSection chunkSection = pipeline.getAffectedSection(); - final int x = oldState.pos.getX() & 15; - final int y = oldState.pos.getY() & 15; - final int z = oldState.pos.getZ() & 15; + final int x = oldState.pos().getX() & 15; + final int y = oldState.pos().getY() & 15; + final int z = oldState.pos().getZ() & 15; final BlockState currentState = chunkSection.getBlockState(x, y, z); if (!currentState.is(newState.getBlock())) { return new EffectResult(newState, true); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java index eecb265b5b7..bf28594d878 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java @@ -50,6 +50,6 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final LevelChunk chunk = pipeline.getAffectedChunk(); // this.unsaved = true; // Vanilla, we'll just call the accessor available chunk.setUnsaved(true); - return new EffectResult(oldState.state, true); + return new EffectResult(oldState.state(), true); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java index baaf064fadd..f47669e56ea 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java @@ -56,9 +56,9 @@ public EffectResult processSideEffect( final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); final ServerLevel world = pipeline.getServerWorld(); - final BlockPos pos = oldState.pos; + final BlockPos pos = oldState.pos(); if (phaseContext instanceof ExplosionContext) { - oldState.state.getBlock().wasExploded(world, pos, ((ExplosionContext) phaseContext).getExplosion()); + oldState.state().getBlock().wasExploded(world, pos, ((ExplosionContext) phaseContext).getExplosion()); } return EffectResult.NULL_PASS; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java index 63f49fc4df6..db70695e346 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java @@ -56,7 +56,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli // if ((flags & 2) != 0 && (!this.isClientSide || (flags & 4) == 0) && (this.isClientSide || chunk.getLocationType() != null && chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING))) { if (flag.notifyClients() && (chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { // this.notifyBlockUpdate(pos, blockstate, newWorldState, flags); - world.sendBlockUpdated(oldState.pos, oldState.state, newState, flag.getRawFlag()); + world.sendBlockUpdated(oldState.pos(), oldState.state(), newState, flag.getRawFlag()); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java index 8702afdf483..f69722fdf70 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java @@ -53,10 +53,10 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli // if (!this.isClientSide && (flags & 1) != 0) { if (flag.updateNeighbors()) { // this.notifyNeighbors(pos, originalState.getBlock()); - world.blockUpdated(oldState.pos, oldState.state.getBlock()); + world.blockUpdated(oldState.pos(), oldState.state().getBlock()); if (newState.hasAnalogOutputSignal()) { // this.updateComparatorOutputLevel(pos, block); - world.updateNeighbourForOutputSignal(oldState.pos, newState.getBlock()); + world.updateNeighbourForOutputSignal(oldState.pos(), newState.getBlock()); } } return EffectResult.NULL_PASS; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java index ffaaf61c60b..e635d85aa93 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java @@ -56,7 +56,7 @@ public EffectResult processSideEffect( // However, since we know we're not on the client (ChunkPipeline is not // used outside of server world context) // we can safely just do oldState.onRemove(this.level, var1, var2, var3). - oldState.state.onRemove(pipeline.getServerWorld(), oldState.pos, newState, flag.movingBlocks()); + oldState.state().onRemove(pipeline.getServerWorld(), oldState.pos(), newState, flag.movingBlocks()); return EffectResult.NULL_PASS; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java index 0e6a2b9d443..c2f898c2c4a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java @@ -46,7 +46,7 @@ public static PerformBlockDropsFromDestruction getInstance() { public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { - Block.dropResources(oldState.state, pipeline.getServerWorld(), oldState.pos, oldState.tileEntity, oldState.destroyer, ItemStack.EMPTY); + Block.dropResources(oldState.state(), pipeline.getServerWorld(), oldState.pos(), oldState.tileEntity(), oldState.destroyer(), ItemStack.EMPTY); return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java index cc118789df8..ff4588db8da 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java @@ -46,11 +46,11 @@ public static RemoveTileEntityFromChunkEffect getInstance() { public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { - final BlockEntity tileEntity = oldState.tileEntity; + final BlockEntity tileEntity = oldState.tileEntity(); if (tileEntity == null) { return EffectResult.NULL_RETURN; } - pipeline.getAffectedChunk().removeBlockEntity(oldState.pos); + pipeline.getAffectedChunk().removeBlockEntity(oldState.pos()); return EffectResult.NULL_RETURN; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java index 7733123bc27..196a7c20bf2 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java @@ -51,8 +51,8 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final int limit ) { final ServerLevel serverWorld = pipeline.getServerWorld(); - final @Nullable BlockEntity blockEntity = oldState.tileEntity; - final BlockPos pos = oldState.pos; + final @Nullable BlockEntity blockEntity = oldState.tileEntity(); + final BlockPos pos = oldState.pos(); if (serverWorld.isOutsideBuildHeight(pos)) { return EffectResult.NULL_RETURN; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java index 6db0b84c8fa..678aa48cff2 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java @@ -46,9 +46,9 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final SpongeBlockChangeFlag flag, final int limit ) { final LevelChunkSection chunkSection = pipeline.getAffectedSection(); - final int x = oldState.pos.getX() & 15; - final int y = oldState.pos.getY() & 15; - final int z = oldState.pos.getZ() & 15; + final int x = oldState.pos().getX() & 15; + final int y = oldState.pos().getY() & 15; + final int z = oldState.pos().getZ() & 15; final BlockState oldStateReturned = chunkSection.setBlockState(x, y, z, newState); if (oldStateReturned == newState) { return EffectResult.NULL_RETURN; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java index b167636ec06..3e144a2249d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java @@ -54,9 +54,9 @@ public EffectResult processSideEffect( final int limit ) { final ServerLevel world = pipeline.getServerWorld(); - final BlockPos pos = oldState.pos; + final BlockPos pos = oldState.pos(); - final List drops = oldState.drops; + final List drops = oldState.drops(); drops.forEach(drop -> Block.popResource(world, pos, drop)); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java index b27cfad1ec7..4cedc0c5810 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java @@ -51,7 +51,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final boolean wasEmpty = pipeline.wasEmpty(); final boolean isStillEmpty = chunkSection.hasOnlyAir(); if (wasEmpty != isStillEmpty) { - pipeline.getServerWorld().getChunkSource().getLightEngine().updateSectionStatus(oldState.pos, isStillEmpty); + pipeline.getServerWorld().getChunkSource().getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java index ca520619017..28049195867 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java @@ -48,12 +48,12 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { final ServerLevel world = pipeline.getServerWorld(); - final BlockPos pos = oldState.pos; + final BlockPos pos = oldState.pos(); if (flag.updateNeighboringShapes() && limit > 0) { // int i = p_241211_3_ & -34; // Vanilla negates 34 to flip neighbor notification and and "state drops" final int withoutNeighborDropsAndNestedNeighborUpdates = flag.asNestedNeighborUpdates().getRawFlag(); // blockstate.updateIndirectNeighbourShapes(this, p_241211_1_, i, p_241211_4_ - 1); - oldState.state.updateIndirectNeighbourShapes(world, pos, withoutNeighborDropsAndNestedNeighborUpdates, limit - 1); + oldState.state().updateIndirectNeighbourShapes(world, pos, withoutNeighborDropsAndNestedNeighborUpdates, limit - 1); // p_241211_2_.updateNeighbourShapes(this, p_241211_1_, i, p_241211_4_ - 1); newState.updateNeighbourShapes(world, pos, withoutNeighborDropsAndNestedNeighborUpdates, limit - 1); // p_241211_2_.updateIndirectNeighbourShapes(this, p_241211_1_, i, p_241211_4_ - 1); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java index 00693ff8e4a..de2b04b4949 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java @@ -53,9 +53,9 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli if (heightMap == null) { throw new IllegalStateException("Heightmap dereferenced!"); } - final int x = oldState.pos.getX() & 15; - final int y = oldState.pos.getY(); - final int z = oldState.pos.getZ() & 15; + final int x = oldState.pos().getX() & 15; + final int y = oldState.pos().getY(); + final int z = oldState.pos().getZ() & 15; heightMap.get(Heightmap.Types.MOTION_BLOCKING).update(x, y, z, newState); heightMap.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(x, y, z, newState); heightMap.get(Heightmap.Types.OCEAN_FLOOR).update(x, y, z, newState); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index 38c38aeaed3..dd71c3d1763 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -24,8 +24,11 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; +import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.lighting.LightEngine; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.world.SpongeBlockChangeFlag; @@ -51,9 +54,8 @@ public EffectResult processSideEffect( if (!flag.updateLighting()) { return EffectResult.NULL_PASS; } - final int originalOpactiy = oldState.opacity; final ServerLevel serverWorld = pipeline.getServerWorld(); - final BlockState currentState = pipeline.getAffectedChunk().getBlockState(oldState.pos); + final BlockState currentState = pipeline.getAffectedChunk().getBlockState(oldState.pos()); // local variable notes: // var2 = oldState.state // var3 = currentState @@ -67,16 +69,21 @@ public EffectResult processSideEffect( // || var2.useShapeForLightOcclusion() // ) // ) { - if (oldState.state != currentState - && (currentState.getLightBlock(serverWorld, oldState.pos) != originalOpactiy - || currentState.getLightEmission() != oldState.state.getLightEmission() - || currentState.useShapeForLightOcclusion() - || oldState.state.useShapeForLightOcclusion() - )) { + if (LightEngine.hasDifferentLightProperties(oldState.state(), currentState)) { + serverWorld.getProfiler().push("updateSkyLightSources"); +// this.skyLightSources.update(this, $$6, $$3, $$8); + final var pos = oldState.pos(); + final var x = pos.getX() % 15; + final var y = pos.getY(); + final var z = pos.getZ() % 15; + + final var levelChunk = serverWorld.getChunk(pos); + levelChunk.getSkyLightSources().update(levelChunk, x, y, z); +// serverWorld.getChunkSource().update(this, $$6, $$3, $$8); // this.profiler.startSection("queueCheckLight"); serverWorld.getProfiler().push("queueCheckLight"); // this.getChunkProvider().getLightManager().checkBlock(pos); - serverWorld.getChunkSource().getLightEngine().checkBlock(oldState.pos); + serverWorld.getChunkSource().getLightEngine().checkBlock(pos); // this.profiler.endSection(); serverWorld.getProfiler().pop(); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java index 0ecc8ef372d..aec887a346a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java @@ -55,12 +55,12 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final ServerLevel serverWorld = pipeline.getServerWorld(); final LevelChunk chunk = pipeline.getAffectedChunk(); if (((BlockStateBridge) newState).bridge$hasTileEntity()) { - final @Nullable BlockEntity maybeNewTileEntity = chunk.getBlockEntity(oldState.pos, LevelChunk.EntityCreationType.CHECK); + final @Nullable BlockEntity maybeNewTileEntity = chunk.getBlockEntity(oldState.pos(), LevelChunk.EntityCreationType.CHECK); if (maybeNewTileEntity == null) { // var15 = ((EntityBlock)var12).newBlockEntity(var1, var2); // Vanilla // tileentity1 = state.createTileEntity(this.world); // Forge // We cast to our bridge for easy access - @Nullable final BlockEntity newBlockEntity = ((BlockStateBridge) newState).bridge$createNewTileEntity(serverWorld, oldState.pos); + @Nullable final BlockEntity newBlockEntity = ((BlockStateBridge) newState).bridge$createNewTileEntity(serverWorld, oldState.pos()); if (newBlockEntity != null) { chunk.addAndRegisterBlockEntity(newBlockEntity); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java index 67608577360..41a44be0d32 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java @@ -45,8 +45,8 @@ public static UpdateWorldRendererEffect getInstance() { public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { - if (oldState.state != newState) { - pipeline.getServerWorld().setBlocksDirty(oldState.pos, oldState.state, newState); + if (oldState.state() != newState) { + pipeline.getServerWorld().setBlocksDirty(oldState.pos(), oldState.state(), newState); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java index 3afdc4e476f..58491086353 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java @@ -46,8 +46,8 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final SpongeBlockChangeFlag flag, final int limit ) { if (flag.notifyPathfinding()) { - pipeline.getServerWorld().onBlockStateChange(oldState.pos, oldState.state, newState); + pipeline.getServerWorld().onBlockStateChange(oldState.pos(), oldState.state(), newState); } - return new EffectResult(oldState.state, true); + return new EffectResult(oldState.state(), true); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java index d1dafaa2841..86e5e16119c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java @@ -47,8 +47,8 @@ public static WorldDestroyBlockLevelEffect getInstance() { public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { - if (!(oldState.state.getBlock() instanceof BaseFireBlock)) { - pipeline.getServerWorld().levelEvent(2001, oldState.pos, Block.getId(oldState.state)); + if (!(oldState.state().getBlock() instanceof BaseFireBlock)) { + pipeline.getServerWorld().levelEvent(2001, oldState.pos(), Block.getId(oldState.state())); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java index 84a00d5bc79..00657ace3cc 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.event.tracking.context.transaction.inventory; -import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; +import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import org.checkerframework.checker.nullness.qual.NonNull; @@ -76,7 +76,7 @@ Optional createInventoryEvent(final List @Override public void restore(final PhaseContext<@NonNull ?> context, final ChangeInventoryEvent event) { - this.player.connection.send(new ClientboundSetCarriedItemPacket(this.prevSlotId)); + this.player.connection.send(new ClientboundSetHeldSlotPacket(this.prevSlotId)); this.player.getInventory().selected = this.prevSlotId; this.handleEventResults(this.player, event); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java index a6b34239bc1..accd704f681 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java @@ -111,10 +111,10 @@ public LevelChunkSection getAffectedSection() { return null; } final ServerLevel serverWorld = this.serverWorld.get(); - final int oldOpacity = currentState.getLightBlock(serverWorld, pos); + final int oldOpacity = currentState.getLightBlock(); final SpongeBlockChangeFlag flag = this.transaction.getBlockChangeFlag(); final @Nullable BlockEntity existing = this.chunkSupplier.get().getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); - PipelineCursor formerState = new PipelineCursor(currentState, oldOpacity, pos, existing, (Entity) null, limit); + PipelineCursor formerState = new PipelineCursor(currentState, pos, existing, (Entity) null, limit); for (final ResultingTransactionBySideEffect effect : this.chunkEffects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { @@ -128,8 +128,8 @@ public LevelChunkSection getAffectedSection() { if (result.hasResult) { return result.resultingState; } - if (formerState.drops.isEmpty() && !result.drops.isEmpty()) { - formerState = new PipelineCursor(currentState, oldOpacity, pos, existing, null, result.drops, limit); + if (formerState.drops().isEmpty() && !result.drops.isEmpty()) { + formerState = new PipelineCursor(currentState, pos, existing, null, result.drops, limit); } } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/PipelineCursor.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/PipelineCursor.java index 6681d1e055c..4b3da670861 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/PipelineCursor.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/PipelineCursor.java @@ -33,57 +33,20 @@ import java.util.Collections; import java.util.List; -import java.util.StringJoiner; -public final class PipelineCursor { - public final BlockState state; - public final int opacity; - public final BlockPos pos; - public final @Nullable BlockEntity tileEntity; - public final @Nullable Entity destroyer; - public final List drops; - public final int limit; - - public PipelineCursor(final BlockState state, final int opacity, final BlockPos pos, - final @Nullable BlockEntity tileEntity, - final @Nullable Entity destroyer, final int limit +public record PipelineCursor( + BlockState state, + BlockPos pos, + @Nullable BlockEntity tileEntity, + @Nullable Entity destroyer, + List drops, + int limit +) { + public PipelineCursor(final BlockState state, final BlockPos pos, + final @Nullable BlockEntity tileEntity, + final @Nullable Entity destroyer, final int limit ) { - this.state = state; - this.opacity = opacity; - this.pos = pos; - this.tileEntity = tileEntity; - this.destroyer = destroyer; - this.drops = Collections.emptyList(); - this.limit = limit; + this(state, pos, tileEntity, destroyer, Collections.emptyList(), limit); } - public PipelineCursor(final BlockState state, final int opacity, final BlockPos pos, - final @Nullable BlockEntity tileEntity, - final @Nullable Entity destroyer, - final List drops, - final int limit - ) { - this.state = state; - this.opacity = opacity; - this.pos = pos; - this.tileEntity = tileEntity; - this.drops = drops; - this.limit = limit; - this.destroyer = destroyer; - } - - @Override - public String toString() { - return new StringJoiner( - ", ", - PipelineCursor.class.getSimpleName() + "[", - "]" - ) - .add("state=" + this.state) - .add("opacity=" + this.opacity) - .add("pos=" + this.pos) - .add("tileEntity=" + this.tileEntity) - .add("drops=" + this.drops) - .toString(); - } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java index ac6fdd6ac4b..2a5dc819629 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java @@ -103,18 +103,17 @@ public boolean processEffects(final PhaseContext context, final PipelineCurso final EffectResult result = effect.effect.processSideEffect( this, currentCursor, - currentCursor.state, + currentCursor.state(), (SpongeBlockChangeFlag) BlockChangeFlags.NONE, - currentCursor.limit + currentCursor.limit() ); - if (result.resultingState != currentCursor.state) { + if (result.resultingState != currentCursor.state()) { currentCursor = new PipelineCursor( result.resultingState, - currentCursor.opacity, - currentCursor.pos, - currentCursor.tileEntity, - currentCursor.destroyer, - currentCursor.limit + currentCursor.pos(), + currentCursor.tileEntity(), + currentCursor.destroyer(), + currentCursor.limit() ); } if (result.hasResult) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java index 81165311770..fe5a8e9b355 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java @@ -98,8 +98,8 @@ public boolean processEffects(final PhaseContext context, final BlockState cu if (oldState == null) { return false; } - final int oldOpacity = oldState.getLightBlock(serverWorld, pos); - PipelineCursor formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, destroyer, limit); + final int oldOpacity = oldState.getLightBlock(); + PipelineCursor formerState = new PipelineCursor(oldState, pos, existing, destroyer, limit); for (final ResultingTransactionBySideEffect effect : this.worldEffects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { @@ -113,8 +113,8 @@ public boolean processEffects(final PhaseContext context, final BlockState cu if (result.hasResult) { return result.resultingState != null; } - if (formerState.drops.isEmpty() && !result.drops.isEmpty()) { - formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, formerState.destroyer, result.drops, limit); + if (formerState.drops().isEmpty() && !result.drops.isEmpty()) { + formerState = new PipelineCursor(oldState, pos, existing, formerState.destroyer(), result.drops, limit); } } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index 8090a7189f6..d7ab7069fe2 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -63,23 +63,23 @@ public class SpongeShapelessRecipe extends ShapelessRecipe { Codec.STRING.optionalFieldOf("group", "").forGetter(ShapelessRecipe::getGroup), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(ShapelessRecipe::category), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), - Ingredient.CODEC_NONEMPTY - .listOf() - .fieldOf(Constants.Recipe.SHAPELESS_INGREDIENTS) - .flatXmap( - $$0x -> { - Ingredient[] $$1 = $$0x.stream().filter($$0xx -> !$$0xx.isEmpty()).toArray(Ingredient[]::new); - if ($$1.length == 0) { - return DataResult.error(() -> "No ingredients for shapeless recipe"); - } else { - return $$1.length > 9 - ? DataResult.error(() -> "Too many ingredients for shapeless recipe") - : DataResult.success(NonNullList.of(Ingredient.EMPTY, $$1)); - } - }, - DataResult::success - ) - .forGetter(ShapelessRecipe::getIngredients), +// Ingredient.CODEC_NONEMPTY +// .listOf() +// .fieldOf(Constants.Recipe.SHAPELESS_INGREDIENTS) +// .flatXmap( +// $$0x -> { +// Ingredient[] $$1 = $$0x.stream().filter($$0xx -> !$$0xx.isEmpty()).toArray(Ingredient[]::new); +// if ($$1.length == 0) { +// return DataResult.error(() -> "No ingredients for shapeless recipe"); +// } else { +// return $$1.length > 9 +// ? DataResult.error(() -> "Too many ingredients for shapeless recipe") +// : DataResult.success(NonNullList.of(Ingredient.EMPTY, $$1)); +// } +// }, +// DataResult::success +// ) +// .forGetter(ShapelessRecipe::getIngredients), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(SpongeShapelessRecipe::resultFunctionId), IngredientResultUtil.CACHED_REMAINING_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_REMAINING_ITEMS).forGetter(SpongeShapelessRecipe::remainingItemsFunctionId) ) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index 8f3cbb0ef54..e484c9722a7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -28,7 +28,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.apache.commons.lang3.NotImplementedException; @@ -82,8 +84,8 @@ public class SpongeIngredient extends Ingredient { if (predicate == null) { return DataResult.error(() -> "Could not find predicate for custom ingredient with id " + raw.predicateId.get()); } - final SpongeIngredient ingredient = new SpongeIngredient(raw.type, - new SpongePredicateItemList(raw.predicateId.get(), predicate, raw.stacks.toArray(new ItemStack[0])), raw.predicateId.orElse(null)); + final var predicateList = new SpongePredicateItemList(raw.predicateId.get(), predicate, raw.stacks.toArray(new ItemStack[0])); + final SpongeIngredient ingredient = new SpongeIngredient(raw.type, predicateList, raw.predicateId.orElse(null)); return DataResult.success(ingredient); } default -> { @@ -93,7 +95,7 @@ public class SpongeIngredient extends Ingredient { }, spongeIngredient -> { switch (spongeIngredient.type) { case SpongeStackItemList.TYPE_STACK -> { - var stacks = Arrays.stream(spongeIngredient.values).flatMap(v -> v.getItems().stream()).toList(); + final var stacks = Arrays.asList(spongeIngredient.list.stacks); return DataResult.success(new SpongeRawIngredient(spongeIngredient.type, stacks, Optional.empty())); } case SpongePredicateItemList.TYPE_PREDICATE -> { @@ -104,18 +106,19 @@ public class SpongeIngredient extends Ingredient { }); public final String type; public final String predicateId; + private final SpongeItemList list; record SpongeRawIngredient(String type, List stacks, Optional predicateId) { } - public SpongeIngredient(final String type, final Stream values, final String predicateId) { + public SpongeIngredient(final String type, final HolderSet values, final String predicateId) { super(values); this.type = type; this.predicateId = predicateId; } - public SpongeIngredient(final String type, final Ingredient.Value value, final String predicateId) { + public SpongeIngredient(final String type, final HolderSet value, final String predicateId) { this(type, Stream.of(value), predicateId); } @@ -129,7 +132,7 @@ public boolean test(final ItemStack testStack) { return false; } - for (final Value acceptedItem : this.values) { + for (final Value acceptedItem : this.list) { if (acceptedItem instanceof SpongeItemList) { if (((SpongeItemList) acceptedItem).test(testStack)) { return true; diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java index 80def6626f2..27a5e0a08b4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java @@ -26,13 +26,25 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.mojang.datafixers.util.Either; +import net.minecraft.Util; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderOwner; +import net.minecraft.core.HolderSet; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; -public abstract class SpongeItemList implements Ingredient.Value { +public abstract class SpongeItemList implements HolderSet { public static final String INGREDIENT_TYPE = "sponge:type"; public static final String INGREDIENT_ITEM = "sponge:item"; @@ -44,6 +56,62 @@ public SpongeItemList(ItemStack... stacks) { } @Override + public Stream> stream() { + return Arrays.stream(this.stacks) + .map(ItemStack::getItemHolder); + } + + @Override + public int size() { + return this.stacks.length; + } + + @Override + public boolean isBound() { + return true; + } + + @Override + public Either, List>> unwrap() { + return Either.right(this.stream().toList()); + } + + @Override + public Optional> getRandomElement(RandomSource source) { + return this.stacks.length == 0 ? Optional.empty() : + Optional.of(Util.getRandom(this.stacks, source)). + map(ItemStack::getItemHolder); + } + + @Override + public Holder get(int var1) { + final var stack = this.stacks[var1]; + return stack.getItemHolder(); + } + + @Override + public boolean contains(Holder var1) { + return false; + } + + @Override + public boolean canSerializeIn(HolderOwner var1) { + // TODO - maybe? What's this for? + return true; + } + + @Override + public Optional> unwrapKey() { + return Optional.empty(); + } + + @Override + public @NotNull Iterator> iterator() { + return Arrays.stream(this.stacks) + .map(ItemStack::getItemHolder) + .iterator(); + } + public Collection getItems() { return Arrays.asList(this.stacks); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index bff50643488..afcabb534b7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -66,7 +66,7 @@ public static SpongeSmithingRecipe of(final String spongeType, final Ingredient public SpongeSmithingRecipe(final Ingredient template, final Ingredient base, final Ingredient addition, final ItemStack spongeResult, final String resultFunctionId) { - super(template, base, addition, spongeResult); + super(Optional.of(template), Optional.ofNullable(base), Optional.ofNullable(addition), spongeResult); this.resultFunctionId = resultFunctionId; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java index 39a62cbb37a..d04005ab503 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java @@ -38,6 +38,7 @@ import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; import java.util.List; +import java.util.Optional; import java.util.function.Function; public class SpongeSmithingRecipeRegistration extends SpongeRecipeRegistration implements @@ -68,7 +69,7 @@ public SpongeSmithingRecipeRegistration(ResourceLocation key, String group, fina public Recipe recipe() { this.ensureCached(); if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, List.of(this.template, this.base, this.addition))) { - return (SmithingRecipe) new SmithingTransformRecipe(this.template, this.base, this.addition, this.spongeResult); + return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), this.spongeResult); } return (SmithingRecipe) new SpongeSmithingRecipe(this.template, this.base, this.addition, this.spongeResult, this.resultFunction == null ? null : this.key.toString()); diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index a2401eadcd8..c468ee037d9 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -58,7 +58,7 @@ public class SpongeStonecuttingRecipe extends StonecutterRecipe implements Resul $$1 -> $$1.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), Codec.STRING.optionalFieldOf("group", "").forGetter(SingleItemRecipe::getGroup), - Ingredient.CODEC_NONEMPTY.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter($$0x -> $$0x.getIngredients().get(0)), + Ingredient.NON_AIR_HOLDER_SET_CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter($$0x -> $$0x.g().get(0)), RESULT_CODEC.forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 8dd24c87c8d..e39f7566be9 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -58,7 +58,6 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; -import net.minecraft.world.item.Tiers; import net.minecraft.world.item.component.FireworkExplosion; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LightLayer; @@ -165,15 +164,16 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.DRIPSTONE_SEGMENT, DripstoneThickness.values()); this.automaticName(RegistryTypes.EQUIPMENT_GROUP, EquipmentSlot.Type.values()); this.automaticName(RegistryTypes.EQUIPMENT_TYPE, EquipmentSlot.values()); - this.automaticName(RegistryTypes.FOX_TYPE, Fox.Type.values()); + this.automaticName(RegistryTypes.FOX_TYPE, Fox.Variant.values()); this.automaticName(RegistryTypes.GAME_MODE, GameType.values()); this.automaticName(RegistryTypes.HAND_PREFERENCE, HumanoidArm.values()); this.automaticName(RegistryTypes.HAND_TYPE, InteractionHand.values()); this.automaticName(RegistryTypes.INSTRUMENT_TYPE, NoteBlockInstrument.values()); this.automaticName(RegistryTypes.ITEM_RARITY, Rarity.values()); - this.automaticName(RegistryTypes.ITEM_TIER, Tiers.values()); + // TODO - Figure out if we should make a registry - Snapshot 24w34a +// this.automaticName(RegistryTypes.ITEM_TIER, ToolMaterial.values()); this.automaticName(RegistryTypes.JIGSAW_BLOCK_ORIENTATION, FrontAndTop.values()); - this.automaticName(RegistryTypes.MOOSHROOM_TYPE, MushroomCow.MushroomType.values()); + this.automaticName(RegistryTypes.MOOSHROOM_TYPE, MushroomCow.Variant.values()); this.automaticName(RegistryTypes.OBJECTIVE_DISPLAY_MODE, ObjectiveCriteria.RenderType.values()); this.automaticName(RegistryTypes.PANDA_GENE, Panda.Gene.values()); this.automaticName(RegistryTypes.PHANTOM_PHASE, Phantom.AttackPhase.values()); @@ -202,7 +202,6 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.GRASS_COLOR_MODIFIER, BiomeSpecialEffects.GrassColorModifier.values()); this.automaticName(RegistryTypes.PRECIPITATION, Biome.Precipitation.values()); this.automaticName(RegistryTypes.TEMPERATURE_MODIFIER, Biome.TemperatureModifier.values()); - this.automaticName(RegistryTypes.CARVING_STEP, GenerationStep.Carving.values()); this.automaticName(RegistryTypes.DECORATION_STEP, GenerationStep.Decoration.values()); this.automaticName(RegistryTypes.PARROT_TYPE, Parrot.Variant.values()); this.automaticName(RegistryTypes.RABBIT_TYPE, Rabbit.Variant.values()); diff --git a/src/main/java/org/spongepowered/common/util/TristateUtil.java b/src/main/java/org/spongepowered/common/util/TristateUtil.java deleted file mode 100644 index eb28df33435..00000000000 --- a/src/main/java/org/spongepowered/common/util/TristateUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.util; - -import com.google.common.collect.EnumBiMap; -import net.minecraft.world.InteractionResult; -import org.spongepowered.api.util.Tristate; - -public final class TristateUtil { - - private static final EnumBiMap map = EnumBiMap.create(InteractionResult.class, Tristate.class); - - static { - TristateUtil.map.put(InteractionResult.FAIL, Tristate.FALSE); - TristateUtil.map.put(InteractionResult.PASS, Tristate.UNDEFINED); - TristateUtil.map.put(InteractionResult.SUCCESS, Tristate.TRUE); - } - - public static Tristate fromActionResult(final InteractionResult result) { - return TristateUtil.map.get(result); - } - - public static InteractionResult toActionResult(final Tristate tristate) { - return TristateUtil.map.inverse().get(tristate); - } - - private TristateUtil() { - } -} diff --git a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java index 52a6f8486aa..2eda4559f3f 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java +++ b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java @@ -25,10 +25,12 @@ package org.spongepowered.common.world; import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Explosion.BlockInteraction; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.world.World; @@ -155,8 +157,8 @@ public Explosion build() throws IllegalStateException { final World world = this.location.world(); final Vector3d origin = this.location.position(); - final net.minecraft.world.level.Explosion explosion = new net.minecraft.world.level.Explosion((Level) world, - (Entity) this.sourceExplosive, null, null, origin.x(), origin.y(), origin.z(), this.radius, + final net.minecraft.world.level.Explosion explosion = new net.minecraft.world.level.ServerExplosion((ServerLevel) world, + (Entity) this.sourceExplosive, null, null, new Vec3(origin.x(), origin.y(), origin.z()), this.radius, this.canCauseFire, this.shouldBreakBlocks ? BlockInteraction.DESTROY : BlockInteraction.KEEP, // TODO configurable explosion particles & sound? ParticleTypes.EXPLOSION, diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java index cea046cce1d..b7af593c2b2 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java @@ -63,7 +63,6 @@ import org.spongepowered.api.world.biome.spawner.NaturalSpawnCost; import org.spongepowered.api.world.biome.spawner.NaturalSpawner; import org.spongepowered.api.world.generation.carver.Carver; -import org.spongepowered.api.world.generation.carver.CarvingStep; import org.spongepowered.api.world.generation.feature.DecorationStep; import org.spongepowered.api.world.generation.feature.PlacedFeature; import org.spongepowered.common.SpongeCommon; @@ -185,7 +184,7 @@ protected BiomeTemplate build0() { final Map, NaturalSpawnCost> spawnerCosts = this.manipulator.getOrElse(Keys.NATURAL_SPAWNER_COST, Map.of()); final Map> features = this.manipulator.getOrElse(Keys.FEATURES, Map.of()); - final Map> carvers = this.manipulator.getOrElse(Keys.CARVERS, Map.of()); + final List carvers = this.manipulator.getOrElse(Keys.CARVERS, List.of()); final BiomeSpecialEffects.Builder effectsBuilder = new BiomeSpecialEffects.Builder() .fogColor(fogColor.rgb()) @@ -214,8 +213,7 @@ protected BiomeTemplate build0() { final BiomeGenerationSettings.Builder generationBuilder = new BiomeGenerationSettings.Builder(placedFeatureRegistry.asLookup(), configuredWorldCarverRegistry.asLookup()); features.forEach((step, list) -> list.forEach(feature -> generationBuilder.addFeature((GenerationStep.Decoration) (Object) step, Holder.direct((net.minecraft.world.level.levelgen.placement.PlacedFeature) (Object) feature)))); - carvers.forEach((step, list) -> list.forEach(carver -> generationBuilder.addCarver((GenerationStep.Carving) (Object) step, - Holder.direct((ConfiguredWorldCarver) (Object) carver)))); + carvers.forEach((carver) -> generationBuilder.addCarver(Holder.direct((ConfiguredWorldCarver) (Object) carver))); final Biome.BiomeBuilder vanillaBuilder = new Biome.BiomeBuilder() .hasPrecipitation(precipitation) diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java index 4c8d9b61c12..13a332df74c 100644 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java @@ -154,7 +154,8 @@ public ConcentricRings count(final int count) { @Override public ConcentricRings preferredBiomes(final Tag preferredBiomes) { final Registry registry = SpongeCommon.vanillaRegistry(Registries.BIOME); - this.preferredBiomes = registry.getOrCreateTag((TagKey) (Object) preferredBiomes); + // TODO - Snapshot 24w34a +// this.preferredBiomes = registry.getOrCreateTag((TagKey) (Object) preferredBiomes); return this; } diff --git a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java index 67f5bce8b7c..ba21ecb1e0a 100644 --- a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java +++ b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java @@ -76,7 +76,7 @@ public SpongeEntityChunk(final ServerLevel level, final Vector3i chunkPosition, public Vector3i min() { if (this.blockMin == null) { if (this.chunkLayout == null) { - this.chunkLayout = new SpongeChunkLayout(this.level.getMinBuildHeight(), this.level.getHeight()); + this.chunkLayout = new SpongeChunkLayout(this.level.getMinY(), this.level.getHeight()); } this.blockMin = this.chunkLayout.forceToWorld(this.chunkPosition); } @@ -87,7 +87,7 @@ public Vector3i min() { public Vector3i max() { if (this.blockMax == null) { if (this.chunkLayout == null) { - this.chunkLayout = new SpongeChunkLayout(this.level.getMinBuildHeight(), this.level.getHeight()); + this.chunkLayout = new SpongeChunkLayout(this.level.getMinY(), this.level.getHeight()); } this.blockMax = this.min().add(this.chunkLayout.chunkSize()).sub(1, 1, 1); } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 5e48525e41b..536f459c49f 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -337,7 +337,7 @@ private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelDat hardcore == null ? defaultLevelData.isHardcore() : hardcore, difficulty == null ? defaultLevelData.getDifficulty() : difficulty, allowCommands == null ? defaultLevelData.isAllowCommands() : allowCommands, - defaultLevelData.getGameRules().copy(), + defaultLevelData.getGameRules().copy(defaultLevelData.enabledFeatures()), defaultLevelData.getDataConfiguration()); } diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index c796d9bf60a..c3c769f502d 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -34,6 +34,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Tuple; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; @@ -242,7 +243,7 @@ public static BiConsumer getOrCloneEnti return shouldCarbonCopy ? (pos, entity) -> { final CompoundTag nbt = new CompoundTag(); entity.save(nbt); - final net.minecraft.world.entity.@Nullable Entity cloned = entity.getType().create(level); + final net.minecraft.world.entity.@Nullable Entity cloned = entity.getType().create(level, EntitySpawnReason.COMMAND); Objects.requireNonNull( cloned, () -> String.format( diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index 215cc24aa91..c370b151d43 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -12,9 +12,8 @@ accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$Stat extendable method net/minecraft/server/players/IpBanList getIpFromAddress (Ljava/net/SocketAddress;)Ljava/lang/String; accessible class net/minecraft/server/commands/TeleportCommand$LookAt extendable class net/minecraft/world/item/crafting/Ingredient -extendable method net/minecraft/world/item/crafting/Ingredient (Ljava/util/stream/Stream;)V -accessible field net/minecraft/world/item/crafting/Ingredient values [Lnet/minecraft/world/item/crafting/Ingredient$Value; -accessible class net/minecraft/world/item/crafting/Ingredient$Value +extendable method net/minecraft/world/item/crafting/Ingredient (Lnet/minecraft/core/HolderSet;)V +accessible field net/minecraft/world/item/crafting/Ingredient values Lnet/minecraft/core/HolderSet; accessible method net/minecraft/world/level/biome/Biome getTemperature (Lnet/minecraft/core/BlockPos;)F accessible class net/minecraft/server/level/ServerLevel$EntityCallbacks accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$Action diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_TypeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java index 3e25a5d44d2..b7af53b114c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_TypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java @@ -28,6 +28,6 @@ import org.spongepowered.api.data.type.FoxType; import org.spongepowered.asm.mixin.Mixin; -@Mixin(Fox.Type.class) -public abstract class Fox_TypeMixin_API implements FoxType { +@Mixin(Fox.Variant.class) +public abstract class Fox_VariantMixin_API implements FoxType { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java index 87d51f488d7..d9c14c85fb8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java @@ -28,6 +28,6 @@ import org.spongepowered.api.data.type.MooshroomType; import org.spongepowered.asm.mixin.Mixin; -@Mixin(MushroomCow.MushroomType.class) +@Mixin(MushroomCow.Variant.class) public abstract class MushroomCow_MushroomTypeMixin_API implements MooshroomType { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/TiersMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java similarity index 65% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/TiersMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java index f737fd964b3..b0394d9d962 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/TiersMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java @@ -24,20 +24,28 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item; -import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; import org.spongepowered.api.data.type.ItemTier; +import org.spongepowered.api.item.recipe.crafting.Ingredient; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; -@Mixin(net.minecraft.world.item.Tiers.class) -public abstract class TiersMixin_API implements ItemTier { +@Mixin(net.minecraft.world.item.ToolMaterial.class) +public abstract class ToolMaterialMixin_API implements ItemTier { // @formatter:off - @Shadow public abstract Ingredient shadow$getRepairIngredient(); + @Shadow @Final private TagKey repairItems; // @formatter:on @Override - public org.spongepowered.api.item.recipe.crafting.Ingredient repairIngredient() { - return (org.spongepowered.api.item.recipe.crafting.Ingredient) (Object) this.shadow$getRepairIngredient(); + public Ingredient repairIngredient() { + HolderGetter holder = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.ITEM); + final var items = holder.getOrThrow(this.repairItems); + return (Ingredient) (Object) SpongeIngredient.of(items); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java index b9b54a45b56..9f544541348 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java @@ -24,9 +24,13 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; +import net.minecraft.core.Holder; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.item.ItemType; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface.Remap; @@ -43,13 +47,12 @@ public abstract class IngredientMixin_API { // @formatter:off - @Shadow public abstract ItemStack[] shadow$getItems(); @Shadow public abstract boolean shadow$test(@Nullable ItemStack p_test_1_); + @Shadow public abstract List> shadow$items(); // @formatter:on - - public List ingredient$displayedItems() { - return Arrays.stream(this.shadow$getItems()).map(ItemStackUtil::snapshotOf).collect(Collectors.toList()); + public List ingredient$displayedItems() { + return this.shadow$items().stream().map((holder) -> (ItemType) holder.value()).toList(); } public boolean ingredient$test(final org.spongepowered.api.item.inventory.ItemStack itemStack) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/GenerationStep_CarvingMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/GenerationStep_CarvingMixin_API.java deleted file mode 100644 index cbc9ad223ce..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/GenerationStep_CarvingMixin_API.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen; - -import net.minecraft.world.level.levelgen.GenerationStep; -import org.spongepowered.api.world.generation.carver.CarvingStep; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(GenerationStep.Carving.class) -public abstract class GenerationStep_CarvingMixin_API implements CarvingStep { - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/IngredientMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/IngredientMixin.java index ade3ce146d4..07dda2bd02b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/IngredientMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/IngredientMixin.java @@ -27,26 +27,33 @@ import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; import net.minecraft.world.item.crafting.Ingredient; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; @Mixin(Ingredient.class) public abstract class IngredientMixin { - @Inject(method = "codec", at = @At(value = "RETURN"), cancellable = true) - private static void impl$modifyCodec(final boolean $$0, final CallbackInfoReturnable> cir) { - final Codec original = cir.getReturnValue(); - var combinedCodec = Codec.xor(SpongeIngredient.CODEC, original).xmap(to -> to.map(si -> si, i -> i), - fr -> { - if (fr instanceof SpongeIngredient si) { - return Either.left(si); - } else { - return Either.right(fr); - } - }); - cir.setReturnValue(combinedCodec); + //@formatter:off + @Shadow @Final @Mutable public static Codec CODEC; + //@formatter:on + + @Redirect( + method = "", + at = @At(value = "FIELD", target = "Lnet/minecraft/world/item/crafting/Ingredient;CODEC:Lcom/mojang/serialization/Codec;") + ) + private static void impl$modifyCodec(Codec value) { + CODEC = Codec.xor(SpongeIngredient.CODEC, value).xmap(to -> to.map(si -> si, i -> i), + fr -> { + if (fr instanceof SpongeIngredient si) { + return Either.left(si); + } else { + return Either.right(fr); + } + }); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 970ac0fd2b3..1e0434aa999 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -619,7 +619,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(RemoveTileEntityFromChunkEffect.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), 0,immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } super.shadow$removeBlockEntity(immutable); @@ -650,7 +650,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(SetAndRegisterBlockEntityToLevelChunk.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), 0,immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index fc1ac639d46..dbd651bafee 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -151,7 +151,7 @@ "minecraft.world.entity.animal.CowMixin_API", "minecraft.world.entity.animal.DolphinMixin_API", "minecraft.world.entity.animal.FlyingAnimalMixin_API", - "minecraft.world.entity.animal.Fox_TypeMixin_API", + "minecraft.world.entity.animal.Fox_VariantMixin_API", "minecraft.world.entity.animal.FoxMixin_API", "minecraft.world.entity.animal.IronGolemMixin_API", "minecraft.world.entity.animal.MushroomCow_MushroomTypeMixin_API", @@ -323,7 +323,7 @@ "minecraft.world.item.ItemStackMixin_API", "minecraft.world.item.JukeboxSongMixin_API", "minecraft.world.item.RarityMixin_API", - "minecraft.world.item.TiersMixin_API", + "minecraft.world.item.ToolMaterialMixin_API", "minecraft.world.item.alchemy.PotionMixin_API", "minecraft.world.item.component.FireworkExplosionMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", @@ -448,7 +448,6 @@ "minecraft.world.level.gameevent.PositionSourceMixin_API", "minecraft.world.level.levelgen.DensityFunctionMixin_API", "minecraft.world.level.levelgen.FlatLevelSourceMixin_API", - "minecraft.world.level.levelgen.GenerationStep_CarvingMixin_API", "minecraft.world.level.levelgen.GenerationStep_DecorationMixin_API", "minecraft.world.level.levelgen.Heightmap_TypeMixin_API", "minecraft.world.level.levelgen.NoiseBasedChunkGeneratorMixin_API", From 59e575abec896b5b1318efd09e90b8577117add5 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 10:50:28 +0200 Subject: [PATCH 002/586] fix BiomeTest --- .../spongepowered/test/worldgen/BiomeTest.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java index e338b45d318..78e35a2572e 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java @@ -79,14 +79,12 @@ private CommandResult info(final CommandContext ctx, final Parameter.Value { - if (!list.isEmpty()) { - ctx.sendMessage(Identity.nil(), Component.text("Carvers Step:", NamedTextColor.DARK_AQUA)); - list.forEach(configuredCarver -> { - ctx.sendMessage(Identity.nil(), Component.text(" - " + configuredCarver.type().getClass().getSimpleName(), NamedTextColor.GRAY)); - }); - } - }); + if (!biome.carvers().isEmpty()) { + ctx.sendMessage(Identity.nil(), Component.text("Carvers Step:", NamedTextColor.DARK_AQUA)); + biome.carvers().forEach(configuredCarver -> { + ctx.sendMessage(Identity.nil(), Component.text(" - " + configuredCarver.type().getClass().getSimpleName(), NamedTextColor.GRAY)); + }); + } biome.ambientMood().ifPresent(mood -> { ctx.sendMessage(Identity.nil(), Component.text("Mood: " + mood, NamedTextColor.DARK_AQUA)); @@ -112,7 +110,7 @@ private CommandResult register(CommandContext commandContext) { final BiomeTemplate template = BiomeTemplate.builder().fromValue(defaultBiome) .add(Keys.FEATURES, Map.of(DecorationSteps.LAKES.get(), List.of(PlacedFeatures.LAKE_LAVA_SURFACE.get()))) - .add(Keys.CARVERS, Map.of()) + .add(Keys.CARVERS, List.of()) .add(Keys.NATURAL_SPAWNERS, Map.of(EntityCategories.MONSTER.get(), spawner)) .add(Keys.AMBIENT_ADDITIONAL_SOUND, SoundConfig.factory().ofAdditional(SoundTypes.ENTITY_CREEPER_PRIMED.get(), 0.001)) .add(Keys.AMBIENT_PARTICLE, ParticleConfig.of(ParticleTypes.BUBBLE.get(), 0.01f)) From 3354a0a619d815d5fa4979e02e30b09251405b90 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 10:50:37 +0200 Subject: [PATCH 003/586] fix Ingredient --- .../recipe/ingredient/SpongeIngredient.java | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index e484c9722a7..8a295623225 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -30,7 +30,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.apache.commons.lang3.NotImplementedException; @@ -45,7 +44,6 @@ import java.util.Map; import java.util.Optional; import java.util.function.Predicate; -import java.util.stream.Stream; public class SpongeIngredient extends Ingredient { @@ -95,7 +93,7 @@ public class SpongeIngredient extends Ingredient { }, spongeIngredient -> { switch (spongeIngredient.type) { case SpongeStackItemList.TYPE_STACK -> { - final var stacks = Arrays.asList(spongeIngredient.list.stacks); + final var stacks = Arrays.asList(spongeIngredient.itemList.stacks); return DataResult.success(new SpongeRawIngredient(spongeIngredient.type, stacks, Optional.empty())); } case SpongePredicateItemList.TYPE_PREDICATE -> { @@ -106,20 +104,17 @@ public class SpongeIngredient extends Ingredient { }); public final String type; public final String predicateId; - private final SpongeItemList list; + private final SpongeItemList itemList; record SpongeRawIngredient(String type, List stacks, Optional predicateId) { } - public SpongeIngredient(final String type, final HolderSet values, final String predicateId) { - super(values); + public SpongeIngredient(final String type, final SpongeItemList itemList, final String predicateId) { + super(HolderSet.direct(itemList.stream().toList())); this.type = type; this.predicateId = predicateId; - } - - public SpongeIngredient(final String type, final HolderSet value, final String predicateId) { - this(type, Stream.of(value), predicateId); + this.itemList = itemList; } public static void clearCache() { @@ -132,22 +127,7 @@ public boolean test(final ItemStack testStack) { return false; } - for (final Value acceptedItem : this.list) { - if (acceptedItem instanceof SpongeItemList) { - if (((SpongeItemList) acceptedItem).test(testStack)) { - return true; - } - } else { - // TODO caching (relevant for TagList) - for (final ItemStack stack : acceptedItem.getItems()) { - if (stack.getItem() == testStack.getItem()) { - return true; - } - } - } - } - - return false; + return this.itemList.test(testStack); } public static SpongeIngredient spongeFromStacks(net.minecraft.world.item.ItemStack... stacks) { From f956a364498a85e51703e0271ff28cd14815e334 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 10:53:53 +0200 Subject: [PATCH 004/586] fix adventure selector conversion --- .../org/spongepowered/common/adventure/SpongeAdventure.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 32a311d9c66..ca69e960bd9 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -265,7 +265,7 @@ private static MutableComponent asVanillaMutable0(final Component component) { return net.minecraft.network.chat.Component.score($this.name(), $this.objective()); } if (component instanceof final SelectorComponent $this) { - return net.minecraft.network.chat.Component.selector($this, SpongeAdventure.asVanillaOpt($this.separator())); + return net.minecraft.network.chat.Component.selector(SelectorPattern.parse($this.pattern()).getOrThrow(), SpongeAdventure.asVanillaOpt($this.separator())); } if (component instanceof NBTComponent) { if (component instanceof final BlockNBTComponent $this) { From 8fdd9c469f4bf882e57ed6ce93efcebb0c533cd1 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:00:23 +0200 Subject: [PATCH 005/586] fix vanilla ingredient check --- .../common/item/recipe/SpongeRecipeRegistration.java | 8 ++------ .../recipe/cooking/SpongeCookingRecipeRegistration.java | 3 ++- .../shaped/SpongeShapedCraftingRecipeRegistration.java | 6 +++++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java index 7688025bf6a..f07c7c3e005 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java @@ -53,6 +53,7 @@ import java.io.IOException; import java.util.Collection; +import java.util.Optional; import java.util.function.Function; public abstract class SpongeRecipeRegistration> implements RecipeRegistration { @@ -101,12 +102,7 @@ public static boolean isVanillaSerializer(final ItemStac if (!resultStack.getComponents().isEmpty() || resultFunction != null || remainingItemsFunction != null) { return false; } - for (final Ingredient value : ingredients) { - if (value instanceof SpongeIngredient) { - return false; - } - } - return true; + return ingredients.stream().noneMatch(value -> value instanceof SpongeIngredient); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java index 040c5be9642..8cb16a97911 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java @@ -48,6 +48,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.function.Function; public class SpongeCookingRecipeRegistration extends SpongeRecipeRegistration implements SpongeRecipeRegistration.ResultFunctionRegistration{ @@ -118,7 +119,7 @@ public Recipe recipe() { final int ticksCookingTime = SpongeTicks.toSaturatedIntOrInfinite(this.cookingTime); final String resultFunctionId = this.resultFunction == null ? null : this.key.toString(); - final List ingredientList = Collections.singletonList(ingredient); + final var ingredientList = Collections.singletonList(ingredient); final boolean isVanilla = SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, ingredientList); if (type == RecipeType.BLASTING) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java index b65c5c09b99..831718b6ff3 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java @@ -30,6 +30,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; @@ -39,6 +40,8 @@ import org.spongepowered.api.item.recipe.crafting.ShapedCraftingRecipe; import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; +import java.util.List; +import java.util.Optional; import java.util.function.Function; public class SpongeShapedCraftingRecipeRegistration extends SpongeRecipeRegistration implements @@ -79,7 +82,8 @@ public Function> remainingItems() { @Override public Recipe recipe() { - if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, this.remainingItemsFunction, this.pattern.ingredients())) { + final var ingredients = this.pattern.ingredients().stream().filter(Optional::isPresent).map(Optional::get).toList(); + if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, this.remainingItemsFunction, ingredients)) { return (ShapedCraftingRecipe) new ShapedRecipe(this.group, this.craftingBookCategory, this.pattern, this.spongeResult, this.showNotification); } this.ensureCached(); From 1bfcd73e8d288039c842d244216197fc69aa53ad Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:00:35 +0200 Subject: [PATCH 006/586] bump API --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 44857814d3c..a9e5275ee19 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 44857814d3ce80343bf5b1c4f59e315c0be96a07 +Subproject commit a9e5275ee1951b39618a03a1ca95235595abeafc From 84dbf5cf8acd673046d9dcd355f8f28d743140e5 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:29:15 +0200 Subject: [PATCH 007/586] fixing recipes --- .../crafting/ShapelessRecipeAccessor.java | 37 +++++++++++++++++++ .../resources/mixins.sponge.accessors.json | 1 + .../shapeless/SpongeShapelessRecipe.java | 28 ++++---------- .../recipe/ingredient/IngredientUtil.java | 7 +++- .../SpongeStonecuttingRecipe.java | 4 +- 5 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/ShapelessRecipeAccessor.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/ShapelessRecipeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/ShapelessRecipeAccessor.java new file mode 100644 index 00000000000..b0343958027 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/ShapelessRecipeAccessor.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.item.crafting; + +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.ShapelessRecipe; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(ShapelessRecipe.class) +public interface ShapelessRecipeAccessor { + @Accessor("ingredients") List accessor$ingredients(); +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index b7084dbaae1..dc63b837474 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -138,6 +138,7 @@ "world.item.AdventureModePredicateAccessor", "world.item.ItemCooldowns_CooldownInstanceAccessor", "world.item.component.CustomDataAccessor", + "world.item.crafting.ShapelessRecipeAccessor", "world.item.enchantment.ItemEnchantmentsAccessor", "world.item.trading.MerchantOfferAccessor", "world.level.BaseCommandBlockAccessor", diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index d7ab7069fe2..59849a785cf 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -25,7 +25,6 @@ package org.spongepowered.common.item.recipe.crafting.shapeless; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; @@ -36,6 +35,7 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.level.Level; +import org.spongepowered.common.accessor.world.item.crafting.ShapelessRecipeAccessor; import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; @@ -63,23 +63,9 @@ public class SpongeShapelessRecipe extends ShapelessRecipe { Codec.STRING.optionalFieldOf("group", "").forGetter(ShapelessRecipe::getGroup), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(ShapelessRecipe::category), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), -// Ingredient.CODEC_NONEMPTY -// .listOf() -// .fieldOf(Constants.Recipe.SHAPELESS_INGREDIENTS) -// .flatXmap( -// $$0x -> { -// Ingredient[] $$1 = $$0x.stream().filter($$0xx -> !$$0xx.isEmpty()).toArray(Ingredient[]::new); -// if ($$1.length == 0) { -// return DataResult.error(() -> "No ingredients for shapeless recipe"); -// } else { -// return $$1.length > 9 -// ? DataResult.error(() -> "Too many ingredients for shapeless recipe") -// : DataResult.success(NonNullList.of(Ingredient.EMPTY, $$1)); -// } -// }, -// DataResult::success -// ) -// .forGetter(ShapelessRecipe::getIngredients), + Ingredient.CODEC.listOf(1,9) + .fieldOf(Constants.Recipe.SHAPELESS_INGREDIENTS) + .forGetter(sr -> ((ShapelessRecipeAccessor) sr).accessor$ingredients()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(SpongeShapelessRecipe::resultFunctionId), IngredientResultUtil.CACHED_REMAINING_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_REMAINING_ITEMS).forGetter(SpongeShapelessRecipe::remainingItemsFunctionId) ) @@ -96,7 +82,7 @@ public static SpongeShapelessRecipe of( final String groupIn, final CraftingBookCategory category, final ItemStack recipeOutputIn, - final NonNullList recipeItemsIn, + final List recipeItemsIn, final Optional resultFunctionId, final Optional remainingItemsFunctionId) { @@ -106,7 +92,7 @@ public static SpongeShapelessRecipe of( public SpongeShapelessRecipe(final String groupIn, final CraftingBookCategory category, - final NonNullList recipeItemsIn, + final List recipeItemsIn, final ItemStack spongeResultStack, final String resultFunctionId, final String remainingItemsFunctionId) { @@ -129,7 +115,7 @@ public boolean matches(final CraftingInput $$0, final Level $$1) { if (this.onlyVanillaIngredients) { return super.matches($$0, $$1); } - return SpongeShapelessRecipe.matches($$0.items(), this.getIngredients()); + return SpongeShapelessRecipe.matches($$0.items(), ((ShapelessRecipeAccessor) this).accessor$ingredients()); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java index 6dfd4c78f46..d10e3386b81 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java @@ -24,6 +24,9 @@ */ package org.spongepowered.common.item.recipe.ingredient; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -34,6 +37,7 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.Arrays; @@ -58,7 +62,8 @@ public static org.spongepowered.api.item.recipe.crafting.Ingredient of(ItemType. public static org.spongepowered.api.item.recipe.crafting.@Nullable Ingredient of(ResourceKey tagKey) { final TagKey key = TagKey.create(Registries.ITEM, (ResourceLocation) (Object) tagKey); - return IngredientUtil.fromNative(Ingredient.of(key)); + var holderset = BuiltInRegistries.ITEM.getTag(key).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return IngredientUtil.fromNative(Ingredient.of(holderset)); } private static net.minecraft.world.item.ItemStack[] toNativeStacks(ItemStack[] stacks) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index c468ee037d9..819cf425181 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -58,8 +58,8 @@ public class SpongeStonecuttingRecipe extends StonecutterRecipe implements Resul $$1 -> $$1.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), Codec.STRING.optionalFieldOf("group", "").forGetter(SingleItemRecipe::getGroup), - Ingredient.NON_AIR_HOLDER_SET_CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter($$0x -> $$0x.g().get(0)), - RESULT_CODEC.forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), + Ingredient.CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter($$0x -> $$0x.ingredient), + RESULT_CODEC.forGetter($$0x -> $$0x.result), ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) ) From 8271de869b1a9c46a5e2b117be9152ded0b378b5 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:35:00 +0200 Subject: [PATCH 008/586] fix ToolRuleFactory --- .../common/item/SpongeToolRuleFactory.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java index 5850e53f41d..3e7cee1cab6 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java +++ b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.item; +import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.tags.TagKey; @@ -41,12 +42,16 @@ public class SpongeToolRuleFactory implements ToolRule.Factory { @Override public ToolRule minesAndDrops(final List blocks, final double speed) { - return (ToolRule) (Object) Tool.Rule.minesAndDrops(blocks.stream().map(Block.class::cast).toList(), (float) speed); + // TODO is Holder::direct allowed here? + final var holderSet = HolderSet.direct(blocks.stream().map(Block.class::cast).map(Holder::direct).toList()); + return (ToolRule) (Object) Tool.Rule.minesAndDrops(holderSet, (float) speed); } @Override public ToolRule minesAndDrops(final Tag blockTypeTag, final double speed) { - return (ToolRule) (Object) Tool.Rule.minesAndDrops((TagKey) (Object) blockTypeTag, (float) speed); + final var tag = (TagKey) (Object) blockTypeTag; + final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return (ToolRule) (Object) Tool.Rule.minesAndDrops(holderSet, (float) speed); } @Override @@ -58,17 +63,22 @@ public ToolRule deniesDrops(final List blocks) { @Override public ToolRule deniesDrops(final Tag blockTypeTag) { - return (ToolRule) (Object) Tool.Rule.deniesDrops((TagKey) (Object) blockTypeTag); + final var tag = (TagKey) (Object) blockTypeTag; + final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return (ToolRule) (Object) Tool.Rule.deniesDrops(holderSet); } @Override public ToolRule overrideSpeed(final List blocks, final double speed) { - return (ToolRule) (Object) Tool.Rule.overrideSpeed(blocks.stream().map(Block.class::cast).toList(), (float) speed); + final var holderSet = HolderSet.direct(blocks.stream().map(Block.class::cast).map(Block::builtInRegistryHolder).toList()); + return (ToolRule) (Object) Tool.Rule.overrideSpeed(holderSet, (float) speed); } @Override public ToolRule overrideSpeed(final Tag blockTypeTag, final double speed) { - return (ToolRule) (Object) Tool.Rule.overrideSpeed((TagKey) (Object) blockTypeTag, (float) speed); + final var tag = (TagKey) (Object) blockTypeTag; + final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return (ToolRule) (Object) Tool.Rule.overrideSpeed(holderSet, (float) speed); } @Override @@ -81,7 +91,8 @@ public ToolRule forBlocks(final List blocks, @Nullable final Double s @Override public ToolRule forTag(final Tag blockTypeTag, @Nullable final Double speed, @Nullable final Boolean drops) { // See Tool#forTag - final var holderSet = BuiltInRegistries.BLOCK.getOrCreateTag((TagKey) (Object) blockTypeTag); + final var tag = (TagKey) (Object) blockTypeTag; + final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) new Tool.Rule(holderSet, Optional.ofNullable(speed).map(Double::floatValue), Optional.ofNullable(drops)); } } From 9dd2d49c42b3fa811227c425f23fa496c75fb7c3 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:00:57 +0200 Subject: [PATCH 009/586] git ignore snapshot run dir --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f00aaf21910..da7570735e6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ dist lib out run +run_snap /target *.com *.class From 0e653d1d25612a9bc66b2ec1234893796ea0ec23 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:45:57 +0200 Subject: [PATCH 010/586] fix explosion builder --- .../common/world/SpongeExplosionBuilder.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java index 2eda4559f3f..1f05bad1569 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java +++ b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java @@ -24,12 +24,9 @@ */ package org.spongepowered.common.world; -import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Explosion.BlockInteraction; -import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.explosive.Explosive; @@ -159,11 +156,7 @@ public Explosion build() throws IllegalStateException { final Vector3d origin = this.location.position(); final net.minecraft.world.level.Explosion explosion = new net.minecraft.world.level.ServerExplosion((ServerLevel) world, (Entity) this.sourceExplosive, null, null, new Vec3(origin.x(), origin.y(), origin.z()), this.radius, - this.canCauseFire, this.shouldBreakBlocks ? BlockInteraction.DESTROY : BlockInteraction.KEEP, - // TODO configurable explosion particles & sound? - ParticleTypes.EXPLOSION, - ParticleTypes.EXPLOSION_EMITTER, - SoundEvents.GENERIC_EXPLODE); + this.canCauseFire, this.shouldBreakBlocks ? BlockInteraction.DESTROY : BlockInteraction.KEEP); ((ExplosionBridge) explosion).bridge$setShouldBreakBlocks(this.shouldBreakBlocks); ((ExplosionBridge) explosion).bridge$setShouldDamageEntities(this.shouldDamageEntities); ((ExplosionBridge) explosion).bridge$setShouldPlaySmoke(this.shouldSmoke); From 2e13d65b890658881827d6c2d0cd56f9dbd5f6fa Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 11:48:18 +0200 Subject: [PATCH 011/586] tab list order --- .../spongepowered/common/entity/player/tab/SpongeTabList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java index cf350b3d665..8d49e1212f2 100644 --- a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java +++ b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java @@ -190,11 +190,11 @@ public Optional removeEntry(final UUID uniqueId) { @SuppressWarnings("ConstantConditions") void sendUpdate(final TabListEntry entry, final EnumSet actions) { final ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, List.of()); - + int listOrder = 0; // TODO expose to API final RemoteChatSession.Data chatSessionData = ((SpongeTabListEntry) entry).profilePublicKey() == null ? null : new RemoteChatSession.Data(entry.profile().uuid(), ((SpongeTabListEntry) entry).profilePublicKey()); final net.minecraft.network.chat.Component displayName = entry.displayName().isPresent() ? SpongeAdventure.asVanilla(entry.displayName().get()) : null; final ClientboundPlayerInfoUpdatePacket.Entry data = new ClientboundPlayerInfoUpdatePacket.Entry(entry.profile().uniqueId(), SpongeGameProfile.toMcProfile(entry.profile()), - entry.listed(), entry.latency(), (GameType) (Object) entry.gameMode(), displayName, chatSessionData); + entry.listed(), entry.latency(), (GameType) (Object) entry.gameMode(), displayName, listOrder, chatSessionData); ((ClientboundPlayerInfoUpdatePacketAccessor) packet).accessor$entries(List.of(data)); this.player.connection.send(packet); } From c2689a458472c38f7b44c84c1c8daf3e4ef74b34 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 12:08:20 +0200 Subject: [PATCH 012/586] item component --- .../provider/item/stack/ItemStackData.java | 98 +++++++------------ 1 file changed, 34 insertions(+), 64 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 616b362f397..224a401847c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -25,47 +25,49 @@ package org.spongepowered.common.data.provider.item.stack; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemUseAnimation; import net.minecraft.world.item.Items; import net.minecraft.world.item.Rarity; import net.minecraft.world.item.component.ChargedProjectiles; +import net.minecraft.world.item.component.Consumable; import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; -import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.item.component.UseRemainder; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.ConsumeEffect; +import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; +import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; import org.spongepowered.api.Platform; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.effect.potion.PotionEffect; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.util.Ticks; -import org.spongepowered.api.util.weighted.ChanceTable; -import org.spongepowered.api.util.weighted.NestedTableEntry; -import org.spongepowered.api.util.weighted.TableEntry; -import org.spongepowered.api.util.weighted.WeightedObject; -import org.spongepowered.api.util.weighted.WeightedTable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.item.util.ItemStackUtil; -import java.util.ArrayList; import java.util.List; -import java.util.Optional; @SuppressWarnings({"unchecked", "UnstableApiUsage"}) public final class ItemStackData { - public static final FoodProperties DEFAULT_FOOD_PROPERTIES = new FoodProperties(0, 0, false, 1.6F, Optional.empty(), List.of()); + public static final FoodProperties DEFAULT_FOOD_PROPERTIES = new FoodProperties(0, 0, false); + public static final Consumable DEFAULT_CONSUMABLE_PROPERTIES = new Consumable(1.6F, ItemUseAnimation.EAT, null, true, List.of()); private ItemStackData() { } @@ -87,49 +89,19 @@ public static void register(final DataProviderRegistrator registrator) { // TODO DataComponents.RECIPES - for Items.KNOWLEDGE_BOOK // TODO DataComponents.MAX_STACK_SIZE; incompatible with MAX_DAMAGE? // TODO DataComponents.OMINOUS_BOTTLE_AMPLIFIER 1.21 - registrator - .asMutable(ItemStack.class) - .create(Keys.APPLICABLE_POTION_EFFECTS) - .get(h -> { - if (h.has(DataComponents.FOOD)) { - final var itemEffects = h.get(DataComponents.FOOD).effects(); - final WeightedTable effects = new WeightedTable<>(); - final ChanceTable chance = new ChanceTable<>(); - for (final var effect : itemEffects) { - chance.add((PotionEffect) effect.effect(), effect.probability()); - } - effects.add(new NestedTableEntry<>(1, chance)); + // TODO rework applicable potion effects to consume effects + final var applicablePotionEffects = Keys.APPLICABLE_POTION_EFFECTS; + ConsumeEffect newPotionEffects = new ApplyStatusEffectsConsumeEffect(List.of()); + ConsumeEffect teleportRand = new TeleportRandomlyConsumeEffect(5); + ConsumeEffect removeStatusEffects = new RemoveStatusEffectsConsumeEffect(HolderSet.empty()); + ConsumeEffect clearStatusEffects = new ClearAllStatusEffectsConsumeEffect(); + ConsumeEffect playSoundEffect = new PlaySoundConsumeEffect(Holder.direct(null)); - return effects; - } - return null; - }) - .set((h, v) -> { - List newEffects = new ArrayList<>(); - for (final TableEntry entry : v.entries()) { - if (entry instanceof NestedTableEntry nestedTableEntry) { - if (nestedTableEntry.getNestedTable() instanceof ChanceTable chanceTable) { - for (final TableEntry te : chanceTable.entries()) { - if (te instanceof WeightedObject wo) { - newEffects.add(new FoodProperties.PossibleEffect((MobEffectInstance) wo.get(), (float) te.weight())); - } - } - } - } - } - h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), fp.saturation(), fp.canAlwaysEat(), fp.eatSeconds(), fp.usingConvertsTo(), newEffects)); - }) - + registrator + .asMutable(ItemStack.class) .create(Keys.BURN_TIME) - .get(h -> { - final Integer burnTime = AbstractFurnaceBlockEntity.getFuel().get(h.getItem()); - if (burnTime != null && burnTime > 0) { - return burnTime; - } - return null; - }) + .get(h -> SpongeCommon.server().fuelValues().burnDuration(h)) .create(Keys.CONTAINER_ITEM) .get(h -> (ItemType) h.getItem().getCraftingRemainingItem()) .create(Keys.DISPLAY_NAME) @@ -213,37 +185,35 @@ public static void register(final DataProviderRegistrator registrator) { return food == null ? null : food.nutrition(); }) .set((h, v) -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(v, fp.saturation(), fp.canAlwaysEat(), fp.eatSeconds(), fp.usingConvertsTo(), fp.effects()))) + fp -> new FoodProperties(v, fp.saturation(), fp.canAlwaysEat()))) .create(Keys.REPLENISHED_SATURATION) .get(h -> { final var food = h.get(DataComponents.FOOD); return food == null ? null : (double) food.saturation(); }) .set((h, v) -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), v.floatValue(), fp.canAlwaysEat(), fp.eatSeconds(), fp.usingConvertsTo(), fp.effects()))) + fp -> new FoodProperties(fp.nutrition(), v.floatValue(), fp.canAlwaysEat()))) .create(Keys.CAN_ALWAYS_EAT) .get(h -> { final var food = h.get(DataComponents.FOOD); return food == null ? null : food.canAlwaysEat(); }) .set((h, v) -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), fp.saturation(), v, fp.eatSeconds(), fp.usingConvertsTo(), fp.effects()))) + fp -> new FoodProperties(fp.nutrition(), fp.saturation(), v))) .create(Keys.EATING_TIME) .get(h -> { - final var food = h.get(DataComponents.FOOD); - return food == null ? null : Ticks.of(food.eatDurationTicks()); + final var consumable = h.get(DataComponents.CONSUMABLE); + return consumable == null ? null : Ticks.of(consumable.consumeTicks()); }) - .set((h, v) -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), fp.saturation(), fp.canAlwaysEat(), v.ticks() / 20f, fp.usingConvertsTo(), fp.effects()))) + .set((h, v) -> h.update(DataComponents.CONSUMABLE, DEFAULT_CONSUMABLE_PROPERTIES, + c -> new Consumable(v.ticks() / 20f, c.animation(), c.sound(), c.hasConsumeParticles(), c.onConsumeEffects()))) .create(Keys.FOOD_CONVERTS_TO) .get(h -> { - final var food = h.get(DataComponents.FOOD); - return food == null ? null : food.usingConvertsTo().map(ItemStackUtil::fromNative).orElse(null); + final var remainder = h.get(DataComponents.USE_REMAINDER); + return remainder == null ? null : ItemStackUtil.fromNative(remainder.convertInto()); }) - .set((h, v) -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), fp.saturation(), fp.canAlwaysEat(), fp.eatSeconds(), Optional.ofNullable(ItemStackUtil.toNative(v)), fp.effects()))) - .delete(h -> h.update(DataComponents.FOOD, DEFAULT_FOOD_PROPERTIES, - fp -> new FoodProperties(fp.nutrition(), fp.saturation(), fp.canAlwaysEat(), fp.eatSeconds(), Optional.empty(), fp.effects()))) + .set((h, v) -> h.set(DataComponents.USE_REMAINDER, new UseRemainder(ItemStackUtil.toNative(v)))) + .delete(h -> h.remove(DataComponents.USE_REMAINDER)) .create(Keys.REPAIR_COST) .get(h -> h.getOrDefault(DataComponents.REPAIR_COST, 0)) .set((stack, cost) -> stack.set(DataComponents.REPAIR_COST, cost)) From 8de6accc905bc45fdf2f0abd825a0d2fa9154a80 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 12:16:21 +0200 Subject: [PATCH 013/586] fix resendProfile --- .../data/provider/entity/ServerPlayerData.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 61c63ce3516..687a84ce8fd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -143,16 +143,8 @@ private static void resendProfile(final ServerPlayer h) { // Add Entity h.serverLevel().getChunkSource().addEntity(h); // Reconnect local player - h.connection.send(new ClientboundRespawnPacket(new CommonPlayerSpawnInfo( - h.level().dimensionTypeRegistration(), - h.level().dimension(), - BiomeManager.obfuscateSeed(h.serverLevel().getSeed()), - h.gameMode.getGameModeForPlayer(), - h.gameMode.getPreviousGameModeForPlayer(), - h.serverLevel().isDebug(), - h.serverLevel().isFlat(), - h.getLastDeathLocation(), - h.getPortalCooldown()), (byte) 0)); + final var commonSpawnInfo = h.createCommonSpawnInfo(h.serverLevel()); + h.connection.send(new ClientboundRespawnPacket(commonSpawnInfo, (byte) 0)); // tp - just in case h.connection.teleport(h.getX(), h.getY(), h.getZ(), h.getYRot(), h.getXRot()); // resend remaining player data... (see ServerPlayer#changeDimension) From b69739987462750d211f57274983c0888f5013e4 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 12:16:36 +0200 Subject: [PATCH 014/586] fix BlockTypeItemStackData --- .../data/provider/item/stack/BlockTypeItemStackData.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java index f05aa2200fb..5ed5a6769a5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java @@ -29,6 +29,7 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.AdventureModePredicate; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; @@ -78,7 +79,8 @@ private static boolean set(final ItemStack stack, final DataComponentType Date: Mon, 26 Aug 2024 12:18:35 +0200 Subject: [PATCH 015/586] TODO fix client --- .../spongepowered/vanilla/client/gui/widget/ScrollPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index cc70debc8d9..98052cf6988 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -189,7 +189,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, RenderSystem.enableScissor((int) (this.left * scale), (int) (this.client.getWindow().getHeight() - (this.bottom * scale)), (int) (this.width * scale), (int) (this.height * scale)); - RenderSystem.setShader(GameRenderer::getPositionTexColorShader); +// TODO fix me RenderSystem.setShader(GameRenderer::getPositionTexColorShader); RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); final float texScale = 32.0F; @@ -219,7 +219,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, } // RenderSystem.disableTexture(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); + // TODO fix me RenderSystem.setShader(GameRenderer::getPositionColorShader); worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); From 668a7c014336ae7fda0bfd7ef04698b53190d6f1 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 12:20:22 +0200 Subject: [PATCH 016/586] ClientboundSetCarriedItemPacket -> ClientboundSetHeldSlotPacket --- .../world/entity/player/InventoryMixin_Bridge_Inventory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java index 76465fafa51..267bc686dcb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.inventory.impl.world.entity.player; import net.minecraft.core.NonNullList; -import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; +import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Inventory; @@ -85,7 +85,7 @@ private void onConstructed(final Player playerIn, final CallbackInfo ci) { public void bridge$setSelectedItem(int itemIndex, final boolean notify) { itemIndex = itemIndex % 9; if (notify && this.player instanceof ServerPlayer) { - final ClientboundSetCarriedItemPacket packet = new ClientboundSetCarriedItemPacket(itemIndex); + final var packet = new ClientboundSetHeldSlotPacket(itemIndex); ((ServerPlayer)this.player).connection.send(packet); } this.selected = itemIndex; From cafd3ed39ce3b5a7e7e5094750a460ec9889ca3d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 14:06:53 +0200 Subject: [PATCH 017/586] fix sponge chunk data --- .../storage/SerializableChunkDataBridge.java | 34 +++++++ ...> SerializableChunkDataMixin_Tracker.java} | 98 +++++++++++++------ .../resources/mixins.sponge.tracker.json | 2 +- 3 files changed, 103 insertions(+), 31 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java rename src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/{ChunkSerializerMixin_Tracker.java => SerializableChunkDataMixin_Tracker.java} (54%) diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java new file mode 100644 index 00000000000..70dec219725 --- /dev/null +++ b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.bridge.world.level.chunk.storage; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.chunk.ChunkAccess; + +public interface SerializableChunkDataBridge { + + void bridge$copySpongeData(ChunkAccess chunkAccess); + void bridge$parseSpongeData(CompoundTag tag); +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/ChunkSerializerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java similarity index 54% rename from src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/ChunkSerializerMixin_Tracker.java rename to src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java index d33ce42dfdd..f15289bbeb9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/ChunkSerializerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java @@ -24,22 +24,27 @@ */ package org.spongepowered.common.mixin.tracker.world.level.chunk.storage; +import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.storage.ChunkSerializer; import net.minecraft.world.level.chunk.storage.RegionStorageInfo; +import net.minecraft.world.level.chunk.storage.SerializableChunkData; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; +import org.spongepowered.common.bridge.world.level.chunk.storage.SerializableChunkDataBridge; import org.spongepowered.common.entity.PlayerTracker; import org.spongepowered.common.util.Constants; @@ -47,28 +52,48 @@ import java.util.Map; import java.util.function.BiConsumer; -@Mixin(ChunkSerializer.class) -public abstract class ChunkSerializerMixin_Tracker { +@Mixin(SerializableChunkData.class) +public abstract class SerializableChunkDataMixin_Tracker implements SerializableChunkDataBridge { - @Inject(method = "write", at = @At(value = "RETURN")) - private static void impl$writeSpongeLevelData(final ServerLevel param0, final ChunkAccess param1, final CallbackInfoReturnable cir) { - if (!(param1 instanceof LevelChunk)) { + + @Shadow @Final private boolean lightCorrect; + private Map tracker$shortPlayerPos = null; + private Map tracker$intPlayerPos = null; + + @Inject(method = "copyOf", at = @At(value = "RETURN")) + private static void impl$copySpongeLevelData(final ServerLevel $$0, final ChunkAccess $$1, final CallbackInfoReturnable cir) { + final var chunkData = cir.getReturnValue(); + ((SerializableChunkDataBridge) (Object) chunkData).bridge$copySpongeData($$1); + } + + @Override + public void bridge$copySpongeData(final ChunkAccess chunkAccess) { + if (!(chunkAccess instanceof LevelChunk)) { return; } - final LevelChunkBridge chunk = (LevelChunkBridge) param1; + final LevelChunkBridge chunk = (LevelChunkBridge) chunkAccess; if (!chunk.bridge$getTrackedShortPlayerPositions().isEmpty() || !chunk.bridge$getTrackedIntPlayerPositions().isEmpty()) { - final CompoundTag level = cir.getReturnValue(); - final CompoundTag trackedNbt = new CompoundTag(); - final ListTag positions = new ListTag(); - trackedNbt.put(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, positions); - level.put(Constants.Sponge.Data.V2.SPONGE_DATA, trackedNbt); - - ChunkSerializerMixin_Tracker.impl$writeMap(positions, chunk.bridge$getTrackedShortPlayerPositions(), (nbt, pos) -> nbt.putShort("pos", pos)); - ChunkSerializerMixin_Tracker.impl$writeMap(positions, chunk.bridge$getTrackedIntPlayerPositions(), (nbt, pos) -> nbt.putInt("ipos", pos)); + this.tracker$shortPlayerPos = chunk.bridge$getTrackedShortPlayerPositions(); + this.tracker$intPlayerPos = chunk.bridge$getTrackedIntPlayerPositions(); + } + } + + @Inject(method = "write", at = @At(value = "RETURN")) + private void tracker$writeSpongeLevelData(final CallbackInfoReturnable cir) { + if (this.tracker$intPlayerPos == null && this.tracker$shortPlayerPos == null) { + return; } + final CompoundTag level = cir.getReturnValue(); + final CompoundTag trackedNbt = new CompoundTag(); + final ListTag positions = new ListTag(); + trackedNbt.put(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, positions); + level.put(Constants.Sponge.Data.V2.SPONGE_DATA, trackedNbt); + + SerializableChunkDataMixin_Tracker.tracker$writeMap(positions, this.tracker$shortPlayerPos, (nbt, pos) -> nbt.putShort("pos", pos)); + SerializableChunkDataMixin_Tracker.tracker$writeMap(positions, this.tracker$intPlayerPos, (nbt, pos) -> nbt.putInt("ipos", pos)); } - private static void impl$writeMap(final ListTag positions, final Map map, final BiConsumer consumer) { + private static void tracker$writeMap(final ListTag positions, final Map map, final BiConsumer consumer) { for (final Map.Entry mapEntry : map.entrySet()) { final T pos = mapEntry.getKey(); final int ownerUniqueIdIndex = mapEntry.getValue().creatorindex; @@ -81,21 +106,23 @@ public abstract class ChunkSerializerMixin_Tracker { } } - @Redirect(method = "read", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setLightCorrect(Z)V")) - private static void impl$readSpongeLevelData(final ChunkAccess chunkAccess, final boolean var1, final ServerLevel param0, final PoiManager param2, final RegionStorageInfo $$2, final ChunkPos param3, final CompoundTag param4) { - if (!(chunkAccess instanceof LevelChunk)) { - return; - } - final CompoundTag spongeData = param4.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); + + @Inject(method = "parse", at = @At(value = "RETURN")) + private static void impl$parseSpongeLevelData(LevelHeightAccessor $$0, RegistryAccess $$1, CompoundTag $$2, final CallbackInfoReturnable cir) { + final var chunkData = cir.getReturnValue(); + ((SerializableChunkDataBridge) (Object) chunkData).bridge$parseSpongeData(); + } + + @Override + public void bridge$parseSpongeData(final CompoundTag fullTag) { + final CompoundTag spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); if (spongeData.isEmpty()) { return; } - final Map trackedIntPlayerPositions = new HashMap<>(); - final Map trackedShortPlayerPositions = new HashMap<>(); + this.tracker$intPlayerPos = new HashMap<>(); + this.tracker$shortPlayerPos = new HashMap<>(); final ListTag list = spongeData.getList(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, 10); - final LevelChunkBridge chunk = (LevelChunkBridge) chunkAccess; for (final Tag tag : list) { final PlayerTracker tracker = new PlayerTracker(); final CompoundTag data = (CompoundTag) tag; @@ -108,13 +135,24 @@ public abstract class ChunkSerializerMixin_Tracker { } if (tracker.notifierIndex != -1 || tracker.creatorindex != -1) { if (isShortPos) { - trackedShortPlayerPositions.put(data.getShort("pos"), tracker); + this.tracker$shortPlayerPos.put(data.getShort("pos"), tracker); } else { - trackedIntPlayerPositions.put(data.getInt("ipos"), tracker); + this.tracker$intPlayerPos.put(data.getInt("ipos"), tracker); } } } - chunk.bridge$setTrackedIntPlayerPositions(trackedIntPlayerPositions); - chunk.bridge$setTrackedShortPlayerPositions(trackedShortPlayerPositions); + } + + @Redirect(method = "read", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setLightCorrect(Z)V")) + private void impl$readSpongeLevelData(final ChunkAccess chunkAccess, final boolean lightCorrect) { + chunkAccess.setLightCorrect(lightCorrect); + if (!(chunkAccess instanceof LevelChunk)) { + return; + } + + final LevelChunkBridge chunk = (LevelChunkBridge) chunkAccess; + chunk.bridge$setTrackedIntPlayerPositions(this.tracker$intPlayerPos); + chunk.bridge$setTrackedShortPlayerPositions(this.tracker$shortPlayerPos); } } diff --git a/src/mixins/resources/mixins.sponge.tracker.json b/src/mixins/resources/mixins.sponge.tracker.json index 4cc2dc73bf8..3ddf7243821 100644 --- a/src/mixins/resources/mixins.sponge.tracker.json +++ b/src/mixins/resources/mixins.sponge.tracker.json @@ -44,7 +44,7 @@ "world.level.block.entity.BlockEntityTypeMixin_Tracker", "world.level.chunk.ChunkAccessMixin_Tracker", "world.level.chunk.LevelChunkMixin_Tracker", - "world.level.chunk.storage.ChunkSerializerMixin_Tracker", + "world.level.chunk.storage.SerializableChunkDataMixin_Tracker", "world.level.dimension.end.EndDragonFightMixin_Tracker", "world.level.redstone.NeighborUpdaterMixin_Tracker", "world.ticks.LevelTicksMixin_Tracker", From 59a388dd36340605f2425c1ac5cac3fc28c6b859 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 14:12:11 +0200 Subject: [PATCH 018/586] TODO check overwrite - fix interaction result --- .../level/ServerPlayerGameModeMixin_Tracker.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 91e3465fc9a..06fb1b321cc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -30,7 +30,6 @@ import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.MenuProvider; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; @@ -82,7 +81,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { @Inject(method = "useItem", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemCooldowns;isOnCooldown(Lnet/minecraft/world/item/Item;)Z")) + target = "Lnet/minecraft/world/item/ItemCooldowns;isOnCooldown(Lnet/minecraft/world/item/ItemStack;)Z")) public void impl$callInteractItemSecondary(final ServerPlayer player, final Level level, final ItemStack stack, final InteractionHand hand, final CallbackInfoReturnable cir ) { @@ -137,14 +136,14 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl final boolean flag1 = playerIn.isSecondaryUseActive() && flag; final ItemStack copiedStack = stackIn.copy(); if (useBlock != Tristate.FALSE && !flag1) { // Sponge check useBlock - final ItemInteractionResult result = blockstate.useItemOn(playerIn.getItemInHand(handIn), worldIn, playerIn, handIn, blockRaytraceResultIn); + final InteractionResult result = blockstate.useItemOn(playerIn.getItemInHand(handIn), worldIn, playerIn, handIn, blockRaytraceResultIn); if (result.consumesAction()) { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack); - return result.result(); + return result; } - if (result == ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION && handIn == InteractionHand.MAIN_HAND) { + if (result instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge final InteractionResult result2 = blockstate.useWithoutItem(worldIn, playerIn, blockRaytraceResultIn); if (result2.consumesAction()) { @@ -169,7 +168,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl } } - if (!stackIn.isEmpty() && !playerIn.getCooldowns().isOnCooldown(stackIn.getItem())) { + if (!stackIn.isEmpty() && !playerIn.getCooldowns().isOnCooldown(stackIn)) { // Sponge start if (useItem == Tristate.FALSE) { ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(true); From c00e592e0dd6ab69e9007822dbfa686ab33773b9 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 14:16:15 +0200 Subject: [PATCH 019/586] fix interaction --- .../common/mixin/core/item/EmptyMapItemMixin.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java index 6bb0aeb5a62..be61d545ace 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java @@ -27,7 +27,7 @@ import com.google.common.collect.Sets; import net.minecraft.core.component.DataComponents; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.EmptyMapItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -110,11 +110,11 @@ public abstract class EmptyMapItemMixin { private void impl$returnFailResultIfMapWasNotCreated(final Level level, final net.minecraft.world.entity.player.Player playerIn, final InteractionHand handIn, - final CallbackInfoReturnable> cir, + final CallbackInfoReturnable cir, final ItemStack itemstack) { if (itemstack.isEmpty()) { cir.cancel(); - cir.setReturnValue(InteractionResultHolder.fail(playerIn.getItemInHand(handIn))); + cir.setReturnValue(InteractionResult.FAIL); } } From 1a5747a931e3fb6da92a12c21e33d7aa1c4e8704 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 14:19:25 +0200 Subject: [PATCH 020/586] TODO check if correctly consumed - fix interaction --- .../common/mixin/core/world/item/EnderEyeItemMixin.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/EnderEyeItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/EnderEyeItemMixin.java index 572050becb8..31681eb2e25 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/EnderEyeItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/EnderEyeItemMixin.java @@ -28,7 +28,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.EnderEyeItem; @@ -90,14 +89,14 @@ public abstract class EnderEyeItemMixin extends ItemMixin { cancellable = true ) private void impl$ThrowForPreEvent(final Level worldIn, final Player playerIn, final InteractionHand handIn, - final CallbackInfoReturnable> cir, final ItemStack used, final BlockHitResult rayTraceResult, final ServerLevel world, final BlockPos targetPos) { + final CallbackInfoReturnable cir, final ItemStack used, final BlockHitResult rayTraceResult, final ServerLevel world, final BlockPos targetPos) { if (targetPos != null && !((LevelBridge) worldIn).bridge$isFake() && ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) { final ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(PhaseTracker.getCauseStackManager().currentCause(), ServerLocation.of((ServerWorld) worldIn, playerIn.getX(), playerIn.getY() + (double) (playerIn.getDimensions(playerIn .getPose()).height() / 2.0F), playerIn.getZ()), new Vector3d(0, 0, 0), EntityTypes.EYE_OF_ENDER.get()); if (SpongeCommon.post(event)) { - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, used)); + cir.setReturnValue(InteractionResult.SUCCESS_SERVER); } } } @@ -108,14 +107,14 @@ public abstract class EnderEyeItemMixin extends ItemMixin { @SuppressWarnings("Duplicates") @Surrogate private void impl$ThrowForPreEvent(final Level worldIn, final Player playerIn, final InteractionHand handIn, - final CallbackInfoReturnable> cir, final ItemStack used, @Nullable final BlockPos targetPos) { + final CallbackInfoReturnable cir, final ItemStack used, @Nullable final BlockPos targetPos) { if (targetPos != null && !((LevelBridge) worldIn).bridge$isFake() && ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) { final ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(PhaseTracker.getCauseStackManager().currentCause(), ServerLocation.of((ServerWorld) worldIn, playerIn.getX(), playerIn.getY() + (double) (playerIn.getDimensions(playerIn .getPose()).height() / 2.0F), playerIn.getZ()), new Vector3d(0, 0, 0), EntityTypes.EYE_OF_ENDER.get()); if (SpongeCommon.post(event)) { - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, used)); + cir.setReturnValue(InteractionResult.SUCCESS_SERVER); } } } From 6b6629172b85413f5190366435b847c625cc9026 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 26 Aug 2024 14:51:11 +0200 Subject: [PATCH 021/586] TODO MovementType fix random teleport effect --- ...Mixin.java => TeleportRandomlyConsumeEffectMixin.java} | 8 ++++---- src/mixins/resources/mixins.sponge.core.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/core/world/item/{ChorusFruitItemMixin.java => TeleportRandomlyConsumeEffectMixin.java} (87%) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ChorusFruitItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java similarity index 87% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/item/ChorusFruitItemMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java index 01d1d24a33e..115c4446263 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ChorusFruitItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.world.item; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ChorusFruitItem; +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.cause.entity.MovementTypes; @@ -34,10 +34,10 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.event.tracking.PhaseTracker; -@Mixin(ChorusFruitItem.class) -public abstract class ChorusFruitItemMixin { +@Mixin(TeleportRandomlyConsumeEffect.class) +public abstract class TeleportRandomlyConsumeEffectMixin { - @Redirect(method = "finishUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZ)Z")) + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZ)Z")) private boolean impl$createCauseFrameForTeleport(final LivingEntity entity, final double x, final double y, final double z, final boolean p_213373_7_) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index b844181843a..5280515fe61 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -188,7 +188,7 @@ "world.entity.vehicle.VehicleEntityMixin", "world.food.FoodDataMixin", "world.inventory.StonecutterMenuMixin", - "world.item.ChorusFruitItemMixin", + "world.item.TeleportRandomlyConsumeEffectMixin", "world.item.EnderEyeItemMixin", "world.item.FireworkRocketItemMixin", "world.item.FishingRodItemMixin", From 11ff944a3a216b34e27dffef689ff8adfa5bd554 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 01:10:03 +0200 Subject: [PATCH 022/586] fix firework rocket interaction --- .../world/item/FireworkRocketItemMixin.java | 71 +++++++++++-------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FireworkRocketItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FireworkRocketItemMixin.java index 56c7a4349d6..32df5b872f4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FireworkRocketItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FireworkRocketItemMixin.java @@ -24,12 +24,11 @@ */ package org.spongepowered.common.mixin.core.world.item; -import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.item.FireworkRocketItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; @@ -87,9 +86,9 @@ public abstract class FireworkRocketItemMixin { cancellable = true ) private void impl$throwPreBeforeSpawning(final Level worldIn, final net.minecraft.world.entity.player.Player playerIn, final InteractionHand handIn, - final CallbackInfoReturnable> cir, final ItemStack stack) { + final CallbackInfoReturnable cir, final ItemStack stack) { if (this.impl$throwConstructPreEvent(worldIn, playerIn, stack)) { - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, stack)); + cir.setReturnValue(InteractionResult.SUCCESS); } } @@ -117,8 +116,8 @@ public abstract class FireworkRocketItemMixin { /** * Private method for bridging the duplicate between - * {@link #spongeImpl$ThrowPreBeforeSpawning(World, PlayerEntity, Hand, CallbackInfoReturnable, ItemStack)} and - * {@link #spongeImpl$ThrowPrimeEventsIfCancelled(ItemUseContext, CallbackInfoReturnable)} + * {@link #impl$throwPreBeforeSpawning} and + * {@link #impl$throwPrimeEventsIfCancelled} * since both follow the same logic, but differ in how they are called. * * @param world The world @@ -141,41 +140,53 @@ public abstract class FireworkRocketItemMixin { return false; } + private boolean impl$useOnCancelled = false; + + @Redirect(method = "useOn", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Projectile;spawnProjectile(Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/projectile/Projectile;") + ) + private T impl$onSpawnProjectileForUseOn(final T rocket, final ServerLevel $$1, final ItemStack usedItem, final UseOnContext context) { + this.impl$useOnCancelled = this.impl$throwPrimeEventAndGetCancel(context.getLevel(), context.getPlayer(), (FireworkRocketEntity) rocket, usedItem); + if (!this.impl$useOnCancelled) { + return Projectile.spawnProjectile(rocket, $$1, usedItem); + } + return rocket; + } + @Inject(method = "useOn", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Projectile;spawnProjectile(Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/projectile/Projectile;", + shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) - private void impl$injectPrimeEventAndCancel(final UseOnContext context, final CallbackInfoReturnable cir, final Level world, - final ItemStack usedItem, final net.minecraft.world.phys.Vec3 vec3d, final Direction direction, final FireworkRocketEntity rocket) { - if (this.impl$throwPrimeEventAndGetCancel(context.getLevel(), context.getPlayer(), rocket, usedItem)) { + private void impl$afterSpawnProjectileForUseOn(final UseOnContext context, final CallbackInfoReturnable cir) { + if (this.impl$useOnCancelled) { cir.setReturnValue(InteractionResult.SUCCESS); } } - private FireworkRocketEntity impl$capturedRocket; + private boolean impl$useCancelled = false; - @Redirect(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean impl$captureFireworkRocket(Level world, Entity p_217376_1_) { - this.impl$capturedRocket = (FireworkRocketEntity) p_217376_1_; - return true; + @Redirect(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Projectile;spawnProjectile(Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/projectile/Projectile;")) + private T impl$onSpawnProjectileForUse(final T rocket, final ServerLevel serverLevel, final ItemStack usedItem, + final Level $$0, final net.minecraft.world.entity.player.Player player, InteractionHand $$2) { + this.impl$useCancelled = this.impl$throwPrimeEventAndGetCancel(serverLevel, player, (FireworkRocketEntity) rocket, usedItem); + if (!this.impl$useCancelled) { + return Projectile.spawnProjectile(rocket, serverLevel, usedItem); + } + return rocket; } - @Inject(method = "use(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResultHolder;", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.AFTER), - locals = LocalCapture.CAPTURE_FAILHARD, + @Inject(method = "use", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Projectile;spawnProjectile(Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/projectile/Projectile;", + shift = At.Shift.AFTER), cancellable = true ) - private void impl$injectPrimeEventAndCancel(final Level worldIn, final net.minecraft.world.entity.player.Player player, final InteractionHand handIn, - final CallbackInfoReturnable> cir, final ItemStack usedItem) { - if (this.impl$throwPrimeEventAndGetCancel(worldIn, player, this.impl$capturedRocket, usedItem)) { - this.impl$capturedRocket = null; - // We have to still return success because the server/client can get out of sync otherwise. - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, usedItem)); + private void impl$afterSpawnProjectileForUse(final Level $$0, final net.minecraft.world.entity.player.Player $$1, + final InteractionHand $$2, final CallbackInfoReturnable cir) { + if (this.impl$useCancelled) { + cir.setReturnValue(InteractionResult.SUCCESS); } - - worldIn.addFreshEntity(this.impl$capturedRocket); - this.impl$capturedRocket = null; } /** @@ -183,8 +194,8 @@ public abstract class FireworkRocketItemMixin { * the prime is cancelled, then the firework will not be spawned. * This is to bridge the same logic between * - * {@link #impl$injectPrimeEventAndCancel(UseOnContext, CallbackInfoReturnable, Level, ItemStack, net.minecraft.world.phys.Vec3, Direction, FireworkRocketEntity)} - * {@link #impl$injectPrimeEventAndCancel(Level, net.minecraft.world.entity.player.Player, InteractionHand, CallbackInfoReturnable, ItemStack)} + * {@link #impl$onSpawnProjectileForUseOn} + * {@link #impl$onSpawnProjectileForUse} * * @param world The world * @param player The player using the item From ab49fd3b802c7beb2f62377de93baa83347f259a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 01:14:24 +0200 Subject: [PATCH 023/586] fix fishing rod interaction --- .../mixin/core/world/item/FishingRodItemMixin.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java index ec6a39b5881..6b53414d803 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java @@ -27,7 +27,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FishingHook; @@ -53,17 +52,16 @@ public abstract class FishingRodItemMixin { @Inject(method = "use", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/projectile/FishingHook;retrieve(Lnet/minecraft/world/item/ItemStack;)I"), cancellable = true) - private void cancelHookRetraction(Level world, Player player, InteractionHand hand, CallbackInfoReturnable> cir) { + private void cancelHookRetraction(Level world, Player player, InteractionHand hand, CallbackInfoReturnable cir) { if (player.fishing != null) { - // Event was cancelled - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, player.getItemInHand(hand))); + cir.setReturnValue(InteractionResult.SUCCESS); // Event was cancelled } } @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V", ordinal = 1), cancellable = true) - private void onThrowEvent(Level level, Player player, InteractionHand hand, CallbackInfoReturnable> cir) { + private void onThrowEvent(Level level, Player player, InteractionHand hand, CallbackInfoReturnable cir) { if (level.isClientSide) { // Only fire event on server-side to avoid crash on client return; @@ -73,12 +71,12 @@ private void onThrowEvent(Level level, Player player, InteractionHand hand, Call if (level instanceof ServerLevel serverLevel) { int $$6 = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemstack, player) * 20.0F); int $$7 = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemstack, player); - FishingHook fishHook = new FishingHook(player, level, $$7, $$6); + FishingHook fishHook = new FishingHook(player, level, $$7, $$6, itemstack); PhaseTracker.getCauseStackManager().pushCause(player); if (SpongeCommon.post(SpongeEventFactory.createFishingEventStart(PhaseTracker.getCauseStackManager().currentCause(), (FishingBobber) fishHook))) { fishHook.remove(Entity.RemovalReason.DISCARDED); // Bye - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, player.getItemInHand(hand))); + cir.setReturnValue(InteractionResult.SUCCESS); } else { this.impl$fishHook = fishHook; } @@ -87,7 +85,7 @@ private void onThrowEvent(Level level, Player player, InteractionHand hand, Call } @Redirect(method = "use", at = @At(value = "NEW", target = "net/minecraft/world/entity/projectile/FishingHook")) - private FishingHook onNewEntityFishHook(Player p_i50220_1_, Level p_i50220_2_, int p_i50220_3_, int p_i50220_4_) { + private FishingHook onNewEntityFishHook(final Player $$0, final Level $$1, final int $$2, final int $$3, final ItemStack $$4) { // Use the fish hook we created for the event FishingHook fishHook = this.impl$fishHook; this.impl$fishHook = null; From 3d42e5465ee3c8072e812b0e5c09825528494099 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 01:50:42 +0200 Subject: [PATCH 024/586] fix SerializableChunkData --- .../storage/SerializableChunkDataBridge.java | 19 ++- .../level/chunk/ChunkSerializerMixin.java | 69 ----------- .../chunk/SerializableChunkDataMixin.java | 112 ++++++++++++++++++ .../SerializableChunkDataMixin_Tracker.java | 54 ++------- src/mixins/resources/mixins.sponge.core.json | 2 +- 5 files changed, 138 insertions(+), 118 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkSerializerMixin.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java index 70dec219725..f731c3d8352 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java @@ -25,10 +25,23 @@ package org.spongepowered.common.bridge.world.level.chunk.storage; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; public interface SerializableChunkDataBridge { - void bridge$copySpongeData(ChunkAccess chunkAccess); - void bridge$parseSpongeData(CompoundTag tag); + void bridge$setTrackerData(LevelChunk chunkAccess); + + void bridge$writeTrackerData(CompoundTag level); + + void bridge$parseTrackerData(CompoundTag tag); + + void bridge$writeDataHolderData(CompoundTag level); + + void bridge$setDataHolderData(LevelChunk levelChunk); + + void bridge$parseDataHolderData(CompoundTag tag); + + void bridge$readTrackerDataFrom(LevelChunk levelChunk); + + void bridge$readDataHolderDataFrom(LevelChunk levelChunk); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkSerializerMixin.java deleted file mode 100644 index 04956c160d1..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkSerializerMixin.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.level.chunk; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.ai.village.poi.PoiManager; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ImposterProtoChunk; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.storage.ChunkSerializer; -import net.minecraft.world.level.chunk.storage.RegionStorageInfo; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.bridge.data.DataCompoundHolder; -import org.spongepowered.common.data.DataUtil; - -@Mixin(ChunkSerializer.class) -public abstract class ChunkSerializerMixin { - - @Inject(method = "write", at = @At(value = "RETURN")) - private static void impl$writeSpongeChunkData(final ServerLevel level, final ChunkAccess chunk, final CallbackInfoReturnable cir) { - if (!(chunk instanceof LevelChunk)) { - return; - } - - final CompoundTag compound = cir.getReturnValue(); - if (DataUtil.syncDataToTag(chunk)) { - compound.merge(((DataCompoundHolder) chunk).data$getCompound()); - } - } - - @Inject(method = "read", at = @At("RETURN")) - private static void impl$readSpongeChunkData(final ServerLevel level, final PoiManager poi, final RegionStorageInfo $$2, final ChunkPos pos, final CompoundTag compound, final CallbackInfoReturnable cir) { - if (!(cir.getReturnValue() instanceof ImposterProtoChunk imposter)) { - return; - } - - ((DataCompoundHolder) imposter.getWrapped()).data$setCompound(compound); - DataUtil.syncTagToData(imposter.getWrapped()); - ((DataCompoundHolder) imposter.getWrapped()).data$setCompound(null); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java new file mode 100644 index 00000000000..ba833dee911 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java @@ -0,0 +1,112 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.level.chunk; + +import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.storage.SerializableChunkData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.bridge.data.DataCompoundHolder; +import org.spongepowered.common.bridge.world.level.chunk.storage.SerializableChunkDataBridge; +import org.spongepowered.common.data.DataUtil; + +@Mixin(SerializableChunkData.class) +public abstract class SerializableChunkDataMixin implements SerializableChunkDataBridge { + + private CompoundTag impl$tag; + + @Inject(method = "copyOf", at = @At(value = "RETURN")) + private static void impl$copyOfSpongeData(final ServerLevel $$0, final ChunkAccess chunkAccess, final CallbackInfoReturnable cir) { + if (chunkAccess instanceof LevelChunk levelChunk) { + final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); + bridge.bridge$setTrackerData(levelChunk); + bridge.bridge$setDataHolderData(levelChunk); + } + } + + @Override + public void bridge$setDataHolderData(final LevelChunk levelChunk) { + this.impl$tag = null; + if (DataUtil.syncDataToTag(levelChunk)) { + this.impl$tag = ((DataCompoundHolder) levelChunk).data$getCompound(); + } + } + + @Inject(method = "write", at = @At(value = "RETURN")) + private void tracker$writeSpongeData(final CallbackInfoReturnable cir) { + final CompoundTag level = cir.getReturnValue(); + this.bridge$writeTrackerData(level); + this.bridge$writeDataHolderData(level); + } + + @Override + public void bridge$writeDataHolderData(final CompoundTag level) { + if (this.impl$tag != null) { + level.merge(this.impl$tag); + } + } + + @Inject(method = "parse", at = @At(value = "RETURN")) + private static void tracker$parseSpongeData(final LevelHeightAccessor $$0, final RegistryAccess $$1, final CompoundTag tag, final CallbackInfoReturnable cir) { + final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); + bridge.bridge$parseTrackerData(tag); + bridge.bridge$parseDataHolderData(tag); + } + + @Override + public void bridge$parseDataHolderData(final CompoundTag tag) { + this.impl$tag = tag; + } + + @Redirect(method = "read", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setLightCorrect(Z)V")) + private void impl$readSpongeLevelData(final ChunkAccess chunkAccess, final boolean lightCorrect) { + chunkAccess.setLightCorrect(lightCorrect); + + if (!(chunkAccess instanceof LevelChunk levelChunk)) { + return; + } + + this.bridge$readTrackerDataFrom(levelChunk); + this.bridge$readDataHolderDataFrom(levelChunk); + } + + @Override + public void bridge$readDataHolderDataFrom(final LevelChunk levelChunk) { + ((DataCompoundHolder) levelChunk).data$setCompound(this.impl$tag); + DataUtil.syncTagToData(levelChunk); + ((DataCompoundHolder) levelChunk).data$setCompound(null); + } + + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java index f15289bbeb9..08a90ddd88b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java @@ -24,25 +24,12 @@ */ package org.spongepowered.common.mixin.tracker.world.level.chunk.storage; -import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.ai.village.poi.PoiManager; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import net.minecraft.world.level.chunk.storage.SerializableChunkData; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.bridge.world.level.chunk.storage.SerializableChunkDataBridge; import org.spongepowered.common.entity.PlayerTracker; @@ -55,22 +42,11 @@ @Mixin(SerializableChunkData.class) public abstract class SerializableChunkDataMixin_Tracker implements SerializableChunkDataBridge { - - @Shadow @Final private boolean lightCorrect; private Map tracker$shortPlayerPos = null; private Map tracker$intPlayerPos = null; - @Inject(method = "copyOf", at = @At(value = "RETURN")) - private static void impl$copySpongeLevelData(final ServerLevel $$0, final ChunkAccess $$1, final CallbackInfoReturnable cir) { - final var chunkData = cir.getReturnValue(); - ((SerializableChunkDataBridge) (Object) chunkData).bridge$copySpongeData($$1); - } - @Override - public void bridge$copySpongeData(final ChunkAccess chunkAccess) { - if (!(chunkAccess instanceof LevelChunk)) { - return; - } + public void bridge$setTrackerData(final LevelChunk chunkAccess) { final LevelChunkBridge chunk = (LevelChunkBridge) chunkAccess; if (!chunk.bridge$getTrackedShortPlayerPositions().isEmpty() || !chunk.bridge$getTrackedIntPlayerPositions().isEmpty()) { this.tracker$shortPlayerPos = chunk.bridge$getTrackedShortPlayerPositions(); @@ -78,12 +54,11 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable } } - @Inject(method = "write", at = @At(value = "RETURN")) - private void tracker$writeSpongeLevelData(final CallbackInfoReturnable cir) { + @Override + public void bridge$writeTrackerData(final CompoundTag level) { if (this.tracker$intPlayerPos == null && this.tracker$shortPlayerPos == null) { return; } - final CompoundTag level = cir.getReturnValue(); final CompoundTag trackedNbt = new CompoundTag(); final ListTag positions = new ListTag(); trackedNbt.put(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, positions); @@ -93,6 +68,7 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable SerializableChunkDataMixin_Tracker.tracker$writeMap(positions, this.tracker$intPlayerPos, (nbt, pos) -> nbt.putInt("ipos", pos)); } + private static void tracker$writeMap(final ListTag positions, final Map map, final BiConsumer consumer) { for (final Map.Entry mapEntry : map.entrySet()) { final T pos = mapEntry.getKey(); @@ -106,15 +82,8 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable } } - - @Inject(method = "parse", at = @At(value = "RETURN")) - private static void impl$parseSpongeLevelData(LevelHeightAccessor $$0, RegistryAccess $$1, CompoundTag $$2, final CallbackInfoReturnable cir) { - final var chunkData = cir.getReturnValue(); - ((SerializableChunkDataBridge) (Object) chunkData).bridge$parseSpongeData(); - } - @Override - public void bridge$parseSpongeData(final CompoundTag fullTag) { + public void bridge$parseTrackerData(final CompoundTag fullTag) { final CompoundTag spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); if (spongeData.isEmpty()) { return; @@ -143,16 +112,11 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable } } - @Redirect(method = "read", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setLightCorrect(Z)V")) - private void impl$readSpongeLevelData(final ChunkAccess chunkAccess, final boolean lightCorrect) { - chunkAccess.setLightCorrect(lightCorrect); - if (!(chunkAccess instanceof LevelChunk)) { - return; - } - - final LevelChunkBridge chunk = (LevelChunkBridge) chunkAccess; + @Override + public void bridge$readTrackerDataFrom(final LevelChunk levelChunk) { + final LevelChunkBridge chunk = (LevelChunkBridge) levelChunk; chunk.bridge$setTrackedIntPlayerPositions(this.tracker$intPlayerPos); chunk.bridge$setTrackedShortPlayerPositions(this.tracker$shortPlayerPos); } + } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 5280515fe61..6da22cdc516 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -250,7 +250,7 @@ "world.level.block.state.BlockStateMixin", "world.level.border.WorldBorderMixin", "world.level.chunk.ChunkGeneratorMixin", - "world.level.chunk.ChunkSerializerMixin", + "world.level.chunk.SerializableChunkDataMixin", "world.level.chunk.ChunkStatusTasksMixin", "world.level.chunk.LevelChunkMixin", "world.level.chunk.storage.EntityStorageMixin", From e05fe22e5376f1df24ad68cad8d360dfd0079b40 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 02:08:20 +0200 Subject: [PATCH 025/586] fix ChunkMapMixin SerializationBehavior --- .../storage/SerializableChunkDataBridge.java | 3 +++ .../core/server/level/ChunkMapMixin.java | 21 ++++----------- .../chunk/SerializableChunkDataMixin.java | 27 +++++++++++++++++-- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java index f731c3d8352..815da991b19 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/chunk/storage/SerializableChunkDataBridge.java @@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.chunk.LevelChunk; +import org.spongepowered.api.world.SerializationBehavior; public interface SerializableChunkDataBridge { @@ -44,4 +45,6 @@ public interface SerializableChunkDataBridge { void bridge$readTrackerDataFrom(LevelChunk levelChunk); void bridge$readDataHolderDataFrom(LevelChunk levelChunk); + + void bridge$setSerializationBehavior(SerializationBehavior serializationBehavior); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java index 2df47d7beea..4780c5edbcd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java @@ -33,7 +33,6 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.storage.ChunkSerializer; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.world.chunk.ChunkEvent; @@ -68,6 +67,7 @@ import org.spongepowered.math.vector.Vector3i; import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; @Mixin(ChunkMap.class) public abstract class ChunkMapMixin implements ChunkMapBridge { @@ -99,26 +99,15 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { } @Redirect(method = "save", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/chunk/storage/ChunkSerializer;write(Lnet/minecraft/server/level/ServerLevel;" - + "Lnet/minecraft/world/level/chunk/ChunkAccess;)Lnet/minecraft/nbt/CompoundTag;")) - private CompoundTag impl$useSerializationBehaviorForChunkSave(final ServerLevel worldIn, final ChunkAccess chunkIn) { + target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture impl$doNotWriteIfWeHaveNoData(final ChunkMap chunkManager, final ChunkPos pos, final Supplier compound) { final PrimaryLevelDataBridge infoBridge = (PrimaryLevelDataBridge) this.level.getLevelData(); final SerializationBehavior serializationBehavior = infoBridge.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC); if (serializationBehavior == SerializationBehavior.AUTOMATIC || serializationBehavior == SerializationBehavior.MANUAL) { - return ChunkSerializer.write(worldIn, chunkIn); + return chunkManager.write(pos, compound); } - return null; - } - - @Redirect(method = "save", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/nbt/CompoundTag;)Ljava/util/concurrent/CompletableFuture;")) - private CompletableFuture impl$doNotWriteIfWeHaveNoData(final ChunkMap chunkManager, final ChunkPos pos, final CompoundTag compound) { - if (compound == null) { - return CompletableFuture.completedFuture(null); - } - - return chunkManager.write(pos, compound); + return CompletableFuture.completedFuture(null); } @Redirect(method = "lambda$scheduleUnload$12", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java index ba833dee911..bc55b4669ed 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java @@ -31,6 +31,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.storage.SerializableChunkData; +import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -38,22 +39,35 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.bridge.world.level.chunk.storage.SerializableChunkDataBridge; +import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.data.DataUtil; @Mixin(SerializableChunkData.class) public abstract class SerializableChunkDataMixin implements SerializableChunkDataBridge { private CompoundTag impl$tag; + private SerializationBehavior impl$serializationBehavior; + @Inject(method = "copyOf", at = @At(value = "RETURN")) - private static void impl$copyOfSpongeData(final ServerLevel $$0, final ChunkAccess chunkAccess, final CallbackInfoReturnable cir) { + private static void impl$copyOfSpongeData(final ServerLevel level, final ChunkAccess chunkAccess, final CallbackInfoReturnable cir) { + final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); + if (level.getLevelData() instanceof PrimaryLevelDataBridge levelBridge) { + final var behavior = levelBridge.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC); + bridge.bridge$setSerializationBehavior(behavior); + } if (chunkAccess instanceof LevelChunk levelChunk) { - final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); + bridge.bridge$setTrackerData(levelChunk); bridge.bridge$setDataHolderData(levelChunk); } } + @Override + public void bridge$setSerializationBehavior(final SerializationBehavior serializationBehavior) { + this.impl$serializationBehavior = serializationBehavior; + } + @Override public void bridge$setDataHolderData(final LevelChunk levelChunk) { this.impl$tag = null; @@ -62,6 +76,15 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat } } + @Inject(method = "write", at = @At(value = "HEAD"), cancellable = true) + private void tracker$beforeWrite(final CallbackInfoReturnable cir) { + switch (this.impl$serializationBehavior) { + case AUTOMATIC, MANUAL -> {} // write normally + default -> cir.setReturnValue(null); + } + + } + @Inject(method = "write", at = @At(value = "RETURN")) private void tracker$writeSpongeData(final CallbackInfoReturnable cir) { final CompoundTag level = cir.getReturnValue(); From 61b5d71d71d07e3c9a3847db870f1952f20b3059 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 02:13:47 +0200 Subject: [PATCH 026/586] delete PowerableMobMixin_API --- .../world/entity/PowerableMobMixin_API.java | 33 ------------------- src/mixins/resources/mixins.sponge.api.json | 1 - 2 files changed, 34 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/PowerableMobMixin_API.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/PowerableMobMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/PowerableMobMixin_API.java deleted file mode 100644 index 47588fb4481..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/PowerableMobMixin_API.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.api.minecraft.world.entity; - -import net.minecraft.world.entity.PowerableMob; -import org.spongepowered.api.entity.Chargeable; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(PowerableMob.class) -public interface PowerableMobMixin_API extends Chargeable { -} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index dbd651bafee..194ff0a12d9 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -116,7 +116,6 @@ "minecraft.world.entity.OwnableEntityMixin_API", "minecraft.world.entity.PathfinderMobMixin_API", "minecraft.world.entity.PortalProcessorMixin_API", - "minecraft.world.entity.PowerableMobMixin_API", "minecraft.world.entity.SaddleableMixin_API", "minecraft.world.entity.TamableAnimalMixin_API", "minecraft.world.entity.TargetingMixin_API", From 547d7ff89c41a9339872d4722d81abfd13e8761f Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 02:35:09 +0200 Subject: [PATCH 027/586] TODO fix ServerExplosionMixin_Tracker --- .../world/level/ExplosionMixin_Tracker.java | 176 ------------------ .../level/ServerExplosionMixin_Tracker.java | 90 +++++++++ .../resources/mixins.sponge.tracker.json | 2 +- 3 files changed, 91 insertions(+), 177 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ExplosionMixin_Tracker.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ExplosionMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ExplosionMixin_Tracker.java deleted file mode 100644 index 747a96b39a1..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ExplosionMixin_Tracker.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.tracker.world.level; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.Util; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BaseFireBlock; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.bridge.world.TrackedWorldBridge; -import org.spongepowered.common.bridge.world.level.ExplosionBridge; -import org.spongepowered.common.event.tracking.BlockChangeFlagManager; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.context.transaction.effect.AddBlockLootDropsEffect; -import org.spongepowered.common.event.tracking.context.transaction.effect.ExplodeBlockEffect; -import org.spongepowered.common.event.tracking.context.transaction.effect.SpawnDestructBlocksEffect; -import org.spongepowered.common.event.tracking.context.transaction.effect.WorldBlockChangeCompleteEffect; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; -import org.spongepowered.common.util.Constants; - -@Mixin(Explosion.class) -public abstract class ExplosionMixin_Tracker { - - @Shadow @Final private Level level; - @Shadow @Final private double x; - @Shadow @Final private double y; - @Shadow @Final private double z; - @Shadow @Final private Explosion.BlockInteraction blockInteraction; - @Shadow @Final private float radius; - @Shadow @Final private ObjectArrayList toBlow; - - @Shadow @Final private boolean fire; - @Shadow @Final private RandomSource random; - - /** - * @author gabziou - * @author zidane - * @reason Run explosion logic through tracking - */ - @Overwrite - public void finalizeExplosion(final boolean spawnParticles) { - // Sponge Start - In Sponge, we no longer call doExplosionB client-side (kills client perf) - if (this.level.isClientSide) { - return; - } - // Sponge End - - // Sponge Start - Send the sound packet down. We must do this as we do not call doExplosionB client-side - this.level.playSound(null, this.x, this.y, this.z, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.BLOCKS, 4.0F, - (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F); - // Sponge End - - final boolean flag = this.blockInteraction != Explosion.BlockInteraction.KEEP; - if (spawnParticles) { - if (!(this.radius < 2.0F) && (flag || ((ExplosionBridge) this).bridge$getShouldDamageBlocks())) { - // Sponge Start - Use WorldServer methods since we prune the explosion packets - // to avoid spamming/lagging the client out when some ~idiot~ decides to explode - // hundreds of explosions at once - if (this.level instanceof ServerLevel) { - ((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D); - } else { - this.level.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); - } - // Sponge End - } else { - // Sponge Start - Use WorldServer methods since we prune the explosion packets - // to avoid spamming/lagging the client out when some ~idiot~ decides to explode - // hundreds of explosions at once - if (this.level instanceof ServerLevel) { - ((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D); - } else { - this.level.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); - } - // Sponge End - } - } - - if (flag) { - // Sponge Start - Forward changes through a WorldPipeline to associate side effects - // Vanilla - uses a list of itemstacks to do a bunch of pre-merging - // ObjectArrayList> objectarraylist = new ObjectArrayList<>(); - Util.shuffle(this.toBlow, this.level.random); - - for (final BlockPos blockpos : this.toBlow) { - final BlockState blockstate = this.level.getBlockState(blockpos); - // Block block = blockstate.getBlock(); // Sponge - we don't use this - if (!blockstate.isAir()) { - final BlockPos blockpos1 = blockpos.immutable(); - this.level.getProfiler().push("explosion_blocks"); - - // Sponge - All of this is forwarded to the effects - // if (block.canDropFromExplosion(this) && this.level instanceof ServerLevel) { - // BlockEntity var6 = block.isEntityBlock() ? this.level.getBlockEntity(blockpos) : null; - // LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerLevel)this.level)).withRandom(this.level.rand).withParameter( - // LootParameters.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, var6).withNullableParameter(LootParameters.THIS_ENTITY, this.source); - // if (this.blockInteraction == Explosion.BlockInteraction.DESTROY) { - // lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, this.radius); - // } - - // var3.getDrops(var7).forEach((param2) -> addBlockDrops(var1, param2, var5)); - // } - - //this.level.setBlock(blockpos, Blocks.AIR.defaultState(), 3); - //block.onExplosionDestroy(this.world, blockpos, this); - - final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext(); - ((TrackedWorldBridge) this.level).bridge$startBlockChange(blockpos1, Blocks.AIR.defaultBlockState(), 3) - .ifPresent(builder -> { - final WorldPipeline build = builder - .addEffect(AddBlockLootDropsEffect.getInstance()) - .addEffect(ExplodeBlockEffect.getInstance()) - .addEffect(SpawnDestructBlocksEffect.getInstance()) - .addEffect(WorldBlockChangeCompleteEffect.getInstance()) - .build(); - build.processEffects(context, blockstate, Blocks.AIR.defaultBlockState(), blockpos1, - null, - BlockChangeFlagManager.fromNativeInt(3), - Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT); - }); - // Sponge End - this.level.getProfiler().pop(); - } - } - // Sponge Start - This is built into the SpawnDestructBlocksEffect - // for(Pair var8 : objectarraylist) { - // Block.popResource(this.level, var8.getSecond(), var8.getFirst()); - // } - // Sponge End - } - - if (this.fire) { - for(final BlockPos blockpos2 : this.toBlow) { - if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockpos2).isAir() && this.level.getBlockState(blockpos2.below()).isSolidRender(this.level, blockpos2.below())) { - this.level.setBlockAndUpdate(blockpos2, BaseFireBlock.getState(this.level, blockpos2)); - } - } - } - - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java new file mode 100644 index 00000000000..5f5f71eebca --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java @@ -0,0 +1,90 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.tracker.world.level; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.world.TrackedWorldBridge; +import org.spongepowered.common.event.tracking.BlockChangeFlagManager; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.context.transaction.effect.AddBlockLootDropsEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.ExplodeBlockEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.SpawnDestructBlocksEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.WorldBlockChangeCompleteEffect; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; +import org.spongepowered.common.util.Constants; + +import java.util.function.BiConsumer; + +@Mixin(ServerExplosion.class) +public abstract class ServerExplosionMixin_Tracker { + + + // TODO sounds & particles? + + @Redirect(method = "interactWithBlocks", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;popResource(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;)V")) + private void tracker$onPopResource(final Level $$0, final BlockPos $$1, final ItemStack $$2) { + // This is built into the SpawnDestructBlocksEffect + // Block.popResource(this.level, $$3.pos, $$3.stack); + } + + + @Redirect(method = "interactWithBlocks", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;onExplosionHit(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/Explosion;Ljava/util/function/BiConsumer;)V")) + private void tracker$onExplosionHit(final BlockState instance, final ServerLevel serverLevel, + final BlockPos blockPos, final Explosion explosion, final BiConsumer biConsumer) { + // this.level.getBlockState($$2).onExplosionHit(this.level, $$2, this, ($$1x, $$2x) -> addOrAppendStack($$1, $$1x, $$2x)); + + // TODO addOrAppendStack? ItemStack pre merging + final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext(); + ((TrackedWorldBridge) serverLevel).bridge$startBlockChange(blockPos, Blocks.AIR.defaultBlockState(), 3) + .ifPresent(builder -> { + final WorldPipeline build = builder + .addEffect(AddBlockLootDropsEffect.getInstance()) + .addEffect(ExplodeBlockEffect.getInstance()) + .addEffect(SpawnDestructBlocksEffect.getInstance()) + .addEffect(WorldBlockChangeCompleteEffect.getInstance()) + .build(); + build.processEffects(context, instance, Blocks.AIR.defaultBlockState(), blockPos, + null, + BlockChangeFlagManager.fromNativeInt(3), + Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT); + }); + } + + +} diff --git a/src/mixins/resources/mixins.sponge.tracker.json b/src/mixins/resources/mixins.sponge.tracker.json index 3ddf7243821..79857ecd615 100644 --- a/src/mixins/resources/mixins.sponge.tracker.json +++ b/src/mixins/resources/mixins.sponge.tracker.json @@ -32,7 +32,7 @@ "world.item.BoneMealItemMixin_Tracker", "world.item.ItemStackMixin_Tracker", "world.level.BlockEventDataMixin_Tracker", - "world.level.ExplosionMixin_Tracker", + "world.level.ServerExplosionMixin_Tracker", "world.level.LevelAccessorMixin_Tracker", "world.level.LevelHeightAccessorMixin_Tracker", "world.level.LevelMixin_Tracker", From ed6e428f6fe042206782a5ecbec8a3de3ed22e84 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 10:40:54 +0200 Subject: [PATCH 028/586] fix fluid blockstate tracking --- .../spongepowered/common/event/tracking/TrackingUtil.java | 4 +--- .../tracker/server/level/ServerLevelMixin_Tracker.java | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java index 2f559132d4f..135c7c3c626 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java @@ -230,12 +230,10 @@ public static void updateTickBlock( } public static void updateTickFluid( - final TrackedWorldBridge mixinWorld, final FluidState fluidState, final BlockPos pos - ) { + final TrackedWorldBridge mixinWorld, final FluidState fluidState, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState blockState) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; - final net.minecraft.world.level.block.state.BlockState blockState = fluidState.createLegacyBlock(); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot snapshot = mixinWorld.bridge$createSnapshot(blockState, pos, BlockChangeFlags.NONE); final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(PhaseTracker.getCauseStackManager().currentCause(), snapshot); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 1e0434aa999..eac1573a878 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -162,9 +162,9 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @Redirect(method = "tickFluid(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/material/Fluid;)V", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/material/FluidState;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V")) - private void tracker$wrapFluidTick(final FluidState fluidState, final net.minecraft.world.level.Level level, final BlockPos pos) { - TrackingUtil.updateTickFluid(this, fluidState, pos); + target = "Lnet/minecraft/world/level/material/FluidState;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) + private void tracker$wrapFluidTick(final FluidState fluidState, final net.minecraft.world.level.Level level, final BlockPos pos, final BlockState blockState) { + TrackingUtil.updateTickFluid(this, fluidState, pos, blockState); } private ScheduledTick tracker$createTick(final BlockPos pos, final T type, final int triggerTick, final TickPriority priority) { From 7a8612db5aa5af22fe0a1ee3ecda4b301a73e843 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 13:57:28 +0200 Subject: [PATCH 029/586] start fixing explosions --- .../bridge/explosives/ExplosiveBridge.java | 7 +- .../bridge/world/TrackedWorldBridge.java | 3 - .../boss/enderdragon/EndCrystalBridge.java | 7 +- .../projectile/LargeFireballBridge.java | 6 +- .../entity/projectile/WitherSkullBridge.java | 5 +- .../bridge/world/level/ExplosionBridge.java | 3 + .../event/SpongeCommonEventFactory.java | 19 --- .../boss/enderdragon/EndCrystalMixin_API.java | 3 +- .../projectile/LargeFireballMixin_API.java | 8 +- .../projectile/WitherSkullMixin_API.java | 5 +- ...API.java => ServerExplosionMixin_API.java} | 14 +- .../mixin/core/world/entity/EntityMixin.java | 9 ++ .../mixin/core/world/entity/MobMixin.java | 6 + .../boss/enderdragon/EndCrystalMixin.java | 37 ++--- .../world/entity/item/PrimedTntMixin.java | 44 +----- .../world/entity/monster/CreeperMixin.java | 31 +--- .../projectile/FireworkRocketEntityMixin.java | 11 +- .../entity/projectile/LargeFireballMixin.java | 48 ++---- .../entity/projectile/ProjectileMixin.java | 2 + .../entity/projectile/WitherSkullMixin.java | 35 ++--- .../entity/vehicle/MinecartTNTMixin.java | 31 +--- ...onMixin.java => ServerExplosionMixin.java} | 22 ++- .../level/ServerLevelMixin_Tracker.java | 147 ++++++++++-------- .../world/level/LevelMixin_Tracker.java | 3 + src/mixins/resources/mixins.sponge.api.json | 2 +- src/mixins/resources/mixins.sponge.core.json | 2 +- 26 files changed, 206 insertions(+), 304 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/{ExplosionMixin_API.java => ServerExplosionMixin_API.java} (92%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/level/{ExplosionMixin.java => ServerExplosionMixin.java} (96%) diff --git a/src/main/java/org/spongepowered/common/bridge/explosives/ExplosiveBridge.java b/src/main/java/org/spongepowered/common/bridge/explosives/ExplosiveBridge.java index c53341e74bb..34aac1a2009 100644 --- a/src/main/java/org/spongepowered/common/bridge/explosives/ExplosiveBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/explosives/ExplosiveBridge.java @@ -31,7 +31,10 @@ public interface ExplosiveBridge { - Optional bridge$getExplosionRadius(); + Optional bridge$getExplosionRadius(); + + void bridge$setExplosionRadius(@Nullable Float radius); + + default void bridge$cancelExplosion() {} - void bridge$setExplosionRadius(@Nullable Integer radius); } diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index fbc9060b94c..072e6c79190 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -55,9 +55,6 @@ public interface TrackedWorldBridge { boolean bridge$forceSpawnEntity(Entity entity); - net.minecraft.world.level.Explosion tracker$triggerInternalExplosion(Explosion explosion, Function> contextCreator); - Optional bridge$startBlockChange(BlockPos pos, BlockState state, int rawFlags); /** diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/boss/enderdragon/EndCrystalBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/boss/enderdragon/EndCrystalBridge.java index 931c19522f0..9f58f8701eb 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/boss/enderdragon/EndCrystalBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/boss/enderdragon/EndCrystalBridge.java @@ -25,13 +25,10 @@ package org.spongepowered.common.bridge.world.entity.boss.enderdragon; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; public interface EndCrystalBridge { - @Nullable Explosion bridge$throwExplosionEventAndExplode(Level world, @Nullable Entity nil, double x, - double y, double z, boolean smoking, @Nullable DamageSource source); + void bridge$wrappedExplode(double x, + double y, double z, @Nullable DamageSource source, final DamageSource causeSource); } diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/LargeFireballBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/LargeFireballBridge.java index 95d1f438633..b2282c0c20d 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/LargeFireballBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/LargeFireballBridge.java @@ -24,13 +24,9 @@ */ package org.spongepowered.common.bridge.world.entity.projectile; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; -import org.checkerframework.checker.nullness.qual.Nullable; public interface LargeFireballBridge { - @Nullable Explosion bridge$throwExplosionEventAndExplode(Level worldObj, @Nullable Entity nil, - double x, double y, double z, float strength, boolean flaming, Level.ExplosionInteraction mode); + void bridge$wrappedExplode(double x, double y, double z, float strength, boolean flaming, Level.ExplosionInteraction mode); } diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/WitherSkullBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/WitherSkullBridge.java index 8e87c427a77..78301e468b1 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/WitherSkullBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/projectile/WitherSkullBridge.java @@ -24,13 +24,10 @@ */ package org.spongepowered.common.bridge.world.entity.projectile; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; -import org.checkerframework.checker.nullness.qual.Nullable; public interface WitherSkullBridge { - @Nullable Explosion bridge$throwExplosionEventAndExplosde(net.minecraft.world.level.Level worldObj, Entity self, double x, + void bridge$wrappedExplode(double x, double y, double z, float strength, boolean flaming, Level.ExplosionInteraction mode); } diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java index 68f67ee2665..a4f666afe44 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.bridge.world.level; +import org.spongepowered.api.world.explosion.Explosion; + public interface ExplosionBridge { boolean bridge$getShouldDamageBlocks(); @@ -50,4 +52,5 @@ public interface ExplosionBridge { double bridge$getKnockback(); + Explosion.Builder bridge$asBuilder(); } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 79a8f646077..24f5ab202f2 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -103,7 +103,6 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.CreatorTrackedBridge; -import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.map.MapIdTrackerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.TrackedWorldBridge; @@ -626,24 +625,6 @@ public static SetAITargetEvent callSetAttackTargetEvent(final @Nullable Entity t return event; } - public static Optional detonateExplosive(final ExplosiveBridge explosiveBridge, final Explosion.Builder builder) { - final DetonateExplosiveEvent event = SpongeEventFactory.createDetonateExplosiveEvent( - PhaseTracker.getCauseStackManager().currentCause(), builder, (Explosive) explosiveBridge, builder.build() - ); - if (!Sponge.eventManager().post(event)) { - final Explosion explosion = event.explosionBuilder().build(); - if (explosion.radius() > 0) { - ((TrackedWorldBridge) ((Explosive) explosiveBridge).world()) - .tracker$triggerInternalExplosion( - explosion, - e -> GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER).explosion(e) - ); - } - return Optional.of((net.minecraft.world.level.Explosion) explosion); - } - return Optional.empty(); - } - /** * @author gabizou - April 19th, 2018 * Creates two events here: diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EndCrystalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EndCrystalMixin_API.java index 7f4490eef6a..0d9c4860db7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EndCrystalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EndCrystalMixin_API.java @@ -39,8 +39,7 @@ public abstract class EndCrystalMixin_API extends EntityMixin_API implements End @Override public void detonate() { this.shadow$discard(); - ((EndCrystalBridge) this).bridge$throwExplosionEventAndExplode(this.shadow$getCommandSenderWorld(), null, this.shadow$getX(), - this.shadow$getY(), this.shadow$getZ(), true, null); + ((EndCrystalBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), null, null); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java index 1956c863015..3fcf7053f0b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java @@ -39,14 +39,12 @@ @Mixin(LargeFireball.class) public abstract class LargeFireballMixin_API extends FireballMixin_API implements ExplosiveFireball { - @Shadow public int explosionPower; + @Shadow private int explosionPower; @Override public void detonate() { - final boolean flag = this.shadow$getCommandSenderWorld().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); - final Level.ExplosionInteraction mode = flag ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE; - ((LargeFireballBridge) this).bridge$throwExplosionEventAndExplode(this.shadow$getCommandSenderWorld(), null, this.shadow$getX(), - this.shadow$getY(), this.shadow$getZ(), this.explosionPower, flag, mode); + final boolean causesFire = this.shadow$getCommandSenderWorld().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + ((LargeFireballBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), this.explosionPower, causesFire, Level.ExplosionInteraction.MOB); this.shadow$discard(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java index 387579d5e62..72742b09d19 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -39,9 +38,7 @@ public abstract class WitherSkullMixin_API extends AbstractHurtingProjectileMixi @Override public void detonate() { - final Level.ExplosionInteraction mode = this.shadow$getCommandSenderWorld().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE; - ((WitherSkullBridge) this).bridge$throwExplosionEventAndExplosde(this.shadow$getCommandSenderWorld(), (net.minecraft.world.entity.projectile.WitherSkull) (Object) this, - this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), 1.0F, false, mode); + ((WitherSkullBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), 1.0F, false, Level.ExplosionInteraction.MOB); this.shadow$discard(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ExplosionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ExplosionMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java index 480737ccfea..67b0224e734 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ExplosionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.world.level; import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.world.explosion.Explosion; @@ -34,21 +35,22 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.level.ExplosionBridge; +import org.spongepowered.common.util.VecHelper; import java.util.Optional; -@Mixin(net.minecraft.world.level.Explosion.class) -public abstract class ExplosionMixin_API implements Explosion { +@Mixin(net.minecraft.world.level.ServerExplosion.class) +public abstract class ServerExplosionMixin_API implements Explosion { //@formatter:off @Shadow @Final private boolean fire; @Shadow @Final private net.minecraft.world.level.Level level; - @Shadow @Final private double x; - @Shadow @Final private double y; - @Shadow @Final private double z; + @Shadow @Final private Entity source; @Shadow @Final private float radius; @Shadow @Final private net.minecraft.world.level.Explosion.BlockInteraction blockInteraction; + @Shadow @Final private Vec3 center; + //@formatter:on @Nullable private ServerLocation api$location; @@ -56,7 +58,7 @@ public abstract class ExplosionMixin_API implements Explosion { @Override public ServerLocation location() { if (this.api$location == null) { - this.api$location = ServerLocation.of((ServerWorld) this.level, this.x, this.y, this.z); + this.api$location = ServerLocation.of((ServerWorld) this.level, VecHelper.toVector3d(this.center)); } return this.api$location; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 62911ab93fe..6d6693d348d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -43,6 +43,7 @@ import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; @@ -183,6 +184,14 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow @javax.annotation.Nullable public PortalProcessor portalProcess; // @formatter:on + @Shadow public abstract void move(final MoverType $$0, final Vec3 $$1); + + @Shadow public abstract boolean save(final CompoundTag $$0); + + @Shadow public abstract Vec3 calculateViewVector(final float $$0, final float $$1); + + @Shadow public abstract Level level(); + private boolean impl$isConstructing = true; private VanishState impl$vanishState = VanishState.unvanished(); protected boolean impl$transient = false; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 1e00bcd8358..9649c89ee30 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -27,8 +27,10 @@ import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.MoveControl; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.Entity; @@ -68,6 +70,10 @@ public abstract class MobMixin extends LivingEntityMixin { // @formatter:on + @Shadow public abstract boolean wantsToPickUp(final ItemStack $$0); + + @Shadow protected MoveControl moveControl; + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;registerGoals()V")) private void impl$registerGoals(final Mob this$0) { this.impl$setupGoalSelectors(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java index 358c4ebdd50..260354e7d87 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java @@ -31,9 +31,6 @@ import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -41,7 +38,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.world.entity.boss.enderdragon.EndCrystalBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; import org.spongepowered.common.util.Constants; @@ -52,49 +48,42 @@ @Mixin(EndCrystal.class) public abstract class EndCrystalMixin extends EntityMixin implements ExplosiveBridge, EndCrystalBridge { - private int impl$explosionStrength = Constants.Entity.EnderCrystal.DEFAULT_EXPLOSION_STRENGTH; + private float impl$explosionRadius = Constants.Entity.EnderCrystal.DEFAULT_EXPLOSION_STRENGTH; // Explosive Impl @Override - public Optional bridge$getExplosionRadius() { - return Optional.of(this.impl$explosionStrength); + public Optional bridge$getExplosionRadius() { + return Optional.of(this.impl$explosionRadius); } @Override - public void bridge$setExplosionRadius(@Nullable final Integer radius) { - this.impl$explosionStrength = radius == null ? Constants.Entity.EnderCrystal.DEFAULT_EXPLOSION_STRENGTH : radius; + public void bridge$setExplosionRadius(final @Nullable Float radius) { + this.impl$explosionRadius = radius == null ? Constants.Entity.EnderCrystal.DEFAULT_EXPLOSION_STRENGTH : radius; } @Redirect(method = "hurt", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;" + target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)V" ) ) - private net.minecraft.world.level.@Nullable Explosion impl$throwEventWithEntity(final net.minecraft.world.level.Level world, + private void impl$onHurtExplode(final net.minecraft.world.level.Level world, final Entity entityIn, final DamageSource damageSource, final ExplosionDamageCalculator exDamageCalc, final double xIn, final double yIn, final double zIn, final float explosionRadius, - final boolean fire, final Level.ExplosionInteraction modeIn) { - // TODO fire? - // TODO smoking value correct? - return this.bridge$throwExplosionEventAndExplode(world, entityIn, xIn, yIn, zIn, modeIn.compareTo(Level.ExplosionInteraction.TNT) <= 0, damageSource); + final boolean fire, final Level.ExplosionInteraction modeIn, final DamageSource causeSource, final float $$1) { + this.bridge$wrappedExplode(xIn, yIn, zIn, damageSource, causeSource); } @Override - public net.minecraft.world.level.@Nullable Explosion bridge$throwExplosionEventAndExplode(final net.minecraft.world.level.Level world, - @Nullable final Entity nil, final double x, final double y, final double z, final boolean smoking, - @Nullable final DamageSource source) { + public void bridge$wrappedExplode(final double x, final double y, final double z, + @Nullable final DamageSource source, final DamageSource causeSource) { final CauseStackManager causeStackManager = PhaseTracker.getCauseStackManager(); try (final CauseStackManager.StackFrame frame = causeStackManager.pushCauseFrame()) { frame.pushCause(this); if (source != null) { - frame.pushCause(source); + frame.pushCause(causeSource); } - return SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) world, x, y, z)) - .radius(this.impl$explosionStrength) - .shouldPlaySmoke(smoking)) - .orElse(null); + this.level().explode( (Entity) (Object) this, source, null, x, y, z, this.impl$explosionRadius, false, Level.ExplosionInteraction.BLOCK); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java index 8f239cc52af..91e09a95ade 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java @@ -28,16 +28,12 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.level.Explosion.BlockInteraction; import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.explosive.fused.PrimedTNT; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -47,7 +43,6 @@ import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; import org.spongepowered.common.bridge.world.entity.item.PrimedTntBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; import org.spongepowered.common.util.Constants; @@ -60,10 +55,11 @@ public abstract class PrimedTntMixin extends EntityMixin implements PrimedTntBri // @formatter:off @Shadow public abstract int shadow$getFuse(); @Shadow public abstract void shadow$setFuse(int var1); + @Shadow private float explosionPower; + // @formatter:on @Nullable private LivingEntity impl$detonator; - private int bridge$explosionRadius = Constants.Entity.PrimedTNT.DEFAULT_EXPLOSION_RADIUS; private int bridge$fuseDuration = Constants.Entity.PrimedTNT.DEFAULT_FUSE_DURATION; @Override @@ -77,13 +73,13 @@ public abstract class PrimedTntMixin extends EntityMixin implements PrimedTntBri } @Override - public Optional bridge$getExplosionRadius() { - return Optional.of(this.bridge$explosionRadius); + public Optional bridge$getExplosionRadius() { + return Optional.of(this.explosionPower); } @Override - public void bridge$setExplosionRadius(@Nullable final Integer radius) { - this.bridge$explosionRadius = radius == null ? Constants.Entity.PrimedTNT.DEFAULT_EXPLOSION_RADIUS : radius; + public void bridge$setExplosionRadius(final @Nullable Float radius) { + this.explosionPower = radius == null ? Constants.Entity.PrimedTNT.DEFAULT_EXPLOSION_RADIUS : radius; } @Override @@ -106,34 +102,6 @@ public abstract class PrimedTntMixin extends EntityMixin implements PrimedTntBri this.shadow$setFuse(fuseTicks); } - @Redirect( - method = "explode", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;" - ) - ) - private net.minecraft.world.level.@Nullable Explosion impl$useSpongeExplosion(final Level world, - final Entity entityIn, - final DamageSource damageSource, - final ExplosionDamageCalculator explosionDamageCalculator, - final double xIn, final double yIn, final double zIn, final - float explosionRadius, - final boolean falseValue, - final Level.ExplosionInteraction modeIn) { - return SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) world, xIn, yIn, zIn)) - .sourceExplosive((PrimedTNT) this) - .radius(this.bridge$explosionRadius) - .shouldPlaySmoke(modeIn.ordinal() > BlockInteraction.KEEP.ordinal()) - .shouldBreakBlocks(modeIn.ordinal() > BlockInteraction.KEEP.ordinal())) - .orElseGet(() -> { - ((PrimedTNT) this).offer(Keys.IS_PRIMED, false); - return null; - }); - } - - @Inject(method = "tick()V", at = @At("RETURN")) private void impl$updateTNTPushPrime(final CallbackInfo ci) { if (this.shadow$getFuse() == this.bridge$fuseDuration - 1 && !this.shadow$level().isClientSide) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java index 76bdff39e87..7c24224a7e0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java @@ -30,10 +30,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.entity.living.monster.Creeper; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -42,8 +38,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; -import org.spongepowered.common.bridge.world.entity.GrieferBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.util.Constants; import java.util.Optional; @@ -68,13 +62,13 @@ public abstract class CreeperMixin extends MonsterMixin implements FusedExplosiv // FusedExplosive Impl @Override - public Optional bridge$getExplosionRadius() { - return Optional.of(this.explosionRadius); + public Optional bridge$getExplosionRadius() { + return Optional.of((float) this.explosionRadius); } @Override - public void bridge$setExplosionRadius(@Nullable final Integer radius) { - this.explosionRadius = radius == null ? Constants.Entity.Creeper.DEFAULT_EXPLOSION_RADIUS : radius; + public void bridge$setExplosionRadius(final @Nullable Float radius) { + this.explosionRadius = radius == null ? Constants.Entity.Creeper.DEFAULT_EXPLOSION_RADIUS : radius.intValue(); } @Override @@ -136,25 +130,16 @@ public abstract class CreeperMixin extends MonsterMixin implements FusedExplosiv } } - @Redirect(method = "explodeCreeper", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) - private net.minecraft.world.level.@Nullable Explosion impl$useSpongeExplosion(final net.minecraft.world.level.Level world, final Entity self, final double x, - final double y, final double z, final float strength, final Level.ExplosionInteraction mode) { - return SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) world, x, y, z)) - .sourceExplosive(((Creeper) this)) - .radius(strength) - .shouldPlaySmoke(mode != Level.ExplosionInteraction.NONE) - .shouldBreakBlocks(mode != Level.ExplosionInteraction.NONE && ((GrieferBridge) this).bridge$canGrief())) - .orElseGet(() -> { - this.impl$detonationCancelled = true; - return null; - }); + @Override + public void bridge$cancelExplosion() { + this.impl$detonationCancelled = true; } @Inject(method = "explodeCreeper", at = @At("RETURN")) private void impl$postExplode(final CallbackInfo ci) { if (this.impl$detonationCancelled) { this.impl$detonationCancelled = this.dead = false; + this.shadow$unsetRemoved(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java index 221f8b7917b..be51b1f5a52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java @@ -54,7 +54,7 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen @Shadow private int lifetime; // @formatter:on - private int impl$explosionRadius = Constants.Entity.Firework.DEFAULT_EXPLOSION_RADIUS; + private float impl$explosionRadius = Constants.Entity.Firework.DEFAULT_EXPLOSION_RADIUS; @Override public int bridge$getFuseDuration() { @@ -78,12 +78,12 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen } @Override - public Optional bridge$getExplosionRadius() { + public Optional bridge$getExplosionRadius() { return Optional.of(this.impl$explosionRadius); } @Override - public void bridge$setExplosionRadius(final @Nullable Integer radius) { + public void bridge$setExplosionRadius(final @Nullable Float radius) { this.impl$explosionRadius = radius == null ? Constants.Entity.Firework.DEFAULT_EXPLOSION_RADIUS : radius; } @@ -102,10 +102,11 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen // won't be triggered (the default behavior). frame.pushCause(this); frame.addContext(EventContextKeys.PROJECTILE_SOURCE, this.impl$getProjectileSource()); - SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() + final var explosionBuilder = Explosion.builder() .sourceExplosive(((FireworkRocket) this)) .location(((FireworkRocket) this).serverLocation()) - .radius(this.impl$explosionRadius)) + .radius(this.impl$explosionRadius); + SpongeCommonEventFactory.detonateExplosive(this, explosionBuilder) .ifPresent(explosion -> world.broadcastEntityEvent(self, state)); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java index ed564bd5957..8accd786833 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java @@ -30,20 +30,14 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.projectile.Projectile; -import org.spongepowered.api.entity.projectile.explosive.fireball.ExplosiveFireball; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; -import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.bridge.world.entity.projectile.LargeFireballBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.Constants; @@ -53,54 +47,38 @@ public abstract class LargeFireballMixin extends AbstractHurtingProjectileMixin implements LargeFireballBridge, ExplosiveBridge { // @formatter:off - @Shadow public int explosionPower; + @Shadow private int explosionPower; // @formatter:on - /** - * @author gabizou April 13th, 2018 - * @reason Due to changes from Forge, we have to redirect osr modify the gamerule check, - * but since forge doesn't allow us to continue to check the gamerule method call here, - * we have to modify the arguments passed in (the two booleans). There may be a better way, - * which may include redirecting the world.newExplosion method call instead of modifyargs, - * but, it is what it is. - */ @Redirect(method = "onHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;" + target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)V" ) ) - public net.minecraft.world.level.@Nullable Explosion impl$throwExplosionEventAndExplode(final net.minecraft.world.level.Level worldObj, @Nullable final Entity nil, - final double x, final double y, final double z, final float strength, final boolean flaming, final Level.ExplosionInteraction mode) { - return this.bridge$throwExplosionEventAndExplode(worldObj, nil, x, y, z, strength, flaming, mode); + public void impl$onHitExplode(final Level world, final Entity thisEntity, + final double x, final double y, final double z, final float explosionRadius, final boolean causesFire, + final Level.ExplosionInteraction mode) { + this.bridge$wrappedExplode(x, y, z, explosionRadius, causesFire, mode); } @Override - public net.minecraft.world.level.Explosion bridge$throwExplosionEventAndExplode(net.minecraft.world.level.Level worldObj, @Nullable Entity nil, - double x, double y, double z, float strength, boolean flaming, Level.ExplosionInteraction mode) { - final boolean griefer = ((GrieferBridge) this).bridge$canGrief(); + public void bridge$wrappedExplode(final double x, final double y, final double z, + final float explosionRadius, final boolean causesFire, final Level.ExplosionInteraction mode) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.pushCause(this); ((Projectile) this).get(Keys.SHOOTER).ifPresent(shooter -> frame.addContext(EventContextKeys.PROJECTILE_SOURCE, shooter)); - final Optional ex = SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) worldObj, x, y, z)) - .sourceExplosive(((ExplosiveFireball) this)) - .radius(strength) - .canCauseFire(flaming && griefer) - .shouldPlaySmoke(mode != Level.ExplosionInteraction.NONE && griefer) - .shouldBreakBlocks(mode != Level.ExplosionInteraction.NONE && griefer)); - - return ex.orElse(null); + this.level().explode((LargeFireball) (Object) this, x, y, z, explosionRadius, causesFire, mode); } } @Override - public Optional bridge$getExplosionRadius() { - return Optional.of(this.explosionPower); + public Optional bridge$getExplosionRadius() { + return Optional.of((float) this.explosionPower); } @Override - public void bridge$setExplosionRadius(@Nullable final Integer radius) { - this.explosionPower = radius == null ? Constants.Entity.Fireball.DEFAULT_EXPLOSION_RADIUS : radius; + public void bridge$setExplosionRadius(final @Nullable Float radius) { + this.explosionPower = radius == null ? Constants.Entity.Fireball.DEFAULT_EXPLOSION_RADIUS : radius.intValue(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java index 5af1962961e..d16b1e3086e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java @@ -53,6 +53,8 @@ public abstract class ProjectileMixin extends EntityMixin { @Shadow public abstract @Nullable Entity shadow$getOwner(); @Shadow protected abstract ProjectileDeflection shadow$hitTargetOrDeflectSelf(HitResult $$0); + @Shadow protected abstract ProjectileDeflection hitTargetOrDeflectSelf(final HitResult $$0); + // @formatter:on private ProjectileSource impl$projectileSource = UnknownProjectileSource.UNKNOWN; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java index 2377fa1317f..fa4610c95bb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java @@ -25,25 +25,20 @@ package org.spongepowered.common.mixin.core.world.entity.projectile; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.projectile.WitherSkull; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.projectile.Projectile; -import org.spongepowered.api.entity.projectile.explosive.WitherSkull; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.accessor.world.entity.projectile.ProjectileAccessor; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; -import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.bridge.world.entity.projectile.WitherSkullBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.Constants; @@ -52,7 +47,7 @@ @Mixin(net.minecraft.world.entity.projectile.WitherSkull.class) public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin implements WitherSkullBridge, ExplosiveBridge { - private int impl$explosionRadius = Constants.Entity.WitherSkull.DEFAULT_EXPLOSION_RADIUS; + private float impl$explosionRadius = Constants.Entity.WitherSkull.DEFAULT_EXPLOSION_RADIUS; // TODO Key not implemented private float impl$damage = 0.0f; @@ -72,41 +67,31 @@ public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin im // Explosive Impl @Override - public Optional bridge$getExplosionRadius() { + public Optional bridge$getExplosionRadius() { return Optional.of(this.impl$explosionRadius); } @Override - public void bridge$setExplosionRadius(final @Nullable Integer explosionRadius) { + public void bridge$setExplosionRadius(final @Nullable Float explosionRadius) { this.impl$explosionRadius = explosionRadius == null ? Constants.Entity.WitherSkull.DEFAULT_EXPLOSION_RADIUS : explosionRadius; } @Redirect(method = "onHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) - public net.minecraft.world.level.@Nullable Explosion impl$CreateAndProcessExplosionEvent(final net.minecraft.world.level.Level worldObj, final Entity self, - final double x, final double y, final double z, final float strength, final boolean flaming, final Level.ExplosionInteraction mode) { - return this.bridge$throwExplosionEventAndExplosde(worldObj, self, x, y, z, strength, flaming, mode); + target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)V")) + public void impl$onHitExplode(final net.minecraft.world.level.Level worldObj, final Entity self, + final double x, final double y, final double z, final float explosionRadius, final boolean causesFire, final Level.ExplosionInteraction mode) { + this.bridge$wrappedExplode(x, y, z, explosionRadius, causesFire, mode); } @Override - public net.minecraft.world.level.Explosion bridge$throwExplosionEventAndExplosde( - final net.minecraft.world.level.Level worldObj, final Entity self, - final double x, final double y, final double z, final float strength, final boolean flaming, final Level.ExplosionInteraction mode) { - final boolean griefer = ((GrieferBridge) this).bridge$canGrief(); + public void bridge$wrappedExplode(final double x, final double y, final double z, final float explosionRadius, final boolean causesFire, final Level.ExplosionInteraction mode) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.pushCause(this); ((Projectile) this).get(Keys.SHOOTER).ifPresent(shooter -> { frame.addContext(EventContextKeys.PROJECTILE_SOURCE, shooter); frame.pushCause(shooter); }); - return SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) worldObj, x, y, z)) - .sourceExplosive(((WitherSkull) this)) - .radius(this.impl$explosionRadius) - .canCauseFire(flaming) - .shouldPlaySmoke(mode != Level.ExplosionInteraction.NONE && griefer) - .shouldBreakBlocks(mode != Level.ExplosionInteraction.NONE && griefer)) - .orElse(null); + this.level().explode((WitherSkull) (Object) this, x, y, z, explosionRadius, causesFire, mode); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index db569f5e383..7b8f6dd27c6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -59,18 +59,18 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements @Shadow private int fuse; // @formatter:on - @Nullable private Integer impl$explosionRadius = null; + @Nullable private Float impl$explosionRadius = null; // override for fixed radius private int impl$fuseDuration = Constants.Entity.Minecart.DEFAULT_FUSE_DURATION; private boolean impl$detonationCancelled; @Nullable private Object impl$primeCause; @Override - public Optional bridge$getExplosionRadius() { + public Optional bridge$getExplosionRadius() { return Optional.ofNullable(this.impl$explosionRadius); } @Override - public void bridge$setExplosionRadius(final @Nullable Integer radius) { + public void bridge$setExplosionRadius(final @Nullable Float radius) { this.impl$explosionRadius = radius; } @@ -130,28 +130,9 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements } } - @Redirect( - method = "explode(Lnet/minecraft/world/damagesource/DamageSource;D)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;" - ) - ) - private net.minecraft.world.level.@Nullable Explosion impl$useSpongeExplosion(final net.minecraft.world.level.Level world, final Entity entityIn, - final DamageSource damageSource, final ExplosionDamageCalculator calculator, - final double xIn, final double yIn, final double zIn, final float explosionRadius, final boolean fire, final Level.ExplosionInteraction modeIn) { - // TODO ExplosionDamageCalculator & fire - return SpongeCommonEventFactory.detonateExplosive(this, Explosion.builder() - .location(ServerLocation.of((ServerWorld) world, xIn, yIn, zIn)) - .sourceExplosive((TNTMinecart) this) - .radius(this.impl$explosionRadius != null ? this.impl$explosionRadius : explosionRadius) - .shouldPlaySmoke(modeIn.ordinal() > Level.ExplosionInteraction.NONE.ordinal()) - .shouldBreakBlocks(modeIn.ordinal() > Level.ExplosionInteraction.NONE.ordinal())) - .orElseGet(() -> { - this.impl$detonationCancelled = true; - return null; - } - ); + @Override + public void bridge$cancelExplosion() { + this.impl$detonationCancelled = true; } @Inject(method = "explode(Lnet/minecraft/world/damagesource/DamageSource;D)V", at = @At("RETURN")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ExplosionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/level/ExplosionMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java index 688112d13eb..06347dab9ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ExplosionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java @@ -47,6 +47,7 @@ import org.spongepowered.api.event.world.ExplosionEvent; import org.spongepowered.api.world.explosion.Explosion; import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -69,18 +70,14 @@ import java.util.Set; import java.util.StringJoiner; -@Mixin(net.minecraft.world.level.Explosion.class) -public abstract class ExplosionMixin implements ExplosionBridge { +@Mixin(net.minecraft.world.level.ServerExplosion.class) +public abstract class ServerExplosionMixin implements ExplosionBridge { // @formatter:off @Shadow @Final private ExplosionDamageCalculator damageCalculator; - @Shadow @Final private ObjectArrayList toBlow; @Shadow @Final private Map hitPlayers; @Shadow @Final private boolean fire; @Shadow @Final private net.minecraft.world.level.Level level; - @Shadow @Final private double x; - @Shadow @Final private double y; - @Shadow @Final private double z; @Shadow @Final private Entity source; @Shadow @Final private float radius; @Shadow @Final private net.minecraft.world.level.Explosion.BlockInteraction blockInteraction; @@ -88,6 +85,7 @@ public abstract class ExplosionMixin implements ExplosionBridge { @Shadow @Final private DamageSource damageSource; // @formatter:on + @Shadow @Final private Vec3 center; private boolean impl$shouldBreakBlocks; private boolean impl$shouldDamageEntities; private boolean impl$shouldPlaySmoke; @@ -337,9 +335,19 @@ public void explode() { return this.impl$knockback; } + @Override + public Explosion.Builder bridge$asBuilder() { + var builder = org.spongepowered.api.world.explosion.Explosion.builder(); + // TODO finish building + builder.location(ServerLocation.of((ServerWorld) this.level, VecHelper.toVector3d(this.center))) + .radius(this.radius); + + return builder; + } + @Override public String toString() { - return new StringJoiner(", ", ExplosionMixin.class.getSimpleName() + "[", "]") + return new StringJoiner(", ", ServerExplosionMixin.class.getSimpleName() + "[", "]") .add("causesFire=" + this.fire) .add("mode=" + this.blockInteraction) .add("world=" + this.level) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index eac1573a878..5defde3d228 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -31,9 +31,13 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.RandomSource; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.BlockEventData; import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.ExplosionDamageCalculator; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.piston.PistonBaseBlock; @@ -48,6 +52,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.entity.BlockEntity; +import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.SpongeEventFactory; @@ -55,6 +60,8 @@ import org.spongepowered.api.event.world.ExplosionEvent; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.LocatableBlock; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -66,8 +73,11 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.TrackableBridge; +import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.TrackedWorldBridge; +import org.spongepowered.common.bridge.world.entity.GrieferBridge; +import org.spongepowered.common.bridge.world.level.ExplosionBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.TrackableBlockEventDataBridge; import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; @@ -99,6 +109,7 @@ import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; +import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; import org.spongepowered.common.event.tracking.phase.tick.TickPhase; import org.spongepowered.common.mixin.tracker.world.level.LevelMixin_Tracker; import org.spongepowered.common.util.Constants; @@ -120,6 +131,10 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @Shadow @Final List players; // @formatting:on + @Shadow public abstract boolean isFlat(); + + @Shadow public abstract void resetEmptyTime(); + @Redirect( // This normally would target this.entityTickList.forEach((var2x) -> // but we don't have lambda syntax support yet. @@ -329,81 +344,83 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge return list.add(blockEventData); } - @SuppressWarnings({"unchecked", "rawtypes"}) - @Override - public Explosion tracker$triggerInternalExplosion(org.spongepowered.api.world.explosion.Explosion explosion, - final Function> contextCreator) { - // Sponge start - final Explosion originalExplosion = (Explosion) explosion; + @Redirect(method = "explode", at = @At(value = "NEW", + target = "(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;Lnet/minecraft/world/phys/Vec3;FZLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/ServerExplosion;")) + private ServerExplosion tracker$onExplode(final ServerLevel $$0, final Entity entity, final DamageSource $$2, + final ExplosionDamageCalculator $$3, final Vec3 $$4, final float radius, final boolean $$6, + final Explosion.BlockInteraction blockInteraction) { + final var cannotGrief = entity instanceof GrieferBridge grieferBridge && !grieferBridge.bridge$canGrief(); + var finalRadius = radius; + if (entity instanceof ExplosiveBridge bridge) { + finalRadius = bridge.bridge$getExplosionRadius().orElse(finalRadius); + } + + return new ServerExplosion($$0, entity, $$2, $$3, $$4, finalRadius, $$6, cannotGrief ? Explosion.BlockInteraction.KEEP : blockInteraction); + } + + @Redirect(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;explode()V")) + private void tracker$onExplode(final ServerExplosion instance) { + var mcExplosion = instance; + final var entity = instance.getDirectSourceEntity(); + // TODO entity can be null, what is our API explosive then? + // TODO API explosive can be smth. that is not an entity? + final var thisWorld = (ServerWorld) this; + final var explosionBuilder = ((ExplosionBridge)mcExplosion).bridge$asBuilder(); + + Explosive apiExplosive = (Explosive) entity; + final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(PhaseTracker.getCauseStackManager().currentCause(), + explosionBuilder, apiExplosive, (org.spongepowered.api.world.explosion.Explosion) instance); + if (Sponge.eventManager().post(detonateEvent)) { + this.tracker$cancelExplosionEffects(entity); + return; + } + + // Build the explosion from event + var apiExplosion = detonateEvent.explosionBuilder().build(); + if (apiExplosion.radius() <= 0) { + this.tracker$cancelExplosionEffects(entity); + return; + } + if (ShouldFire.EXPLOSION_EVENT_PRE) { // Set up the pre event - final ExplosionEvent.Pre - event = - SpongeEventFactory.createExplosionEventPre( - PhaseTracker.SERVER.currentCause(), - explosion, ((org.spongepowered.api.world.server.ServerWorld) this)); + final ExplosionEvent.Pre event = + SpongeEventFactory.createExplosionEventPre(PhaseTracker.SERVER.currentCause(), apiExplosion, thisWorld); if (SpongeCommon.post(event)) { - return (Explosion) explosion; + this.tracker$cancelExplosionEffects(entity); + return; } - explosion = event.explosion(); - } - final Explosion mcExplosion; - try { - // Since we already have the API created implementation Explosion, let's use it. - mcExplosion = (Explosion) explosion; - } catch (final Exception e) { - new org.spongepowered.asm.util.PrettyPrinter(60).add("Explosion not compatible with this implementation").centre().hr() - .add("An explosion that was expected to be used for this implementation does not") - .add("originate from this implementation.") - .add(e) - .trace(); - return originalExplosion; - } - - try (final PhaseContext<@NonNull ?> ignored = contextCreator.apply(mcExplosion) - .source(((Optional) explosion.sourceExplosive()).orElse(this))) { - ignored.buildAndSwitch(); - final boolean damagesTerrain = explosion.shouldBreakBlocks(); - // Sponge End - - mcExplosion.explode(); - mcExplosion.finalizeExplosion(true); - if (!damagesTerrain) { - mcExplosion.clearToBlow(); + try { + // Since we already have the API created implementation Explosion, let's use it. + mcExplosion = (ServerExplosion) event.explosion(); + apiExplosion = event.explosion(); + } catch (final ClassCastException e) { + new org.spongepowered.asm.util.PrettyPrinter(60).add("Explosion not compatible with this implementation").centre().hr() + .add("An explosion that was expected to be used for this implementation does not originate from this implementation.") + .trace(); + mcExplosion = (ServerExplosion) detonateEvent.explosionBuilder().build(); } + } - // Sponge Start - Don't send explosion packets, they're spammy, we can replicate it on the server entirely - /* - for (EntityPlayer entityplayer : this.playerEntities) { - if (entityplayer.getDistanceSq(x, y, z) < 4096.0D) { - ((EntityPlayerMP) entityplayer).connection - .sendPacket(new SPacketExplosion(x, y, z, strength, mcExplosion.getAffectedBlockPositions(), - mcExplosion.getPlayerKnockbackMap().get(entityplayer))); - } - } + try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER).explosion(mcExplosion) + .source(((Optional) apiExplosion.sourceExplosive()).orElse(this))) { + ctx.buildAndSwitch(); - */ - // Use the knockback map and set velocities, since the explosion packet isn't sent, we need to replicate - // the players being moved. - for (final ServerPlayer playerEntity : this.players) { - final Vec3 knockback = mcExplosion.getHitPlayers().get(playerEntity); - if (knockback != null) { - // In Vanilla, doExplosionB always updates the 'motion[xyz]' fields for every entity in range. - // However, this field is completely ignored for players (since 'velocityChanged') is never set, and - // a completely different value is sent through 'SPacketExplosion'. - - // To replicate this behavior, we manually send a velocity packet. It's critical that we don't simply - // add to the 'motion[xyz]' fields, as that will end up using the value set by 'doExplosionB', which must be - // ignored. - playerEntity.connection.send(new ClientboundSetEntityMotionPacket(playerEntity.getId(), new Vec3(knockback.x, knockback.y, knockback.z))); - } - } - // Sponge End + mcExplosion.explode(); + } + + // TODO handle sending (or not) ClientboundExplodePacket + // TODO particle/sound? + + } + private void tracker$cancelExplosionEffects(final Entity entity) { + // TODO cancel effects + if (entity instanceof ExplosiveBridge explosiveBridge) { + explosiveBridge.bridge$cancelExplosion(); } - // Sponge End - return mcExplosion; } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java index c513fc0d26b..e393e3ff477 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; @@ -74,6 +75,8 @@ public abstract class LevelMixin_Tracker implements LevelBridge, LevelAccessor { // @formatter:on + @Shadow public abstract GameRules getGameRules(); + /** * We introduce the protected method to be overridden in * {@code org.spongepowered.common.mixin.core.world.server.ServerWorldMixin#tracker$wrapTileEntityTick(ITickableTileEntity)} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 194ff0a12d9..f23b5f23b9a 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -342,7 +342,7 @@ "minecraft.world.item.trading.MerchantOfferMixin_API", "minecraft.world.level.BlockGetterMixin_API", "minecraft.world.level.EntityGetterMixin_API", - "minecraft.world.level.ExplosionMixin_API", + "minecraft.world.level.ServerExplosionMixin_API", "minecraft.world.level.GameRules_KeyMixin_API", "minecraft.world.level.GameTypeMixin_API", "minecraft.world.level.LevelAccessorMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 6da22cdc516..fc6974dac15 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -213,7 +213,7 @@ "world.item.enchantment.EnchantmentMixin", "world.level.BaseSpawnerMixin", "world.level.BlockGetterMixin", - "world.level.ExplosionMixin", + "world.level.ServerExplosionMixin", "world.level.LevelMixin", "world.level.NaturalSpawner_SpawnStateMixin", "world.level.NaturalSpawnerMixin", From fe46fbf68bd0a27fbdf78a8f813a35576a22d313 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 16:36:44 +0200 Subject: [PATCH 030/586] fixing explosions --- SpongeAPI | 2 +- .../vanilla/generator/GeneratorMain.java | 8 + .../bridge/world/level/ExplosionBridge.java | 3 - .../loader/VanillaRegistryLoader.java | 2 + .../common/world/SpongeExplosionBuilder.java | 24 +- .../world/level/ServerExplosionMixin_API.java | 5 +- .../Explosion_BlockInteractionMixin.java | 34 +++ .../world/level/ServerExplosionMixin.java | 278 +++++------------- .../level/ServerLevelMixin_Tracker.java | 58 ++-- src/mixins/resources/mixins.sponge.core.json | 7 +- .../org/spongepowered/test/data/DataTest.java | 2 +- 11 files changed, 180 insertions(+), 243 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/Explosion_BlockInteractionMixin.java diff --git a/SpongeAPI b/SpongeAPI index a9e5275ee19..f84abf5e22c 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a9e5275ee1951b39618a03a1ca95235595abeafc +Subproject commit f84abf5e22cd2023060178d0ead4ec615c20b33e diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 615845a9d49..491cd30f316 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -67,6 +67,7 @@ import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; import net.minecraft.world.item.component.FireworkExplosion; +import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.WorldDataConfiguration; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; @@ -378,6 +379,13 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), + new EnumEntriesValidator<>( + "world.explosion", + "BlockInteractions", + Explosion.BlockInteraction.class, + "name", + "sponge" + ), new RegistryEntriesGenerator<>( "data.type", "ArtTypes", diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java index a4f666afe44..7e28e5a753d 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java @@ -28,9 +28,7 @@ public interface ExplosionBridge { - boolean bridge$getShouldDamageBlocks(); - void bridge$setShouldBreakBlocks(boolean shouldBreakBlocks); boolean bridge$getShouldPlaySmoke(); @@ -52,5 +50,4 @@ public interface ExplosionBridge { double bridge$getKnockback(); - Explosion.Builder bridge$asBuilder(); } diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index e39f7566be9..91b6be54a13 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -59,6 +59,7 @@ import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; import net.minecraft.world.item.component.FireworkExplosion; +import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; @@ -218,6 +219,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.PUSH_REACTION, PushReaction.values()); this.automaticName(RegistryTypes.TRIAL_SPAWNER_STATE, TrialSpawnerState.values()); this.automaticName(RegistryTypes.VAULT_STATE, VaultState.values()); + this.automaticName(RegistryTypes.EXPLOSION_BLOCK_INTERACTION, Explosion.BlockInteraction.values()); } private static RegistryLoader criterion() { diff --git a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java index 1f05bad1569..b1ebdd6ef6b 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java +++ b/src/main/java/org/spongepowered/common/world/SpongeExplosionBuilder.java @@ -26,15 +26,16 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion.BlockInteraction; -import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.ServerExplosion; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.world.World; import org.spongepowered.api.world.explosion.Explosion; +import org.spongepowered.api.world.explosion.ExplosionBlockInteraction; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.common.bridge.world.level.ExplosionBridge; import org.spongepowered.common.util.Preconditions; +import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; import java.util.Objects; @@ -45,13 +46,14 @@ public class SpongeExplosionBuilder implements Explosion.Builder { @Nullable private Explosive sourceExplosive; private float radius; private boolean canCauseFire; - private boolean shouldBreakBlocks = true; + private net.minecraft.world.level.Explosion.BlockInteraction blockInteraction; private boolean shouldSmoke; private boolean shouldDamageEntities = true; private int resolution = 16; private float randomness = 1.0F; private double knockback = 1; + public SpongeExplosionBuilder() { this.reset(); } @@ -93,11 +95,12 @@ public Explosion.Builder shouldPlaySmoke(boolean smoke) { } @Override - public Explosion.Builder shouldBreakBlocks(boolean destroy) { - this.shouldBreakBlocks = destroy; + public Explosion.Builder blockInteraction(final ExplosionBlockInteraction interaction) { + this.blockInteraction = (net.minecraft.world.level.Explosion.BlockInteraction) (Object) interaction; return this; } + @Override public Explosion.Builder resolution(int resolution) { //A value of 1 would cause a DivideByZeroException @@ -123,7 +126,7 @@ public Explosion.Builder from(Explosion value) { this.sourceExplosive = value.sourceExplosive().orElse(null); this.radius = value.radius(); this.canCauseFire = value.canCauseFire(); - this.shouldBreakBlocks = value.shouldBreakBlocks(); + this.blockInteraction = ((ServerExplosion) value).getBlockInteraction(); this.shouldSmoke = value.shouldPlaySmoke(); this.shouldDamageEntities = value.shouldDamageEntities(); this.resolution = value.resolution(); @@ -135,10 +138,10 @@ public Explosion.Builder from(Explosion value) { @Override public SpongeExplosionBuilder reset() { this.location = null; + this.blockInteraction = null; this.sourceExplosive = null; this.radius = 0; this.canCauseFire = false; - this.shouldBreakBlocks = true; this.shouldSmoke = false; this.shouldDamageEntities = true; this.resolution = 16; @@ -154,10 +157,9 @@ public Explosion build() throws IllegalStateException { final World world = this.location.world(); final Vector3d origin = this.location.position(); - final net.minecraft.world.level.Explosion explosion = new net.minecraft.world.level.ServerExplosion((ServerLevel) world, - (Entity) this.sourceExplosive, null, null, new Vec3(origin.x(), origin.y(), origin.z()), this.radius, - this.canCauseFire, this.shouldBreakBlocks ? BlockInteraction.DESTROY : BlockInteraction.KEEP); - ((ExplosionBridge) explosion).bridge$setShouldBreakBlocks(this.shouldBreakBlocks); + final var explosion = new net.minecraft.world.level.ServerExplosion((ServerLevel) world, + (Entity) this.sourceExplosive, null, null, VecHelper.toVanillaVector3d(origin), this.radius, + this.canCauseFire, this.blockInteraction); ((ExplosionBridge) explosion).bridge$setShouldDamageEntities(this.shouldDamageEntities); ((ExplosionBridge) explosion).bridge$setShouldPlaySmoke(this.shouldSmoke); ((ExplosionBridge) explosion).bridge$setResolution(this.resolution); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java index 67b0224e734..ffddf7f6d2e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java @@ -89,7 +89,10 @@ public boolean shouldPlaySmoke() { @Override public boolean shouldBreakBlocks() { - return ((ExplosionBridge) this).bridge$getShouldDamageBlocks(); + return switch (this.blockInteraction) { + case KEEP, TRIGGER_BLOCK -> false; + case DESTROY, DESTROY_WITH_DECAY -> true; + }; } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/Explosion_BlockInteractionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/Explosion_BlockInteractionMixin.java new file mode 100644 index 00000000000..dd00e4d8c1a --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/Explosion_BlockInteractionMixin.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.level; + +import net.minecraft.world.level.Explosion; +import org.spongepowered.api.world.explosion.ExplosionBlockInteraction; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Explosion.BlockInteraction.class) +public interface Explosion_BlockInteractionMixin extends ExplosionBlockInteraction { + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java index 06347dab9ae..c642a2605e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java @@ -24,22 +24,13 @@ */ package org.spongepowered.common.mixin.core.world.level; -import com.google.common.collect.Sets; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.util.Mth; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.spongepowered.api.event.Cause; @@ -50,11 +41,10 @@ import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Surrogate; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.level.ExplosionBridge; @@ -62,12 +52,9 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.VecHelper; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.Set; import java.util.StringJoiner; @Mixin(net.minecraft.world.level.ServerExplosion.class) @@ -80,204 +67,100 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { @Shadow @Final private net.minecraft.world.level.Level level; @Shadow @Final private Entity source; @Shadow @Final private float radius; + @Shadow @Final private Vec3 center; @Shadow @Final private net.minecraft.world.level.Explosion.BlockInteraction blockInteraction; - @Shadow @Final private DamageSource damageSource; + @Shadow protected abstract void shadow$interactWithBlocks(final List $$0); + @Shadow protected abstract List shadow$calculateExplodedPositions(); + @Shadow protected abstract boolean shadow$interactsWithBlocks(); + + @Shadow protected abstract void shadow$createFire(final List $$0); + // @formatter:on - @Shadow @Final private Vec3 center; - private boolean impl$shouldBreakBlocks; + private boolean impl$shouldDamageEntities; private boolean impl$shouldPlaySmoke; private int impl$resolution; private float impl$randomness; - private double impl$knockback; - - @Inject( - method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)V", - at = @At("RETURN") - ) - private void impl$onConstructed(final Level $$0, final Entity $$1, final DamageSource $$2, final ExplosionDamageCalculator $$3, final double $$4, - final double $$5, final double $$6, final float $$7, final boolean $$8, final net.minecraft.world.level.Explosion.BlockInteraction $$9, - final ParticleOptions $$10, final ParticleOptions $$11, final Holder $$12, final CallbackInfo ci) { - // In Vanilla and Forge, 'damagesTerrain' controls both smoke particles and block damage - // Sponge-created explosions will explicitly set 'impl$shouldBreakBlocks' to its proper value - this.impl$shouldBreakBlocks = this.blockInteraction == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY_WITH_DECAY || this.blockInteraction == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY; - this.impl$shouldDamageEntities = true; - this.impl$resolution = 16; - this.impl$randomness = 1.0F; - this.impl$knockback = 1.0; - } + private double impl$knockbackMultiplier; - // (Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;Lnet/minecraft/util/DamageSource;Lnet/minecraft/world/ExplosionContext;DDDFZLnet/minecraft/world/Explosion$Mode;Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V - @Surrogate - private void impl$onConstructed(final Level worldIn, final Entity exploderIn, final DamageSource damageSourceIn, final ExplosionDamageCalculator explosionContextIn, final double xIn, final double yIn, final double zIn, final float sizeIn, final boolean causesFireIn, final net.minecraft.world.level.Explosion.BlockInteraction modeIn, final CallbackInfo ci) { - // In Vanilla and Forge, 'damagesTerrain' controls both smoke particles and block damage - // Sponge-created explosions will explicitly set 'impl$shouldBreakBlocks' to its proper value - this.impl$shouldBreakBlocks = this.blockInteraction == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY_WITH_DECAY || this.blockInteraction == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY; + @Inject(method = "", at = @At("RETURN")) + private void impl$onConstructed(final ServerLevel $$0, final Entity $$1, final DamageSource $$2, + final ExplosionDamageCalculator $$3, final Vec3 $$4, final float $$5, final boolean $$6, + final net.minecraft.world.level.Explosion.BlockInteraction $$7, final CallbackInfo ci) { this.impl$shouldDamageEntities = true; this.impl$resolution = 16; this.impl$randomness = 1.0F; - this.impl$knockback = 1.0; + this.impl$knockbackMultiplier = 1.0; } - /** - * @author gabizou - * @author zidane - * @reason Fire ExplosionEvent.Detonate - */ - @Overwrite - public void explode() { + private List impl$affectedBlocks; - // Sponge Start - Do not run calculation logic on client thread - if (this.level.isClientSide) { - return; + @Redirect(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;calculateExplodedPositions()Ljava/util/List;")) + private List impl$onCalculateExplodedPositions(final ServerExplosion instance) { + // If we don't fire the event and do not affect any blocks we can ignore the calculation + if (!this.fire && !this.shadow$interactsWithBlocks() && !ShouldFire.EXPLOSION_EVENT_DETONATE) { + return List.of(); } - // Sponge End - - // Sponge Start - If the explosion should not break blocks, don't bother calculating it on server thread - if (this.impl$shouldBreakBlocks) { - final Set set = Sets.newHashSet(); - final int i = 16; - - for (int j = 0; j < 16; ++j) { - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - if (j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15) { - double d0 = (double) ((float) j / 15.0F * 2.0F - 1.0F); - double d1 = (double) ((float) k / 15.0F * 2.0F - 1.0F); - double d2 = (double) ((float) l / 15.0F * 2.0F - 1.0F); - final double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); - d0 = d0 / d3; - d1 = d1 / d3; - d2 = d2 / d3; - float f = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F); - double d4 = this.x; - double d6 = this.y; - double d8 = this.z; - for (final float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - final BlockPos blockpos = new BlockPos((int) d4, (int) d6, (int) d8); - final BlockState blockstate = this.level.getBlockState(blockpos); - final FluidState fluidstate = this.level.getFluidState(blockpos); - final Optional optional = this.damageCalculator.getBlockExplosionResistance((net.minecraft.world.level.Explosion) (Object) this, this.level, blockpos, blockstate, fluidstate); - if (optional.isPresent()) { - f -= (optional.get() + 0.3F) * 0.3F; - } - - if (f > 0.0F && this.damageCalculator.shouldBlockExplode((net.minecraft.world.level.Explosion) (Object) this, this.level, blockpos, blockstate, f)) { - set.add(blockpos); - } + this.impl$affectedBlocks = this.shadow$calculateExplodedPositions(); + return this.impl$affectedBlocks; + } - d4 += d0 * (double) 0.3F; - d6 += d1 * (double) 0.3F; - d8 += d2 * (double) 0.3F; - } - } - } - } - } - this.toBlow.addAll(set); + @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List impl$onGetHurtEntities(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + final List entities; + if (this.impl$shouldDamageEntities) { + // filter out invulnerable entities before event + entities = instance.getEntities(sourceEntity, aabb).stream() + .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) + .toList(); + } else { + entities = Collections.emptyList(); } - // Sponge End - - final float f3 = this.radius * 2.0F; - final int k1 = Mth.floor(this.x - (double) f3 - 1.0D); - final int l1 = Mth.floor(this.x + (double) f3 + 1.0D); - final int i2 = Mth.floor(this.y - (double) f3 - 1.0D); - final int i1 = Mth.floor(this.y + (double) f3 + 1.0D); - final int j2 = Mth.floor(this.z - (double) f3 - 1.0D); - final int j1 = Mth.floor(this.z + (double) f3 + 1.0D); - - // Sponge Start - Only query for entities if we're to damage them - final List list = this.impl$shouldDamageEntities ? this.level.getEntities(this.source, - new AABB((double) k1, (double) i2, (double) j2, (double) l1, (double) i1, (double) j1)) : Collections.emptyList(); - // Sponge End if (ShouldFire.EXPLOSION_EVENT_DETONATE) { - final List blockPositions = new ArrayList<>(this.toBlow.size()); - final List entities = new ArrayList<>(list.size()); - for (final BlockPos pos : this.toBlow) { - blockPositions - .add(ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) this.level, pos.getX(), pos.getY(), pos.getZ())); - } - for (final Entity entity : list) { - // Make sure to check the entity is immune first. - if (!entity.ignoreExplosion((net.minecraft.world.level.Explosion) (Object) this)) { - entities.add((org.spongepowered.api.entity.Entity) entity); - } - } + final var apiWorld = (ServerWorld) this.level; + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); - final ExplosionEvent.Detonate detonate = SpongeEventFactory.createExplosionEventDetonate(cause, blockPositions, entities, - (Explosion) this, (org.spongepowered.api.world.server.ServerWorld) this.level); - SpongeCommon.post(detonate); - // Clear the positions so that they can be pulled from the event - this.toBlow.clear(); - if (detonate.isCancelled()) { - return; + final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); + if (SpongeCommon.post(event)) { + this.impl$affectedBlocks.clear(); // no blocks affected + return Collections.emptyList(); // no entities affected } - if (this.impl$shouldBreakBlocks) { - for (final ServerLocation worldLocation : detonate.affectedLocations()) { - this.toBlow.add(VecHelper.toBlockPos(worldLocation)); - } + if (this.shadow$interactsWithBlocks()) { + this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).toList(); } - // Clear the list of entities so they can be pulled from the event. - list.clear(); if (this.impl$shouldDamageEntities) { - for (final org.spongepowered.api.entity.Entity entity : detonate.entities()) { - try { - list.add((Entity) entity); - } catch (final Exception e) { - // Do nothing, a plugin tried to use the wrong entity somehow. - } - } + return event.entities().stream().map(Entity.class::cast).toList(); } } - // Sponge End - - final Vec3 vec3d = new Vec3(this.x, this.y, this.z); + return entities; + } - for (int k2 = 0; k2 < list.size(); ++k2) { - final Entity entity = list.get(k2); - if (!entity.ignoreExplosion((net.minecraft.world.level.Explosion) (Object) this)) { - final double d12 = (Math.sqrt(entity.distanceToSqr(vec3d)) / f3); - if (d12 <= 1.0D) { - double d5 = entity.getX() - this.x; - double d7 = entity.getEyeY() - this.y; - double d9 = entity.getZ() - this.z; - final double d13 = Math.sqrt(d5 * d5 + d7 * d7 + d9 * d9); - if (d13 != 0.0D) { - d5 = d5 / d13; - d7 = d7 / d13; - d9 = d9 / d13; - final double d14 = (double) net.minecraft.world.level.Explosion.getSeenPercent(vec3d, entity); - final double d10 = (1.0D - d12) * d14; - entity.hurt(this.damageSource, (float)((int)((d10 * d10 + d10) / 2.0D * 7.0D * (double)f3 + 1.0D))); - double d11 = d10; - if (entity instanceof LivingEntity living) { - d11 = d10 * (1.0 - living.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE)); - } + @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 impl$onAddKnockback(final double $$0, final double $$1, final double $$2) { + // Honor our knockback value from event + return new Vec3($$0 * this.impl$knockbackMultiplier, + $$1 * this.impl$knockbackMultiplier, + $$2 * this.impl$knockbackMultiplier); + } - // Sponge Start - Honor our knockback value from event - entity.setDeltaMovement(entity.getDeltaMovement().add(d5 * d11 * this.impl$knockback, d7 * d11 * this.impl$knockback, d9 * d11 * this.impl$knockback)); - if (entity instanceof Player) { - final Player playerentity = (Player)entity; - if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.getAbilities().flying)) { - this.hitPlayers.put(playerentity, new Vec3(d5 * d10 * this.impl$knockback, - d7 * d10 * this.impl$knockback, d9 * d10 * this.impl$knockback)); - } - } - // Sponge End - } - } - } - } + @Redirect(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;interactWithBlocks(Ljava/util/List;)V")) + private void impl$onInteractWithBlocks(final ServerExplosion instance, final List $$0) { + this.shadow$interactWithBlocks(this.impl$affectedBlocks); } - @Override - public boolean bridge$getShouldDamageBlocks() { - return this.impl$shouldBreakBlocks; + @Redirect(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;createFire(Ljava/util/List;)V")) + private void impl$onCreateFire(final ServerExplosion instance, final List $$0) { + this.shadow$createFire(this.impl$affectedBlocks); } @Override @@ -285,11 +168,6 @@ public void explode() { return this.impl$shouldDamageEntities; } - @Override - public void bridge$setShouldBreakBlocks(final boolean shouldBreakBlocks) { - this.impl$shouldBreakBlocks = shouldBreakBlocks; - } - @Override public void bridge$setShouldDamageEntities(final boolean shouldDamageEntities) { this.impl$shouldDamageEntities = shouldDamageEntities; @@ -327,42 +205,30 @@ public void explode() { @Override public void bridge$setKnockback(final double knockback) { - this.impl$knockback = knockback; + this.impl$knockbackMultiplier = knockback; } @Override public double bridge$getKnockback() { - return this.impl$knockback; - } - - @Override - public Explosion.Builder bridge$asBuilder() { - var builder = org.spongepowered.api.world.explosion.Explosion.builder(); - // TODO finish building - builder.location(ServerLocation.of((ServerWorld) this.level, VecHelper.toVector3d(this.center))) - .radius(this.radius); - - return builder; + return this.impl$knockbackMultiplier; } @Override public String toString() { return new StringJoiner(", ", ServerExplosionMixin.class.getSimpleName() + "[", "]") .add("causesFire=" + this.fire) - .add("mode=" + this.blockInteraction) + .add("blockInteraction=" + this.blockInteraction) .add("world=" + this.level) - .add("x=" + this.x) - .add("y=" + this.y) - .add("z=" + this.z) + .add("x=" + this.center.x) + .add("y=" + this.center.y) + .add("z=" + this.center.z) .add("exploder=" + this.source) .add("size=" + this.radius) - .add("affectedBlockPositions=" + this.toBlow) .add("playerKnockbackMap=" + this.hitPlayers) - .add("shouldBreakBlocks=" + this.impl$shouldBreakBlocks) .add("shouldDamageEntities=" + this.impl$shouldDamageEntities) .add("resolution=" + this.impl$resolution) .add("randomness=" + this.impl$randomness) - .add("knockback=" + this.impl$knockback) + .add("knockback=" + this.impl$knockbackMultiplier) .toString(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 5defde3d228..8c53e403b52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -26,17 +26,22 @@ import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.particles.ParticleOptions; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.BlockEventData; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -60,11 +65,8 @@ import org.spongepowered.api.event.world.ExplosionEvent; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.LocatableBlock; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -77,7 +79,6 @@ import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.entity.GrieferBridge; -import org.spongepowered.common.bridge.world.level.ExplosionBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.TrackableBlockEventDataBridge; import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; @@ -122,18 +123,10 @@ import java.util.Optional; import java.util.UUID; import java.util.function.Consumer; -import java.util.function.Function; @Mixin(ServerLevel.class) public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implements TrackedWorldBridge { - // @formatting:off - @Shadow @Final List players; - // @formatting:on - - @Shadow public abstract boolean isFlat(); - - @Shadow public abstract void resetEmptyTime(); @Redirect( // This normally would target this.entityTickList.forEach((var2x) -> @@ -358,6 +351,8 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge return new ServerExplosion($$0, entity, $$2, $$3, $$4, finalRadius, $$6, cannotGrief ? Explosion.BlockInteraction.KEEP : blockInteraction); } + private org.spongepowered.api.world.explosion.Explosion tracker$apiExplosion; + @Redirect(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;explode()V")) private void tracker$onExplode(final ServerExplosion instance) { @@ -366,7 +361,8 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge // TODO entity can be null, what is our API explosive then? // TODO API explosive can be smth. that is not an entity? final var thisWorld = (ServerWorld) this; - final var explosionBuilder = ((ExplosionBridge)mcExplosion).bridge$asBuilder(); + + final var explosionBuilder = org.spongepowered.api.world.explosion.Explosion.builder().from((org.spongepowered.api.world.explosion.Explosion) mcExplosion); Explosive apiExplosive = (Explosive) entity; final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(PhaseTracker.getCauseStackManager().currentCause(), @@ -411,9 +407,37 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge mcExplosion.explode(); } - // TODO handle sending (or not) ClientboundExplodePacket - // TODO particle/sound? + this.tracker$apiExplosion = apiExplosion; + } + + /** + * See {@link net.minecraft.client.multiplayer.ClientPacketListener#handleExplosion} for client side handling + */ + @Redirect(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) + private void tracker$onClientboundExplodePacket(final ServerGamePacketListenerImpl instance, final Packet packet) { + final var originalPacket = (ClientboundExplodePacket) packet; + var particle = originalPacket.explosionParticle(); + var sound = originalPacket.explosionSound(); + if (this.tracker$apiExplosion.shouldPlaySmoke()) { + // TODO no sound? + // TODO control which particle is used (API) + // TODO control sound? (ViewerPacketUtil.resolveEvent) + var newPacket = new ClientboundExplodePacket(originalPacket.center(), originalPacket.playerKnockback(), particle, sound); + instance.send(newPacket); + } + else { + originalPacket.playerKnockback().ifPresent(kb -> instance.send(new ClientboundSetEntityMotionPacket(instance.player.getId(), kb))); + // TODO play sound? + } + } + @Inject(method = "explode", at = @At(value = "RETURN")) + private void tracker$afterExplodeCleanup(final Entity $$0, final DamageSource $$1, + final ExplosionDamageCalculator $$2, final double $$3, final double $$4, final double $$5, final float $$6, + final boolean $$7, final Level.ExplosionInteraction $$8, final ParticleOptions $$9, final ParticleOptions $$10, + final Holder $$11, final CallbackInfo ci) { + this.tracker$apiExplosion = null; } private void tracker$cancelExplosionEffects(final Entity entity) { diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index fc6974dac15..6acc7695950 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -188,7 +188,6 @@ "world.entity.vehicle.VehicleEntityMixin", "world.food.FoodDataMixin", "world.inventory.StonecutterMenuMixin", - "world.item.TeleportRandomlyConsumeEffectMixin", "world.item.EnderEyeItemMixin", "world.item.FireworkRocketItemMixin", "world.item.FishingRodItemMixin", @@ -197,6 +196,7 @@ "world.item.ItemStackMixin", "world.item.MapItemMixin", "world.item.ServerItemCooldownsMixin", + "world.item.TeleportRandomlyConsumeEffectMixin", "world.item.crafting.AbstractCookingRecipeMixin", "world.item.crafting.IngredientMixin", "world.item.crafting.RecipeManagerMixin", @@ -213,11 +213,12 @@ "world.item.enchantment.EnchantmentMixin", "world.level.BaseSpawnerMixin", "world.level.BlockGetterMixin", - "world.level.ServerExplosionMixin", + "world.level.Explosion_BlockInteractionMixin", "world.level.LevelMixin", "world.level.NaturalSpawner_SpawnStateMixin", "world.level.NaturalSpawnerMixin", "world.level.SavedDataMixin", + "world.level.ServerExplosionMixin", "world.level.biome.BiomeSourceMixin", "world.level.block.BaseFireBlockMixin", "world.level.block.CactusBlockMixin", @@ -250,9 +251,9 @@ "world.level.block.state.BlockStateMixin", "world.level.border.WorldBorderMixin", "world.level.chunk.ChunkGeneratorMixin", - "world.level.chunk.SerializableChunkDataMixin", "world.level.chunk.ChunkStatusTasksMixin", "world.level.chunk.LevelChunkMixin", + "world.level.chunk.SerializableChunkDataMixin", "world.level.chunk.storage.EntityStorageMixin", "world.level.chunk.storage.IOWorkerMixin", "world.level.chunk.storage.RegionFileMixin", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 84541eb6c7e..a95941ce1ab 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -548,7 +548,7 @@ public void testData(final ServerPlayer player) { this.checkGetData(player, Keys.EXPERIENCE, 7); this.checkOfferData(player, Keys.EXPERIENCE_SINCE_LEVEL, 1); - this.checkOfferData(tntEntity, Keys.EXPLOSION_RADIUS, 1); + this.checkOfferData(tntEntity, Keys.EXPLOSION_RADIUS, 1f); this.checkGetData(player, Keys.EYE_HEIGHT, (double)1.62f); this.checkGetData(sheep, Keys.EYE_HEIGHT, (double)(1.3f * 0.95f)); From 5f1536e91c48aa9035cb77b446035311c35788bb Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:35:00 +0200 Subject: [PATCH 031/586] fix ServerChunkCacheMixin_Tracker --- SpongeAPI | 2 +- .../level/ServerChunkCacheMixin_Tracker.java | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index f84abf5e22c..30055c2aa78 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit f84abf5e22cd2023060178d0ead4ec615c20b33e +Subproject commit 30055c2aa785d67d4a595f933af9100254fe731e diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java index 7ab99989ace..4551170d435 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java @@ -26,6 +26,7 @@ import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.NaturalSpawner; import net.minecraft.world.level.chunk.LevelChunk; import org.checkerframework.checker.nullness.qual.NonNull; @@ -36,33 +37,33 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.generation.GenerationPhase; +import java.util.List; + @Mixin(ServerChunkCache.class) public abstract class ServerChunkCacheMixin_Tracker { @Redirect( - method = "tickChunks", + method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/NaturalSpawner;spawnForChunk(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/world/level/NaturalSpawner$SpawnState;ZZZ)V" + target = "Lnet/minecraft/world/level/NaturalSpawner;spawnForChunk(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/world/level/NaturalSpawner$SpawnState;Ljava/util/List;)V" ) ) private void tracker$wrapEntitySpawner( final ServerLevel serverWorld, final LevelChunk targetChunk, - final NaturalSpawner.SpawnState manager, - final boolean something, - final boolean somethingElse, - final boolean somethingLast + final NaturalSpawner.SpawnState spawnState, + final List mobCategories ) { try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.SERVER) .world(serverWorld)) { context.buildAndSwitch(); - NaturalSpawner.spawnForChunk(serverWorld, targetChunk, manager, something, somethingElse, somethingLast); + NaturalSpawner.spawnForChunk(serverWorld, targetChunk, spawnState, mobCategories); } } @Redirect( - method = "tickChunks", + method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tickCustomSpawners(ZZ)V" From 275598c2e07b39b703519544e7a85c2f7448864d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:38:43 +0200 Subject: [PATCH 032/586] fix entity spawning --- .../common/mixin/core/world/level/LevelMixin.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index f84890c3743..d9df63bf056 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -34,6 +34,7 @@ import net.minecraft.util.datafix.DataFixers; import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; @@ -41,7 +42,9 @@ import net.minecraft.world.entity.decoration.Painting; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Blocks; @@ -195,7 +198,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { final net.minecraft.world.level.Level thisWorld = (net.minecraft.world.level.Level) (Object) this; // Not all entities have a single World parameter as their constructor if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { - entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld); + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); entity.moveTo(x, y, z); ((LightningBolt) entity).setVisualOnly(false); } @@ -203,7 +206,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { if (type == net.minecraft.world.entity.EntityType.ENDER_PEARL) { final ArmorStand tempEntity = new ArmorStand(thisWorld, x, y, z); tempEntity.setPos(tempEntity.getX(), tempEntity.getY() - tempEntity.getEyeHeight(), tempEntity.getZ()); - entity = new ThrownEnderpearl(thisWorld, tempEntity); + entity = new ThrownEnderpearl(thisWorld, tempEntity, Items.ENDER_PEARL.getDefaultInstance()); ((EnderPearl) entity).offer(Keys.SHOOTER, UnknownProjectileSource.UNKNOWN); } // Some entities need to have non-null fields (and the easiest way to @@ -218,7 +221,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { if (entity == null) { final ResourceKey key = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getKey((net.minecraft.world.entity.EntityType) type); try { - entity = ((net.minecraft.world.entity.EntityType) type).create(thisWorld); + entity = ((net.minecraft.world.entity.EntityType) type).create(thisWorld, EntitySpawnReason.EVENT); entity.moveTo(x, y, z); } catch (final Exception e) { throw new RuntimeException("There was an issue attempting to construct " + key, e); From 2a8e173032518b3ccea12a511d8629628552a33a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:40:34 +0200 Subject: [PATCH 033/586] fix entity spawning --- .../common/mixin/core/world/entity/EntityMixin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 6d6693d348d..10f8e940bf0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -41,6 +41,7 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.MoverType; @@ -300,7 +301,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, this.bridge$revive(); level.addDuringTeleport((Entity) (Object) this); */ - var entity = this.shadow$getType().create(level); + var entity = this.shadow$getType().create(level, EntitySpawnReason.DIMENSION_TRAVEL); if (entity == null) { return false; } @@ -515,7 +516,7 @@ public Entity changeDimension(final DimensionTransition transition) { oldLevel.getProfiler().push("changeDimension"); - var newEntity = oldLevel.dimension() == newLevel.dimension() ? thisEntity : thisEntity.getType().create(newLevel); + var newEntity = oldLevel.dimension() == newLevel.dimension() ? thisEntity : thisEntity.getType().create(newLevel, EntitySpawnReason.DIMENSION_TRAVEL); if (newEntity != null) { if (thisEntity != newEntity) { newEntity.restoreFrom(thisEntity); From dcad310933efe11d944e0dc2bc5a9ebc86e78d04 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:41:28 +0200 Subject: [PATCH 034/586] fix checkinsideblock --- .../common/mixin/core/world/entity/EntityMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 10f8e940bf0..018bbe33a06 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -741,7 +741,7 @@ public void stopRiding() { } - @Redirect(method = "checkInsideBlocks", + @Redirect(method = "checkInsideBlocks(Ljava/util/Set;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" ) From b41ac1e1a98fde5053a704ae3e194ed33a41c0b1 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:47:19 +0200 Subject: [PATCH 035/586] fix cooking recipe codec --- .../item/crafting/CookingRecipeBridge.java | 33 +++++++++++++++++++ .../crafting/AbstractCookingRecipeMixin.java | 10 ++++-- .../SimpleCookingSerializerMixin.java | 3 +- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/bridge/world/item/crafting/CookingRecipeBridge.java diff --git a/src/main/java/org/spongepowered/common/bridge/world/item/crafting/CookingRecipeBridge.java b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/CookingRecipeBridge.java new file mode 100644 index 00000000000..61229a08638 --- /dev/null +++ b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/CookingRecipeBridge.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.bridge.world.item.crafting; + +import net.minecraft.world.item.crafting.Ingredient; + +public interface CookingRecipeBridge extends RecipeResultBridge { + + Ingredient bridge$ingredient(); + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java index f2a11346edf..ea42280d5d3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java @@ -26,16 +26,19 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; +import net.minecraft.world.item.crafting.Ingredient; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.bridge.world.item.crafting.CookingRecipeBridge; import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; @Mixin(AbstractCookingRecipe.class) -public abstract class AbstractCookingRecipeMixin implements RecipeResultBridge { +public abstract class AbstractCookingRecipeMixin implements CookingRecipeBridge { // @formatter=off @Shadow @Final protected ItemStack result; + @Shadow @Final protected Ingredient ingredient; // @formatter=on @@ -44,5 +47,8 @@ public abstract class AbstractCookingRecipeMixin implements RecipeResultBridge { return this.result; } - + @Override + public Ingredient bridge$ingredient() { + return this.ingredient; + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java index 1ff1a6a7ddb..c3e0ddf42c2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java @@ -44,6 +44,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.world.item.crafting.CookingRecipeBridge; import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; import org.spongepowered.common.item.recipe.ResultFunctionRecipe; import org.spongepowered.common.item.recipe.cooking.CookingRecipeFactory; @@ -125,7 +126,7 @@ public abstract class SimpleCookingSerializerMixin "custom"), Codec.STRING.optionalFieldOf("group", "").forGetter(AbstractCookingRecipe::getGroup), CookingBookCategory.CODEC.fieldOf("category").orElse(CookingBookCategory.MISC).forGetter(AbstractCookingRecipe::category), - Ingredient.CODEC_NONEMPTY.fieldOf(Constants.Recipe.COOKING_INGREDIENT).forGetter($$0x -> $$0x.getIngredients().get(0)), + Ingredient.CODEC.fieldOf(Constants.Recipe.COOKING_INGREDIENT).forGetter($$0x -> ((CookingRecipeBridge) $$0x).bridge$ingredient()), BuiltInRegistries.ITEM.byNameCodec().xmap(ItemStack::new, ItemStack::getItem).fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), Codec.FLOAT.fieldOf(Constants.Recipe.COOKING_EXP).orElse(0.0F).forGetter(AbstractCookingRecipe::getExperience), Codec.INT.fieldOf(Constants.Recipe.COOKING_TIME).orElse(defaultCookingTime).forGetter(AbstractCookingRecipe::getCookingTime), From b17389531c508b7fe64dd927c9519019c82747e8 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:52:54 +0200 Subject: [PATCH 036/586] fix ProjectileUtilMixin --- .../mixin/core/world/entity/projectile/ProjectileUtilMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java index fefa12138c1..0e8674220a6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java @@ -70,7 +70,7 @@ public abstract class ProjectileUtilMixin { final Vec3 to = from.add(velocity); final Vec3 direction = from.subtract(to); - cir.setReturnValue(BlockHitResult.miss(to, Direction.getNearest(direction.x, direction.y, direction.z), BlockPos.containing(to))); + cir.setReturnValue(BlockHitResult.miss(to, Direction.getApproximateNearest(direction.x, direction.y, direction.z), BlockPos.containing(to))); } } } From 753be557727b39e34ed04eda81b250777b106cee Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:55:31 +0200 Subject: [PATCH 037/586] fix firework explosion --- .../common/mixin/core/world/entity/EntityMixin.java | 2 ++ .../entity/projectile/FireworkRocketEntityMixin.java | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 018bbe33a06..ab65fae1e28 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -193,6 +193,8 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract Level level(); + @Shadow public abstract boolean startRiding(final Entity $$0); + private boolean impl$isConstructing = true; private VanishState impl$vanishState = VanishState.unvanished(); protected boolean impl$transient = false; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java index be51b1f5a52..174d7c289b5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java @@ -28,9 +28,11 @@ import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.projectile.explosive.FireworkRocket; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.world.explosion.Explosion; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -40,7 +42,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.Constants; @@ -106,8 +107,13 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen .sourceExplosive(((FireworkRocket) this)) .location(((FireworkRocket) this).serverLocation()) .radius(this.impl$explosionRadius); - SpongeCommonEventFactory.detonateExplosive(this, explosionBuilder) - .ifPresent(explosion -> world.broadcastEntityEvent(self, state)); + + final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(PhaseTracker.getCauseStackManager().currentCause(), + explosionBuilder, (FireworkRocket) this, explosionBuilder.build()); + if (Sponge.eventManager().post(detonateEvent)) { + return; + } + world.broadcastEntityEvent(self, state); } } From f3cc2dbd061225d0996035e52f4501870b8c7328 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 17:58:28 +0200 Subject: [PATCH 038/586] fix isSpawnAnimals removal (its now always true) --- .../core/world/level/storage/PrimaryLevelDataMixin.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 2c23f0ca607..b695880d11c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -336,11 +336,11 @@ public ServerLevelData overworldData() { final Difficulty difficulty = ((LevelData) this).getDifficulty(); if (difficulty == Difficulty.HARD) { - world.setSpawnSettings(true, true); + world.setSpawnSettings(true); // set spawn enemies true } else if (server.isSingleplayer()) { - world.setSpawnSettings(difficulty != Difficulty.PEACEFUL, true); + world.setSpawnSettings(difficulty != Difficulty.PEACEFUL); } else { - world.setSpawnSettings(((MinecraftServerAccessor) server).invoker$isSpawningMonsters(), server.isSpawningAnimals()); + world.setSpawnSettings(((MinecraftServerAccessor) server).invoker$isSpawningMonsters()); } world.players().forEach(player -> player.connection.send(new ClientboundChangeDifficultyPacket(difficulty, isLocked))); From c4bcdaea357887bdff6133ad38cac53eaa4d0fa7 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:02:59 +0200 Subject: [PATCH 039/586] fix TeleportCommandMixin - TODO this probably needs a rewrite --- .../mixin/core/server/commands/TeleportCommandMixin.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index d8837562c12..89b417e9d52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -32,6 +32,7 @@ import net.minecraft.server.level.TicketType; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.RelativeMovement; @@ -65,6 +66,7 @@ public abstract class TeleportCommandMixin { * @reason Have the teleport command respect our events */ @Overwrite + // TODO check if this is still correct - check if we can get rid of the overwrite private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, Set relativeList, float yaw, float pitch, TeleportCommand.@Nullable LookAt facing) { @@ -134,7 +136,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, // Teleport will create a frame but we want to ensure it'll be the command movement type // TODO check if this is still correct PhaseTracker.getCauseStackManager().addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - ((ServerPlayer) entityIn).teleportTo(worldIn, x, y, z, yaw, pitch); + ((ServerPlayer) entityIn).teleportTo(worldIn, x, y, z, yaw, pitch, true); PhaseTracker.getCauseStackManager().removeContext(EventContextKeys.MOVEMENT_TYPE); } else { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { @@ -160,7 +162,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, } entityIn.unRide(); - final Entity result = entityIn.getType().create(worldIn); + final Entity result = entityIn.getType().create(worldIn, EntitySpawnReason.DIMENSION_TRAVEL); if (result == null) { return; } From 506d801587cf2da28e57383b6e2ba5be4454eca3 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:03:33 +0200 Subject: [PATCH 040/586] fix DifficultyCommandMixin --- .../mixin/core/server/commands/DifficultyCommandMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java index d078c048e3a..c54e3ae3e50 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java @@ -58,7 +58,7 @@ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty } else { final LevelData levelData = source.getLevel().getLevelData(); ((ServerWorldProperties) levelData).setDifficulty((org.spongepowered.api.world.difficulty.Difficulty) (Object) difficulty); - source.getLevel().setSpawnSettings(((MinecraftServerAccessor) SpongeCommon.server()).invoker$isSpawningMonsters(), SpongeCommon.server().isSpawningAnimals()); + source.getLevel().setSpawnSettings(((MinecraftServerAccessor) SpongeCommon.server()).invoker$isSpawningMonsters()); source.getLevel().getPlayers(p -> true).forEach(p -> p.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()))); source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); From 437a53e1e536244e03b22cd0970f28553ef27055 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:20:04 +0200 Subject: [PATCH 041/586] fix api explosion --- .../server/level/ServerLevelBridge.java | 5 ++ .../core/server/level/ServerLevelMixin.java | 51 ++++++++++++++----- .../level/ServerLevelMixin_Tracker.java | 15 +----- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java b/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java index 62ae2c00c00..58a2fd55563 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java @@ -24,8 +24,10 @@ */ package org.spongepowered.common.bridge.server.level; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.server.bossevents.CustomBossEvents; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.world.explosion.Explosion; @@ -42,6 +44,9 @@ public interface ServerLevelBridge { void bridge$triggerExplosion(Explosion explosion); + void bridge$handleExplosionPacket(final ServerGamePacketListenerImpl instance, Explosion apiExplosion, + final ClientboundExplodePacket packet); + void bridge$setManualSave(boolean state); BlockSnapshot bridge$createSnapshot(int x, int y, int z); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 46a6b89598e..03e73b5781a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -27,14 +27,21 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; +import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.bossevents.CustomBossEvents; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.TicketType; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.sounds.SoundEvents; import net.minecraft.util.ProgressListener; import net.minecraft.world.RandomSequences; import net.minecraft.world.entity.ai.village.poi.PoiManager; @@ -43,6 +50,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; @@ -137,6 +145,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow public abstract void levelEvent(@Nullable Player $$0, int $$1, BlockPos $$2, int $$3); @Shadow @Nullable private EndDragonFight dragonFight; + @Shadow @Final private List players; // @formatter:on @@ -229,40 +238,54 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Override public void bridge$triggerExplosion(Explosion explosion) { - // Sponge start // Set up the pre event if (ShouldFire.EXPLOSION_EVENT_PRE) { - final ExplosionEvent.Pre - event = - SpongeEventFactory.createExplosionEventPre(PhaseTracker.getCauseStackManager().currentCause(), - explosion, (org.spongepowered.api.world.server.ServerWorld) this); + final var cause = PhaseTracker.getCauseStackManager().currentCause(); + final ExplosionEvent.Pre event = SpongeEventFactory.createExplosionEventPre(cause, explosion, (ServerWorld) this); if (SpongeCommon.post(event)) { return; } explosion = event.explosion(); } - final net.minecraft.world.level.Explosion mcExplosion = (net.minecraft.world.level.Explosion) explosion; + final ServerExplosion mcExplosion = (ServerExplosion) explosion; try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER) .explosion((net.minecraft.world.level.Explosion) explosion) .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { ignored.buildAndSwitch(); - final boolean shouldBreakBlocks = explosion.shouldBreakBlocks(); - // Sponge End mcExplosion.explode(); - mcExplosion.finalizeExplosion(explosion.shouldPlaySmoke()); - if (!shouldBreakBlocks) { - mcExplosion.clearToBlow(); + // see ServerLevel#explode/Level#explode + ParticleOptions particle = mcExplosion.isSmall() ? ParticleTypes.EXPLOSION : ParticleTypes.EXPLOSION_EMITTER; + var sound = SoundEvents.GENERIC_EXPLODE; + for (ServerPlayer player : this.players) { + if (player.distanceToSqr(mcExplosion.center()) < 4096.0) { + Optional kb = Optional.ofNullable(mcExplosion.getHitPlayers().get(player)); + final var packet = new ClientboundExplodePacket(mcExplosion.center(), kb, particle, sound); + this.bridge$handleExplosionPacket(player.connection, explosion, packet); + player.connection.send(packet); + } } - - // Sponge Start - end processing } - // Sponge End } + @Override + public void bridge$handleExplosionPacket(final ServerGamePacketListenerImpl instance, Explosion apiExplosion, + final ClientboundExplodePacket packet) { + if (apiExplosion.shouldPlaySmoke()) { + // TODO no sound? + // TODO control which particle is used (API) + // TODO control sound? (ViewerPacketUtil.resolveEvent) + var newPacket = new ClientboundExplodePacket(packet.center(), packet.playerKnockback(), packet.explosionParticle(), packet.explosionSound()); + instance.send(newPacket); + } + else { + packet.playerKnockback().ifPresent(kb -> instance.send(new ClientboundSetEntityMotionPacket(instance.player.getId(), kb))); + // TODO play sound? + } + } @Override public void bridge$setManualSave(final boolean state) { this.impl$isManualSave = state; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 8c53e403b52..e4bab6e5c82 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -31,7 +31,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; -import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.sounds.SoundEvent; @@ -417,19 +416,7 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) private void tracker$onClientboundExplodePacket(final ServerGamePacketListenerImpl instance, final Packet packet) { final var originalPacket = (ClientboundExplodePacket) packet; - var particle = originalPacket.explosionParticle(); - var sound = originalPacket.explosionSound(); - if (this.tracker$apiExplosion.shouldPlaySmoke()) { - // TODO no sound? - // TODO control which particle is used (API) - // TODO control sound? (ViewerPacketUtil.resolveEvent) - var newPacket = new ClientboundExplodePacket(originalPacket.center(), originalPacket.playerKnockback(), particle, sound); - instance.send(newPacket); - } - else { - originalPacket.playerKnockback().ifPresent(kb -> instance.send(new ClientboundSetEntityMotionPacket(instance.player.getId(), kb))); - // TODO play sound? - } + ((ServerLevelBridge) this).bridge$handleExplosionPacket(instance, this.tracker$apiExplosion, originalPacket); } @Inject(method = "explode", at = @At(value = "RETURN")) From 02785bde4640f0d50e8af574660109ebd82d784f Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:24:01 +0200 Subject: [PATCH 042/586] fix level min/max/height --- .../minecraft/client/multiplayer/ClientLevelMixin_API.java | 2 +- .../api/minecraft/server/level/ServerLevelMixin_API.java | 2 +- .../api/minecraft/world/level/BlockGetterMixin_API.java | 2 +- .../mixin/api/minecraft/world/level/LevelMixin_API.java | 2 +- .../minecraft/world/level/chunk/LevelChunkMixin_API.java | 6 +++--- .../world/level/levelgen/structure/StructureMixin_API.java | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/client/multiplayer/ClientLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/client/multiplayer/ClientLevelMixin_API.java index 12f66296e46..2750caf8ca2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/client/multiplayer/ClientLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/client/multiplayer/ClientLevelMixin_API.java @@ -70,7 +70,7 @@ public boolean isLoaded() { public ChunkLayout chunkLayout() { if (this.api$chunkLayout == null) { final var height = ((ClientLevel) (Object) this).getHeight(); - final var min = ((ClientLevel) (Object) this).getMinBuildHeight(); + final var min = ((ClientLevel) (Object) this).getMinY(); this.api$chunkLayout = new SpongeChunkLayout(min, height); } return this.api$chunkLayout; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 03c3ef4ca14..b84aa8eede6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -331,7 +331,7 @@ public void setWeather(final WeatherType type, final Ticks ticks) { public ChunkLayout chunkLayout() { if (this.api$chunkLayout == null) { final var height = ((ServerLevel) (Object) this).getHeight(); - final var min = ((ServerLevel) (Object) this).getMinBuildHeight(); + final var min = ((ServerLevel) (Object) this).getMinY(); this.api$chunkLayout = new SpongeChunkLayout(min, height); } return this.api$chunkLayout; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java index c0aa643a6db..e828cec9b9e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java @@ -71,7 +71,7 @@ default int emittedLight(final int x, final int y, final int z) { @Override default int height() { - return ((LevelHeightAccessor) this).getMaxBuildHeight(); + return ((LevelHeightAccessor) this).getHeight(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 71e7937a942..446756cfa4f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -222,7 +222,7 @@ public Vector3i size() { private SpongeChunkLayout api$chunkLayout() { if (this.api$chunkLayout == null) { - final var min = ((Level) (Object) this).getMinBuildHeight(); + final var min = ((Level) (Object) this).getMinY(); final var height = ((Level) (Object) this).getHeight(); this.api$chunkLayout = new SpongeChunkLayout(min, height); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index eb2f28f511c..67380a288bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -377,7 +377,7 @@ public int highestYAt(final int x, final int z) { public Vector3i min() { if (this.api$blockMin == null) { if (this.api$chunkLayout == null) { - this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinBuildHeight(), this.level.getHeight()); + this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinY(), this.level.getHeight()); } this.api$blockMin = this.api$chunkLayout.forceToWorld(this.chunkPosition()); } @@ -388,7 +388,7 @@ public Vector3i min() { public Vector3i max() { if (this.api$blockMax == null) { if (this.api$chunkLayout == null) { - this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinBuildHeight(), this.level.getHeight()); + this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinY(), this.level.getHeight()); } this.api$blockMax = this.min().add(this.api$chunkLayout.chunkSize()).sub(1, 1, 1); } @@ -398,7 +398,7 @@ public Vector3i max() { @Override public Vector3i size() { if (this.api$chunkLayout == null) { - this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinBuildHeight(), this.level.getHeight()); + this.api$chunkLayout = new SpongeChunkLayout(this.level.getMinY(), this.level.getHeight()); } return this.api$chunkLayout.chunkSize(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java index 9e057d9f93d..349ad7f4869 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java @@ -87,7 +87,7 @@ public boolean place(final ServerWorld world, final Vector3i pos) { return false; } ChunkPos.rangeClosed(minPos, maxPos).forEach((chunkPos) -> start.placeInChunk(level, level.structureManager(), chunkSource.getGenerator(), level.getRandom(), - new BoundingBox(chunkPos.getMinBlockX(), level.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), level.getMaxBuildHeight(), chunkPos.getMaxBlockZ()), chunkPos)); + new BoundingBox(chunkPos.getMinBlockX(), level.getMinY(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), level.getMaxY(), chunkPos.getMaxBlockZ()), chunkPos)); return true; } From 3c7997c120033b64cbd18a42e4e1c70ce5087502 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:28:34 +0200 Subject: [PATCH 043/586] fix getTagNames --- .../mixin/api/minecraft/core/MappedRegistryMixin_API.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java index b6f870bd4a5..d2702d2cdde 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java @@ -73,7 +73,7 @@ public abstract class MappedRegistryMixin_API implements Registry { } private Stream> impl$getTagNames() { - return ((net.minecraft.core.Registry) this).getTagNames(); + return ((net.minecraft.core.Registry) this).getTags().map(HolderSet.Named::key); } @Override From 4e0f24f6edb1846cd5fbb837e1359aa02da16577 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:30:46 +0200 Subject: [PATCH 044/586] fix Entity#copy --- .../api/minecraft/world/entity/EntityMixin_API.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index d662b1576c2..e08815a23a8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -35,6 +35,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; @@ -300,10 +301,11 @@ public org.spongepowered.api.entity.Entity copy() { final CompoundTag compound = new CompoundTag(); compound.putString("id", entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()).toString()); this.shadow$saveWithoutId(compound); - final Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, this.shadow$getCommandSenderWorld(), (createdEntity) -> { - createdEntity.setUUID(UUID.randomUUID()); - return createdEntity; - }); + final Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, this.shadow$getCommandSenderWorld(), EntitySpawnReason.COMMAND, + (createdEntity) -> { + createdEntity.setUUID(UUID.randomUUID()); + return createdEntity; + }); return (org.spongepowered.api.entity.Entity) entity; } catch (final Exception e) { throw new IllegalArgumentException("Could not copy the entity:", e); From 8a44dfe5725d314054f3281655017961a56248da Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:40:13 +0200 Subject: [PATCH 045/586] fix recipebook placement --- ...ServerGamePacketListenerImplMixin_Vanilla.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java index 2d3001e6308..c4fcf2bf993 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java @@ -26,6 +26,7 @@ import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.game.ServerGamePacketListener; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.RecipeHolder; @@ -53,21 +54,23 @@ public abstract class ServerGamePacketListenerImplMixin_Vanilla extends ServerCo @SuppressWarnings({"unchecked", "rawtypes"}) @Redirect(method = "lambda$handlePlaceRecipe$10", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerPlayer;)V")) - private void vanilla$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final RecipeHolder recipe, final net.minecraft.server.level.ServerPlayer player) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) + private RecipeBookMenu.PostPlaceAction vanilla$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean creative, final RecipeHolder recipe, final net.minecraft.world.entity.player.Inventory playerInventory) { + final var player = playerInventory.player; final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); if (!(craftInv instanceof CraftingInventory)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + final var postPlaceAction = recipeBookMenu.handlePlacement(shift, creative, recipe, playerInventory); SpongeCommon.logger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire."); - return; + return postPlaceAction; } - try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, (RecipeHolder) recipe, player, (CraftingInventory) craftInv)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, (RecipeHolder) recipe, (ServerPlayer) player, (CraftingInventory) craftInv)) { + final var postPlaceAction = recipeBookMenu.handlePlacement(shift, creative, recipe, playerInventory); player.containerMenu.broadcastChanges(); + return postPlaceAction; } } From efe3a387b97cdd6c31dfeedf29f502f572407b52 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:41:43 +0200 Subject: [PATCH 046/586] fix tp --- .../server/commands/SpreadPlayersCommandMixin_Vanilla.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java index 7fc77f6b85b..3e6bc293e66 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java @@ -41,14 +41,14 @@ @Mixin(SpreadPlayersCommand.class) public abstract class SpreadPlayersCommandMixin_Vanilla { - @Redirect(method = "setPlayerPositions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FF)Z")) + @Redirect(method = "setPlayerPositions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) private static boolean vanilla$createCauseFrameForTeleport( final Entity instance, final ServerLevel level, final double x, final double y, - final double z, final Set relativeMovements, final float yRot, final float xRot) { + final double z, final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - return instance.teleportTo(level, x, y, z, relativeMovements, yRot, xRot); + return instance.teleportTo(level, x, y, z, relativeMovements, yRot, xRot, setCamera); } } } From 5111e338e596ff055c5b99d2faeaa715d78b006c Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:42:56 +0200 Subject: [PATCH 047/586] TODO remove from API? fix spawnanimals --- .../mixin/api/minecraft/server/MinecraftServerMixin_API.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index f6a97235086..a942424b138 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -118,7 +118,7 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRegistryHolder { // @formatter:off - @Shadow @Final public long[] tickTimesNanos; + @Shadow @Final private long[] tickTimesNanos; @Shadow @Final protected WorldData worldData; @Shadow public abstract net.minecraft.world.item.crafting.RecipeManager shadow$getRecipeManager(); @@ -133,7 +133,6 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe @Shadow public abstract boolean shadow$isPvpAllowed(); @Shadow public abstract boolean shadow$isCommandBlockEnabled(); @Shadow public abstract boolean shadow$isSpawningMonsters(); - @Shadow public abstract boolean shadow$isSpawningAnimals(); @Shadow public abstract Commands shadow$getCommands(); @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract net.minecraft.server.packs.resources.ResourceManager shadow$getResourceManager(); @@ -270,7 +269,7 @@ public boolean isMonsterSpawnsEnabled() { @Override public boolean isAnimalSpawnsEnabled() { - return this.shadow$isSpawningAnimals(); + return true; } /** From b4c05ca3993379e9f2d0df7987ed56465f7697ed Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:53:04 +0200 Subject: [PATCH 048/586] fix vanish consume effects --- .../core/world/entity/LivingEntityMixin.java | 26 +-------- .../core/world/item/ConsumableMixin.java | 57 +++++++++++++++++++ src/mixins/resources/mixins.sponge.core.json | 1 + 3 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/ConsumableMixin.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 655aacdd478..d9c258c697d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -191,14 +191,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - @Redirect(method = "triggerItemUseEffects", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;spawnItemParticles(Lnet/minecraft/world/item/ItemStack;I)V")) - private void impl$hideItemParticlesIfVanished(final LivingEntity livingEntity, final ItemStack stack, final int count) { - if (this.bridge$vanishState().createsParticles()) { - this.shadow$spawnItemParticles(stack, count); - } - } + @Inject(method = "randomTeleport", at = @At("HEAD")) private void impl$snapshotPositionBeforeVanillaTeleportLogic(final double x, final double y, final double z, final boolean changeState, @@ -249,23 +242,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - @Redirect( - method = "eat(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/food/FoodProperties;)Lnet/minecraft/world/item/ItemStack;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V" - ) - ) - private void impl$ignoreExperienceLevelSoundsWhileVanished(final net.minecraft.world.level.Level world, - final net.minecraft.world.entity.player.Player player, final double x, final double y, final double z, - final SoundEvent sound, final SoundSource category, final float volume, final float pitch - ) { - if (!this.bridge$vanishState().createsSounds()) { - return; - } - world.playSound(player, x, y, z, sound, category, volume, pitch); - } - @Redirect(method = "checkFallDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;sendParticles(Lnet/minecraft/core/particles/ParticleOptions;DDDIDDDD)I")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ConsumableMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ConsumableMixin.java new file mode 100644 index 00000000000..6aa19ac7470 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ConsumableMixin.java @@ -0,0 +1,57 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.item; + +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.Consumable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.data.VanishableBridge; + +@Mixin(Consumable.class) +public abstract class ConsumableMixin { + + @Redirect(method = "emitParticlesAndSounds", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;spawnItemParticles(Lnet/minecraft/world/item/ItemStack;I)V")) + private void impl$createCauseFrameForTeleport(final LivingEntity instance, final ItemStack $$0, final int $$1) { + if (!(instance instanceof VanishableBridge bridge) || bridge.bridge$vanishState().createsParticles()) { + instance.spawnItemParticles($$0, $$1); + } + } + + + @Redirect(method = "emitParticlesAndSounds", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) + private void impl$ignoreExperienceLevelSoundsWhileVanished(final LivingEntity instance, final SoundEvent soundEvent, + final float $$1, final float $$2) { + if (!(instance instanceof VanishableBridge bridge) || bridge.bridge$vanishState().createsSounds()) { + instance.playSound(soundEvent, $$1, $$2); + } + } + +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 6acc7695950..c2a34dd6354 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -188,6 +188,7 @@ "world.entity.vehicle.VehicleEntityMixin", "world.food.FoodDataMixin", "world.inventory.StonecutterMenuMixin", + "world.item.ConsumableMixin", "world.item.EnderEyeItemMixin", "world.item.FireworkRocketItemMixin", "world.item.FishingRodItemMixin", From f87d7e4ae66d72f30debb8e14352912b1b9d35e2 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:56:38 +0200 Subject: [PATCH 049/586] fix consuming --- .../common/mixin/core/world/entity/LivingEntityMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index d9c258c697d..3bf446f135e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -376,7 +376,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "completeUsingItem", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;triggerItemUseEffects(Lnet/minecraft/world/item/ItemStack;I)V")) + target = "Lnet/minecraft/world/item/ItemStack;finishUsingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/item/ItemStack;")) private void impl$onUpdateItemUse(final CallbackInfo ci) { if (this.shadow$level().isClientSide) { return; From a50197105784896d6f12151dd81087344037949c Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 18:59:33 +0200 Subject: [PATCH 050/586] TODO only when affected? - fix stepon --- .../common/mixin/core/world/entity/EntityMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index ab65fae1e28..d196ea014fb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -723,7 +723,7 @@ public void stopRiding() { } @Redirect( - method = "move", + method = "applyEffectsFromBlocks", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;stepOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/Entity;)V" From eb12d9d13dc96cfde0d95eae820a12b3341f5a17 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:03:09 +0200 Subject: [PATCH 051/586] AgeableWaterCreature --- .../animal/AgeableWaterCreatureMixin_API.java | 37 +++++++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 11 +++--- 2 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java new file mode 100644 index 00000000000..bb00edc6f7c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import net.minecraft.world.entity.animal.AgeableWaterCreature; +import net.minecraft.world.entity.animal.WaterAnimal; +import org.spongepowered.api.entity.Ageable; +import org.spongepowered.api.entity.living.aquatic.Aquatic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; + +@Mixin(AgeableWaterCreature.class) +public abstract class AgeableWaterCreatureMixin_API extends MobMixin_API implements Aquatic, Ageable { + +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index f23b5f23b9a..262a3987259 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -141,6 +141,7 @@ "minecraft.world.entity.animal.AbstractFishMixin_API", "minecraft.world.entity.animal.AbstractGolemMixin_API", "minecraft.world.entity.animal.AbstractSchoolingFishMixin_API", + "minecraft.world.entity.animal.AgeableWaterCreatureMixin_API", "minecraft.world.entity.animal.AnimalMixin_API", "minecraft.world.entity.animal.BeeMixin_API", "minecraft.world.entity.animal.CatMixin_API", @@ -150,7 +151,7 @@ "minecraft.world.entity.animal.CowMixin_API", "minecraft.world.entity.animal.DolphinMixin_API", "minecraft.world.entity.animal.FlyingAnimalMixin_API", - "minecraft.world.entity.animal.Fox_VariantMixin_API", + "minecraft.world.entity.animal.Fox_VariantMixin_API", "minecraft.world.entity.animal.FoxMixin_API", "minecraft.world.entity.animal.IronGolemMixin_API", "minecraft.world.entity.animal.MushroomCow_MushroomTypeMixin_API", @@ -176,8 +177,8 @@ "minecraft.world.entity.animal.WaterAnimalMixin_API", "minecraft.world.entity.animal.WolfMixin_API", "minecraft.world.entity.animal.allay.AllayMixin_API", - "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", + "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", "minecraft.world.entity.animal.camel.CamelMixin_API", "minecraft.world.entity.animal.frog.FrogMixin_API", "minecraft.world.entity.animal.frog.TadpoleMixin_API", @@ -271,7 +272,6 @@ "minecraft.world.entity.projectile.AbstractArrow_PickupMixin_API", "minecraft.world.entity.projectile.AbstractArrowMixin_API", "minecraft.world.entity.projectile.AbstractHurtingProjectileMixin_API", - "minecraft.world.entity.projectile.windcharge.AbstractWindChargeMixin_API", "minecraft.world.entity.projectile.ArrowMixin_API", "minecraft.world.entity.projectile.DragonFireballMixin_API", "minecraft.world.entity.projectile.EvokerFangsMixin_API", @@ -295,6 +295,7 @@ "minecraft.world.entity.projectile.ThrownPotionMixin_API", "minecraft.world.entity.projectile.ThrownTridentMixin_API", "minecraft.world.entity.projectile.WitherSkullMixin_API", + "minecraft.world.entity.projectile.windcharge.AbstractWindChargeMixin_API", "minecraft.world.entity.projectile.windcharge.BreezeWindChargeMixin_API", "minecraft.world.entity.projectile.windcharge.WindChargeMixin_API", "minecraft.world.entity.raid.Raid_RaidStatusMixin_API", @@ -322,7 +323,7 @@ "minecraft.world.item.ItemStackMixin_API", "minecraft.world.item.JukeboxSongMixin_API", "minecraft.world.item.RarityMixin_API", - "minecraft.world.item.ToolMaterialMixin_API", + "minecraft.world.item.ToolMaterialMixin_API", "minecraft.world.item.alchemy.PotionMixin_API", "minecraft.world.item.component.FireworkExplosionMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", @@ -342,7 +343,6 @@ "minecraft.world.item.trading.MerchantOfferMixin_API", "minecraft.world.level.BlockGetterMixin_API", "minecraft.world.level.EntityGetterMixin_API", - "minecraft.world.level.ServerExplosionMixin_API", "minecraft.world.level.GameRules_KeyMixin_API", "minecraft.world.level.GameTypeMixin_API", "minecraft.world.level.LevelAccessorMixin_API", @@ -350,6 +350,7 @@ "minecraft.world.level.LevelReaderMixin_API", "minecraft.world.level.LevelWriterMixin_API", "minecraft.world.level.LightLayerMixin_API", + "minecraft.world.level.ServerExplosionMixin_API", "minecraft.world.level.biome.AmbientAdditionsSettingsMixin_API", "minecraft.world.level.biome.AmbientMoodSettingsMixin_API", "minecraft.world.level.biome.AmbientParticleSettingsMixin_API", From 2f5fc1c068c5c699592f070c00374d77f3d0ed78 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:06:43 +0200 Subject: [PATCH 052/586] fix crafting menu mixin --- SpongeAPI | 2 +- ...MenuMixin_TrackedMenuBridge_Inventory.java | 42 +++++++++++++++++++ ...MenuMixin_TrackedMenuBridge_Inventory.java | 11 +---- .../resources/mixins.sponge.inventory.json | 1 + 4 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java diff --git a/SpongeAPI b/SpongeAPI index 30055c2aa78..0141ef74ad3 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 30055c2aa785d67d4a595f933af9100254fe731e +Subproject commit 0141ef74ad3a775b7a160f634cf3922d3379302f diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java new file mode 100644 index 00000000000..ed93552e28d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.inventory.impl.world.inventory; + +import net.minecraft.world.inventory.AbstractCraftingMenu; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.inventory.ResultContainer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(AbstractCraftingMenu.class) +public abstract class AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory { + + // @formatter:off + @Shadow @Final protected CraftingContainer craftSlots; + @Shadow @Final protected ResultContainer resultSlots; + // @formatter:on + +} \ No newline at end of file diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/CraftingMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/CraftingMenuMixin_TrackedMenuBridge_Inventory.java index 33dd9c1078e..1f06cc385b0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/CraftingMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/CraftingMenuMixin_TrackedMenuBridge_Inventory.java @@ -27,24 +27,15 @@ import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerLevelAccess; -import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.CraftingMenu; -import net.minecraft.world.inventory.ResultContainer; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.inventory.container.TrackedMenuBridge; @Mixin(CraftingMenu.class) -public abstract class CraftingMenuMixin_TrackedMenuBridge_Inventory { - - // @formatter:off - @Shadow @Final private CraftingContainer craftSlots; - @Shadow @Final private ResultContainer resultSlots; - // @formatter:on +public abstract class CraftingMenuMixin_TrackedMenuBridge_Inventory extends AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory { @Inject(method = "(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/inventory/ContainerLevelAccess;)V", at = @At("RETURN")) private void inventory$attachContainerMenu(final int $$0, final Inventory $$1, final ContainerLevelAccess $$2, final CallbackInfo ci) { diff --git a/src/mixins/resources/mixins.sponge.inventory.json b/src/mixins/resources/mixins.sponge.inventory.json index f857d68d370..729b3cfc60c 100644 --- a/src/mixins/resources/mixins.sponge.inventory.json +++ b/src/mixins/resources/mixins.sponge.inventory.json @@ -85,6 +85,7 @@ "impl.world.inventory.AbstractContainerMenuMixin_Bridge_Inventory", "impl.world.inventory.AbstractContainerMenuMixin_Fabric_Inventory", "impl.world.inventory.AbstractContainerMenuMixin_Menu_Inventory", + "impl.world.inventory.AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory", "impl.world.inventory.AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory", "impl.world.inventory.BeaconMenuMixin_TrackedMenuBridge_Inventory", "impl.world.inventory.BrewingStandMenuMixin_TrackedMenuBridge_Inventory", From 43e758700bfcbe745f11deade7de921261834358 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:07:25 +0200 Subject: [PATCH 053/586] AgeableWaterCreature --- .../api/minecraft/world/entity/animal/DolphinMixin_API.java | 2 +- .../mixin/api/minecraft/world/entity/animal/SquidMixin_API.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java index fb794fbe8c7..2cd310baace 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java @@ -32,7 +32,7 @@ import java.util.Set; @Mixin(net.minecraft.world.entity.animal.Dolphin.class) -public abstract class DolphinMixin_API extends WaterAnimalMixin_API implements Dolphin { +public abstract class DolphinMixin_API extends AgeableWaterCreatureMixin_API implements Dolphin { @Override protected Set> api$getVanillaValues() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java index 09582809680..91950d3f8bd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java @@ -28,6 +28,6 @@ import org.spongepowered.asm.mixin.Mixin; @Mixin(net.minecraft.world.entity.animal.Squid.class) -public abstract class SquidMixin_API extends WaterAnimalMixin_API implements Squid { +public abstract class SquidMixin_API extends AgeableWaterCreatureMixin_API implements Squid { } From 17e4f0067988ad228718233ab7ddf67b38d27513 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:08:30 +0200 Subject: [PATCH 054/586] fix crafting menu --- ...gMenuAccessor.java => AbstractCraftingMenuAccessor.java} | 6 +++--- src/accessors/resources/mixins.sponge.accessors.json | 2 +- .../inventory/lens/impl/comp/CraftingGridInventoryLens.java | 4 ++-- .../spongepowered/common/inventory/util/InventoryUtil.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/inventory/{CraftingMenuAccessor.java => AbstractCraftingMenuAccessor.java} (91%) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/CraftingMenuAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractCraftingMenuAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/inventory/CraftingMenuAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractCraftingMenuAccessor.java index dce50afccdf..354247b48d5 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/CraftingMenuAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractCraftingMenuAccessor.java @@ -24,13 +24,13 @@ */ package org.spongepowered.common.accessor.world.inventory; +import net.minecraft.world.inventory.AbstractCraftingMenu; import net.minecraft.world.inventory.CraftingContainer; -import net.minecraft.world.inventory.CraftingMenu; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(CraftingMenu.class) -public interface CraftingMenuAccessor { +@Mixin(AbstractCraftingMenu.class) +public interface AbstractCraftingMenuAccessor { @Accessor("craftSlots") CraftingContainer accessor$craftSlots(); diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index dc63b837474..72d9ec744a8 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -125,7 +125,7 @@ "world.inventory.AbstractFurnaceMenuAccessor", "world.inventory.BeaconMenuAccessor", "world.inventory.BrewingStandMenuAccessor", - "world.inventory.CraftingMenuAccessor", + "world.inventory.AbstractCraftingMenuAccessor", "world.inventory.DispenserMenuAccessor", "world.inventory.HopperMenuAccessor", "world.inventory.HorseInventoryMenuAccessor", diff --git a/src/main/java/org/spongepowered/common/inventory/lens/impl/comp/CraftingGridInventoryLens.java b/src/main/java/org/spongepowered/common/inventory/lens/impl/comp/CraftingGridInventoryLens.java index 6edb093807f..3dc828381ac 100644 --- a/src/main/java/org/spongepowered/common/inventory/lens/impl/comp/CraftingGridInventoryLens.java +++ b/src/main/java/org/spongepowered/common/inventory/lens/impl/comp/CraftingGridInventoryLens.java @@ -28,7 +28,7 @@ import net.minecraft.world.inventory.InventoryMenu; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.crafting.CraftingGridInventory; -import org.spongepowered.common.accessor.world.inventory.CraftingMenuAccessor; +import org.spongepowered.common.accessor.world.inventory.AbstractCraftingMenuAccessor; import org.spongepowered.common.inventory.fabric.Fabric; import org.spongepowered.common.inventory.fabric.OffsetFabric; import org.spongepowered.common.inventory.lens.impl.AbstractLens; @@ -70,7 +70,7 @@ public Inventory getAdapter(Fabric fabric, Inventory parent) { return ((CraftingGridInventory) ((InventoryMenu) fabric).getCraftSlots()); } if (fabric instanceof CraftingMenu) { - return ((CraftingGridInventory) ((CraftingMenuAccessor) fabric).accessor$craftSlots()); + return ((CraftingGridInventory) ((AbstractCraftingMenuAccessor) fabric).accessor$craftSlots()); } throw new IllegalStateException(fabric.getClass().getName() + " is not a known CraftingGridInventory."); } diff --git a/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java b/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java index b6c489f060c..f58776c355a 100644 --- a/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java +++ b/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java @@ -51,7 +51,7 @@ import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.world.inventory.CraftingMenuAccessor; +import org.spongepowered.common.accessor.world.inventory.AbstractCraftingMenuAccessor; import org.spongepowered.common.accessor.world.inventory.SmithingMenuAccessor; import org.spongepowered.common.accessor.world.inventory.StonecutterMenuAccessor; import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; @@ -97,7 +97,7 @@ public static Optional toCraftingInput(final Invent case AbstractFurnaceBlockEntity furnace -> new SingleRecipeInput(furnace.getItem(0)); case CampfireBlockEntity campfire -> campfire.getItems().stream().filter(stack -> !stack.isEmpty()).findFirst() .map(SingleRecipeInput::new).orElse(null); - case CraftingMenuAccessor menu -> menu.accessor$craftSlots().asCraftInput(); + case AbstractCraftingMenuAccessor menu -> menu.accessor$craftSlots().asCraftInput(); case InventoryMenu menu -> menu.getCraftSlots().asCraftInput(); case StonecutterMenu menu -> StonecutterMenuAccessor.invoker$createRecipeInput(menu.container); case SmithingMenuAccessor menu -> menu.invoker$createRecipeInput(); From b2a37dc43c4444500c81a1cc4a8ceb4333b96b4d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:10:28 +0200 Subject: [PATCH 055/586] fix max light is gone? --- .../api/minecraft/world/level/BlockGetterMixin_API.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java index e828cec9b9e..c24ffd822ba 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/BlockGetterMixin_API.java @@ -51,14 +51,8 @@ public interface BlockGetterMixin_API extends PrimitiveGameVolume { @Shadow BlockState shadow$getBlockState(BlockPos p_180495_1_); @Shadow net.minecraft.world.level.material.FluidState shadow$getFluidState(BlockPos p_204610_1_); @Shadow int shadow$getLightEmission(BlockPos p_217298_1_); - @Shadow int shadow$getMaxLightLevel(); //@formatter:on - @Override - default int maximumLight() { - return this.shadow$getMaxLightLevel(); - } - @Override default int emittedLight(final Vector3i position) { return this.shadow$getLightEmission(new BlockPos(position.x(), position.y(), position.z())); From 1f1b67a7592968ad808b7e22b2545f433b57d3ac Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:16:20 +0200 Subject: [PATCH 056/586] fix attack crit --- .../mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index cccccefb39c..86df7fcdff2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -169,7 +169,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I */ @ModifyVariable(method = "attack", ordinal = 2, slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), - to = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/player/Player;walkDist:F")), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnownMovement()Lnet/minecraft/world/phys/Vec3;")), at = @At(value = "JUMP", opcode = Opcodes.IFEQ) ) public boolean attackImpl$critHook(final boolean isCrit) { From fb3b713cfa21eedba5c3a20cebd81a708fa37a89 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:18:39 +0200 Subject: [PATCH 057/586] fix saving world --- .../common/mixin/core/server/level/ServerLevelMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 03e73b5781a..a110b346589 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -140,7 +140,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow private int emptyTime; @Shadow @NonNull public abstract MinecraftServer shadow$getServer(); - @Shadow protected abstract void shadow$saveLevelData(); + @Shadow protected abstract void shadow$saveLevelData(final boolean $$0); @Shadow @Final private MinecraftServer server; @Shadow public abstract void levelEvent(@Nullable Player $$0, int $$1, BlockPos $$2, int $$3); @@ -373,7 +373,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, // We always save the metadata unless it is NONE if (behavior != SerializationBehavior.NONE) { - this.shadow$saveLevelData(); + this.shadow$saveLevelData(flush); // Sponge Start - We do per-world WorldInfo/WorldBorders/BossBars From 203db782068560e56c42772aeb1fed94a870a45d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:22:36 +0200 Subject: [PATCH 058/586] fix ArmorMaterial repairIngredient --- .../world/item/ArmorMaterialMixin_API.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java index 4a003b8b2b3..19692eca8fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java @@ -24,30 +24,29 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item; +import net.minecraft.world.item.ItemStack; import org.spongepowered.api.data.type.ArmorMaterial; -import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.util.ItemStackUtil; -import java.util.Optional; -import java.util.function.Supplier; +import java.util.function.Predicate; @Mixin(net.minecraft.world.item.ArmorMaterial.class) @Implements(@Interface(iface = ArmorMaterial.class, prefix = "armorMaterial$")) public abstract class ArmorMaterialMixin_API implements ArmorMaterial { // @formatter:off - @Shadow @Final private Supplier repairIngredient; + @Shadow @Final private Predicate repairIngredient; // @formatter:on @Override - public Optional repairIngredient() { - final net.minecraft.world.item.crafting.Ingredient repairMaterial = this.repairIngredient.get(); - return Optional.ofNullable(((Ingredient) (Object) repairMaterial)); + public Predicate repairIngredient() { + return (spongeStack) -> this.repairIngredient.test(ItemStackUtil.toNative(spongeStack)); } } From b23aea7d4b9168e61f6e6c3c2a2bd2926ccc523a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:33:45 +0200 Subject: [PATCH 059/586] TODO fix NeighborUpdaterMixin_Tracker --- SpongeAPI | 2 +- .../common/event/tracking/PhaseStateProxy.java | 1 + .../redstone/NeighborUpdaterMixin_Tracker.java | 15 +++++---------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 0141ef74ad3..3de210ac24e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 0141ef74ad3a775b7a160f634cf3922d3379302f +Subproject commit 3de210ac24eb838976c41e36559ca1135195eb1a diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java index 9f2aa7307b0..329f249aeb1 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java @@ -33,6 +33,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.redstone.Orientation; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.ticks.ScheduledTick; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java index e16d22970e2..05776e94678 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java @@ -31,6 +31,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.redstone.NeighborUpdater; +import net.minecraft.world.level.redstone.Orientation; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -50,20 +51,12 @@ public interface NeighborUpdaterMixin_Tracker { /** * Logs a transaction to the {@link PhaseContext} for neighbor notifications. Otherwise, * we will fail to create notification events in the API. This avoids a redirect or overwrite - * - * @param level - * @param targetState - * @param targetPos - * @param fromBlock - * @param fromPos - * @param movement - * @param ci */ @Inject(method = "executeUpdate", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;handleNeighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V" + target = "Lnet/minecraft/world/level/block/state/BlockState;handleNeighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/redstone/Orientation;Z)V" )) - private static void tracker$wrapNeighborUpdateInSideEffect(Level level, BlockState targetState, BlockPos targetPos, Block fromBlock, BlockPos fromPos, boolean movement, CallbackInfo ci) { + private static void tracker$wrapNeighborUpdateInSideEffect(Level level, BlockState targetState, BlockPos targetPos, Block fromBlock, @Nullable Orientation orientation, boolean movement, CallbackInfo ci) { // Sponge start - prepare notification final PhaseContext<@NonNull ?> peek = PhaseTracker.getInstance().getPhaseContext(); if (!(level instanceof ServerLevel serverLevel)) { @@ -76,6 +69,8 @@ public interface NeighborUpdaterMixin_Tracker { targetPos, LevelChunk.EntityCreationType.CHECK ); + + var fromPos = targetPos; // TODO fromPos is gone THIS IS ALMOST CERTAINLY WRONG peek.getTransactor().logNeighborNotification(worldSupplier, fromPos, fromBlock, targetPos, targetState, existingTile); peek.associateNeighborStateNotifier(fromPos, targetState.getBlock(), targetPos, serverLevel, PlayerTracker.Type.NOTIFIER); From 43e02b16aa765dd2f3c7de27a5388982e03abd08 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:36:35 +0200 Subject: [PATCH 060/586] TODO damage is never set? - fix enderpearl --- .../core/world/entity/projectile/ThrownEnderpearlMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java index 878e79e0b9e..f1c466a54de 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java @@ -44,7 +44,7 @@ public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin { @ModifyArg(method = "onHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + target = "Lnet/minecraft/world/entity/player/Player;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) private float impl$onAttackEntityFromWithDamage(final float damage) { return (float) this.impl$damageAmount; } From ff0cdc0d6a61a3de174808961b3ed7528de6ab3c Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:43:22 +0200 Subject: [PATCH 061/586] fix minecart slowdown factor - TODO new behaviour? --- .../entity/vehicle/AbstractMinecartMixin.java | 9 ---- .../vehicle/OldMinecartBehaviourMixin.java | 42 +++++++++++++++++++ src/mixins/resources/mixins.sponge.core.json | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java index deb37eba7df..c89aa2f110d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java @@ -88,15 +88,6 @@ protected double getMaxSpeed() { return vec3d.multiply(this.impl$airborneMod.x(), this.impl$airborneMod.y(), this.impl$airborneMod.z()); } - @Redirect(method = "applyNaturalSlowdown", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/vehicle/AbstractMinecart;isVehicle()Z" - ) - ) - private boolean impl$applyDragIfEmpty(final AbstractMinecart self) { - return !this.impl$slowWhenEmpty || this.shadow$isVehicle(); - } - @Override public double bridge$getMaxSpeed() { return this.impl$maxSpeed; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java new file mode 100644 index 00000000000..c08dbd2504b --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity.vehicle; + +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.OldMinecartBehavior; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractMinecartBridge; + +@Mixin(OldMinecartBehavior.class) +public abstract class OldMinecartBehaviourMixin { + + @Redirect(method = "getSlowdownFactor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/AbstractMinecart;isVehicle()Z")) + private boolean impl$applyDragIfEmpty(final AbstractMinecart minecart) { + return !((AbstractMinecartBridge) minecart).bridge$getSlowWhenEmpty() || minecart.isVehicle(); + } + +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index c2a34dd6354..6921449e40d 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -185,6 +185,7 @@ "world.entity.vehicle.MinecartCommandBlockMixin", "world.entity.vehicle.MinecartFurnaceMixin", "world.entity.vehicle.MinecartTNTMixin", + "world.entity.vehicle.OldMinecartBehaviourMixin", "world.entity.vehicle.VehicleEntityMixin", "world.food.FoodDataMixin", "world.inventory.StonecutterMenuMixin", From 11db1af589931c3598f5887e3aff81b9991b2e8e Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:44:55 +0200 Subject: [PATCH 062/586] set camera on tp --- .../common/mixin/core/server/level/ServerPlayerMixin.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 73fcb2a228c..0a51739bf99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -175,6 +175,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Shadow protected abstract void shadow$triggerDimensionChangeTriggers(ServerLevel serverworld); @Shadow public abstract void shadow$doCloseContainer(); @Shadow public abstract boolean shadow$setGameMode(GameType param0); + @Shadow public abstract void shadow$setCamera(@org.jetbrains.annotations.Nullable final Entity $$0); // @formatter:on private net.minecraft.network.chat.@Nullable Component impl$connectionMessage; @@ -400,7 +401,10 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr * @reason Redirect all teleports through {@link #bridge$changeDimension} to fire our move/rotate/teleport events */ @Overwrite - public void teleportTo(final ServerLevel world, final double x, final double y, final double z, final float yaw, final float pitch) { + public void teleportTo(final ServerLevel world, final double x, final double y, final double z, final float yaw, final float pitch, final boolean setCamera) { + if (setCamera) { + this.shadow$setCamera((net.minecraft.server.level.ServerPlayer) (Object) this); + } final boolean hasMovementContext = PhaseTracker.getCauseStackManager().currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { if (!hasMovementContext) { From aa139162faffc50621f701ee0c5a795795de2f9e Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:48:26 +0200 Subject: [PATCH 063/586] TODO check if this can be simplified now --- .../mixin/tracker/server/level/ServerPlayerMixin_Tracker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java index 9ffbd536d43..8e01da4348c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java @@ -59,12 +59,12 @@ public abstract class ServerPlayerMixin_Tracker extends PlayerMixin_Tracker { method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;" + target = "Lnet/minecraft/server/level/ServerPlayer;createItemStackToDrop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;" ) ) @Nullable private ItemEntity tracker$throwItemDrop( - final Player thisPlayer, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem + final ServerPlayer thisPlayer, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem ) { if (droppedItem.isEmpty()) { return null; From c96ec4f112056068b8a6070cf90a76ba7dadbcbb Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:57:44 +0200 Subject: [PATCH 064/586] fix wool color mapping --- .../accessor/world/entity/animal/SheepAccessor.java | 8 -------- .../common/data/provider/block/state/WoolData.java | 4 +++- .../data/provider/item/stack/WoolItemStackData.java | 3 ++- .../java/org/spongepowered/common/util/DyeColorUtil.java | 4 ++-- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java index f876ba9205c..9bbc8d32fb5 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java @@ -26,14 +26,10 @@ import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.world.entity.animal.Sheep; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.ItemLike; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.common.UntransformedAccessorError; -import java.util.Map; - @Mixin(Sheep.class) public interface SheepAccessor { @@ -41,8 +37,4 @@ public interface SheepAccessor { throw new UntransformedAccessorError(); } - @Accessor("ITEM_BY_DYE") static Map accessor$ITEM_BY_DYE() { - throw new UntransformedAccessorError(); - } - } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java index b0f500b4ea4..38f5b0a74dd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.data.provider.block.state; +import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; @@ -42,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .asImmutable(Block.class) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) DyeColorUtil.COLOR_BY_WOOL.get(h)) - .supports(h -> SheepAccessor.accessor$ITEM_BY_DYE().containsValue(h)); + .supports(LootData.WOOL_ITEM_BY_DYE::containsValue); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java index 1543024420f..a596c792725 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.item.stack; +import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import org.spongepowered.api.data.Keys; @@ -43,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .asImmutable(ItemStack.class) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) DyeColorUtil.COLOR_BY_WOOL.get(((BlockItem) h.getItem()).getBlock())) - .supports(h -> h.getItem() instanceof BlockItem && SheepAccessor.accessor$ITEM_BY_DYE().containsValue(((BlockItem) h.getItem()).getBlock())); + .supports(h -> h.getItem() instanceof BlockItem && LootData.WOOL_ITEM_BY_DYE.containsValue(((BlockItem) h.getItem()).getBlock())); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/util/DyeColorUtil.java b/src/main/java/org/spongepowered/common/util/DyeColorUtil.java index 8a81546118f..fa690dafe0b 100644 --- a/src/main/java/org/spongepowered/common/util/DyeColorUtil.java +++ b/src/main/java/org/spongepowered/common/util/DyeColorUtil.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.util; +import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; import java.util.HashMap; import java.util.Map; @@ -36,7 +36,7 @@ public class DyeColorUtil { - public static final Map COLOR_BY_WOOL = SheepAccessor.accessor$ITEM_BY_DYE().entrySet() + public static final Map COLOR_BY_WOOL = LootData.WOOL_ITEM_BY_DYE.entrySet() .stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); From ba8829842aae82ba5084272b14ef66cca828f927 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Tue, 27 Aug 2024 19:59:02 +0200 Subject: [PATCH 065/586] fix InventoryMenuMixin_TrackedMenuBridge_Inventory --- ...nventoryMenuMixin_TrackedMenuBridge_Inventory.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/InventoryMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/InventoryMenuMixin_TrackedMenuBridge_Inventory.java index 624eb0e6007..088b78c8386 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/InventoryMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/InventoryMenuMixin_TrackedMenuBridge_Inventory.java @@ -27,24 +27,15 @@ import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.inventory.ResultContainer; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.inventory.container.TrackedMenuBridge; @Mixin(InventoryMenu.class) -public abstract class InventoryMenuMixin_TrackedMenuBridge_Inventory { - - // @formatter:off - @Shadow @Final private CraftingContainer craftSlots; - @Shadow @Final private ResultContainer resultSlots; - // @formatter:on +public abstract class InventoryMenuMixin_TrackedMenuBridge_Inventory extends AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory { @Inject(method = "", at = @At("RETURN")) private void inventory$attachContainerMenu(final Inventory $$0, final boolean $$1, final Player $$2, final CallbackInfo ci) { From 1190c778d555d2a0db873151d01ea735213cae50 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 10:00:18 +0200 Subject: [PATCH 066/586] fix ProjectileDispenseBehaviorMixin --- .../dispenser/ProjectileDispenseBehaviorMixin.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/core/dispenser/ProjectileDispenseBehaviorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/core/dispenser/ProjectileDispenseBehaviorMixin.java index 0ef52cdaf02..410158c665e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/core/dispenser/ProjectileDispenseBehaviorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/core/dispenser/ProjectileDispenseBehaviorMixin.java @@ -24,11 +24,13 @@ */ package org.spongepowered.common.mixin.core.core.dispenser; +import net.minecraft.core.Direction; +import net.minecraft.core.Position; import net.minecraft.core.dispenser.BlockSource; import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; import net.minecraft.core.dispenser.ProjectileDispenseBehavior; -import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ProjectileItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import org.spongepowered.api.data.Keys; @@ -42,13 +44,17 @@ public abstract class ProjectileDispenseBehaviorMixin extends DefaultDispenseItemBehavior { @Redirect(method = "execute", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean impl$spawnEntityAndSetShooter(final Level world, final Entity entity, final BlockSource source, final ItemStack stack) { + target = "Lnet/minecraft/world/item/ProjectileItem;asProjectile(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/Position;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/entity/projectile/Projectile;")) + private net.minecraft.world.entity.projectile.Projectile impl$spawnEntityAndSetShooter(final ProjectileItem instance, final Level level, + final Position position, final ItemStack stack, final Direction direction, final BlockSource source) { + final var entity = instance.asProjectile(level, position, stack, direction); + final BlockEntity tileEntity = source.blockEntity(); if (entity instanceof Projectile && tileEntity instanceof ProjectileSource) { ((Projectile) entity).offer(Keys.SHOOTER, (ProjectileSource) tileEntity); } - return world.addFreshEntity(entity); + + return entity; } } From c461c9a124cce0aad858ada16629b0240488ef4b Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 10:16:55 +0200 Subject: [PATCH 067/586] fix recipe ingredients --- .../world/item/crafting/RecipeMixin_API.java | 8 ------ .../item/crafting/ShapedRecipeMixin_API.java | 12 +++++++++ .../crafting/ShapelessRecipeMixin_API.java | 17 +++++++++++++ .../crafting/SingleItemRecipeMixin_API.java | 7 ++++++ .../SmithingTransformRecipeMixin_API.java | 25 +++++++++++++++++++ .../crafting/StonecutterRecipeMixin_API.java | 7 ++++++ 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java index af01bd79ede..7ed649e48ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java @@ -34,12 +34,10 @@ import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.recipe.Recipe; import org.spongepowered.api.item.recipe.RecipeType; -import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.List; @@ -55,7 +53,6 @@ public interface RecipeMixin_API shadow$getRemainingItems(I inv); @Shadow net.minecraft.world.item.crafting.RecipeType shadow$getType(); - @Shadow NonNullList shadow$getIngredients(); // @formatter:on @NonNull @@ -84,11 +81,6 @@ default List remainingItems(@NonNull final I2 inv) { .collect(Collectors.toList()); } - @Override - default List ingredients() { - return this.shadow$getIngredients().stream().map(IngredientUtil::fromNative).collect(Collectors.toList()); - } - @Override default boolean isDynamic() { return this.shadow$isSpecial(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapedRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapedRecipeMixin_API.java index 595db6d9223..e6d14bab52c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapedRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapedRecipeMixin_API.java @@ -26,10 +26,16 @@ import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; +import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.api.item.recipe.crafting.ShapedCraftingRecipe; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @Mixin(ShapedRecipe.class) public abstract class ShapedRecipeMixin_API implements ShapedCraftingRecipe { @@ -52,6 +58,12 @@ public org.spongepowered.api.item.recipe.crafting.Ingredient ingredient(final in return ((org.spongepowered.api.item.recipe.crafting.Ingredient)(Object) this.pattern.ingredients().get(recipeItemIndex)); } + @Override + public List ingredients() { + return this.pattern.ingredients().stream().filter(Optional::isPresent).map(Optional::get) + .map(IngredientUtil::fromNative).collect(Collectors.toList()); + } + @Override public int width() { return this.pattern.width(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapelessRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapelessRecipeMixin_API.java index 94a417304e9..6414b4aa581 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapelessRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/ShapelessRecipeMixin_API.java @@ -25,10 +25,27 @@ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; import net.minecraft.world.item.crafting.ShapelessRecipe; +import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.api.item.recipe.crafting.ShapelessCraftingRecipe; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; + +import java.util.List; +import java.util.stream.Collectors; @Mixin(ShapelessRecipe.class) public abstract class ShapelessRecipeMixin_API implements ShapelessCraftingRecipe { + // @formatter:off + @Shadow @Final private List ingredients; + // @formatter:on + + @Override + public List ingredients() { + return this.ingredients.stream().map(IngredientUtil::fromNative).collect(Collectors.toList()); + } + + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java index 72b94a6aa03..4623309db0d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java @@ -24,10 +24,17 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleItemRecipe; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; @Mixin(SingleItemRecipe.class) public abstract class SingleItemRecipeMixin_API { + // @formatter:off + @Shadow @Final protected Ingredient ingredient; + // @formatter:on + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java index 44c31a04ae4..8ff0d95e645 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java @@ -25,11 +25,36 @@ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; import net.minecraft.world.item.crafting.SmithingTransformRecipe; +import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.api.item.recipe.smithing.SmithingRecipe; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Optional; @Mixin(SmithingTransformRecipe.class) public abstract class SmithingTransformRecipeMixin_API implements SmithingRecipe { + // @formatter:off + @Shadow @Final Optional addition; + @Shadow @Final Optional template; + @Shadow @Final Optional base; + // @formatter:on + + @Override + public Optional templateIngredient() { + return this.template.map(Ingredient.class::cast); + } + + @Override + public Optional baseIngredient() { + return this.base.map(Ingredient.class::cast); + } + + @Override + public Optional additionalIngredient() { + return this.addition.map(Ingredient.class::cast); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java index 5af37c839a3..7cbfc0a5447 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java @@ -27,8 +27,15 @@ import net.minecraft.world.item.crafting.StonecutterRecipe; import org.spongepowered.api.item.recipe.single.StoneCutterRecipe; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; @Mixin(StonecutterRecipe.class) public abstract class StonecutterRecipeMixin_API extends SingleItemRecipeMixin_API implements StoneCutterRecipe { + @Override + public org.spongepowered.api.item.recipe.crafting.Ingredient ingredient() { + return IngredientUtil.fromNative(this.ingredient); + } + + } From 4da752b6d83552c2ff99d4281192b23d2b4b0fed Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 10:21:40 +0200 Subject: [PATCH 068/586] fix recipes --- SpongeAPI | 2 +- .../item/crafting/SmithingRecipeBridge.java | 8 +++++--- .../recipe/smithing/SpongeSmithingRecipe.java | 16 ++++++++-------- .../SpongeSmithingRecipeRegistration.java | 3 ++- .../crafting/SmithingTransformRecipeMixin.java | 14 ++++++++------ 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 3de210ac24e..d174770869e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3de210ac24eb838976c41e36559ca1135195eb1a +Subproject commit d174770869ef946ffcbcdb6c5356d5bc25dc73c5 diff --git a/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java index 1d63566f01b..43b0a377e4e 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java @@ -26,10 +26,12 @@ import net.minecraft.world.item.crafting.Ingredient; +import java.util.Optional; + public interface SmithingRecipeBridge extends RecipeResultBridge { - Ingredient bridge$template(); - Ingredient bridge$base(); - Ingredient bridge$addition(); + Optional bridge$template(); + Optional bridge$base(); + Optional bridge$addition(); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index afcabb534b7..0626bb76ee4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -47,9 +47,9 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe implements Res public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( $$0 -> $$0.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Ingredient.CODEC.fieldOf("template").forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$template()), - Ingredient.CODEC.fieldOf(Constants.Recipe.SMITHING_BASE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$base()), - Ingredient.CODEC.fieldOf(Constants.Recipe.SMITHING_ADDITION_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$addition()), + Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_TEMPLATE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$template()), + Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_BASE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$base()), + Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_ADDITION_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$addition()), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge) $$0x).bridge$result()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) ) @@ -58,15 +58,15 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe implements Res private final String resultFunctionId; - public static SpongeSmithingRecipe of(final String spongeType, final Ingredient template, final Ingredient base, - final Ingredient addition, final ItemStack resultIn, final Optional resultFunctionId) + public static SpongeSmithingRecipe of(final String spongeType, final Optional template, final Optional base, + final Optional addition, final ItemStack resultIn, final Optional resultFunctionId) { return new SpongeSmithingRecipe(template, base, addition, resultIn, resultFunctionId.orElse(null)); } - public SpongeSmithingRecipe(final Ingredient template, final Ingredient base, - final Ingredient addition, final ItemStack spongeResult, final String resultFunctionId) { - super(Optional.of(template), Optional.ofNullable(base), Optional.ofNullable(addition), spongeResult); + public SpongeSmithingRecipe(final Optional template, final Optional base, + final Optional addition, final ItemStack spongeResult, final String resultFunctionId) { + super(template, base, addition, spongeResult); this.resultFunctionId = resultFunctionId; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java index d04005ab503..26261ca7cc3 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java @@ -72,7 +72,8 @@ public Recipe recipe() { return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), this.spongeResult); } - return (SmithingRecipe) new SpongeSmithingRecipe(this.template, this.base, this.addition, this.spongeResult, this.resultFunction == null ? null : this.key.toString()); + return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), Optional.ofNullable(this.base), Optional.ofNullable(this.addition), + this.spongeResult, this.resultFunction == null ? null : this.key.toString()); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java index 531399e070c..0fa9a035e4f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java @@ -32,28 +32,30 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.item.crafting.SmithingRecipeBridge; +import java.util.Optional; + @Mixin(SmithingTransformRecipe.class) public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBridge { // @formatter=off - @Shadow @Final Ingredient template; - @Shadow @Final Ingredient base; - @Shadow @Final Ingredient addition; + @Shadow @Final Optional template; + @Shadow @Final Optional base; + @Shadow @Final Optional addition; @Shadow @Final ItemStack result; // @formatter=on @Override - public Ingredient bridge$template() { + public Optional bridge$template() { return this.template; } @Override - public Ingredient bridge$base() { + public Optional bridge$base() { return this.base; } @Override - public Ingredient bridge$addition() { + public Optional bridge$addition() { return this.addition; } From 645caddcd192b29918cd9fc074fcf7ac8688c774 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 10:25:37 +0200 Subject: [PATCH 069/586] fix SavedDataMixin --- .../common/mixin/core/world/level/SavedDataMixin.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java index cada3864214..1efb73a8c2c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java @@ -30,20 +30,18 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; -import java.io.File; - @Mixin(SavedData.class) public abstract class SavedDataMixin { - @Inject(method = "save(Ljava/io/File;Lnet/minecraft/core/HolderLookup$Provider;)V", + @Inject(method = "save(Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/SavedData;save(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;"), locals = LocalCapture.CAPTURE_FAILHARD) - public void impl$writeAdditionalMapNBT(File file, HolderLookup.Provider registry, final CallbackInfo cir, CompoundTag compound) { + public void impl$writeAdditionalMapNBT(HolderLookup.Provider registry, final CallbackInfoReturnable cir, CompoundTag compound) { if (this instanceof DataCompoundHolder) { if (DataUtil.syncDataToTag(this)) { compound.merge(((DataCompoundHolder) this).data$getCompound()); From 1873391698a77e88f9389c7935672a163dfb2fa3 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 10:34:31 +0200 Subject: [PATCH 070/586] fix registry loading --- .../common/mixin/core/server/WorldLoaderMixin.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index 19289d3d438..f5ad465e91c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -57,4 +57,15 @@ public abstract class WorldLoaderMixin { } + @Redirect(method = "load", at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/LayeredRegistryAccess;replaceFrom(Ljava/lang/Object;[Lnet/minecraft/core/RegistryAccess$Frozen;)Lnet/minecraft/core/LayeredRegistryAccess;")) + private static LayeredRegistryAccess impl$afterLoadDimensionRegistries(final LayeredRegistryAccess instance, + final T $$0, final RegistryAccess.Frozen[] $$1) { + final var lifecycle = Launch.instance().lifecycle(); + lifecycle.establishGlobalRegistries($$1[0], RegistryLayer.DIMENSIONS); + return instance.replaceFrom($$0, $$1); + } + + + } From c1840c2e839442b0f0f10219c40de8165a9b94c8 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:10:17 +0200 Subject: [PATCH 071/586] fix explosion --- ...cessor.java => ServerExplosionAccessor.java} | 15 +++++---------- .../resources/mixins.sponge.accessors.json | 2 +- .../phase/general/ExplosionContext.java | 17 ++++++++--------- .../tracking/phase/general/ExplosionState.java | 6 +++--- .../core/server/level/ServerLevelMixin.java | 2 +- .../world/damagesource/DamageSourcesMixin.java | 4 ++-- 6 files changed, 20 insertions(+), 26 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/level/{ExplosionAccessor.java => ServerExplosionAccessor.java} (85%) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/ExplosionAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/ServerExplosionAccessor.java similarity index 85% rename from src/accessors/java/org/spongepowered/common/accessor/world/level/ExplosionAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/level/ServerExplosionAccessor.java index 6f3e7f1f733..68550648525 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/ExplosionAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/ServerExplosionAccessor.java @@ -24,23 +24,18 @@ */ package org.spongepowered.common.accessor.world.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerExplosion; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(Explosion.class) -public interface ExplosionAccessor { +@Mixin(ServerExplosion.class) +public interface ServerExplosionAccessor { @Accessor("blockInteraction") Explosion.BlockInteraction accessor$blockInteraction(); - @Accessor("level") Level accessor$level(); - - @Accessor("x") double accessor$x(); - - @Accessor("y") double accessor$y(); - - @Accessor("z") double accessor$z(); + @Accessor("level") ServerLevel accessor$level(); @Accessor("radius") float accessor$radius(); diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 72d9ec744a8..0897ccebde8 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -143,7 +143,7 @@ "world.item.trading.MerchantOfferAccessor", "world.level.BaseCommandBlockAccessor", "world.level.BaseSpawnerAccessor", - "world.level.ExplosionAccessor", + "world.level.ServerExplosionAccessor", "world.level.GameRules_ValueAccessor", "world.level.GameRulesAccessor", "world.level.LevelAccessor", diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java index 0c901223d8c..032bf2c6c0c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java @@ -27,16 +27,17 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.ServerExplosion; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.accessor.world.level.ExplosionAccessor; +import org.spongepowered.common.accessor.world.level.ServerExplosionAccessor; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.PrettyPrinter; public final class ExplosionContext extends GeneralPhaseContext { - private Explosion explosion; + private ServerExplosion explosion; public ExplosionContext(PhaseTracker tracker) { super(GeneralPhase.State.EXPLOSION, tracker); @@ -57,12 +58,12 @@ public ExplosionContext potentialExplosionSource(final ServerLevel worldServer, return this; } - public ExplosionContext explosion(final Explosion explosion) { + public ExplosionContext explosion(final ServerExplosion explosion) { this.explosion = explosion; return this; } - public Explosion getExplosion() { + public ServerExplosion getExplosion() { return this.explosion; } @@ -88,12 +89,10 @@ protected boolean isRunaway(final PhaseContext phaseContext) { if (phaseContext.getClass() != ExplosionContext.class) { return false; } - final ExplosionAccessor otherExplosion = (ExplosionAccessor) ((ExplosionContext) phaseContext).explosion; - final ExplosionAccessor thisExplosion = (ExplosionAccessor) this.explosion; + final ServerExplosionAccessor otherExplosion = (ServerExplosionAccessor) ((ExplosionContext) phaseContext).explosion; + final ServerExplosionAccessor thisExplosion = (ServerExplosionAccessor) this.explosion; return otherExplosion.accessor$level() == thisExplosion.accessor$level() - && otherExplosion.accessor$x() == thisExplosion.accessor$x() - && otherExplosion.accessor$y() == thisExplosion.accessor$y() - && otherExplosion.accessor$z() == thisExplosion.accessor$z(); + && ((ExplosionContext) phaseContext).explosion.center().equals(this.explosion.center()); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionState.java index 141853b01aa..26e10b29deb 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionState.java @@ -39,7 +39,7 @@ import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.entity.SpawnEntityEvent; import org.spongepowered.api.util.Tuple; -import org.spongepowered.common.accessor.world.level.ExplosionAccessor; +import org.spongepowered.common.accessor.world.level.ServerExplosionAccessor; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.TrackingUtil; @@ -88,8 +88,8 @@ public void populateLootContext(final ExplosionContext phaseContext, final LootP final Explosion explosion = phaseContext.getExplosion(); lootBuilder.withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); - if (((ExplosionAccessor) explosion).accessor$blockInteraction() == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY) { - lootBuilder.withParameter(LootContextParams.EXPLOSION_RADIUS, ((ExplosionAccessor) explosion).accessor$radius()); + if (((ServerExplosionAccessor) explosion).accessor$blockInteraction() == net.minecraft.world.level.Explosion.BlockInteraction.DESTROY) { + lootBuilder.withParameter(LootContextParams.EXPLOSION_RADIUS, ((ServerExplosionAccessor) explosion).accessor$radius()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index a110b346589..d9f9e8ddc65 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -251,7 +251,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final ServerExplosion mcExplosion = (ServerExplosion) explosion; try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER) - .explosion((net.minecraft.world.level.Explosion) explosion) + .explosion(mcExplosion) .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { ignored.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/damagesource/DamageSourcesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/damagesource/DamageSourcesMixin.java index 097b90cd9c2..9d4bc671a77 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/damagesource/DamageSourcesMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/damagesource/DamageSourcesMixin.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.accessor.world.level.ExplosionAccessor; +import org.spongepowered.common.accessor.world.level.ServerExplosionAccessor; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; @@ -45,7 +45,7 @@ private LivingEntity onSetExplosionSource(final Explosion explosion) { // When indirect source is not set if (explosion.getIndirectSourceEntity() == null && explosion.getDirectSourceEntity() instanceof CreatorTrackedBridge creatorBridge - && !((LevelBridge) ((ExplosionAccessor) explosion).accessor$level()).bridge$isFake()) { + && !((LevelBridge) ((ServerExplosionAccessor) explosion).accessor$level()).bridge$isFake()) { // check creator var indirectSource = creatorBridge.tracker$getCreatorUUID().flatMap(x -> Sponge.server().player(x)); if (indirectSource.isPresent()) { From 8bfcb6d4ca27b41662ecb61e7bb8501f2fb2135e Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:11:52 +0200 Subject: [PATCH 072/586] fix IOWorkerMixin --- .../mixin/core/world/level/chunk/storage/IOWorkerMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java index e94a7e7fddf..2d2109cd0b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java @@ -60,6 +60,7 @@ import java.util.BitSet; import java.util.Map; +import java.util.SequencedMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -73,7 +74,7 @@ public abstract class IOWorkerMixin implements IOWorkerBridge { @Shadow @Final private AtomicBoolean shutdownRequested; @Shadow @Final private ProcessorMailbox mailbox; @Shadow @Final private RegionFileStorage storage; - @Shadow @Final private Map pendingWrites; + @Shadow @Final private SequencedMap pendingWrites; @Shadow protected abstract boolean shadow$isOldChunk(CompoundTag $$0); @Shadow protected abstract void shadow$tellStorePending(); From 877dd35fad8f7fb3b03d9d227b5337f5c490663d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:13:02 +0200 Subject: [PATCH 073/586] fix DimensionDataStorageMixin --- .../core/world/level/storage/DimensionDataStorageMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java index 31bd3782263..ddde9ac9d2b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java @@ -37,7 +37,7 @@ import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; -import java.io.File; +import java.nio.file.Path; import java.util.function.BiFunction; @Mixin(DimensionDataStorage.class) @@ -46,7 +46,7 @@ public abstract class DimensionDataStorageMixin { @Inject(method = "readSavedData", at = @At(value = "RETURN", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) public void readSpongeMapData(BiFunction var1, DataFixTypes $$1, String var2, CallbackInfoReturnable cir, - File var3, CompoundTag rootTag) { + Path var3, CompoundTag rootTag) { final SavedData savedData = cir.getReturnValue(); if (savedData instanceof DataCompoundHolder) { ((DataCompoundHolder) savedData).data$setCompound(rootTag); From 12c9b3dfc741a696ac408e4dcef9fd57eb3310c6 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:14:21 +0200 Subject: [PATCH 074/586] fix ChunkMapMixin_Tracker --- .../mixin/tracker/server/level/ChunkMapMixin_Tracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java index d868c48c8f8..894d7e8a63d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java @@ -60,7 +60,7 @@ public abstract class ChunkMapMixin_Tracker { return exception; } - @Redirect(method = "lambda$prepareTickingChunk$27", + @Redirect(method = "lambda$prepareTickingChunk$25", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;startTickingChunk(Lnet/minecraft/world/level/chunk/LevelChunk;)V")) private void tracker$wrapUnpackTicks(final ServerLevel level, final LevelChunk chunk) { if (!PhaseTracker.SERVER.onSidedThread()) { From 672dc5bf9b0c4a3ba765a284ecffa9e12693d918 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:26:21 +0200 Subject: [PATCH 075/586] fix tracked players --- .../chunk/storage/SerializableChunkDataMixin_Tracker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java index 08a90ddd88b..50e2973ce6d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java @@ -85,11 +85,12 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable @Override public void bridge$parseTrackerData(final CompoundTag fullTag) { final CompoundTag spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); + this.tracker$intPlayerPos = new HashMap<>(); + this.tracker$shortPlayerPos = new HashMap<>(); + if (spongeData.isEmpty()) { return; } - this.tracker$intPlayerPos = new HashMap<>(); - this.tracker$shortPlayerPos = new HashMap<>(); final ListTag list = spongeData.getList(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, 10); for (final Tag tag : list) { From 0334c6d1028450ee61c1100bde183c9c20e7c08a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 11:48:28 +0200 Subject: [PATCH 076/586] fix spawnlimits --- .../NaturalSpawner_SpawnStateAccessor.java | 9 +--- .../core/world/level/NaturalSpawnerMixin.java | 44 +++++-------------- 2 files changed, 11 insertions(+), 42 deletions(-) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/NaturalSpawner_SpawnStateAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/NaturalSpawner_SpawnStateAccessor.java index 7aa47292f9d..9b12a614bd1 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/NaturalSpawner_SpawnStateAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/NaturalSpawner_SpawnStateAccessor.java @@ -24,22 +24,15 @@ */ package org.spongepowered.common.accessor.world.level; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.NaturalSpawner; -import net.minecraft.world.level.chunk.ChunkAccess; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(NaturalSpawner.SpawnState.class) public interface NaturalSpawner_SpawnStateAccessor { - @Invoker("canSpawn") boolean invoker$canSpawn(EntityType p_234969_1_, BlockPos p_234969_2_, ChunkAccess p_234969_3_); - @Invoker("afterSpawn") void invoker$afterSpawn(Mob p_234970_1_, ChunkAccess p_234970_2_); - - @Invoker("canSpawnForCategory") boolean invoker$canSpawnForCategory(MobCategory category, final ChunkPos pos); + @Invoker("canSpawnForCategoryLocal") boolean invoker$canSpawnForCategoryLocal(MobCategory category, final ChunkPos pos); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/NaturalSpawnerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/NaturalSpawnerMixin.java index 4876dfc1d35..8327962e8cf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/NaturalSpawnerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/NaturalSpawnerMixin.java @@ -26,12 +26,11 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.NaturalSpawner; -import net.minecraft.world.level.chunk.LevelChunk; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.accessor.world.level.NaturalSpawner_SpawnStateAccessor; import org.spongepowered.common.bridge.world.level.NaturalSpawner_SpawnStateBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; @@ -40,46 +39,23 @@ @Mixin(NaturalSpawner.class) public abstract class NaturalSpawnerMixin { - // @formatter:off - @Shadow @Final private static MobCategory[] SPAWNING_CATEGORIES; - @Shadow static public void spawnCategoryForChunk(final MobCategory p_234967_0_, final ServerLevel p_234967_1_, final LevelChunk p_234967_2_, - final NaturalSpawner.SpawnPredicate p_234967_3_, final NaturalSpawner.AfterSpawnCallback p_234967_4_) { + @Redirect(method = "spawnForChunk", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/NaturalSpawner$SpawnState;canSpawnForCategoryLocal(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/world/level/ChunkPos;)Z")) + private static boolean impl$canSpawnForCategoryLocal(final NaturalSpawner.SpawnState instance, final MobCategory $$0, final ChunkPos $$1, final ServerLevel level) { + return NaturalSpawnerMixin.impl$canSpawnInLevel(instance, $$0, level, $$1); } - // @formatter:on - /** - * @author morph - January 3rd, 2021 - Minecraft 1.16.4 - * @reason Use world configured spawn limits - */ - @Overwrite - public static void spawnForChunk(final ServerLevel world, final LevelChunk chunk, final NaturalSpawner.SpawnState manager, final boolean spawnFriendlies, final boolean spawnEnemies, final boolean doMobSpawning) { - world.getProfiler().push("spawner"); - - for (final MobCategory entityclassification : SPAWNING_CATEGORIES) { - if ((spawnFriendlies || !entityclassification.isFriendly()) && (spawnEnemies || entityclassification.isFriendly()) && (doMobSpawning || !entityclassification.isPersistent()) && NaturalSpawnerMixin.impl$canSpawnInLevel(manager, entityclassification, world, chunk)) { - // spawnCategoryForChunk(var0, param0, param1, (param1x, param2x, param3x) -> param2.canSpawn(param1x, param2x, - // param3x), (param1x, param2x) -> param2.afterSpawn(param1x, param2x)); - NaturalSpawnerMixin.spawnCategoryForChunk(entityclassification, world, chunk, - (p_234969_1_, p_234969_2_, p_234969_3_) -> ((NaturalSpawner_SpawnStateAccessor) manager).invoker$canSpawn(p_234969_1_, p_234969_2_, p_234969_3_), - (p_234970_1_, p_234970_2_) -> ((NaturalSpawner_SpawnStateAccessor) manager).invoker$afterSpawn(p_234970_1_, p_234970_2_) - ); - } - } - - world.getProfiler().pop(); - } - - private static boolean impl$canSpawnInLevel(final NaturalSpawner.SpawnState manager, final MobCategory classification, final ServerLevel level, final LevelChunk chunk) { + private static boolean impl$canSpawnInLevel(final NaturalSpawner.SpawnState spawnState, final MobCategory classification, final ServerLevel level, final ChunkPos chunkPos) { final int tick = NaturalSpawnerMixin.impl$getSpawningTickRate(classification, level); // Unknown category/use default if (tick == -1) { - return ((NaturalSpawner_SpawnStateAccessor) manager).invoker$canSpawnForCategory(classification, chunk.getPos()); + return ((NaturalSpawner_SpawnStateAccessor) spawnState).invoker$canSpawnForCategoryLocal(classification, chunkPos); } // Turn off spawns if (tick == 0) { return false; } - return level.getGameTime() % tick == 0L && ((NaturalSpawner_SpawnStateBridge) manager).bridge$canSpawnForCategoryInWorld(classification, level); + return level.getGameTime() % tick == 0L && ((NaturalSpawner_SpawnStateBridge) spawnState).bridge$canSpawnForCategoryInWorld(classification, level); } private static int impl$getSpawningTickRate(final MobCategory classification, final ServerLevel world) { From 028dab592b1398b0aeac01eb232766b253b82a75 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 12:16:06 +0200 Subject: [PATCH 077/586] fix cooldowns --- SpongeAPI | 2 +- .../world/item/ItemCooldownsMixin_API.java | 93 ++++++++++++++----- .../core/world/item/ItemCooldownsMixin.java | 25 +++-- .../world/item/ServerItemCooldownsMixin.java | 17 ++-- .../test/data/InfiniteTicksDataTest.java | 7 +- 5 files changed, 102 insertions(+), 42 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index d174770869e..587166fe62e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d174770869ef946ffcbcdb6c5356d5bc25dc73c5 +Subproject commit 587166fe62e139311793bbc07873fc761811643c diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java index 023fb869015..6296ba85737 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java @@ -25,15 +25,18 @@ package org.spongepowered.common.mixin.api.minecraft.world.item; -import net.minecraft.world.item.Item; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import net.minecraft.world.item.ItemCooldowns; -import org.spongepowered.api.item.ItemType; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.util.Ticks; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.accessor.world.item.ItemCooldowns_CooldownInstanceAccessor; import org.spongepowered.common.bridge.world.item.ItemCooldownsBridge; +import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.SpongeTicks; import java.util.Map; @@ -45,25 +48,55 @@ public abstract class ItemCooldownsMixin_API implements org.spongepowered.api.entity.living.player.CooldownTracker { // @formatter:off - @Shadow @Final private Map cooldowns; @Shadow private int tickCount; - @Shadow public abstract boolean shadow$isOnCooldown(Item itemIn); - @Shadow public abstract float shadow$getCooldownPercent(Item itemIn, float partialTicks); - @Shadow public abstract void shadow$addCooldown(final Item item, final int ticks); + @Shadow public abstract boolean shadow$isOnCooldown(ItemStack stack); + @Shadow public abstract float shadow$getCooldownPercent(ItemStack stack, float partialTicks); + @Shadow public abstract void shadow$addCooldown(final ItemStack stack, final int ticks); + @Shadow public abstract void shadow$addCooldown(final ResourceLocation group, final int ticks); + @Shadow @Final private Map cooldowns; + // @formatter:on + + @Shadow public abstract ResourceLocation getCooldownGroup(final ItemStack $$0); + + @Override + public boolean hasCooldown(final org.spongepowered.api.item.inventory.ItemStack stack) { + Objects.requireNonNull(stack, "ItemStack cannot be null!"); + return this.shadow$isOnCooldown(ItemStackUtil.toNative(stack)); + } + + /** + * see {@link ItemCooldowns#getCooldownPercent(ItemStack, float)} + */ @Override - public boolean hasCooldown(final ItemType type) { - Objects.requireNonNull(type, "Item type cannot be null!"); - return this.shadow$isOnCooldown((Item) type); + public boolean hasCooldown(final ResourceKey group) { + Objects.requireNonNull(group, "group cannot be null!"); + return impl$getCooldownPercent((Object) group) > 0; + } + + private float impl$getCooldownPercent(final Object group) { + final var cooldown = this.cooldowns.get((ResourceLocation) group); + if (cooldown != null) { + float $$4 = (float)(cooldown.accessor$endTime() - cooldown.accessor$startTime()); + float $$5 = (float)cooldown.accessor$endTime() - ((float)this.tickCount); + return Mth.clamp($$5 / $$4, 0.0F, 1.0F); + } + return 0; } @Override - public Optional cooldown(final ItemType type) { - Objects.requireNonNull(type, "Item type cannot be null!"); + public Optional cooldown(final org.spongepowered.api.item.inventory.ItemStack stack) { + Objects.requireNonNull(stack, "ItemStack cannot be null!"); + final var group = this.getCooldownGroup(ItemStackUtil.toNative(stack)); + return this.cooldown((ResourceKey) (Object) group); + } - final ItemCooldowns_CooldownInstanceAccessor cooldown = (ItemCooldowns_CooldownInstanceAccessor) this.cooldowns.get((Item) type); + @Override + public Optional cooldown(final ResourceKey group) { + Objects.requireNonNull(group, "group cannot be null!"); + final var cooldown = this.cooldowns.get(group); if (cooldown != null) { final int remainingCooldown = cooldown.accessor$endTime() - this.tickCount; @@ -75,22 +108,32 @@ public Optional cooldown(final ItemType type) { } @Override - public boolean setCooldown(final ItemType type, final Ticks ticks) { - Objects.requireNonNull(type, "Item type cannot be null!"); - this.shadow$addCooldown((Item) type, SpongeTicks.toSaturatedIntOrInfinite(ticks)); + public boolean setCooldown(final org.spongepowered.api.item.inventory.ItemStack stack, final Ticks ticks) { + Objects.requireNonNull(stack, "ItemStack cannot be null!"); + this.shadow$addCooldown(ItemStackUtil.toNative(stack), SpongeTicks.toSaturatedIntOrInfinite(ticks)); return ((ItemCooldownsBridge) this).bridge$getSetCooldownResult(); } + @Override + public boolean setCooldown(final ResourceKey group, final Ticks ticks) { + Objects.requireNonNull(group, "group cannot be null!"); + this.shadow$addCooldown((ResourceLocation) (Object) group, SpongeTicks.toSaturatedIntOrInfinite(ticks)); + return ((ItemCooldownsBridge) this).bridge$getSetCooldownResult(); + } + @Override + public boolean resetCooldown(final org.spongepowered.api.item.inventory.ItemStack stack) { + return this.setCooldown(stack, Ticks.zero()); + } @Override - public boolean resetCooldown(final ItemType type) { - return this.setCooldown(type, Ticks.zero()); + public boolean resetCooldown(final ResourceKey group) { + return this.setCooldown(group, Ticks.zero()); } @Override - public OptionalDouble fractionRemaining(final ItemType type) { - Objects.requireNonNull(type, "Item type cannot be null!"); - final float cooldown = this.shadow$getCooldownPercent((Item) type, 0); + public OptionalDouble fractionRemaining(final org.spongepowered.api.item.inventory.ItemStack stack) { + Objects.requireNonNull(stack, "ItemStack cannot be null!"); + final float cooldown = this.shadow$getCooldownPercent(ItemStackUtil.toNative(stack), 0); if (cooldown > 0.0F) { return OptionalDouble.of(cooldown); @@ -98,5 +141,13 @@ public OptionalDouble fractionRemaining(final ItemType type) { return OptionalDouble.empty(); } - + @Override + public OptionalDouble fractionRemaining(final ResourceKey group) { + Objects.requireNonNull(group, "group cannot be null!"); + final float cooldown = this.impl$getCooldownPercent(group); + if (cooldown > 0.0F) { + return OptionalDouble.of(cooldown); + } + return OptionalDouble.empty(); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java index a7d72253a0e..113ff390aef 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java @@ -24,9 +24,10 @@ */ package org.spongepowered.common.mixin.core.world.item; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemCooldowns; -import org.spongepowered.api.item.ItemType; +import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -49,12 +50,15 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { // @formatter:off @Shadow @Final private Map cooldowns; + @Shadow public abstract ResourceLocation shadow$getCooldownGroup(final ItemStack $$0); + // @formatter:on + private int impl$lastSetCooldownResult; @Inject( - method = "addCooldown", + method = "addCooldown(Lnet/minecraft/resources/ResourceLocation;I)V", at = @At( value = "HEAD", remap = false @@ -62,15 +66,15 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) - private void impl$throwEventOnSetAndTrackResult(final Item item, final int ticks, final CallbackInfo ci) { - this.impl$lastSetCooldownResult = this.impl$throwSetCooldownEvent((ItemType) item, ticks); + private void impl$throwEventOnSetAndTrackResult(final ResourceLocation group, final int ticks, final CallbackInfo ci) { + this.impl$lastSetCooldownResult = this.impl$throwSetCooldownEvent(group, ticks); if (this.impl$lastSetCooldownResult == Constants.Sponge.Entity.Player.ITEM_COOLDOWN_CANCELLED) { ci.cancel(); } } @ModifyVariable( - method = "addCooldown", + method = "addCooldown(Lnet/minecraft/resources/ResourceLocation;I)V", at = @At( value = "HEAD", remap = false @@ -82,16 +86,16 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { } @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;", remap = false)) - private Object onTick(final Map.Entry entry) { - this.impl$throwEndCooldownEvent((ItemType) entry.getKey()); + private Object onTick(final Map.Entry entry) { + this.impl$throwEndCooldownEvent(entry.getKey()); return entry.getKey(); } - protected int impl$throwSetCooldownEvent(final ItemType type, final int ticks) { + protected int impl$throwSetCooldownEvent(final ResourceLocation group, final int ticks) { return 0; } - protected void impl$throwEndCooldownEvent(final ItemType type) { + protected void impl$throwEndCooldownEvent(final ResourceLocation group) { } @@ -101,7 +105,8 @@ private Object onTick(final Map.Entry entry) { } @Inject(method = "getCooldownPercent", at = @At("HEAD"), cancellable = true) - private void impl$getCooldownPercentInfiniteCooldown(final Item $$0, final float $$1, final CallbackInfoReturnable cir) { + private void impl$getCooldownPercentInfiniteCooldown(final ItemStack $$0, final float $$1, final CallbackInfoReturnable cir) { + ResourceLocation $$2 = this.shadow$getCooldownGroup($$0); final ItemCooldowns_CooldownInstanceAccessor cooldown = (ItemCooldowns_CooldownInstanceAccessor) this.cooldowns.get($$0); if (cooldown != null && cooldown.accessor$endTime() == cooldown.accessor$startTime() - 1) { cir.setReturnValue(1.0F); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java index c4dd41280f8..b21875fe6fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java @@ -24,8 +24,11 @@ */ package org.spongepowered.common.mixin.core.world.item; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ServerItemCooldowns; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.CooldownTracker; import org.spongepowered.api.entity.living.player.server.ServerPlayer; @@ -50,20 +53,20 @@ public abstract class ServerItemCooldownsMixin extends ItemCooldownsMixin { // @formmater:off @Shadow @Final private net.minecraft.server.level.ServerPlayer player; - @Shadow protected abstract void shadow$onCooldownStarted(Item itemIn, int ticksIn); + @Shadow protected abstract void shadow$onCooldownStarted(ResourceLocation group, int ticksIn); // @formmater:on @Override - protected int impl$throwSetCooldownEvent(final ItemType type, final int ticks) { + protected int impl$throwSetCooldownEvent(final ResourceLocation group, final int ticks) { if (ticks == 0) { return 0; } - final Optional beforeCooldown = ((CooldownTracker) this).cooldown(type); + final Optional beforeCooldown = ((CooldownTracker) this).cooldown((ResourceKey) (Object)group); final CooldownEvent.Set event = SpongeEventFactory.createCooldownEventSet(PhaseTracker.getCauseStackManager().currentCause(), - SpongeTicks.ticksOrInfinite(ticks), SpongeTicks.ticksOrInfinite(ticks), type, (ServerPlayer) this.player, beforeCooldown); + SpongeTicks.ticksOrInfinite(ticks), SpongeTicks.ticksOrInfinite(ticks), (ResourceKey) (Object) group, (ServerPlayer) this.player, beforeCooldown); if (Sponge.eventManager().post(event)) { - this.shadow$onCooldownStarted((Item) type, beforeCooldown.map(x -> (int) x.ticks()).orElse(0)); + this.shadow$onCooldownStarted(group, beforeCooldown.map(x -> (int) x.ticks()).orElse(0)); return Constants.Sponge.Entity.Player.ITEM_COOLDOWN_CANCELLED; } else { return SpongeTicks.toSaturatedIntOrInfinite(event.newCooldown()); @@ -71,9 +74,9 @@ public abstract class ServerItemCooldownsMixin extends ItemCooldownsMixin { } @Override - protected void impl$throwEndCooldownEvent(final ItemType type) { + protected void impl$throwEndCooldownEvent(final ResourceLocation group) { final CooldownEvent.End event = SpongeEventFactory.createCooldownEventEnd(PhaseTracker.getCauseStackManager().currentCause(), - type, (ServerPlayer) this.player); + (ResourceKey) (Object) group, (ServerPlayer) this.player); Sponge.eventManager().post(event); } diff --git a/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java index 29dfbfa6ae1..a2785f03f9b 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java @@ -169,6 +169,7 @@ private void onRegisterCommand(final RegisterCommandEvent final Parameter.Value potionEffectParameter = Parameter.registryElement(TypeToken.get(PotionEffectType.class), RegistryTypes.POTION_EFFECT_TYPE, "minecraft").key("potionEffectType").build(); final Parameter.Value itemTypeParameter = Parameter.registryElement(TypeToken.get(ItemType.class), RegistryTypes.ITEM_TYPE, "minecraft").key("itemType").build(); final Parameter.Value weatherTypeParameter = Parameter.registryElement(TypeToken.get(WeatherType.class), RegistryTypes.WEATHER_TYPE, "sponge").key("weatherType").build(); + final Parameter.Value resourceKeyParameter = Parameter.resourceKey().key("resourceKey").build(); event.register(this.plugin, Command.builder() .addParameter(entityParameter) @@ -250,11 +251,11 @@ private void onRegisterCommand(final RegisterCommandEvent }).build(), "offerInfiniteRangedAttackDelay"); event.register(this.plugin, Command.builder() - .addParameter(itemTypeParameter) + .addParameter(resourceKeyParameter) .executor(context -> { final ServerPlayer player = context.cause().first(ServerPlayer.class).get(); - final ItemType itemType = context.requireOne(itemTypeParameter); - if (player.cooldownTracker().setCooldown(itemType, Ticks.infinite())) { + final ResourceKey group = context.requireOne(resourceKeyParameter); + if (player.cooldownTracker().setCooldown(group, Ticks.infinite())) { context.sendMessage(Component.text("Applied!", NamedTextColor.GREEN)); return CommandResult.success(); } else { From 6eb5338071a0573d6bcb1bd162e8d9d15495c7d5 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 28 Aug 2024 13:47:21 +0200 Subject: [PATCH 078/586] fix server ticking --- .../common/mixin/core/server/MinecraftServerMixin.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index fdc015ccfdc..9f600459888 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -56,6 +56,7 @@ import org.spongepowered.api.service.permission.SubjectProxy; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -64,6 +65,7 @@ import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -228,8 +230,10 @@ public String getServerModName() { ci.cancel(); } - @ModifyConstant(method = "tickServer", constant = @Constant(intValue = 0, ordinal = 0)) - private int getSaveTickInterval(final int zero) { + @ModifyConstant(method = "tickServer", + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/server/MinecraftServer;ticksUntilAutosave:I", ordinal = 0)), + constant = @Constant(intValue = 0, ordinal = 0, expandZeroConditions = Constant.Condition.LESS_THAN_OR_EQUAL_TO_ZERO)) + private int impl$getSaveTickInterval(final int zero) { if (!this.shadow$isDedicatedServer()) { return zero; } else if (!this.shadow$isRunning()) { From 811851f837735e19d4c23e760b3a70ab57b66c14 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Thu, 29 Aug 2024 10:00:25 +0200 Subject: [PATCH 079/586] 24w35a --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c3b4e0178b4..28254be5348 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w34a +minecraftVersion=24w35a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 43aa9be40f0e59407d6131599bb56e0fb818f11d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Thu, 29 Aug 2024 11:26:41 +0200 Subject: [PATCH 080/586] fix registry usage --- .../spongepowered/common/SpongeCommon.java | 2 +- .../common/adventure/SpongeAdventure.java | 13 ++-- .../BlockStateSerializerDeserializer.java | 2 +- .../common/block/SpongeBlockSnapshot.java | 2 +- .../data/provider/entity/PaintingData.java | 2 +- .../item/stack/BlockTypeItemStackData.java | 2 +- .../item/stack/BookPagesItemStackData.java | 2 +- .../common/effect/util/ViewerPacketUtil.java | 2 +- .../damage/SpongeDamageSourceBuilder.java | 2 +- .../common/item/SpongeToolRuleFactory.java | 8 +-- .../SpongeRandomEnchantmentListBuilder.java | 6 +- .../recipe/ingredient/IngredientUtil.java | 2 +- .../network/packet/SpongePacketHandler.java | 2 +- .../registry/ProxiedRegistryAccess.java | 65 ------------------- .../common/registry/RegistryHolderLogic.java | 10 ++- .../loader/CommandRegistryLoader.java | 2 +- .../registry/loader/SpongeRegistryLoader.java | 2 +- .../biome/SpongeBiomeProviderFactory.java | 8 +-- .../world/biome/SpongeBiomeTemplate.java | 2 +- .../provider/SpongeMultiNoiseBiomeConfig.java | 4 +- .../SpongeChunkGeneratorFactory.java | 12 ++-- .../flat/SpongeFlatGeneratorConfig.java | 4 +- .../feature/SpongePlacedFeatureTemplate.java | 4 +- .../world/schematic/SchematicTranslator.java | 6 +- .../world/server/SpongeWorldManager.java | 6 +- .../world/server/SpongeWorldTemplate.java | 4 +- .../world/server/SpongeWorldTypeTemplate.java | 2 +- .../teleport/ConfigTeleportHelperFilter.java | 4 +- .../world/volume/VolumeStreamUtils.java | 2 +- ..._API.java => BlockBehaviourMixin_API.java} | 4 +- .../api/minecraft/block/BlockMixin_API.java | 3 +- .../core/MappedRegistryMixin_API.java | 6 +- .../server/MinecraftServerMixin_API.java | 2 +- .../world/level/LevelAccessorMixin_API.java | 2 +- .../world/level/LevelReaderMixin_API.java | 2 +- .../level/chunk/LevelChunkMixin_API.java | 4 +- .../core/server/level/ServerLevelMixin.java | 2 +- .../world/entity/EntityTypeMixin_Tracker.java | 9 +-- src/mixins/resources/mixins.sponge.api.json | 2 +- .../world/entity/EntityTypeMixin_Vanilla.java | 6 +- .../block/BlocksMixin_Vanilla_Tracker.java | 26 ++++---- 41 files changed, 95 insertions(+), 157 deletions(-) delete mode 100644 src/main/java/org/spongepowered/common/registry/ProxiedRegistryAccess.java rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/{AbstractBlockMixin_API.java => BlockBehaviourMixin_API.java} (94%) diff --git a/src/main/java/org/spongepowered/common/SpongeCommon.java b/src/main/java/org/spongepowered/common/SpongeCommon.java index 2789b1c36bc..7238fe6e054 100644 --- a/src/main/java/org/spongepowered/common/SpongeCommon.java +++ b/src/main/java/org/spongepowered/common/SpongeCommon.java @@ -101,7 +101,7 @@ public static RegistryAccess.Frozen vanillaRegistryAccess() { } public static Registry vanillaRegistry(ResourceKey> key) { - return SpongeCommon.vanillaRegistryAccess().registryOrThrow(key); + return SpongeCommon.vanillaRegistryAccess().lookupOrThrow(key); } public static ServerScheduler serverScheduler() { diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index ca69e960bd9..afd8a7a3f8c 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -548,7 +548,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv return new net.minecraft.network.chat.HoverEvent( Action.SHOW_ENTITY, new net.minecraft.network.chat.HoverEvent.EntityTooltipInfo( - entityTypeRegistry.get(SpongeAdventure.asVanilla(value.type())), + entityTypeRegistry.getValue(SpongeAdventure.asVanilla(value.type())), value.id(), SpongeAdventure.asVanillaNullable(value.name()) ) @@ -559,7 +559,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv return new net.minecraft.network.chat.HoverEvent( Action.SHOW_ITEM, HoverEvent_ItemStackInfoAccessor.invoker$new( - Holder.direct(itemRegistry.get(SpongeAdventure.asVanilla(value.item()))), + Holder.direct(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))), value.count(), SpongeAdventure.asVanilla(value.dataComponents()) ) @@ -731,12 +731,11 @@ public static DataComponentPatch asVanilla(final Map co return DataComponentPatch.EMPTY; } final DataComponentPatch.Builder builder = DataComponentPatch.builder(); - componentMap.forEach((key, value) -> { - final DataComponentType type = BuiltInRegistries.DATA_COMPONENT_TYPE.get(SpongeAdventure.asVanilla(key)); - if (type != null && value instanceof SpongeDataComponentValue dcv) { - builder.set(type, dcv.value.orElse(null)); + componentMap.forEach((key, value) -> BuiltInRegistries.DATA_COMPONENT_TYPE.getOptional(SpongeAdventure.asVanilla(key)).ifPresent(type -> { + if (value instanceof SpongeDataComponentValue dcv) { + builder.set((DataComponentType) type, dcv.value.orElse(null)); } - }); + })); return builder.build(); } diff --git a/src/main/java/org/spongepowered/common/block/BlockStateSerializerDeserializer.java b/src/main/java/org/spongepowered/common/block/BlockStateSerializerDeserializer.java index 90903c5dad1..8e7d9204630 100644 --- a/src/main/java/org/spongepowered/common/block/BlockStateSerializerDeserializer.java +++ b/src/main/java/org/spongepowered/common/block/BlockStateSerializerDeserializer.java @@ -43,7 +43,7 @@ public static String serialize(final BlockState state) { public static Optional deserialize(final String string) { final String state = Objects.requireNonNull(string, "Id cannot be null!").toLowerCase(Locale.ENGLISH); try { - final BlockStateParser.BlockResult result = BlockStateParser.parseForBlock(SpongeCommon.vanillaRegistry(Registries.BLOCK).asLookup(), state, true); + final BlockStateParser.BlockResult result = BlockStateParser.parseForBlock(SpongeCommon.vanillaRegistry(Registries.BLOCK), state, true); return Optional.of((BlockState) result.blockState()); } catch (final CommandSyntaxException e) { return Optional.empty(); diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index 0b0c48012fe..5fd5dee4143 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -275,7 +275,7 @@ public Optional createArchetype() { return Optional.of(SpongeBlockEntityArchetypeBuilder.pooled() .state(this.state()) - .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).get(ResourceLocation.tryParse(blockEntityId))) + .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).getOptional(ResourceLocation.tryParse(blockEntityId)).orElse(null)) .blockEntityData(NBTTranslator.INSTANCE.translate(compound)) .build()); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java index b5f7f253f77..97771ab0dfc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java @@ -53,7 +53,7 @@ public static void register(final DataProviderRegistrator registrator) { .setAnd((h, v) -> { if (!h.level().isClientSide) { final Holder oldArt = h.getVariant(); - var newArt = SpongeCommon.server().registryAccess().registryOrThrow(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); + var newArt = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); h.setVariant(newArt); ((HangingEntityAccessor) h).invoker$setDirection(h.getDirection()); if (!h.survives()) { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java index 5ed5a6769a5..18306b9294b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java @@ -79,7 +79,7 @@ private static boolean set(final ItemStack stack, final DataComponentType value if (value.isEmpty()) { return BookPagesItemStackData.delete(holder, component); } - final var registry = SpongeCommon.server().registryAccess().registryOrThrow(Registries.ENCHANTMENT); + final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); holder.update(component, ItemEnchantments.EMPTY, ench -> { final ItemEnchantments.Mutable mutable = new ItemEnchantments.Mutable(ench); mutable.keySet().clear(); diff --git a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java index 96a9911c73c..a8cfbed2216 100644 --- a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java +++ b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java @@ -109,7 +109,7 @@ public static ClientboundStopSoundPacket stopSound(final SoundStop stop) { public static ClientboundLevelEventPacket playMusicDisc(final int x, final int y, final int z, final MusicDisc musicDisc, final RegistryAccess registryAccess) { Objects.requireNonNull(musicDisc, "musicDisc"); - final int songId = registryAccess.registryOrThrow(Registries.JUKEBOX_SONG).getId((JukeboxSong) (Object) musicDisc); + final int songId = registryAccess.lookupOrThrow(Registries.JUKEBOX_SONG).getId((JukeboxSong) (Object) musicDisc); return new ClientboundLevelEventPacket(1010, new BlockPos(x, y, z), songId, false); } diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java index 6e3b1bb45ce..c2141f4b563 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java @@ -63,7 +63,7 @@ public DamageSource build() throws IllegalStateException { @Override public DamageSource.Builder type(final DamageType damageType) { - final var registry = SpongeCommon.server().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE); + final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.DAMAGE_TYPE); this.damageType = registry.wrapAsHolder((net.minecraft.world.damagesource.DamageType) (Object) damageType); return this; } diff --git a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java index 3e7cee1cab6..5ce79c4d06f 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java +++ b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java @@ -50,7 +50,7 @@ public ToolRule minesAndDrops(final List blocks, final double speed) @Override public ToolRule minesAndDrops(final Tag blockTypeTag, final double speed) { final var tag = (TagKey) (Object) blockTypeTag; - final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.minesAndDrops(holderSet, (float) speed); } @@ -64,7 +64,7 @@ public ToolRule deniesDrops(final List blocks) { @Override public ToolRule deniesDrops(final Tag blockTypeTag) { final var tag = (TagKey) (Object) blockTypeTag; - final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.deniesDrops(holderSet); } @@ -77,7 +77,7 @@ public ToolRule overrideSpeed(final List blocks, final double speed) @Override public ToolRule overrideSpeed(final Tag blockTypeTag, final double speed) { final var tag = (TagKey) (Object) blockTypeTag; - final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.overrideSpeed(holderSet, (float) speed); } @@ -92,7 +92,7 @@ public ToolRule forBlocks(final List blocks, @Nullable final Double s public ToolRule forTag(final Tag blockTypeTag, @Nullable final Double speed, @Nullable final Boolean drops) { // See Tool#forTag final var tag = (TagKey) (Object) blockTypeTag; - final var holderSet = BuiltInRegistries.BLOCK.getTag(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) new Tool.Rule(holderSet, Optional.ofNullable(speed).map(Double::floatValue), Optional.ofNullable(drops)); } } diff --git a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java index 1c8c25e8881..7c2699c0549 100644 --- a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java +++ b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java @@ -93,8 +93,8 @@ public List build() throws IllegalStateException { if (this.pool == null || this.pool.isEmpty()) { Objects.requireNonNull(this.item, "The item cannot be null"); this.randomSource.setSeed(this.seed + this.option); - final var registry = SpongeCommon.server().registryAccess().registryOrThrow(Registries.ENCHANTMENT); - var stream = registry.holders().map($$0x -> (Holder)$$0x); + final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); + var stream = registry.listElements().map($$0x -> (Holder)$$0x); enchantments = EnchantmentHelper.selectEnchantment(this.randomSource, ItemStackUtil.toNative(this.item), this.level, stream); } else { this.randomSource.setSeed(this.seed + this.option); @@ -139,7 +139,7 @@ public static List fromNative(final List list) } public static List toNative(final List list) { - final var registry = SpongeCommon.server().registryAccess().registryOrThrow(Registries.ENCHANTMENT); + final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); return list.stream().map(ench -> { var mcEnch = registry.wrapAsHolder((net.minecraft.world.item.enchantment.Enchantment) (Object) ench.type()); return new EnchantmentInstance(mcEnch, ench.level()); diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java index d10e3386b81..4bea6f57398 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java @@ -62,7 +62,7 @@ public static org.spongepowered.api.item.recipe.crafting.Ingredient of(ItemType. public static org.spongepowered.api.item.recipe.crafting.@Nullable Ingredient of(ResourceKey tagKey) { final TagKey key = TagKey.create(Registries.ITEM, (ResourceLocation) (Object) tagKey); - var holderset = BuiltInRegistries.ITEM.getTag(key).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + var holderset = BuiltInRegistries.ITEM.get(key).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return IngredientUtil.fromNative(Ingredient.of(holderset)); } diff --git a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java index a77808af907..7c611271f66 100644 --- a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java +++ b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java @@ -99,7 +99,7 @@ public static void init(final SpongeChannelManager registry) { return; } - final DimensionType dimensionType = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).get(packet.dimensionLogic); + final DimensionType dimensionType = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(packet.dimensionLogic); ((ClientLevelAccessor) world).accessor$effects(DimensionSpecialEffects.forType(dimensionType)); } ); diff --git a/src/main/java/org/spongepowered/common/registry/ProxiedRegistryAccess.java b/src/main/java/org/spongepowered/common/registry/ProxiedRegistryAccess.java deleted file mode 100644 index f37c2ef7ac5..00000000000 --- a/src/main/java/org/spongepowered/common/registry/ProxiedRegistryAccess.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.registry; - -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.ResourceKey; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -public final class ProxiedRegistryAccess implements RegistryAccess { - - private final RegistryAccess access; - private final Map>, Registry> overrides; - - public ProxiedRegistryAccess(final RegistryAccess access, final Map>, Registry> overrides) { - this.access = access; - this.overrides = Map.copyOf(overrides); - } - - @Override - @SuppressWarnings("unchecked") - public Optional> registry(final ResourceKey> var1) { - final @Nullable Registry override = this.overrides.get(var1); - if (override != null) { - return Optional.of((Registry) override); - } - return this.access.registry(var1); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public Stream> registries() { - return Stream.concat( - this.access.registries().filter(entry -> !this.overrides.containsKey(entry.key())), - (Stream>) (Stream) this.overrides.entrySet().stream().map(entry -> new RegistryAccess.RegistryEntry(entry.getKey(), entry.getValue())) - ); - } - -} diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 5b1d397126f..2e48e15fb31 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -94,14 +94,12 @@ public void setRootMinecraftRegistry(final net.minecraft.core.Registry Registry registry(final RegistryType type) { - final net.minecraft.core.Registry> root = this.roots.get(Objects.requireNonNull(type, "type").root()); + final var root = this.roots.get(Objects.requireNonNull(type, "type").root()); if (root == null) { throw new ValueNotFoundException(String.format("No '%s' root registry has been defined", type.root())); } - final net.minecraft.core.Registry registry = root.get((ResourceLocation) (Object) type.location()); - if (registry == null) { - throw new ValueNotFoundException(String.format("No '%s' registry has been defined in root '%s'", type.location(), type.root())); - } + final var registry = root.getOptional((ResourceLocation) (Object) type.location()) + .orElseThrow(() -> new ValueNotFoundException(String.format("No '%s' registry has been defined in root '%s'", type.location(), type.root()))); return (Registry) registry; } @@ -161,7 +159,7 @@ public Registry createRegistry(final RegistryType type, final @Nullabl if (root == null) { throw new ValueNotFoundException(String.format("No '%s' root registry has been defined", type.root())); } - net.minecraft.core.Registry registry = root.get((ResourceLocation) (Object) type.location()); + var registry = root.getValue((ResourceLocation) (Object) type.location()); final boolean exists = registry != null; if (!replace && exists) { throw new DuplicateRegistrationException(String.format("Registry '%s' in root '%s' has already been defined", type.location(), type.root())); diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index 4b6f07a7b43..63d3a85e769 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -293,7 +293,7 @@ public static RegistryLoader> commandRegistrarType() { // Helper static ArgumentType argumentTypeFromKey(ResourceKey key, CommandBuildContext ctx) { - final ArgumentTypeInfo argumentTypeInfo = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.get((ResourceLocation) (Object) key); + final ArgumentTypeInfo argumentTypeInfo = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getValue((ResourceLocation) (Object) key); if (argumentTypeInfo instanceof SingletonArgumentInfo s) { return s.unpack(null).instantiate(ctx); } diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index de3bfb4931a..54cc7107c21 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -581,7 +581,7 @@ public static RegistryLoader noiseConfig() { } public static RegistryLoader flatGeneratorConfig(RegistryAccess registryAccess) { - final Registry registry = registryAccess.registryOrThrow(Registries.FLAT_LEVEL_GENERATOR_PRESET); + final Registry registry = registryAccess.lookupOrThrow(Registries.FLAT_LEVEL_GENERATOR_PRESET); return RegistryLoader.of(l -> { for (final var entry : registry.entrySet()) { l.add(RegistryKey.of(RegistryTypes.FLAT_GENERATOR_CONFIG, (ResourceKey) (Object) entry.getKey().location()), () -> (FlatGeneratorConfig) entry.getValue().settings()); diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java index 44d1b9fdcd8..5e41f562610 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java @@ -61,7 +61,7 @@ public final class SpongeBiomeProviderFactory implements BiomeProvider.Factory { @Override public ConfigurableBiomeProvider overworld() { final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); return (ConfigurableBiomeProvider) MultiNoiseBiomeSource.createFromPreset(holder); } @@ -77,7 +77,7 @@ public ConfigurableBiomeProvider multiNoise(final MultiNo @Override public ConfigurableBiomeProvider nether() { final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); return (ConfigurableBiomeProvider) MultiNoiseBiomeSource.createFromPreset(holder); } @@ -94,7 +94,7 @@ public ConfigurableBiomeProvider endStyle(final EndStyleBio @Override public ConfigurableBiomeProvider end() { - return (ConfigurableBiomeProvider) TheEndBiomeSource.create(this.registry().asLookup()); + return (ConfigurableBiomeProvider) TheEndBiomeSource.create(this.registry()); } @Override @@ -114,6 +114,6 @@ private Registry registry() { } private Holder biomeHolder(final RegistryReference biome) { - return this.registry().getHolderOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) biome.location())); + return this.registry().getOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) biome.location())); } } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java index b7af593c2b2..9849bc7e832 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java @@ -210,7 +210,7 @@ protected BiomeTemplate build0() { final Registry placedFeatureRegistry = SpongeCommon.vanillaRegistry(Registries.PLACED_FEATURE); final Registry> configuredWorldCarverRegistry = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_CARVER); - final BiomeGenerationSettings.Builder generationBuilder = new BiomeGenerationSettings.Builder(placedFeatureRegistry.asLookup(), configuredWorldCarverRegistry.asLookup()); + final BiomeGenerationSettings.Builder generationBuilder = new BiomeGenerationSettings.Builder(placedFeatureRegistry, configuredWorldCarverRegistry); features.forEach((step, list) -> list.forEach(feature -> generationBuilder.addFeature((GenerationStep.Decoration) (Object) step, Holder.direct((net.minecraft.world.level.levelgen.placement.PlacedFeature) (Object) feature)))); carvers.forEach((carver) -> generationBuilder.addCarver(Holder.direct((ConfiguredWorldCarver) (Object) carver))); diff --git a/src/main/java/org/spongepowered/common/world/biome/provider/SpongeMultiNoiseBiomeConfig.java b/src/main/java/org/spongepowered/common/world/biome/provider/SpongeMultiNoiseBiomeConfig.java index 8ce6d49e842..8d6a39836ad 100644 --- a/src/main/java/org/spongepowered/common/world/biome/provider/SpongeMultiNoiseBiomeConfig.java +++ b/src/main/java/org/spongepowered/common/world/biome/provider/SpongeMultiNoiseBiomeConfig.java @@ -131,7 +131,7 @@ public static final class FactoryImpl implements Factory { @Override public MultiNoiseBiomeConfig nether() { final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); final var biomeSource = (MultiNoiseBiomeSourceAccessor) MultiNoiseBiomeSource.createFromPreset(holder); return new BuilderImpl().addMcBiomes(biomeSource.accessor$parameters()).build(); } @@ -139,7 +139,7 @@ public MultiNoiseBiomeConfig nether() { @Override public MultiNoiseBiomeConfig overworld() { final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); final var biomeSource = (MultiNoiseBiomeSourceAccessor) MultiNoiseBiomeSource.createFromPreset(holder); return new BuilderImpl().addMcBiomes(biomeSource.accessor$parameters()).build(); } diff --git a/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java b/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java index 81c290117ee..9c52d42e4b0 100644 --- a/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java @@ -72,26 +72,26 @@ public ConfigurableChunkGenerator noise(final BiomeProvide public ConfigurableChunkGenerator overworld() { var noiseGeneratorSettingsRegistry = SpongeCommon.vanillaRegistry(Registries.NOISE_SETTINGS); final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.OVERWORLD); final var biomeSource = MultiNoiseBiomeSource.createFromPreset(holder); - return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getHolderOrThrow(NoiseGeneratorSettings.OVERWORLD)); + return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.OVERWORLD)); } @Override public ConfigurableChunkGenerator theNether() { var noiseGeneratorSettingsRegistry = SpongeCommon.vanillaRegistry(Registries.NOISE_SETTINGS); final var registry = SpongeCommon.vanillaRegistry(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST); - final var holder = registry.getHolderOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); + final var holder = registry.getOrThrow(MultiNoiseBiomeSourceParameterLists.NETHER); final var biomeSource = MultiNoiseBiomeSource.createFromPreset(holder); - return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getHolderOrThrow(NoiseGeneratorSettings.NETHER)); + return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER)); } @Override public ConfigurableChunkGenerator theEnd() { var biomeRegistry = SpongeCommon.vanillaRegistry(Registries.BIOME); var noiseGeneratorSettingsRegistry = SpongeCommon.vanillaRegistry(Registries.NOISE_SETTINGS); - var biomeSource = TheEndBiomeSource.create(biomeRegistry.asLookup()); - return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getHolderOrThrow(NoiseGeneratorSettings.END)); + var biomeSource = TheEndBiomeSource.create(biomeRegistry); + return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)); } @Override diff --git a/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java b/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java index 0581d934635..40eb67f8158 100644 --- a/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java +++ b/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java @@ -138,10 +138,10 @@ public FlatGeneratorConfig.Builder from(final FlatGeneratorConfig value) { throw new IllegalStateException("Flat generation requires at least 1 Layer!"); } final Registry biomeRegistry = SpongeCommon.vanillaRegistry(Registries.BIOME); - final HolderLookup.RegistryLookup placedFeatureRegistryLookup = SpongeCommon.vanillaRegistry(Registries.PLACED_FEATURE).asLookup(); + final HolderLookup.RegistryLookup placedFeatureRegistryLookup = SpongeCommon.vanillaRegistry(Registries.PLACED_FEATURE); final Holder.Reference biome = - biomeRegistry.asLookup().getOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) this.biome.location())); + biomeRegistry.getOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) this.biome.location())); return (FlatGeneratorConfig) FlatLevelGeneratorSettingsAccessor.invoker$new( this.structureSets == null ? Optional.empty() : Optional.of(HolderSet.direct((Function) Holder::direct, this.structureSets)), (List) (Object) this.layers, diff --git a/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java b/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java index 637c7386973..77a0b06ab0c 100644 --- a/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java +++ b/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java @@ -131,7 +131,7 @@ public Builder feature(final Feature feature) { if (key == null) { this.feature = Holder.direct((ConfiguredFeature) (Object) feature); } else { - this.feature = registry.getHolderOrThrow(net.minecraft.resources.ResourceKey.create(Registries.CONFIGURED_FEATURE, key)); + this.feature = registry.getOrThrow(net.minecraft.resources.ResourceKey.create(Registries.CONFIGURED_FEATURE, key)); } return this; } @@ -141,7 +141,7 @@ public Builder feature(final FeatureTemplate feature) { final Registry> registry = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE); final net.minecraft.resources.ResourceKey> key = net.minecraft.resources.ResourceKey.create(Registries.CONFIGURED_FEATURE, ((ResourceLocation) (Object) feature.key())); - this.feature = Holder.Reference.createStandAlone(registry.asLookup(), key); + this.feature = Holder.Reference.createStandAlone(registry, key); return this; } diff --git a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java index d3c32a85a77..54b41bbb76d 100644 --- a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java +++ b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java @@ -327,7 +327,7 @@ private static void deserializeBiomeContainer( .orElseThrow(() -> new InvalidDataException("Missing BiomePalette as required by the schematic spec")); final Set biomeKeys = biomeMap.keys(false); - final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().registryOrThrow(Registries.BIOME)); + final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BIOME)); biomePalette = new MutableBimapPalette<>( PaletteTypes.BIOME_PALETTE.get(), biomeRegistry, @@ -454,7 +454,7 @@ public DataView addTo(final Schematic schematic, final DataView data) { final Registry blockRegistry = VolumeStreamUtils.nativeToSpongeRegistry( - SpongeCommon.server().registryAccess().registryOrThrow(Registries.BLOCK)); + SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BLOCK)); SchematicTranslator.writePaletteToView( blockData, palette, blockRegistry, Constants.Sponge.Schematic.BLOCK_PALETTE, BlockState::type, @@ -506,7 +506,7 @@ public DataView addTo(final Schematic schematic, final DataView data) { // Should never reach here. } - final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().registryOrThrow(Registries.BIOME)); + final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BIOME)); SchematicTranslator.writePaletteToView( biomeContainer, biomePalette, biomeRegistry, Constants.Sponge.Schematic.BIOME_PALETTE, diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 536f459c49f..c5095887444 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -279,7 +279,7 @@ public CompletableFuture loadWorld(final ResourceKey key) { // First find a loaded level-stem / To load based on a datapack load using the WorldTemplate instead final net.minecraft.resources.ResourceKey rKey = net.minecraft.resources.ResourceKey.create(Registries.LEVEL_STEM, (ResourceLocation) (Object) key); - final LevelStem levelStem = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).get(rKey); + final LevelStem levelStem = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).getValue(rKey); if (levelStem != null) { return this.loadWorld0(registryKey, levelStem); } @@ -796,7 +796,7 @@ private PrimaryLevelData getOrCreateLevelData(@Nullable final Dynamic dynamic } private PrimaryLevelData loadLevelData(final RegistryAccess.Frozen access, final WorldDataConfiguration datapackConfig, final Dynamic dataTag) { - final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions(dataTag, datapackConfig, access.registryOrThrow(Registries.LEVEL_STEM), access); + final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions(dataTag, datapackConfig, access.lookupOrThrow(Registries.LEVEL_STEM), access); return (PrimaryLevelData) levelData.worldData(); } @@ -883,7 +883,7 @@ private ServerLevel prepareWorld(final ServerLevel world) { } } else if (levelData.worldGenOptions().generateBonusChest()) { final BlockPos pos = levelData.getSpawnPos(); - final ConfiguredFeature bonusChestFeature = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE).get(MiscOverworldFeatures.BONUS_CHEST); + final ConfiguredFeature bonusChestFeature = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE).getValue(MiscOverworldFeatures.BONUS_CHEST); bonusChestFeature.place(world, world.getChunkSource().getGenerator(), world.random, pos); } levelData.setInitialized(true); diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java index 96183174218..05a87b59d10 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java @@ -289,12 +289,12 @@ protected WorldTemplate build0() { @NonNull private static Holder dimensionTypeHolder(final WorldType worldType) { - final Registry dimensionTypeRegistry = SpongeCommon.server().registryAccess().registryOrThrow(Registries.DIMENSION_TYPE); + final Registry dimensionTypeRegistry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); final ResourceLocation key = dimensionTypeRegistry.getKey((DimensionType) (Object) worldType); if (key == null) { return Holder.direct((DimensionType) (Object) worldType); } - return dimensionTypeRegistry.getHolderOrThrow(net.minecraft.resources.ResourceKey.create(Registries.DIMENSION_TYPE, key)); + return dimensionTypeRegistry.getOrThrow(net.minecraft.resources.ResourceKey.create(Registries.DIMENSION_TYPE, key)); } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java index b5ae4af961c..586e9d4380d 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java @@ -139,7 +139,7 @@ public Builder reset() { this.data = DataManipulator.mutableOf(); this.key = null; this.pack = DataPacks.WORLD_TYPE; - final DimensionType defaultOverworld = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).get(BuiltinDimensionTypes.OVERWORLD); + final DimensionType defaultOverworld = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(BuiltinDimensionTypes.OVERWORLD); this.fromValue((WorldType) (Object) defaultOverworld); return this; } diff --git a/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java b/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java index 8349954ede6..ee6f96040e5 100644 --- a/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java +++ b/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java @@ -66,7 +66,7 @@ private static void updateCacheIfNecessary() { final TeleportHelperCategory teleportHelperCat = SpongeConfigs.getCommon().get().teleportHelper; ConfigTeleportHelperFilter.floorBlockTypes = teleportHelperCat.unsafeFloorBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> (BlockType) blockRegistry.get((ResourceLocation) (Object) x)) + .map(x -> (BlockType) blockRegistry.getValue((ResourceLocation) (Object) x)) .filter(Objects::nonNull) .collect(Collectors.toList()); @@ -79,7 +79,7 @@ private static void updateCacheIfNecessary() { ConfigTeleportHelperFilter.bodyBlockTypes = teleportHelperCat.unsafeBlockBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> (BlockType) blockRegistry.get((ResourceLocation) (Object) x)) + .map(x -> (BlockType) blockRegistry.getValue((ResourceLocation) (Object) x)) .filter(Objects::nonNull) .collect(Collectors.toList()); diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index c3c769f502d..e76db24809d 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -509,7 +509,7 @@ public static > VolumeStream biomeRegistry = reader.registryAccess().registryOrThrow(Registries.BIOME); + final Registry biomeRegistry = reader.registryAccess().lookupOrThrow(Registries.BIOME); backingVolume = new ObjectArrayMutableBiomeBuffer(min, size, VolumeStreamUtils.nativeToSpongeRegistry(biomeRegistry)); } else { backingVolume = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/AbstractBlockMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockBehaviourMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/AbstractBlockMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockBehaviourMixin_API.java index 9de7530be58..d1282ec8124 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/AbstractBlockMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockBehaviourMixin_API.java @@ -35,12 +35,14 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(value = BlockBehaviour.class) -public abstract class AbstractBlockMixin_API implements BlockType { +public abstract class BlockBehaviourMixin_API implements BlockType { // @formatter:off @Shadow @Final @org.spongepowered.asm.mixin.Mutable protected boolean isRandomlyTicking; @Shadow public abstract Item shadow$asItem(); @Shadow @Final protected SoundType soundType; + @Shadow public abstract String shadow$getDescriptionId(); + // @formatter:on @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java index 3ad68ef92b5..a308240cd85 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java @@ -51,13 +51,12 @@ import java.util.stream.Collectors; @Mixin(value = Block.class, priority = 999) -public abstract class BlockMixin_API extends AbstractBlockMixin_API implements SpongeImmutableDataHolder { +public abstract class BlockMixin_API extends BlockBehaviourMixin_API implements SpongeImmutableDataHolder { // @formatter:off @Shadow @Final protected StateDefinition stateDefinition; @Shadow @Final private Holder.Reference builtInRegistryHolder; - @Shadow public abstract String shadow$getDescriptionId(); @Shadow public abstract net.minecraft.world.level.block.state.BlockState shadow$defaultBlockState(); // @formatter:on diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java index d2702d2cdde..b1ff4f5c63e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java @@ -58,7 +58,7 @@ public abstract class MappedRegistryMixin_API implements Registry { @Shadow public abstract Holder.Reference shadow$register(final net.minecraft.resources.ResourceKey $$0, final T $$1, final RegistrationInfo $$2); @Shadow public abstract net.minecraft.resources.ResourceKey> shadow$key(); - @Shadow @Nullable public abstract T shadow$get(@Nullable ResourceLocation var1); + @Shadow @Nullable public abstract T shadow$getValue(@Nullable ResourceLocation var1); private ResourceLocation impl$getKey(final T value) { return ((net.minecraft.core.Registry) this).getKey(value); @@ -69,7 +69,7 @@ public abstract class MappedRegistryMixin_API implements Registry { } private Optional> impl$getTag(TagKey var1) { - return ((net.minecraft.core.Registry) this).getTag(var1); + return ((net.minecraft.core.Registry) this).get(var1); } private Stream> impl$getTagNames() { @@ -114,7 +114,7 @@ public Optional findValue(final ResourceKey key) { @Override public V value(final ResourceKey key) { - final V value = (V) this.shadow$get((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + final V value = (V) this.shadow$getValue((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); if (value != null) { return value; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index a942424b138..513fa1cd3bd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -285,7 +285,7 @@ public WorldGenerationConfig worldGenerationConfig() { final WorldData overworldData = this.shadow$getWorldData(); final WorldGenSettings settings = new WorldGenSettings(overworldData.worldGenOptions(), - new WorldDimensions(this.registryAccess().registryOrThrow(Registries.LEVEL_STEM))); + new WorldDimensions(this.registryAccess().lookupOrThrow(Registries.LEVEL_STEM))); return (WorldGenerationConfig) (Object) settings; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java index 8fbcb34e6c5..7e88eb2b746 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java @@ -82,7 +82,7 @@ default Palette blockPalette( return PaletteWrapper.of( PaletteTypes.BLOCK_STATE_PALETTE.get(), Block.BLOCK_STATE_REGISTRY, - (org.spongepowered.api.registry.Registry) ((LevelAccessor) (Object) this).registryAccess().registryOrThrow(Registries.BLOCK) + (org.spongepowered.api.registry.Registry) ((LevelAccessor) (Object) this).registryAccess().lookupOrThrow(Registries.BLOCK) ); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java index 236f5c76662..05edacf69d2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java @@ -89,7 +89,7 @@ default Palette blockPalette() { return PaletteWrapper.of( PaletteTypes.BLOCK_STATE_PALETTE.get(), Block.BLOCK_STATE_REGISTRY, - (Registry) this.shadow$registryAccess().registryOrThrow(Registries.BLOCK) + (Registry) this.shadow$registryAccess().lookupOrThrow(Registries.BLOCK) ); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index 67380a288bc..cbd945278b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -129,7 +129,7 @@ public Palette blockPalette() { return PaletteWrapper.of( PaletteTypes.BLOCK_STATE_PALETTE.get(), Block.BLOCK_STATE_REGISTRY, - (org.spongepowered.api.registry.Registry) this.level.registryAccess().registry(Registries.BLOCK).get() + (org.spongepowered.api.registry.Registry) this.level.registryAccess().lookupOrThrow(Registries.BLOCK) ); } @@ -339,7 +339,7 @@ public VolumeStream biomeStream(final Vector3i min, final Vec final Vector3i size = max.sub(min).add(1, 1 ,1); final @MonotonicNonNull ObjectArrayMutableBiomeBuffer backingVolume; if (shouldCarbonCopy) { - final Registry biomeRegistry = this.level.registryAccess().registryOrThrow(Registries.BIOME); + final Registry biomeRegistry = this.level.registryAccess().lookupOrThrow(Registries.BIOME); backingVolume = new ObjectArrayMutableBiomeBuffer(min, size, VolumeStreamUtils.nativeToSpongeRegistry(biomeRegistry)); } else { backingVolume = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index d9f9e8ddc65..814729115da 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -554,7 +554,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, @Override public String toString() { - final Optional worldTypeKey = Optional.ofNullable(this.server.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE).getKey(this.shadow$dimensionType())).map(ResourceKey.class::cast); + final Optional worldTypeKey = Optional.ofNullable(this.server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE).getKey(this.shadow$dimensionType())).map(ResourceKey.class::cast); return new StringJoiner(",", ServerLevel.class.getSimpleName() + "[", "]") .add("key=" + this.shadow$dimension()) .add("worldType=" + worldTypeKey.map(ResourceKey::toString).orElse("inline")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java index 1c1a0fbc372..b4e1f3b7b37 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java @@ -26,6 +26,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.EntityType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -37,14 +38,14 @@ @Mixin(EntityType.class) public abstract class EntityTypeMixin_Tracker implements RegistryBackedTrackableBridge> { - @Redirect(method = "register", + @Redirect(method = "register(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/entity/EntityType$Builder;)Lnet/minecraft/world/entity/EntityType;", at = @At( value = "INVOKE", - target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;" + target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Lnet/minecraft/resources/ResourceKey;Ljava/lang/Object;)Ljava/lang/Object;" ) ) - private static Object impl$initializeTrackerState(final Registry registry, final String key, final Object toRegister) { - final Object registered = Registry.register(registry, key, toRegister); + private static V impl$initializeTrackerState(final Registry registry, final ResourceKey key, final V toRegister) { + final V registered = Registry.register(registry, key, toRegister); final RegistryBackedTrackableBridge> trackableBridge = (RegistryBackedTrackableBridge>) toRegister; trackableBridge.bridge$refreshTrackerStates(); diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 262a3987259..59e3ae2e275 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -18,7 +18,7 @@ "minecraft.advancements.CriterionTriggerInstanceMixin_API", "minecraft.advancements.CriterionTriggerMixin_API", "minecraft.advancements.DisplayInfoMixin_API", - "minecraft.block.AbstractBlockMixin_API", + "minecraft.block.BlockBehaviourMixin_API", "minecraft.block.BlockMixin_API", "minecraft.block.BlockSoundGroupMixin_API", "minecraft.commands.CommandSourceStackMixin_API", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java index 3ff3a9d9344..8b8eda0b2cc 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java @@ -26,6 +26,9 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import org.spongepowered.asm.mixin.Mixin; @@ -41,13 +44,14 @@ public abstract class EntityTypeMixin_Vanilla { @Inject(method = "", at = @At("TAIL")) private static void impl$createHumanType(CallbackInfo ci) { + final var loc = ResourceLocation.fromNamespaceAndPath("sponge", "human"); SpongeEntityTypes.HUMAN = Registry.register(BuiltInRegistries.ENTITY_TYPE, HumanEntity.KEY, EntityType.Builder.of(HumanEntity::new, MobCategory.MISC) .noSave() .sized(0.6F, 1.8F) .clientTrackingRange(Constants.Entity.Player.TRACKING_RANGE) .updateInterval(2) - .build("sponge:human") + .build(ResourceKey.create(Registries.ENTITY_TYPE, loc)) ); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/world/level/block/BlocksMixin_Vanilla_Tracker.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/world/level/block/BlocksMixin_Vanilla_Tracker.java index bee1fba6587..eaf69d196bd 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/world/level/block/BlocksMixin_Vanilla_Tracker.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/world/level/block/BlocksMixin_Vanilla_Tracker.java @@ -24,34 +24,34 @@ */ package org.spongepowered.vanilla.mixin.tracker.world.level.block; -import net.minecraft.resources.ResourceKey; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.storage.loot.LootTable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.accessor.world.level.block.state.BlockBehaviourAccessor; import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; @Mixin(Blocks.class) public abstract class BlocksMixin_Vanilla_Tracker { - @Redirect(method = "", + @Inject(method = "", at = @At( - value = "INVOKE", + value = "RETURN", target = "Lnet/minecraft/world/level/block/Block;getLootTable()Lnet/minecraft/resources/ResourceKey;" ) ) - private static ResourceKey impl$initializeTrackerState(final Block block) { - final boolean randomlyTicking = ((BlockBehaviourAccessor) block).invoker$isRandomlyTicking(block.defaultBlockState()); + private static void impl$initializeTrackerState(final CallbackInfo ci) { + for (final Block block : BuiltInRegistries.BLOCK) { + final boolean randomlyTicking = ((BlockBehaviourAccessor) block).invoker$isRandomlyTicking(block.defaultBlockState()); - // TODO Not the best check but the tracker options only matter during block ticks... - if (randomlyTicking) { - final var trackableBridge = (RegistryBackedTrackableBridge) block; - trackableBridge.bridge$refreshTrackerStates(); + // TODO Not the best check but the tracker options only matter during block ticks... + if (randomlyTicking) { + final var trackableBridge = (RegistryBackedTrackableBridge) block; + trackableBridge.bridge$refreshTrackerStates(); + } } - - return block.getLootTable(); } } From 119694b9773bc335f908e1e9285242b12f766a78 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Thu, 29 Aug 2024 12:44:13 +0200 Subject: [PATCH 081/586] fix UpdateLightSideEffect --- .../context/transaction/effect/UpdateLightSideEffect.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index dd71c3d1763..6e0ede228dd 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -73,9 +73,9 @@ public EffectResult processSideEffect( serverWorld.getProfiler().push("updateSkyLightSources"); // this.skyLightSources.update(this, $$6, $$3, $$8); final var pos = oldState.pos(); - final var x = pos.getX() % 15; - final var y = pos.getY(); - final var z = pos.getZ() % 15; + final var x = pos.getX() & 15; + final var y = pos.getY() & 15; + final var z = pos.getZ() & 15; final var levelChunk = serverWorld.getChunk(pos); levelChunk.getSkyLightSources().update(levelChunk, x, y, z); From 4b9d701cfd6614b9d1b4c03df9a7d7624311744b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 8 Sep 2024 16:32:24 -0700 Subject: [PATCH 082/586] feat: update to 24w36a --- gradle.properties | 2 +- gradle/verification-metadata.xml | 34 ++++++++++++ .../trialspawner/TrialSpawnerAccessor.java | 5 +- .../entity/TrialSpawnerDataProvider.java | 9 ++-- .../item/stack/ArmorItemStackData.java | 52 +++++++++++-------- .../lens/impl/slot/EquipmentSlotLens.java | 6 +-- .../loader/VanillaRegistryLoader.java | 11 ++++ .../world/entity/EntityMixin_API.java | 8 +-- .../entity/vehicle/Boat_TypeMixin_API.java | 6 ++- .../world/item/ArmorMaterialMixin_API.java | 15 +++--- .../world/level/ServerExplosionMixin_API.java | 3 +- .../core/server/MinecraftServerMixin.java | 2 +- .../server/commands/TeleportCommandMixin.java | 19 ++++--- .../core/server/level/ServerPlayerMixin.java | 37 ++++++++----- .../ServerGamePacketListenerImplMixin.java | 23 +++++--- .../mixin/core/world/entity/EntityMixin.java | 4 +- .../world/entity/PortalProcessorMixin.java | 10 ++-- .../world/level/ServerExplosionMixin.java | 3 +- .../level/block/EndPortalBlockMixin.java | 2 +- .../level/chunk/storage/IOWorkerMixin.java | 19 ++++--- .../SpreadPlayersCommandMixin_Vanilla.java | 4 +- 21 files changed, 182 insertions(+), 92 deletions(-) diff --git a/gradle.properties b/gradle.properties index 28254be5348..72f2fbf1a5a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w35a +minecraftVersion=24w36a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e897213b226..7d9c9c94e30 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -548,6 +548,14 @@ + + + + + + + + @@ -571,6 +579,11 @@ + + + + + @@ -650,6 +663,14 @@ + + + + + + + + @@ -728,6 +749,11 @@ + + + + + @@ -2417,6 +2443,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java index 2b34f3284d2..82c6ff5adfa 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.accessor.world.level.block.entity.trialspawner; +import net.minecraft.core.Holder; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig; import org.spongepowered.asm.mixin.Mixin; @@ -33,6 +34,6 @@ @Mixin(TrialSpawner.class) public interface TrialSpawnerAccessor { - @Mutable @Accessor("normalConfig") void accessor$normalConfig(TrialSpawnerConfig normalConfig); - @Mutable @Accessor("ominousConfig") void accessor$ominousConfig(TrialSpawnerConfig ominousConfig); + @Mutable @Accessor("normalConfig") void accessor$normalConfig(Holder normalConfig); + @Mutable @Accessor("ominousConfig") void accessor$ominousConfig(Holder ominousConfig); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java index 2c8195bd761..1c383d849e4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.block.entity; +import net.minecraft.core.Holder; import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig; import org.spongepowered.api.data.Keys; @@ -68,8 +69,8 @@ public static void register(final DataProviderRegistrator registrator) { final var newOminiousConfig = new TrialSpawnerConfig(v.intValue(), ominousConfig.totalMobs(), ominousConfig.simultaneousMobs(), ominousConfig.totalMobsAddedPerPlayer(), ominousConfig.simultaneousMobsAddedPerPlayer(), ominousConfig.ticksBetweenSpawn(), ominousConfig.spawnPotentialsDefinition(), ominousConfig.lootTablesToEject(), ominousConfig.itemsToDropWhenOminous()); final var accessor = (TrialSpawnerAccessor) (Object) h.getTrialSpawner(); - accessor.accessor$normalConfig(newNormalConfig); - accessor.accessor$ominousConfig(newOminiousConfig); + accessor.accessor$normalConfig(Holder.direct(newNormalConfig)); + accessor.accessor$ominousConfig(Holder.direct(newOminiousConfig)); }) // TODO totalMobs // TODO simultaneousMobs @@ -91,8 +92,8 @@ public static void register(final DataProviderRegistrator registrator) { final var newOminiousConfig = new TrialSpawnerConfig(ominousConfig.spawnRange(), ominousConfig.totalMobs(), ominousConfig.simultaneousMobs(), ominousConfig.totalMobsAddedPerPlayer(), ominousConfig.simultaneousMobsAddedPerPlayer(), ominousConfig.ticksBetweenSpawn(), spawnPotentials, ominousConfig.lootTablesToEject(), ominousConfig.itemsToDropWhenOminous()); final var accessor = (TrialSpawnerAccessor) (Object) h.getTrialSpawner(); - accessor.accessor$normalConfig(newNormalConfig); - accessor.accessor$ominousConfig(newOminiousConfig); + accessor.accessor$normalConfig(Holder.direct(newNormalConfig)); + accessor.accessor$ominousConfig(Holder.direct(newOminiousConfig)); }); // TODO lootTablesToEject // TODO itemsToDropWhenOminous diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index 58f68dec195..fb77ce9b733 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -24,11 +24,18 @@ */ package org.spongepowered.common.data.provider.item.stack; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemAttributeModifiers; +import net.minecraft.world.item.equipment.Equippable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.type.ArmorMaterial; -import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; +import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.api.registry.RegistryEntry; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class ArmorItemStackData { @@ -42,37 +49,38 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.ARMOR_MATERIAL) .get(h -> { - if (h.getItem() instanceof ArmorItem armorItem) { - return (ArmorMaterial) (Object) armorItem.getMaterial().value(); + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; } - return null; + return equippable.model() + .map(rl -> (ResourceKey) (Object) rl) + .flatMap(rk -> RegistryTypes.ARMOR_MATERIAL.get().findEntry(rk)) + .map(RegistryEntry::value) + .orElse(null); }) .supports(h -> h.getItem() instanceof ArmorItem) .create(Keys.DAMAGE_ABSORPTION) .get(h -> { - if (h.getItem() instanceof ArmorItem armorItem) { - return (double) armorItem.getDefense(); + final @Nullable ItemAttributeModifiers modifiersContainer = h.get(DataComponents.ATTRIBUTE_MODIFIERS); + if (modifiersContainer == null) { + return null; } - return null; + return modifiersContainer.modifiers().stream() + .filter(e1 -> e1.attribute() == Attributes.ARMOR) + .findFirst() + .map(e -> e.modifier().amount()) + .orElse(null); }) .supports(h -> h.getItem() instanceof ArmorItem) .create(Keys.EQUIPMENT_TYPE) .get(h -> { - if (h.getItem() instanceof ArmorItem armorItem) { - switch (armorItem.getEquipmentSlot()) { - case FEET: - return EquipmentTypes.FEET.get(); - case LEGS: - return EquipmentTypes.LEGS.get(); - case CHEST: - return EquipmentTypes.CHEST.get(); - case HEAD: - return EquipmentTypes.HEAD.get(); - default: - break; - } + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; } - return null; + + return (EquipmentType) (Object) equippable.slot(); }) .supports(h -> h.getItem() instanceof ArmorItem); } diff --git a/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/EquipmentSlotLens.java b/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/EquipmentSlotLens.java index 0af32460cec..0e9e9eb737b 100644 --- a/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/EquipmentSlotLens.java +++ b/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/EquipmentSlotLens.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.inventory.lens.impl.slot; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.Equipable; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.equipment.EquipmentType; @@ -52,8 +52,8 @@ private static FilteringSlotLens.ItemStackFilter equipmentTypeFilter(EquipmentTy if (item.isEmpty()) { return true; } - final var equipable = Equipable.get(ItemStackUtil.toNative(item)); - final var itemSlotType = equipable != null ? equipable.getEquipmentSlot() : EquipmentSlot.MAINHAND; + final var equippable = ItemStackUtil.toNative(item).get(DataComponents.EQUIPPABLE); + final var itemSlotType = equippable != null ? equippable.slot() : EquipmentSlot.MAINHAND; return itemSlotType == (Object) type; }; } diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 91b6be54a13..7fbcc93da10 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -142,6 +142,17 @@ private void loadInstanceRegistries() { map.put(EnderDragonPhase.HOVERING, "hover"); }, phase -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, ((EnderDragonPhaseAccessor) phase).accessor$name())); this.holder.createRegistry(RegistryTypes.FIREWORK_SHAPE, VanillaRegistryLoader.fireworkShape()); +// final var materials = new HashMap(); +// materials.put(ArmorMaterials.LEATHER, ArmorMaterials.LEATHER.modelId().toString()); +// materials.put(ArmorMaterials.CHAIN, ArmorMaterials.CHAIN.modelId().toString()); +// materials.put(ArmorMaterials.IRON, ArmorMaterials.IRON.modelId().toString()); +// materials.put(ArmorMaterials.GOLD, ArmorMaterials.GOLD.modelId().toString()); +// materials.put(ArmorMaterials.DIAMOND, ArmorMaterials.DIAMOND.modelId().toString()); +// materials.put(ArmorMaterials.TURTLE_SCUTE, ResourceKey.minecraft("turtle").toString()); +// materials.put(ArmorMaterials.NETHERITE, ArmorMaterials.NETHERITE.modelId().toString()); +// materials.put(ArmorMaterials.ARMADILLO_SCUTE, ArmorMaterials.ARMADILLO_SCUTE.modelId().toString()); +// +// this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); this.knownName(RegistryTypes.GAME_RULE, GameRulesAccessor.accessor$GAME_RULE_TYPES().keySet(), rule -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, rule.getId())); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index e08815a23a8..ed797b1ede1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -36,7 +36,8 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.entity.Relative; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; @@ -82,6 +83,7 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.Entity { // @formatter:off + @Shadow private Vec3 position; @Shadow private float yRot; @Shadow private float xRot; @Shadow @Final protected net.minecraft.util.RandomSource random; @@ -106,6 +108,7 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.En @Shadow public abstract Level shadow$level(); // @formatter:on + @Override public Source random() { return (Source) this.random; @@ -197,8 +200,7 @@ public void setRotation(final Vector3d rotation) { } if (((Entity) (Object) this) instanceof ServerPlayer && ((ServerPlayer) (Object) this).connection != null) { // Force an update, this also set the rotation in this entity - ((ServerPlayer) (Object) this).connection.teleport(this.position().x(), this.position().y(), - this.position().z(), (float) rotation.y(), (float) rotation.x(), EnumSet.noneOf(RelativeMovement.class)); + ((ServerPlayer) (Object) this).connection.teleport(new PositionMoveRotation(this.position, Vec3.ZERO, (float) rotation.y(), (float) rotation.x()), EnumSet.noneOf(Relative.class)); } else { // Let the entity tracker do its job, this just updates the variables this.shadow$setRot((float) rotation.y(), (float) rotation.x()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java index a21cd6e2815..77171d3854d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java @@ -25,6 +25,8 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.type.BoatType; @@ -36,11 +38,11 @@ public abstract class Boat_TypeMixin_API implements BoatType { // @formatter:off - @Shadow @Final private Block planks; + @Shadow @Final private Item planks; // @formatter:on @Override public BlockType representedBlock() { - return (BlockType) this.planks; + return (BlockType) ((BlockItem) this.planks).getBlock(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java index 19692eca8fa..144190b7a3b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ArmorMaterialMixin_API.java @@ -24,29 +24,30 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item; -import net.minecraft.world.item.ItemStack; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; import org.spongepowered.api.data.type.ArmorMaterial; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.function.Predicate; -@Mixin(net.minecraft.world.item.ArmorMaterial.class) +@Mixin(net.minecraft.world.item.equipment.ArmorMaterial.class) @Implements(@Interface(iface = ArmorMaterial.class, prefix = "armorMaterial$")) public abstract class ArmorMaterialMixin_API implements ArmorMaterial { // @formatter:off - @Shadow @Final private Predicate repairIngredient; - + @Shadow @Final private TagKey repairIngredient; // @formatter:on - @Override - public Predicate repairIngredient() { - return (spongeStack) -> this.repairIngredient.test(ItemStackUtil.toNative(spongeStack)); + @Unique + public Predicate armorMaterial$repairIngredient() { + return (spongeStack) -> ItemStackUtil.toNative(spongeStack).is(this.repairIngredient); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java index ffddf7f6d2e..ddf60b67eff 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/ServerExplosionMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; @@ -44,7 +45,7 @@ public abstract class ServerExplosionMixin_API implements Explosion { //@formatter:off @Shadow @Final private boolean fire; - @Shadow @Final private net.minecraft.world.level.Level level; + @Shadow @Final private ServerLevel level; @Shadow @Final private Entity source; @Shadow @Final private float radius; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 9f600459888..682ec494e10 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -129,7 +129,7 @@ public abstract class MinecraftServerMixin implements SpongeServer, MinecraftSer //MinecraftServer Executor to prevent changes in timings. @Override - protected @NonNull Runnable wrapRunnable(@NonNull Runnable runnable) { + public Runnable wrapRunnable(Runnable runnable) { return runnable; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index 89b417e9d52..55155b24cd4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -35,8 +35,10 @@ import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PathfinderMob; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.entity.Relative; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.CauseStackManager; @@ -68,7 +70,7 @@ public abstract class TeleportCommandMixin { @Overwrite // TODO check if this is still correct - check if we can get rid of the overwrite private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, - Set relativeList, float yaw, float pitch, TeleportCommand.@Nullable LookAt facing) { + Set relativeList, float yaw, float pitch, TeleportCommand.@Nullable LookAt facing) { double actualX = x; double actualY = y; @@ -112,18 +114,19 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, actualPitch = rotateEvent.isCancelled() ? entityIn.getXRot() : rotateEvent.toRotation().x(); } - if (entityIn instanceof ServerPlayer) { + if (entityIn instanceof ServerPlayer sp) { ChunkPos chunkpos = new ChunkPos(new BlockPos((int) actualX, (int) actualY, (int) actualZ)); worldIn.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, entityIn.getId()); entityIn.stopRiding(); - if (((ServerPlayer)entityIn).isSleeping()) { - ((ServerPlayer)entityIn).stopSleepInBed(true, true); + if (sp.isSleeping()) { + sp.stopSleepInBed(true, true); } - ((ServerPlayer)entityIn).connection.teleport(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch, relativeList); + sp.connection.teleport( + new PositionMoveRotation(new Vec3( actualX, actualY, actualZ), Vec3.ZERO, (float) actualYaw, (float) actualPitch), relativeList); } else { entityIn.moveTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch); } @@ -131,12 +134,12 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, entityIn.setYHeadRot((float) actualYaw); } } else { - if (entityIn instanceof ServerPlayer) { + if (entityIn instanceof ServerPlayer sp) { // To ensure mod code is caught, handling the world change for players happens in teleport // Teleport will create a frame but we want to ensure it'll be the command movement type // TODO check if this is still correct PhaseTracker.getCauseStackManager().addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - ((ServerPlayer) entityIn).teleportTo(worldIn, x, y, z, yaw, pitch, true); + sp.teleportTo(worldIn, x, y, z, relativeList, yaw, pitch, true); PhaseTracker.getCauseStackManager().removeContext(EventContextKeys.MOVEMENT_TYPE); } else { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 0a51739bf99..0f409f9d2f0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -62,6 +62,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.entity.Relative; import net.minecraft.world.entity.animal.AbstractFish; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -148,6 +150,7 @@ import org.spongepowered.common.world.border.PlayerOwnBorderListener; import org.spongepowered.math.vector.Vector3d; +import java.util.EnumSet; import java.util.HashSet; import java.util.Locale; import java.util.Objects; @@ -230,7 +233,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr } if (!isChangeOfWorld) { - this.connection.teleport(pos.x(), pos.y(), pos.z(), this.shadow$getYRot(), this.shadow$getXRot(), new HashSet<>()); + this.connection.teleport(new PositionMoveRotation(VecHelper.toVanillaVector3d(pos), Vec3.ZERO, this.shadow$getYRot(), this.shadow$getXRot()), new HashSet<>()); this.connection.resetPosition(); } else { this.bridge$changeDimension(new DimensionTransition(level, VecHelper.toVanillaVector3d(pos), thisPlayer.getKnownMovement(), @@ -401,7 +404,14 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr * @reason Redirect all teleports through {@link #bridge$changeDimension} to fire our move/rotate/teleport events */ @Overwrite - public void teleportTo(final ServerLevel world, final double x, final double y, final double z, final float yaw, final float pitch, final boolean setCamera) { + public boolean teleportTo(final ServerLevel world, + final double x, + final double y, + final double z, + Set relative, + final float yaw, + final float pitch, + final boolean setCamera) { if (setCamera) { this.shadow$setCamera((net.minecraft.server.level.ServerPlayer) (Object) this); } @@ -412,8 +422,8 @@ public void teleportTo(final ServerLevel world, final double x, final double y, } final var thisPlayer = (net.minecraft.server.level.ServerPlayer) (Object) this; - this.bridge$changeDimension(new DimensionTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, - e -> world.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, e.chunkPosition(), 1, thisPlayer.getId()))); + return this.bridge$changeDimension(new DimensionTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, + e -> world.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, e.chunkPosition(), 1, thisPlayer.getId()))) != null; } } @@ -450,7 +460,7 @@ public void teleportTo(final ServerLevel world, final double x, final double y, // Sponge End if (newLevel.dimension() == oldLevel.dimension()) { // actually no dimension change - this.connection.teleport(transition.pos().x, transition.pos().y, transition.pos().z, transition.yRot(), transition.xRot()); + this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); this.connection.resetPosition(); transition.postDimensionTransition().onTransition(thisPlayer); // TODO setYHeadRot after would rotate event result @@ -473,7 +483,7 @@ public void teleportTo(final ServerLevel world, final double x, final double y, oldLevel.getProfiler().push("placing"); thisPlayer.setServerLevel(newLevel); - this.connection.teleport(transition.pos().x, transition.pos().y, transition.pos().z, transition.yRot(), transition.xRot()); + this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); this.connection.resetPosition(); newLevel.addDuringTeleport(thisPlayer); oldLevel.getProfiler().pop(); @@ -522,7 +532,7 @@ public void teleportTo(final ServerLevel world, final double x, final double y, frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); } - final var originalDest = VecHelper.toVector3d(transition.pos()); + final var originalDest = VecHelper.toVector3d(transition.position()); final @Nullable Vector3d newDest; if (isDimensionChange) { @@ -533,10 +543,11 @@ public void teleportTo(final ServerLevel world, final double x, final double y, } if (preEvent.destinationWorld() != preEvent.originalDestinationWorld()) { transition = new DimensionTransition((ServerLevel) preEvent.destinationWorld(), - transition.pos(), - transition.speed(), + transition.position(), + transition.deltaMovement(), transition.yRot(), transition.xRot(), transition.missingRespawnBlock(), + EnumSet.noneOf(Relative.class), transition.postDimensionTransition()); } } @@ -560,9 +571,10 @@ public void teleportTo(final ServerLevel world, final double x, final double y, // if changed override the DimensionTransition transition = new DimensionTransition(transition.newLevel(), VecHelper.toVanillaVector3d(newDest), - transition.speed(), + transition.deltaMovement(), transition.yRot(), transition.xRot(), transition.missingRespawnBlock(), + EnumSet.noneOf(Relative.class), transition.postDimensionTransition()); } @@ -575,10 +587,11 @@ public void teleportTo(final ServerLevel world, final double x, final double y, } if (toRot != newToRot) { transition = new DimensionTransition(transition.newLevel(), - transition.pos(), - transition.speed(), + transition.position(), + transition.deltaMovement(), (float) newToRot.y(), (float) newToRot.x(), transition.missingRespawnBlock(), + EnumSet.noneOf(Relative.class), transition.postDimensionTransition()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index f2eeea9e38f..1762b453256 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -54,7 +54,8 @@ import net.minecraft.util.StringUtil; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.entity.Relative; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ClipContext; @@ -127,7 +128,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack @Shadow private double vehicleFirstGoodZ; @Shadow private int chatSpamTickCount; - @Shadow public abstract void shadow$teleport(double x, double y, double z, float yaw, float pitch, Set relativeArguments); + @Shadow public abstract void shadow$teleport(PositionMoveRotation pitch, Set relativeArguments); @Shadow protected abstract CompletableFuture> shadow$filterTextPacket(final List $$0); @Shadow protected abstract void shadow$performUnsignedChatCommand(final String $$0); @Shadow protected abstract void shadow$performSignedChatCommand(ServerboundChatCommandSignedPacket $$0, LastSeenMessages $$1); @@ -256,9 +257,13 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack this.player.absMoveTo(fromPosition.x(), fromPosition.y(), fromPosition.z()); this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); - this.shadow$teleport(fromPosition.x(), fromPosition.y(), fromPosition.z(), - (float) toRotation.y(), (float) toRotation.x(), - EnumSet.of(RelativeMovement.X_ROT, RelativeMovement.Y_ROT)); + this.shadow$teleport(new PositionMoveRotation( + VecHelper.toVanillaVector3d(fromPosition), + Vec3.ZERO, + (float) toRotation.y(), (float) toRotation.x() + ), + EnumSet.of(Relative.X_ROT, Relative.Y_ROT) + ); ci.cancel(); return; } @@ -272,9 +277,11 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack this.player.absMoveTo(originalToPosition.x(), originalToPosition.y(), originalToPosition.z()); this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); - this.shadow$teleport(toPosition.x(), toPosition.y(), toPosition.z(), - (float) toRotation.y(), (float) toRotation.x(), - EnumSet.allOf(RelativeMovement.class)); + this.shadow$teleport(new PositionMoveRotation( + VecHelper.toVanillaVector3d(toPosition), + Vec3.ZERO, + (float) toRotation.y(), (float) toRotation.x()), + EnumSet.allOf(Relative.class)); ci.cancel(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index d196ea014fb..4e7cf05aeba 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -525,8 +525,8 @@ public Entity changeDimension(final DimensionTransition transition) { this.shadow$removeAfterChangingDimensions(); } - newEntity.moveTo(transition.pos().x, transition.pos().y, transition.pos().z, transition.yRot(), newEntity.getXRot()); - newEntity.setDeltaMovement(transition.speed()); + newEntity.moveTo(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), newEntity.getXRot()); + newEntity.setDeltaMovement(transition.deltaMovement()); if (thisEntity != newEntity) { newLevel.addDuringTeleport(newEntity); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java index ba4e8190e87..4b86c61d707 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java @@ -29,6 +29,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.PortalProcessor; +import net.minecraft.world.entity.Relative; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Portal; @@ -52,6 +53,8 @@ import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; +import java.util.EnumSet; + @Mixin(PortalProcessor.class) public abstract class PortalProcessorMixin implements PortalProcessorBridge { // @formatter:off @@ -128,10 +131,10 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { spongEntity.position(), spongEntity.rotation(), (ServerWorld) transition.newLevel(), - VecHelper.toVector3d(transition.pos()), - VecHelper.toVector3d(transition.pos()), + VecHelper.toVector3d(transition.position()), + VecHelper.toVector3d(transition.position()), preWorldChangeEvent.destinationWorld(), // with modified preWorldChangeEvent destination world - VecHelper.toVector3d(transition.speed()), + VecHelper.toVector3d(transition.deltaMovement()), (PortalLogic) finalPortal); if (SpongeCommon.post(tpEvent)) { wrapperTransaction.markCancelled(); @@ -145,6 +148,7 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { (float) tpEvent.toRotation().x(), (float) tpEvent.toRotation().y(), transition.missingRespawnBlock(), + EnumSet.noneOf(Relative.class), transition.postDimensionTransition()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java index c642a2605e2..dcde1d3930a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java @@ -61,10 +61,9 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { // @formatter:off - @Shadow @Final private ExplosionDamageCalculator damageCalculator; @Shadow @Final private Map hitPlayers; @Shadow @Final private boolean fire; - @Shadow @Final private net.minecraft.world.level.Level level; + @Shadow @Final private ServerLevel level; @Shadow @Final private Entity source; @Shadow @Final private float radius; @Shadow @Final private Vec3 center; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java index 74e5aca88c8..5a7c0c28ba3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java @@ -67,7 +67,7 @@ public abstract class EndPortalBlockMixin implements PortalBlockBridge { if (entity instanceof ServerPlayer player) { var transition = player.findRespawnPositionAndUseSpawnBlock(false, DimensionTransition.DO_NOTHING); - return ServerLocation.of((ServerWorld) transition.newLevel(), VecHelper.toVector3d(transition.pos())); + return ServerLocation.of((ServerWorld) transition.newLevel(), VecHelper.toVector3d(transition.position())); } final var sharedSpawnPos = toLevel.getSharedSpawnPos(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java index 2d2109cd0b9..053438fdbe4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java @@ -31,8 +31,7 @@ import net.minecraft.nbt.visitors.CollectFields; import net.minecraft.nbt.visitors.FieldSelector; import net.minecraft.resources.ResourceKey; -import net.minecraft.util.thread.ProcessorMailbox; -import net.minecraft.util.thread.StrictQueue; +import net.minecraft.util.thread.PriorityConsecutiveExecutor; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.storage.IOWorker; @@ -45,6 +44,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; @@ -59,7 +59,6 @@ import org.spongepowered.math.vector.Vector3i; import java.util.BitSet; -import java.util.Map; import java.util.SequencedMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; @@ -72,7 +71,7 @@ public abstract class IOWorkerMixin implements IOWorkerBridge { @Shadow @Final private static Logger LOGGER; @Shadow @Final private AtomicBoolean shutdownRequested; - @Shadow @Final private ProcessorMailbox mailbox; + @Shadow @Final private PriorityConsecutiveExecutor consecutiveExecutor; @Shadow @Final private RegionFileStorage storage; @Shadow @Final private SequencedMap pendingWrites; @@ -164,16 +163,20 @@ private CompletableFuture createOldDataForRegion(final int x, final int }); } + @Unique private CompletableFuture impl$submitTaskCancellable(final Supplier> supplier) { - final CompletableFuture future = this.mailbox.askEither(processor -> new StrictQueue.IntRunnable(0, () -> { + final CompletableFuture future = this.consecutiveExecutor.scheduleWithResult(0, f -> { if (!this.shutdownRequested.get()) { - processor.tell(supplier.get()); + supplier.get() + .ifLeft(f::complete) + .ifRight(f::completeExceptionally); + f.complete(supplier.get().orThrow()); } else { - processor.tell(Either.right(SpongeUnloadedChunkException.INSTANCE)); //Sponge: Complete exceptionally if shutdown was requested + f.completeExceptionally(SpongeUnloadedChunkException.INSTANCE); //Sponge: Complete exceptionally if shutdown was requested } this.shadow$tellStorePending(); - })); + }); //Sponge start: Complete exceptionally if shutdown was requested if (this.shutdownRequested.get()) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java index 3e6bc293e66..f47673ed676 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java @@ -27,7 +27,7 @@ import net.minecraft.server.commands.SpreadPlayersCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.Relative; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.cause.entity.MovementTypes; @@ -44,7 +44,7 @@ public abstract class SpreadPlayersCommandMixin_Vanilla { @Redirect(method = "setPlayerPositions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) private static boolean vanilla$createCauseFrameForTeleport( final Entity instance, final ServerLevel level, final double x, final double y, - final double z, final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera) { + final double z, final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); From 4fb3a6b795d6fe1c6bba21cc6d29f7700d7b77c8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 11 Sep 2024 21:22:50 -0700 Subject: [PATCH 083/586] feat: update to 24w37a --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 19 ++++++++++++++ .../block/state/StateHolderAccessor.java | 3 ++- .../provider/entity/AreaEffectCloudData.java | 4 +-- .../data/provider/entity/ArrowData.java | 2 +- .../data/provider/entity/PotionData.java | 2 +- .../provider/item/stack/ItemStackData.java | 25 +++++++++++++++---- .../item/stack/PotionItemStackData.java | 12 ++++----- .../effect/UpdateLightSideEffect.java | 10 +++++--- .../minecraft/state/PropertyMixin_API.java | 3 ++- .../entity/vehicle/Boat_TypeMixin_API.java | 8 ------ .../core/server/level/ServerPlayerMixin.java | 11 +++++--- .../mixin/core/world/entity/EntityMixin.java | 11 +++++--- .../block/entity/LecternBlockEntityMixin.java | 5 ++-- 15 files changed, 79 insertions(+), 40 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 587166fe62e..b3b13e92bf8 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 587166fe62e139311793bbc07873fc761811643c +Subproject commit b3b13e92bf80ffb4761008d1c523bbe956ef9e9d diff --git a/gradle.properties b/gradle.properties index 72f2fbf1a5a..efebbd07d3b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w36a +minecraftVersion=24w37a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7d9c9c94e30..f6fe1436bdf 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1162,6 +1162,17 @@ + + + + + + + + + + + @@ -1184,6 +1195,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java index 8e1e4e05408..05380ef49fc 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java @@ -30,11 +30,12 @@ import org.spongepowered.common.UntransformedInvokerError; import java.util.Collection; +import java.util.List; @Mixin(StateHolder.class) public interface StateHolderAccessor { - @Invoker("findNextInCollection") static T invoker$findNextInCollection(final Collection collection, final T element) { + @Invoker("findNextInCollection") static T invoker$findNextInCollection(final List $$0, final T $$1) { throw new UntransformedInvokerError(); } } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java index a62aab53c6a..95ec7d9b635 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java @@ -50,7 +50,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> Color.ofRgb(((AreaEffectCloudAccessor) h).accessor$potionContents().getColor())) .set((h, v) -> { var contents = ((AreaEffectCloudAccessor) h).accessor$potionContents(); - h.setPotionContents(new PotionContents(contents.potion(), Optional.of(v.rgb()), contents.customEffects())); + h.setPotionContents(new PotionContents(contents.potion(), Optional.of(v.rgb()), contents.customEffects(), contents.customName())); }) .create(Keys.DURATION) .get(x -> new SpongeTicks(x.getDuration())) @@ -97,7 +97,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> PotionEffectUtil.copyAsPotionEffects(Streams.stream(h.accessor$potionContents().getAllEffects()).toList())) .set((h, v) -> { final PotionContents contents = h.accessor$potionContents(); - ((AreaEffectCloud) h).setPotionContents(new PotionContents(contents.potion(), contents.customColor(), PotionEffectUtil.copyAsEffectInstances(v))); + ((AreaEffectCloud) h).setPotionContents(new PotionContents(contents.potion(), contents.customColor(), PotionEffectUtil.copyAsEffectInstances(v), contents.customName())); }) .create(Keys.REAPPLICATION_DELAY) .get(h -> new SpongeTicks(h.accessor$reapplicationDelay())) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java index b2f6a9a0769..d10b56dbd69 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java @@ -56,7 +56,7 @@ public static void register(final DataProviderRegistrator registrator) { .set((h, v) -> { final PotionContents previousContents = ((ArrowAccessor) h).invoker$getPotionContents(); final List list = v.stream().map(effect -> ArrowData.clone((MobEffectInstance) effect)).toList(); - ((ArrowAccessor) h).invoker$setPotionContents(new PotionContents(previousContents.potion(), previousContents.customColor(), list)); + ((ArrowAccessor) h).invoker$setPotionContents(new PotionContents(previousContents.potion(), previousContents.customColor(), list, previousContents.customName())); }); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java index 124becfdac8..8a4699c6344 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java @@ -46,7 +46,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> Streams.of(h.getItem().getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getAllEffects()).map(PotionEffect.class::cast).toList()) .set((h, v) -> { final var mcEffects = v.stream().map(MobEffectInstance.class::cast).toList(); - h.getItem().update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), mcEffects)); + h.getItem().update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), mcEffects, contents.customName())); }); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 224a401847c..36ea328fbdf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -27,10 +27,15 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; +import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageSources; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemUseAnimation; @@ -39,6 +44,7 @@ import net.minecraft.world.item.component.ChargedProjectiles; import net.minecraft.world.item.component.Consumable; import net.minecraft.world.item.component.CustomModelData; +import net.minecraft.world.item.component.DamageResistant; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; @@ -49,6 +55,7 @@ import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Platform; import org.spongepowered.api.data.Keys; import org.spongepowered.api.item.ItemRarity; @@ -244,18 +251,26 @@ public static void register(final DataProviderRegistrator registrator) { }) .delete(stack -> stack.remove(DataComponents.CONTAINER)) .create(Keys.FIRE_RESISTANT) - .get(h -> h.get(DataComponents.FIRE_RESISTANT) != null) + .get(h -> { + final @Nullable DamageResistant resist = h.get(DataComponents.DAMAGE_RESISTANT); + if (resist == null) { + return false; + } + return resist.types().location().equals(DamageTypes.IN_FIRE.location()); + }) .set((h, value) -> { if (value) { - h.set(DataComponents.FIRE_RESISTANT, Unit.INSTANCE); + h.applyComponents(DataComponentPatch.builder() + .set(DataComponents.DAMAGE_RESISTANT, new DamageResistant(DamageTypeTags.IS_FIRE)) + .build()); } else { - h.remove(DataComponents.FIRE_RESISTANT); + h.remove(DataComponents.DAMAGE_RESISTANT); } }) - .delete(stack -> stack.remove(DataComponents.FIRE_RESISTANT)) + .delete(stack -> stack.remove(DataComponents.DAMAGE_RESISTANT)) .create(Keys.ITEM_NAME) .get(h -> { - final Component component = h.get(DataComponents.ITEM_NAME); + final @Nullable Component component = h.get(DataComponents.ITEM_NAME); if (component == null) { return null; } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java index be2f98a5f69..5c22eacc624 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java @@ -56,8 +56,8 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.COLOR) .get(h -> Color.ofRgb(h.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor())) - .set((h, v) -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.of(v.rgb()), contents.customEffects()))) - .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.empty(), contents.customEffects()))) + .set((h, v) -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.of(v.rgb()), contents.customEffects(), contents.customName()))) + .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.empty(), contents.customEffects(), contents.customName()))) .supports(h -> h.getItem() == Items.POTION || h.getItem() == Items.SPLASH_POTION || h.getItem() == Items.LINGERING_POTION || h.getItem() == Items.TIPPED_ARROW) .create(Keys.CUSTOM_POTION_EFFECTS) .get(h -> { @@ -66,17 +66,17 @@ public static void register(final DataProviderRegistrator registrator) { }) .set((h, v) -> { final var mcList = v.stream().map(MobEffectInstance.class::cast).toList(); - h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), mcList)); + h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), mcList, contents.customName())); }) - .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), Collections.emptyList()))) + .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), contents.customColor(), Collections.emptyList(), contents.customName()))) .supports(h -> h.getItem() == Items.POTION || h.getItem() == Items.SPLASH_POTION || h.getItem() == Items.LINGERING_POTION || h.getItem() == Items.TIPPED_ARROW) .create(Keys.POTION_TYPE) .get(h -> (PotionType) h.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).potion().map(Holder::value).orElse(null)) // TODO empty POTION gone? .set((h, v) -> { final var potion = Optional.ofNullable(v).map(Potion.class::cast).map(BuiltInRegistries.POTION::wrapAsHolder); // TODO set empty POTION? same as delete? - h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(potion, contents.customColor(), contents.customEffects())); + h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(potion, contents.customColor(), contents.customEffects(), contents.customName())); }) - .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(Optional.empty(), contents.customColor(), contents.customEffects()))) + .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(Optional.empty(), contents.customColor(), contents.customEffects(), contents.customName()))) .supports(h -> h.getItem() == Items.POTION || h.getItem() == Items.SPLASH_POTION || h.getItem() == Items.LINGERING_POTION || h.getItem() == Items.TIPPED_ARROW) .create(Keys.POTION_EFFECTS) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index 6e0ede228dd..01d18bfb80f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -26,6 +26,8 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.lighting.LightEngine; @@ -70,7 +72,9 @@ public EffectResult processSideEffect( // ) // ) { if (LightEngine.hasDifferentLightProperties(oldState.state(), currentState)) { - serverWorld.getProfiler().push("updateSkyLightSources"); + ProfilerFiller filler = Profiler.get(); + + filler.push("updateSkyLightSources"); // this.skyLightSources.update(this, $$6, $$3, $$8); final var pos = oldState.pos(); final var x = pos.getX() & 15; @@ -81,11 +85,11 @@ public EffectResult processSideEffect( levelChunk.getSkyLightSources().update(levelChunk, x, y, z); // serverWorld.getChunkSource().update(this, $$6, $$3, $$8); // this.profiler.startSection("queueCheckLight"); - serverWorld.getProfiler().push("queueCheckLight"); + filler.push("queueCheckLight"); // this.getChunkProvider().getLightManager().checkBlock(pos); serverWorld.getChunkSource().getLightEngine().checkBlock(pos); // this.profiler.endSection(); - serverWorld.getProfiler().pop(); + filler.pop(); } return EffectResult.NULL_PASS; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/state/PropertyMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/state/PropertyMixin_API.java index 49224e9717c..b9c2e3f1044 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/state/PropertyMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/state/PropertyMixin_API.java @@ -30,6 +30,7 @@ import org.spongepowered.asm.mixin.Shadow; import java.util.Collection; +import java.util.List; import java.util.Optional; import java.util.function.Predicate; @@ -44,7 +45,7 @@ public abstract class PropertyMixin_API> implements Stat // @formatter:off @Shadow public abstract Class shadow$getValueClass(); - @Shadow public abstract Collection shadow$getPossibleValues(); + @Shadow public abstract List shadow$getPossibleValues(); @Shadow public abstract String shadow$getName(); // @formatter:on diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java index 77171d3854d..3172e7b914d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java @@ -37,12 +37,4 @@ @Mixin(Boat.Type.class) public abstract class Boat_TypeMixin_API implements BoatType { - // @formatter:off - @Shadow @Final private Item planks; - // @formatter:on - - @Override - public BlockType representedBlock() { - return (BlockType) ((BlockItem) this.planks).getBlock(); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 0f409f9d2f0..836cc0e4aa6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -56,6 +56,8 @@ import net.minecraft.stats.Stat; import net.minecraft.stats.Stats; import net.minecraft.util.Unit; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; @@ -475,18 +477,19 @@ public boolean teleportTo(final ServerLevel world, oldLevel.removePlayerImmediately(thisPlayer, Entity.RemovalReason.CHANGED_DIMENSION); this.shadow$unsetRemoved(); - oldLevel.getProfiler().push("moving"); + final ProfilerFiller filler = Profiler.get(); + filler.push("moving"); if (oldLevel.dimension() == Level.OVERWORLD && newLevel.dimension() == Level.NETHER) { this.enteredNetherPosition = thisPlayer.position(); } - oldLevel.getProfiler().pop(); + filler.pop(); - oldLevel.getProfiler().push("placing"); + filler.push("placing"); thisPlayer.setServerLevel(newLevel); this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); this.connection.resetPosition(); newLevel.addDuringTeleport(thisPlayer); - oldLevel.getProfiler().pop(); + filler.pop(); this.shadow$triggerDimensionChangeTriggers(oldLevel); // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic this was only done when using a portal this.connection.send(new ClientboundPlayerAbilitiesPacket(thisPlayer.getAbilities())); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 4e7cf05aeba..238e99fadfa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -38,6 +38,8 @@ import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityDimensions; @@ -516,7 +518,8 @@ public Entity changeDimension(final DimensionTransition transition) { } } - oldLevel.getProfiler().push("changeDimension"); + ProfilerFiller filler = Profiler.get(); + filler.push("changeDimension"); var newEntity = oldLevel.dimension() == newLevel.dimension() ? thisEntity : thisEntity.getType().create(newLevel, EntitySpawnReason.DIMENSION_TRAVEL); if (newEntity != null) { @@ -543,7 +546,7 @@ public Entity changeDimension(final DimensionTransition transition) { // TODO impl$fireMoveEvent when not changing dimensions (e.g. EndGateways) - oldLevel.getProfiler().pop(); + filler.pop(); return newEntity; } @@ -723,7 +726,7 @@ public void stopRiding() { } @Redirect( - method = "applyEffectsFromBlocks", + method = "applyEffectsFromBlocks(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;stepOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/Entity;)V" @@ -743,7 +746,7 @@ public void stopRiding() { } - @Redirect(method = "checkInsideBlocks(Ljava/util/Set;)V", + @Redirect(method = "applyEffectsFromBlocks(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/LecternBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/LecternBlockEntityMixin.java index bb91ec378a9..885ec0481d1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/LecternBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/LecternBlockEntityMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.level.block.entity; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.LecternBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; @@ -37,14 +38,14 @@ public abstract class LecternBlockEntityMixin implements CommandSourceProviderBridge { @Shadow - private CommandSourceStack createCommandSourceStack(@Nullable final Player playerEntity) { + private CommandSourceStack createCommandSourceStack(@Nullable final Player playerEntity, final ServerLevel $$1) { throw new AssertionError("This method should be a shadow."); } @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { // We assume that if a player is in the Cause, they're the one reading the book. - return this.createCommandSourceStack(cause.first(Player.class).orElse(null)); + return this.createCommandSourceStack(cause.first(Player.class).orElse(null), cause.first(ServerLevel.class).orElse(null)); } } From 69a2ccac4874a0bfbd5db785bb24d080b3394076 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 12 Sep 2024 18:02:18 -0700 Subject: [PATCH 084/586] chore(ci): disable snapshot builds of forge --- .github/workflows/deploy.yaml | 4 ++-- settings.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 009eda82dbb..39ac80dae55 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -44,8 +44,8 @@ jobs: echo "GIT_BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - name: Publish to Sponge Maven & GitHub Packages - run: ./gradlew -s -PenableSpongeForge=true :publish :SpongeVanilla:publish :SpongeForge:publish - # run: ./gradlew -s -PenableSpongeForge=true :publish :SpongeVanilla:publish +# run: ./gradlew -s -PenableSpongeForge=true :publish :SpongeVanilla:publish :SpongeForge:publish + run: ./gradlew -s -PenableSpongeForge=true :publish :SpongeVanilla:publish env: CI_SYSTEM: Github Actions GITHUB_USERNAME: "${{ github.actor }}" diff --git a/settings.gradle.kts b/settings.gradle.kts index 6ad57d49c5e..2484c22d7a1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -89,7 +89,7 @@ if (spongeForge.exists()) { ).joinToString(separator = System.lineSeparator(), postfix = System.lineSeparator())) } val spongeForgeEnabledInCi: String = startParameter.projectProperties.getOrDefault("enableSpongeForge", "false") -if (spongeForgeEnabledInCi.toBoolean()) { +if (false && spongeForgeEnabledInCi.toBoolean()) { include(":SpongeForge") project(":SpongeForge").projectDir = file("forge") } From f0701fbe2318db5cfe36da45743e8db64bc403e5 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 12 Sep 2024 22:49:02 -0700 Subject: [PATCH 085/586] fix: allow the snapshot to compile Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../vanilla/generator/GeneratorMain.java | 9 +- .../generator/RegistryEntriesGenerator.java | 4 +- .../generator/RegistryEntriesValidator.java | 10 +- .../vanilla/generator/TagGenerator.java | 2 +- .../block/state/StateHolderAccessor.java | 1 - .../common/bridge/block/BlockBridge.java | 68 ------------- .../bridge/world/TrackedWorldBridge.java | 3 - .../bridge/world/level/ExplosionBridge.java | 1 - .../level/block/TrackableBlockBridge.java | 2 - .../data/provider/block/state/WoolData.java | 2 - .../provider/entity/ServerPlayerData.java | 2 - .../provider/item/stack/ItemStackData.java | 2 - .../item/stack/WoolItemStackData.java | 1 - .../event/SpongeCommonEventFactory.java | 4 - .../event/tracking/PhaseStateProxy.java | 1 - .../effect/UpdateLightSideEffect.java | 2 - .../phase/general/ExplosionContext.java | 1 - .../item/recipe/SpongeRecipeRegistration.java | 1 - .../SpongeCookingRecipeRegistration.java | 2 - ...pongeShapedCraftingRecipeRegistration.java | 2 - .../recipe/ingredient/IngredientUtil.java | 2 - .../common/util/ReflectionUtil.java | 35 ------- .../SpongeStructurePlacementBuilder.java | 1 - .../animal/AgeableWaterCreatureMixin_API.java | 1 - .../entity/vehicle/Boat_TypeMixin_API.java | 6 -- .../item/crafting/IngredientMixin_API.java | 3 - .../common/mixin/core/block/BlockMixin.java | 19 ---- .../core/server/MinecraftServerMixin.java | 1 - .../core/world/entity/LivingEntityMixin.java | 2 - .../world/entity/item/PrimedTntMixin.java | 7 -- .../world/entity/monster/CreeperMixin.java | 2 - .../entity/vehicle/MinecartTNTMixin.java | 7 -- .../world/item/ServerItemCooldownsMixin.java | 3 - .../crafting/AbstractCookingRecipeMixin.java | 1 - .../mixin/core/world/level/LevelMixin.java | 1 - ...MenuMixin_TrackedMenuBridge_Inventory.java | 2 +- .../level/ServerPlayerMixin_Tracker.java | 1 - .../world/level/block/BlockMixin_Tracker.java | 9 +- .../common/test/block/SpongeBlock.java | 10 -- .../common/util/ReflectionTest.java | 99 ------------------- .../client/gui/widget/ScrollPanel.java | 1 - 42 files changed, 13 insertions(+), 322 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index b3b13e92bf8..942b191aa03 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b3b13e92bf80ffb4761008d1c523bbe956ef9e9d +Subproject commit 942b191aa039f3a4088ced1ee9a38f82de6d71e1 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 491cd30f316..efeb54e0d78 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -217,7 +217,7 @@ private static List generators(final Context context) { // Prepare a set of generators // We are starting out by just generating Vanilla registry-backed catalogs // Enum-backed (automatically-named) catalogs can be added later as necessary - return List.of( + return List.of( new MapEntriesValidator<>( "world.gamerule", "GameRules", @@ -253,13 +253,6 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), - new RegistryEntriesGenerator<>( - "data.type", - "ArmorMaterials", - "ARMOR_MATERIAL", - context.relativeClass("data.type", "ArmorMaterial"), - Registries.ARMOR_MATERIAL - ), new RegistryEntriesGenerator<>( "map.decoration", "MapDecorationTypes", diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index 769325db35d..72abbf31d06 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -121,9 +121,9 @@ public void generate(final Context ctx) throws IOException { clazz.addAnnotation(Types.suppressWarnings("unused")); final RegistryScope scopeType; - Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()); + Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()).orElse(null); if (registry == null) { - registry = ctx.registries().registry(this.registry).orElse(null); + registry = ctx.registries().lookup(this.registry).orElse(null); if (registry == null) { throw new IllegalArgumentException("Unknown registry " + this.registry); } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java index 5fed02e72aa..8adf3830a3f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java @@ -96,12 +96,10 @@ public void generate(final Context ctx) { final var primaryTypeDeclaration = compilationUnit.getPrimaryType() .orElseThrow(() -> new IllegalStateException("Could not find primary type for registry type " + this.targetClassSimpleName)); - Registry registry = ctx.registries().registry(this.registry).orElse(null); + Registry registry = ctx.registries().lookup(this.registry).orElse(null); if (registry == null) { - registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()); - if (registry == null) { - throw new IllegalArgumentException("Unknown registry " + this.registry); - } + registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()) + .orElseThrow(() -> new IllegalArgumentException("Unknown registry " + this.registry)); } primaryTypeDeclaration.setJavadocComment(new Javadoc(JavadocDescription.parseText(Generator.GENERATED_FILE_JAVADOCS))); @@ -130,7 +128,7 @@ public void generate(final Context ctx) { final Set allKeys = new HashSet<>(registry.keySet()); allKeys.addAll(this.extraEntries); for (final ResourceLocation key : allKeys) { - if (!this.filter.test(registry.get(key))) { + if (!this.filter.test(registry.getValue(key))) { continue; } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java index 0e72fb03ce7..68d9d95b4ed 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java @@ -94,7 +94,7 @@ public void generate(final Context ctx) throws IOException { ).build(); - ctx.registries().registryOrThrow(this.taggedRegistry).getTags() + ctx.registries().lookupOrThrow(this.taggedRegistry).getTags() .>map(HolderSet.Named::key) .map(TagKey::location) .sorted(Comparator.naturalOrder()) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java index 05380ef49fc..7e1331995f3 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/state/StateHolderAccessor.java @@ -29,7 +29,6 @@ import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; -import java.util.Collection; import java.util.List; @Mixin(StateHolder.class) diff --git a/src/main/java/org/spongepowered/common/bridge/block/BlockBridge.java b/src/main/java/org/spongepowered/common/bridge/block/BlockBridge.java index 28100f5f238..abe2566bcf0 100644 --- a/src/main/java/org/spongepowered/common/bridge/block/BlockBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/block/BlockBridge.java @@ -27,14 +27,8 @@ import net.minecraft.world.level.block.Block; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.data.DataManipulator.Immutable; -import org.spongepowered.api.data.Key; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.common.bridge.server.level.ServerLevelBridge; -import java.util.List; -import java.util.Optional; -import java.util.function.BiConsumer; /** * A quasi interface to mix into every possible {@link Block} such that their @@ -52,66 +46,8 @@ * they already know the type they need to focus on.

*/ public interface BlockBridge { - - /** - * Gets all the {@link Immutable}s for the provided - * {@link BlockState}. - * - * @param blockState The block state being passed in - * @return The list of immutable manipulators - */ - List bridge$getManipulators(BlockState blockState); - - /** - * A simple check whether the class is supported by the block or not. - * - * @param immutable The immutable class - * @return True if the data possibly represented by an instance of the class is supported - */ - boolean bridge$supports(Class immutable); - - /** - * Instead of delegating to a block processor, we can delegate to the block - * to retrieve the correct {@link BlockState} if supported. Considering - * block processors would require to know of the blocks themselves, it is - * easier to use the block to understand what data is being offered, - * and the current block state being used. Since all of the data is already - * relatively kept in the block state instance, it is therefor very well - * possible to cycle according to the block instance. - * - * @param blockState The block state to use as a base - * @param key The key to the data - * @param value The value - * @param The type of value, for type checking - * @return The blockstate with the new value, if available and compatible - */ - Optional bridge$getStateWithValue(BlockState blockState, Key> key, E value); - - /** - * Again, another delegate method directly to the block, usually not all - * required, but it does help if the block does support the manipulator - * in the first place. Considering that most manipulators are single - * data typed, it is discernible for the block to easily check what - * data is being offered and therefor validate whether the data is - * allowed for the specific block state. The block state passed in - * is not changed, but rather used as a blueprint so to speak due to - * the various pre-set data that the block state may contain, such as - * red stone power levels, plant types, etc. etc. etc. - * - * @param blockState The block state to base off of - * @param manipulator The manipulator being offered - * @return The block state with the requested data, if available - */ - Optional bridge$getStateWithData(BlockState blockState, Immutable manipulator); - // Normal API methods - boolean bridge$isVanilla(); - - boolean bridge$hasCollideLogic(); - - boolean bridge$hasCollideWithStateLogic(); - /** * Used only for Forge's dummy air block that is acting as a surrogate block for missing * mod blocks. Usually when a block is simply marked for replacement when a mod is re-introduced. @@ -122,8 +58,4 @@ public interface BlockBridge { return false; } - default BiConsumer bridge$getTickFrameModifier() { - return (frame, world) -> { - }; - } } diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index 072e6c79190..740a8eed68c 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -34,17 +34,14 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.world.BlockChangeFlag; -import org.spongepowered.api.world.explosion.Explosion; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; -import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import java.util.Optional; -import java.util.function.Function; /** * A specialized {@link LevelBridge} or {@link ServerLevelBridge} diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java index 7e28e5a753d..a83c1171fa5 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/ExplosionBridge.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.bridge.world.level; -import org.spongepowered.api.world.explosion.Explosion; public interface ExplosionBridge { diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/block/TrackableBlockBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/block/TrackableBlockBridge.java index 8c8a4418464..719aaf81726 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/block/TrackableBlockBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/block/TrackableBlockBridge.java @@ -26,8 +26,6 @@ public interface TrackableBlockBridge { - boolean bridge$overridesNeighborNotificationLogic(); - boolean bridge$hasEntityInsideLogic(); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java index 38f5b0a74dd..a1965961b20 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java @@ -26,10 +26,8 @@ import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.storage.loot.BuiltInLootTables; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; -import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.DyeColorUtil; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 687a84ce8fd..1d238384131 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -32,13 +32,11 @@ import net.minecraft.network.protocol.game.ClientboundRespawnPacket; import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; -import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.PlayerList; import net.minecraft.stats.Stat; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.level.GameType; -import net.minecraft.world.level.biome.BiomeManager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.living.player.chat.ChatVisibilities; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 36ea328fbdf..bff85314924 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -33,8 +33,6 @@ import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java index a596c792725..6ab69a33d37 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java @@ -29,7 +29,6 @@ import net.minecraft.world.item.ItemStack; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; -import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.DyeColorUtil; diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 24f5ab202f2..7b64ad7d24a 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -63,7 +63,6 @@ import org.spongepowered.api.effect.sound.music.MusicDisc; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.EntityTypes; -import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.entity.living.Agent; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.entity.living.player.Player; @@ -85,7 +84,6 @@ import org.spongepowered.api.event.entity.MoveEntityEvent; import org.spongepowered.api.event.entity.RotateEntityEvent; import org.spongepowered.api.event.entity.ai.SetAITargetEvent; -import org.spongepowered.api.event.entity.explosive.DetonateExplosiveEvent; import org.spongepowered.api.event.item.inventory.DropItemEvent; import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.event.sound.PlaySoundEvent; @@ -97,7 +95,6 @@ import org.spongepowered.api.world.DefaultWorldKeys; import org.spongepowered.api.world.LocatableBlock; import org.spongepowered.api.world.World; -import org.spongepowered.api.world.explosion.Explosion; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.SpongeCommon; @@ -115,7 +112,6 @@ import org.spongepowered.common.entity.projectile.UnknownProjectileSource; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.map.SpongeMapStorage; import org.spongepowered.common.registry.provider.DirectionFacingProvider; diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java index 329f249aeb1..9f2aa7307b0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java @@ -33,7 +33,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.redstone.Orientation; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.ticks.ScheduledTick; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index 01d18bfb80f..f571c241138 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -24,12 +24,10 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; -import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.lighting.LightEngine; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java index 032bf2c6c0c..eb40f98eba9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/ExplosionContext.java @@ -26,7 +26,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ServerExplosion; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java index f07c7c3e005..372eeb77cda 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java @@ -53,7 +53,6 @@ import java.io.IOException; import java.util.Collection; -import java.util.Optional; import java.util.function.Function; public abstract class SpongeRecipeRegistration> implements RecipeRegistration { diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java index 8cb16a97911..6a1b01b74e4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java @@ -47,8 +47,6 @@ import org.spongepowered.common.util.SpongeTicks; import java.util.Collections; -import java.util.List; -import java.util.Optional; import java.util.function.Function; public class SpongeCookingRecipeRegistration extends SpongeRecipeRegistration implements SpongeRecipeRegistration.ResultFunctionRegistration{ diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java index 831718b6ff3..8574bdcfaeb 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java @@ -30,7 +30,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; @@ -40,7 +39,6 @@ import org.spongepowered.api.item.recipe.crafting.ShapedCraftingRecipe; import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; -import java.util.List; import java.util.Optional; import java.util.function.Function; diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java index 4bea6f57398..230dc68b847 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.item.recipe.ingredient; -import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -37,7 +36,6 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.Arrays; diff --git a/src/main/java/org/spongepowered/common/util/ReflectionUtil.java b/src/main/java/org/spongepowered/common/util/ReflectionUtil.java index 5332287af6d..5f19de68ba2 100644 --- a/src/main/java/org/spongepowered/common/util/ReflectionUtil.java +++ b/src/main/java/org/spongepowered/common/util/ReflectionUtil.java @@ -28,7 +28,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import org.apache.logging.log4j.Marker; @@ -48,40 +47,16 @@ public final class ReflectionUtil { public static final Marker REFLECTION_SCANNING = MarkerManager.getMarker("REFLECTION_SCANNING"); - private static final Class[] NEIGHBOR_CHANGED_METHOD_ARGS = { - BlockState.class, - Level.class, - BlockPos.class, - Block.class, - BlockPos.class, - boolean.class - }; private static final Class[] ENTITY_INSIDE_METHOD_ARGS = { BlockState.class, Level.class, BlockPos.class, Entity.class }; - private static final Class[] STEP_ON_METHOD_ARGS = { - Level.class, - BlockPos.class, - BlockState.class, - Entity.class - }; private static final Class[] PLAYER_TOUCH_METHOD_ARGS= { Player.class }; - public static boolean isNeighborChangedDeclared(final Class targetClass) { - return ReflectionUtil.doesMethodExist( - targetClass, - Block.class, - "neighborChanged", - ReflectionUtil.NEIGHBOR_CHANGED_METHOD_ARGS, - void.class - ); - } - public static boolean isEntityInsideDeclared(final Class targetClass) { return ReflectionUtil.doesMethodExist( targetClass, @@ -92,16 +67,6 @@ public static boolean isEntityInsideDeclared(final Class targetClass) { ); } - public static boolean isStepOnDeclared(final Class targetClass) { - return ReflectionUtil.doesMethodExist( - targetClass, - Block.class, - "stepOn", - ReflectionUtil.STEP_ON_METHOD_ARGS, - void.class - ); - } - public static boolean isPlayerTouchDeclared(final Class targetClass) { return ReflectionUtil.doesMethodExist( targetClass, diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java index 13a332df74c..60ed58a9dad 100644 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java @@ -28,7 +28,6 @@ import net.minecraft.core.Registry; import net.minecraft.core.Vec3i; import net.minecraft.core.registries.Registries; -import net.minecraft.tags.TagKey; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java index bb00edc6f7c..cb0730af804 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AgeableWaterCreatureMixin_API.java @@ -25,7 +25,6 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; import net.minecraft.world.entity.animal.AgeableWaterCreature; -import net.minecraft.world.entity.animal.WaterAnimal; import org.spongepowered.api.entity.Ageable; import org.spongepowered.api.entity.living.aquatic.Aquatic; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java index 3172e7b914d..3011507b930 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java @@ -25,14 +25,8 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; import net.minecraft.world.entity.vehicle.Boat; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.type.BoatType; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; @Mixin(Boat.Type.class) public abstract class Boat_TypeMixin_API implements BoatType { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java index 9f544541348..c3eae56d75b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java @@ -30,7 +30,6 @@ import net.minecraft.world.item.crafting.Ingredient; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface.Remap; @@ -38,9 +37,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.item.util.ItemStackUtil; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; @Mixin(Ingredient.class) @Implements(@Interface(iface = org.spongepowered.api.item.recipe.crafting.Ingredient.class, prefix = "ingredient$", remap = Remap.NONE)) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java index 2427e47a603..ff3e6aae610 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java @@ -46,16 +46,11 @@ import org.spongepowered.common.bridge.block.DyeColorBlockBridge; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.util.ReflectionUtil; import org.spongepowered.math.vector.Vector3d; @Mixin(value = Block.class) public abstract class BlockMixin implements BlockBridge, TrackableBridge { - private final boolean impl$isVanilla = this.getClass().getName().startsWith("net.minecraft."); - private final boolean impl$hasCollideLogic = ReflectionUtil.isStepOnDeclared(this.getClass()); - private final boolean impl$hasCollideWithStateLogic = ReflectionUtil.isEntityInsideDeclared(this.getClass()); - /** * We captured the dye color when creating the Block.Properties. * As the Properties objects are discarded we transfer it over to the Block itself now. @@ -131,18 +126,4 @@ public abstract class BlockMixin implements BlockBridge, TrackableBridge { } } - @Override - public boolean bridge$isVanilla() { - return this.impl$isVanilla; - } - - @Override - public boolean bridge$hasCollideLogic() { - return this.impl$hasCollideLogic; - } - - @Override - public boolean bridge$hasCollideWithStateLogic() { - return this.impl$hasCollideWithStateLogic; - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 682ec494e10..b6e770f86fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -56,7 +56,6 @@ import org.spongepowered.api.service.permission.SubjectProxy; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 3bf446f135e..fcca3360918 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -29,8 +29,6 @@ import net.minecraft.core.particles.ParticleOptions; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java index 91e09a95ade..4798a567ca4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java @@ -24,21 +24,14 @@ */ package org.spongepowered.common.mixin.core.world.entity.item; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.entity.explosive.fused.PrimedTNT; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java index 7c24224a7e0..bd1f332b893 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java @@ -24,11 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.entity.monster; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index 7b8f6dd27c6..67731871c9a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -27,25 +27,18 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.vehicle.MinecartTNT; -import net.minecraft.world.level.ExplosionDamageCalculator; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.entity.vehicle.minecart.TNTMinecart; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.DamageEventUtil; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java index b21875fe6fa..97b7bba16c6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java @@ -25,8 +25,6 @@ package org.spongepowered.common.mixin.core.world.item; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ServerItemCooldowns; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -34,7 +32,6 @@ import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.entity.living.player.CooldownEvent; -import org.spongepowered.api.item.ItemType; import org.spongepowered.api.util.Ticks; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java index ea42280d5d3..f154a0bc0cb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java @@ -31,7 +31,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.item.crafting.CookingRecipeBridge; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; @Mixin(AbstractCookingRecipe.class) public abstract class AbstractCookingRecipeMixin implements CookingRecipeBridge { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index d9df63bf056..8bec5197a89 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -42,7 +42,6 @@ import net.minecraft.world.entity.decoration.Painting; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.ThrownEnderpearl; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java index ed93552e28d..1d66bc49ace 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory.java @@ -39,4 +39,4 @@ public abstract class AbstractCraftingMenuMixin_TrackedMenuBridge_Inventory { @Shadow @Final protected ResultContainer resultSlots; // @formatter:on -} \ No newline at end of file +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java index 8e01da4348c..0837a8cffc3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java @@ -27,7 +27,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.CauseStackManager; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java index 3534f5443bb..093ad2e886a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java @@ -37,6 +37,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -52,16 +53,12 @@ @Mixin(Block.class) public abstract class BlockMixin_Tracker implements TrackableBlockBridge, RegistryBackedTrackableBridge { - private final boolean tracker$hasNeighborLogicOverridden = ReflectionUtil.isNeighborChangedDeclared(this.getClass()); + @Unique private final boolean tracker$hasEntityInsideLogicOverridden = ReflectionUtil.isEntityInsideDeclared(this.getClass()); + @Unique @Nullable private static EffectTransactor tracker$effectTransactorForDrops = null; - @Override - public boolean bridge$overridesNeighborNotificationLogic() { - return this.tracker$hasNeighborLogicOverridden; - } - @Override public boolean bridge$hasEntityInsideLogic() { return this.tracker$hasEntityInsideLogicOverridden; diff --git a/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java b/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java index 7174e1aa314..3fbae6a0c5f 100644 --- a/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java +++ b/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java @@ -24,21 +24,11 @@ */ package org.spongepowered.common.test.block; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -@SuppressWarnings("deprecation") public class SpongeBlock extends Block { public SpongeBlock(Properties param0) { super(param0); } - @Override - public void neighborChanged( - BlockState param0, Level param1, BlockPos param2, Block param3, BlockPos param4, boolean param5 - ) { - super.neighborChanged(param0, param1, param2, param3, param4, param5); - } } diff --git a/src/test/java/org/spongepowered/common/util/ReflectionTest.java b/src/test/java/org/spongepowered/common/util/ReflectionTest.java index 67cbcee200c..6f40b536677 100644 --- a/src/test/java/org/spongepowered/common/util/ReflectionTest.java +++ b/src/test/java/org/spongepowered/common/util/ReflectionTest.java @@ -24,113 +24,14 @@ */ package org.spongepowered.common.util; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; import org.spongepowered.common.test.UnitTestExtension; -import org.spongepowered.common.test.block.SpongeBlock; -import java.lang.reflect.Method; @Disabled @ExtendWith(UnitTestExtension.class) public class ReflectionTest { - @Test - public void testCheckNeighborChangedDeclared() { - final boolean isNeighborChangedDeclared = ReflectionUtil.isNeighborChangedDeclared(SpongeBlock.class); - Assertions.assertTrue(isNeighborChangedDeclared, "NeighborChanged should be declared on SpongeBlock"); - } - - @Test - public void testEntityInsideNotDeclared() { - final boolean entityInsideDeclared = ReflectionUtil.isEntityInsideDeclared(SpongeBlock.class); - Assertions.assertFalse(entityInsideDeclared, "isEntityInsideDeclared is not declared on SpongeBlock"); - } - - @Test - public void testNonExistentMethodOnCustomClass() { - final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "org/spongepowered/common/test/block/BombDummy", null, "net/minecraft/world/level/block/Block", null); - { - final MethodVisitor ctor = writer.visitMethod( - Opcodes.ACC_PUBLIC, - "", - "(Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V", - null, - null - ); - ctor.visitCode(); - ctor.visitVarInsn(Opcodes.ALOAD, 0); - ctor.visitVarInsn(Opcodes.ALOAD, 1); - ctor.visitMethodInsn( - Opcodes.INVOKESPECIAL, - "net/minecraft/world/level/block/Block", - "", - "(Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V", - false - ); - ctor.visitInsn(Opcodes.RETURN); - ctor.visitMaxs(0, 0); - } - { - final MethodVisitor el = writer.visitMethod( - Opcodes.ACC_PUBLIC, - "neighborChanged", - "(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V", - null, - null - ); - el.visitCode(); - el.visitInsn(Opcodes.RETURN); - el.visitMaxs(0,0); - } - { - final MethodVisitor bomb = writer.visitMethod( - Opcodes.ACC_PUBLIC, - "throwup", - "(Lcom/example/doesnt/Exist;)V", - null, - null - ); - bomb.visitCode(); - bomb.visitInsn(Opcodes.RETURN); - bomb.visitMaxs(0, 0); - } - - final DefinableClassLoader loader = new DefinableClassLoader(this.getClass().getClassLoader()); - final byte[] bombClazzBytes = writer.toByteArray(); - final Class clazz = loader.defineClass("org.spongepowered.common.test.block.BombDummy", bombClazzBytes); - final boolean neighborChanged = ReflectionUtil.isNeighborChangedDeclared(clazz); - Assertions.assertTrue(neighborChanged, "NeighborChanged should have been defined on BombDummy"); - final boolean entityInside = ReflectionUtil.isEntityInsideDeclared(clazz); - Assertions.assertFalse(entityInside, "isEntityInsideDeclared is not defined on BombDummy"); - NoClassDefFoundError e = null; - try { - ReflectionTest.getNeighborChanged(clazz); - } catch (final Exception ex) { - Assertions.fail("Expected a class not found exception for com/example/doesnt/Exist"); - } catch (final NoClassDefFoundError ee) { - e = ee; - } - Assertions.assertNotNull(e, "Should have gotten a class exception"); - } - - private static void getNeighborChanged(final Class clazz) throws Exception, Error { - final Method m = clazz.getMethod("neighborChanged", BlockState.class, - Level.class, - BlockPos.class, - Block.class, - BlockPos.class, - boolean.class); - } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 98052cf6988..60c70d1ca23 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -36,7 +36,6 @@ import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.renderer.GameRenderer; import java.util.Collections; import java.util.List; From 668afe21bf2f1db268963225945bcba935451714 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 22 Sep 2024 16:44:06 -0700 Subject: [PATCH 086/586] chore(update): update to 24w38a Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- gradle/verification-metadata.xml | 3 + .../common/util/DirectionUtil.java | 275 ++++++------------ .../ServerGamePacketListenerImplMixin.java | 1 - .../level/LevelAccessorMixin_Tracker.java | 53 ---- .../resources/mixins.sponge.tracker.json | 1 - 6 files changed, 101 insertions(+), 234 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelAccessorMixin_Tracker.java diff --git a/gradle.properties b/gradle.properties index efebbd07d3b..07907e93000 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w37a +minecraftVersion=24w38a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 66820b2590a..572a51234d3 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1195,6 +1195,9 @@
+ + + diff --git a/src/main/java/org/spongepowered/common/util/DirectionUtil.java b/src/main/java/org/spongepowered/common/util/DirectionUtil.java index dcbede764bb..d7d8dd9365f 100644 --- a/src/main/java/org/spongepowered/common/util/DirectionUtil.java +++ b/src/main/java/org/spongepowered/common/util/DirectionUtil.java @@ -25,7 +25,7 @@ package org.spongepowered.common.util; -import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; import org.spongepowered.api.util.Direction; import java.util.Objects; @@ -34,45 +34,31 @@ public final class DirectionUtil { public static net.minecraft.core.Direction getFor(final Direction direction) { Objects.requireNonNull(direction); - switch (direction) { - case UP: - return net.minecraft.core.Direction.UP; - case DOWN: - return net.minecraft.core.Direction.DOWN; - case WEST: - return net.minecraft.core.Direction.WEST; - case SOUTH: - return net.minecraft.core.Direction.SOUTH; - case EAST: - return net.minecraft.core.Direction.EAST; - case NORTH: - return net.minecraft.core.Direction.NORTH; - default: - return null; - } + return switch (direction) { + case UP -> net.minecraft.core.Direction.UP; + case DOWN -> net.minecraft.core.Direction.DOWN; + case WEST -> net.minecraft.core.Direction.WEST; + case SOUTH -> net.minecraft.core.Direction.SOUTH; + case EAST -> net.minecraft.core.Direction.EAST; + case NORTH -> net.minecraft.core.Direction.NORTH; + default -> null; + }; } public static Direction getFor(final net.minecraft.core.Direction facing) { Objects.requireNonNull(facing); - switch (facing) { - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - case WEST: - return Direction.WEST; - case SOUTH: - return Direction.SOUTH; - case EAST: - return Direction.EAST; - case NORTH: - return Direction.NORTH; - default: - throw new IllegalStateException(); - } + return switch (facing) { + case UP -> Direction.UP; + case DOWN -> Direction.DOWN; + case WEST -> Direction.WEST; + case SOUTH -> Direction.SOUTH; + case EAST -> Direction.EAST; + case NORTH -> Direction.NORTH; + default -> throw new IllegalStateException(); + }; } - public static net.minecraft.world.level.block.state.BlockState set(final net.minecraft.world.level.block.state.BlockState holder, final Direction value, final DirectionProperty property) { + public static net.minecraft.world.level.block.state.BlockState set(final net.minecraft.world.level.block.state.BlockState holder, final Direction value, final EnumProperty property) { final net.minecraft.core.Direction direction = DirectionUtil.getFor(value); if (direction == null || !property.getPossibleValues().contains(direction)) { return holder; @@ -81,168 +67,101 @@ public static net.minecraft.world.level.block.state.BlockState set(final net.min } public static Direction fromRotation(int i) { - switch (i) { - case 0: - return Direction.SOUTH; - case 1: - return Direction.SOUTH_SOUTHWEST; - case 2: - return Direction.SOUTHWEST; - case 3: - return Direction.WEST_SOUTHWEST; - case 4: - return Direction.WEST; - case 5: - return Direction.WEST_NORTHWEST; - case 6: - return Direction.NORTHWEST; - case 7: - return Direction.NORTH_NORTHWEST; - case 8: - return Direction.NORTH; - case 9: - return Direction.NORTH_NORTHEAST; - case 10: - return Direction.NORTHEAST; - case 11: - return Direction.EAST_NORTHEAST; - case 12: - return Direction.EAST; - case 13: - return Direction.EAST_SOUTHEAST; - case 14: - return Direction.SOUTHEAST; - case 15: - return Direction.SOUTH_SOUTHEAST; - default: - return Direction.NORTH; - } + return switch (i) { + case 0 -> Direction.SOUTH; + case 1 -> Direction.SOUTH_SOUTHWEST; + case 2 -> Direction.SOUTHWEST; + case 3 -> Direction.WEST_SOUTHWEST; + case 4 -> Direction.WEST; + case 5 -> Direction.WEST_NORTHWEST; + case 6 -> Direction.NORTHWEST; + case 7 -> Direction.NORTH_NORTHWEST; + case 8 -> Direction.NORTH; + case 9 -> Direction.NORTH_NORTHEAST; + case 10 -> Direction.NORTHEAST; + case 11 -> Direction.EAST_NORTHEAST; + case 12 -> Direction.EAST; + case 13 -> Direction.EAST_SOUTHEAST; + case 14 -> Direction.SOUTHEAST; + case 15 -> Direction.SOUTH_SOUTHEAST; + default -> Direction.NORTH; + }; } public static int toRotation(final Direction direction) { - switch (direction) { - case SOUTH: - return 0; - case SOUTH_SOUTHWEST: - return 1; - case SOUTHWEST: - return 2; - case WEST_SOUTHWEST: - return 3; - case WEST: - return 4; - case WEST_NORTHWEST: - return 5; - case NORTHWEST: - return 6; - case NORTH_NORTHWEST: - return 7; - case NORTH: - return 8; - case NORTH_NORTHEAST: - return 9; - case NORTHEAST: - return 10; - case EAST_NORTHEAST: - return 11; - case EAST: - return 12; - case EAST_SOUTHEAST: - return 13; - case SOUTHEAST: - return 14; - case SOUTH_SOUTHEAST: - return 15; - default: - return 0; - } + return switch (direction) { + case SOUTH -> 0; + case SOUTH_SOUTHWEST -> 1; + case SOUTHWEST -> 2; + case WEST_SOUTHWEST -> 3; + case WEST -> 4; + case WEST_NORTHWEST -> 5; + case NORTHWEST -> 6; + case NORTH_NORTHWEST -> 7; + case NORTH -> 8; + case NORTH_NORTHEAST -> 9; + case NORTHEAST -> 10; + case EAST_NORTHEAST -> 11; + case EAST -> 12; + case EAST_SOUTHEAST -> 13; + case SOUTHEAST -> 14; + case SOUTH_SOUTHEAST -> 15; + default -> 0; + }; } public static Direction fromHorizontalHanging(int i) { - switch (i) { - case 0: - return Direction.SOUTH; - case 1: - return Direction.WEST; - case 2: - return Direction.NORTH; - case 3: - return Direction.EAST; - default: - return Direction.NORTH; - } + return switch (i) { + case 0 -> Direction.SOUTH; + case 1 -> Direction.WEST; + case 2 -> Direction.NORTH; + case 3 -> Direction.EAST; + default -> Direction.NORTH; + }; } public static int toHorizontalHanging(Direction direction) { - switch (direction) { - case SOUTH: - return 0; - case WEST: - return 1; - case NORTH: - return 2; - case EAST: - return 3; - default: - return 0; - } + return switch (direction) { + case SOUTH -> 0; + case WEST -> 1; + case NORTH -> 2; + case EAST -> 3; + default -> 0; + }; } public static Direction fromHanging(int i) { - switch (i) { - case 0: - return Direction.DOWN; - case 1: - return Direction.UP; - case 2: - return Direction.NORTH; - case 3: - return Direction.SOUTH; - case 4: - return Direction.WEST; - case 5: - return Direction.EAST; - default: - return Direction.DOWN; - } + return switch (i) { + case 0 -> Direction.DOWN; + case 1 -> Direction.UP; + case 2 -> Direction.NORTH; + case 3 -> Direction.SOUTH; + case 4 -> Direction.WEST; + case 5 -> Direction.EAST; + default -> Direction.DOWN; + }; } public static int toHanging(Direction direction) { - switch (direction) { - case DOWN: - return 0; - case UP: - return 1; - case NORTH: - return 2; - case SOUTH: - return 3; - case WEST: - return 4; - case EAST: - return 5; - default: - return 0; - } + return switch (direction) { + case DOWN -> 0; + case UP -> 1; + case NORTH -> 2; + case SOUTH -> 3; + case WEST -> 4; + case EAST -> 5; + default -> 0; + }; } public static int directionToIndex(final Direction direction) { - switch (direction) { - case NORTH: - case NORTHEAST: - case NORTHWEST: - return 0; - case SOUTH: - case SOUTHEAST: - case SOUTHWEST: - return 1; - case EAST: - return 2; - case WEST: - return 3; - default: - throw new IllegalArgumentException("Unexpected direction"); - } + return switch (direction) { + case NORTH, NORTHEAST, NORTHWEST -> 0; + case SOUTH, SOUTHEAST, SOUTHWEST -> 1; + case EAST -> 2; + case WEST -> 3; + default -> throw new IllegalArgumentException("Unexpected direction"); + }; } private DirectionUtil() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 1762b453256..b5ce112479b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -126,7 +126,6 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack @Shadow private double vehicleFirstGoodX; @Shadow private double vehicleFirstGoodY; @Shadow private double vehicleFirstGoodZ; - @Shadow private int chatSpamTickCount; @Shadow public abstract void shadow$teleport(PositionMoveRotation pitch, Set relativeArguments); @Shadow protected abstract CompletableFuture> shadow$filterTextPacket(final List $$0); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelAccessorMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelAccessorMixin_Tracker.java deleted file mode 100644 index 4ae817d3e95..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelAccessorMixin_Tracker.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.tracker.world.level; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.storage.LevelData; -import net.minecraft.world.ticks.LevelTickAccess; -import net.minecraft.world.ticks.TickPriority; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(LevelAccessor.class) -public interface LevelAccessorMixin_Tracker { - - // @formatter:off - @Shadow LevelData shadow$getLevelData(); - @Shadow long shadow$nextSubTickCount(); - @Shadow LevelTickAccess shadow$getBlockTicks(); - @Shadow LevelTickAccess shadow$getFluidTicks(); - - // Shadow methods to be overridden in ServerLevelMixin_Tracker - @Shadow void shadow$scheduleTick(BlockPos pos, Block block, int $$2, TickPriority priority); - @Shadow void shadow$scheduleTick(BlockPos pos, Block block, int $$2); - @Shadow void shadow$scheduleTick(BlockPos pos, Fluid fluid, int $$2, TickPriority priority); - @Shadow void shadow$scheduleTick(BlockPos pos, Fluid fluid, int $$2); - // @formatter:on - -} diff --git a/src/mixins/resources/mixins.sponge.tracker.json b/src/mixins/resources/mixins.sponge.tracker.json index 79857ecd615..d3969c69be7 100644 --- a/src/mixins/resources/mixins.sponge.tracker.json +++ b/src/mixins/resources/mixins.sponge.tracker.json @@ -33,7 +33,6 @@ "world.item.ItemStackMixin_Tracker", "world.level.BlockEventDataMixin_Tracker", "world.level.ServerExplosionMixin_Tracker", - "world.level.LevelAccessorMixin_Tracker", "world.level.LevelHeightAccessorMixin_Tracker", "world.level.LevelMixin_Tracker", "world.level.block.BlockMixin_Tracker", From 42a6077fcb790505fb38cf1ca01a9603ca218c6a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 28 Sep 2024 13:14:43 -0700 Subject: [PATCH 087/586] chore: update dependency metadata Signed-off-by: Gabriel Harris-Rouquette --- gradle/verification-metadata.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 572a51234d3..ad17c5edb2c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1201,6 +1201,9 @@ + + + From dac0c11384bb165dc99a1393485eb1f695793510 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 2 Oct 2024 23:48:00 -0700 Subject: [PATCH 088/586] chore(update): update to 24w39a Signed-off-by: Gabriel Harris-Rouquette --- .../vanilla/generator/GeneratorMain.java | 7 -- gradle.properties | 2 +- .../accessor/world/entity/EntityAccessor.java | 2 - .../TargetingConditionsAccessor.java | 2 +- .../entity/decoration/ItemFrameAccessor.java | 3 +- .../world/entity/player/PlayerAccessor.java | 2 + ...ccessor.java => AbstractBoatAccessor.java} | 8 +-- .../accessor/world/food/FoodDataAccessor.java | 2 + .../resources/mixins.sponge.accessors.json | 2 +- ...oatBridge.java => AbstractBoatBridge.java} | 2 +- .../provider/block/entity/LockableData.java | 6 +- .../common/data/provider/entity/BoatData.java | 39 +++++------ .../data/provider/entity/PlayerData.java | 2 +- .../item/stack/BlockItemStackData.java | 24 +++---- .../SpongeAvoidLivingGoalBuilder.java | 4 +- ...indNearestAttackableTargetGoalBuilder.java | 5 +- .../event/SpongeCommonEventFactory.java | 2 +- .../common/event/tracking/IPhaseState.java | 9 ++- .../event/tracking/PhaseStateProxy.java | 11 +-- .../type/BlockTransactionType.java | 4 +- .../tracking/phase/general/CommandState.java | 3 +- .../packet/player/PacketCommandState.java | 3 +- .../packet/player/PlaceBlockPacketState.java | 2 +- .../packet/player/UseItemPacketState.java | 3 +- .../phase/tick/BlockEventTickPhaseState.java | 3 +- .../phase/tick/EntityTickPhaseState.java | 12 ++-- .../tick/LocationBasedTickPhaseState.java | 3 +- .../loader/VanillaRegistryLoader.java | 1 - .../selector/EntitySelectorMixin_API.java | 3 +- .../world/entity/EntityMixin_API.java | 8 ++- .../ai/goal/AvoidEntityGoalMixin_API.java | 14 ++-- .../NearestAttackableTargetGoalMixin_API.java | 4 +- .../FireworkRocketEntityMixin_API.java | 7 +- .../projectile/LargeFireballMixin_API.java | 6 +- ...in_API.java => AbstractBoatMixin_API.java} | 5 +- ...I.java => AbstractChestBoatMixin_API.java} | 4 +- .../entity/vehicle/Boat_TypeMixin_API.java | 34 --------- .../BaseContainerBlockEntityMixin_API.java | 7 +- .../level/storage/LevelDataMixin_API.java | 45 ------------ .../storage/ServerLevelDataMixin_API.java | 53 ++++++++++++++ .../commands/CommandSourceStackMixin.java | 7 +- .../mixin/core/nbt/CompoundTagMixin.java | 41 +++++------ .../server/commands/GameRuleCommandMixin.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 4 +- .../mixin/core/world/entity/EntityMixin.java | 56 ++++++--------- .../core/world/entity/ExperienceOrbMixin.java | 5 +- .../core/world/entity/LivingEntityMixin.java | 10 +-- .../entity/LivingEntityMixin_Attack_Impl.java | 70 +++++++++---------- .../mixin/core/world/entity/MobMixin.java | 7 -- .../world/entity/MobMixin_Attack_Impl.java | 6 +- .../world/entity/ai/sensing/SensorMixin.java | 3 +- .../world/entity/animal/SnowGolemMixin.java | 11 ++- .../boss/enderdragon/EndCrystalMixin.java | 19 ++--- .../boss/enderdragon/EnderDragonMixin.java | 15 ++-- .../entity/decoration/ArmorStandMixin.java | 42 +++++------ .../decoration/BlockAttachedEntityMixin.java | 7 +- .../entity/decoration/ItemFrameMixin.java | 8 ++- .../world/entity/item/ItemEntityMixin.java | 6 +- .../core/world/entity/player/PlayerMixin.java | 2 +- .../player/PlayerMixin_Attack_Impl.java | 22 +++--- .../entity/projectile/AbstractArrowMixin.java | 9 ++- .../projectile/FireworkRocketEntityMixin.java | 11 ++- .../entity/projectile/ShulkerBulletMixin.java | 5 +- .../entity/projectile/SnowballMixin.java | 2 +- .../entity/projectile/ThrownEggMixin.java | 2 +- .../projectile/ThrownEnderpearlMixin.java | 2 +- .../entity/projectile/WitherSkullMixin.java | 2 +- ...{BoatMixin.java => AbstractBoatMixin.java} | 8 +-- .../entity/vehicle/AbstractMinecartMixin.java | 3 +- .../entity/vehicle/MinecartFurnaceMixin.java | 5 +- .../entity/vehicle/MinecartTNTMixin.java | 10 +-- .../entity/vehicle/VehicleEntityMixin.java | 6 +- .../mixin/core/world/food/FoodDataMixin.java | 12 +--- .../core/world/level/block/TntBlockMixin.java | 7 +- .../block/entity/BeaconBlockEntityMixin.java | 15 +++- .../level/ServerLevelMixin_Tracker.java | 8 +-- .../world/entity/EntityMixin_Tracker.java | 9 +-- .../entity/LivingEntityMixin_Tracker.java | 2 +- .../world/level/LevelMixin_Tracker.java | 3 - src/mixins/resources/mixins.sponge.api.json | 5 +- src/mixins/resources/mixins.sponge.core.json | 8 ++- .../entity/LivingEntityMixin_Attack_Impl.java | 6 +- ...la.java => AbstractBoatMixin_Vanilla.java} | 8 +-- .../resources/mixins.spongevanilla.core.json | 2 +- 84 files changed, 421 insertions(+), 432 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/{BoatAccessor.java => AbstractBoatAccessor.java} (88%) rename src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/{BoatBridge.java => AbstractBoatBridge.java} (97%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{BoatMixin_API.java => AbstractBoatMixin_API.java} (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ChestBoatMixin_API.java => AbstractChestBoatMixin_API.java} (90%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{BoatMixin.java => AbstractBoatMixin.java} (94%) rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/{BoatMixin_Vanilla.java => AbstractBoatMixin_Vanilla.java} (89%) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index efeb54e0d78..a9000d3d50e 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -246,13 +246,6 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), - new EnumEntriesValidator<>( - "data.type", - "BoatTypes", - Boat.Type.class, - "getSerializedName", - "sponge" - ), new RegistryEntriesGenerator<>( "map.decoration", "MapDecorationTypes", diff --git a/gradle.properties b/gradle.properties index 07907e93000..0c97c7f9c08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w38a +minecraftVersion=24w39a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityAccessor.java index 538bfb02607..8a3171168a1 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityAccessor.java @@ -87,8 +87,6 @@ public interface EntityAccessor { @Invoker("getFireImmuneTicks") int invoker$getFireImmuneTicks(); - @Invoker("getPermissionLevel") int invoker$getPermissionLevel(); - @Invoker("unsetRemoved") void invoker$unsetRemoved(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java index e975fb1e014..3a2a459743e 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java @@ -34,6 +34,6 @@ @Mixin(TargetingConditions.class) public interface TargetingConditionsAccessor { - @Accessor("selector") Predicate accessor$selector(); + @Accessor("selector") TargetingConditions.Selector accessor$selector(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ItemFrameAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ItemFrameAccessor.java index f633ffb127a..d6cb0289c74 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ItemFrameAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ItemFrameAccessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.accessor.world.entity.decoration; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.ItemFrame; import org.spongepowered.asm.mixin.Mixin; @@ -32,6 +33,6 @@ @Mixin(ItemFrame.class) public interface ItemFrameAccessor { - @Invoker("dropItem") void invoker$dropItem(final Entity entity, final boolean drop); + @Invoker("dropItem") void invoker$dropItem(final ServerLevel level, final Entity entity, final boolean drop); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java index 9a12ace2ef0..1a91a66d7ad 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java @@ -29,6 +29,7 @@ import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedAccessorError; @Mixin(Player.class) @@ -57,6 +58,7 @@ public interface PlayerAccessor { @Accessor("DATA_SHOULDER_RIGHT") static EntityDataAccessor accessor$DATA_SHOULDER_RIGHT() { throw new UntransformedAccessorError(); } + @Invoker("getPermissionLevel") int invoker$getPermissionLevel(); @Accessor("sleepCounter") void accessor$sleepCounter(final int sleepCounter); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/BoatAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java similarity index 88% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/BoatAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java index 13c13fa8e5f..36f4de0698a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/BoatAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java @@ -24,13 +24,13 @@ */ package org.spongepowered.common.accessor.world.entity.vehicle; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(Boat.class) -public interface BoatAccessor { +@Mixin(AbstractBoat.class) +public interface AbstractBoatAccessor { - @Accessor("status") Boat.Status accessor$status(); + @Accessor("status") AbstractBoat.Status accessor$status(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/food/FoodDataAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/food/FoodDataAccessor.java index d01f6e281c3..4d7892de036 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/food/FoodDataAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/food/FoodDataAccessor.java @@ -37,4 +37,6 @@ public interface FoodDataAccessor { @Accessor("exhaustionLevel") void accessor$exhaustionLevel(final float exhaustionLevel); + @Accessor("exhaustionLevel") float accessor$exhaustionLevel(); + } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 0897ccebde8..ede87acc68c 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -118,7 +118,7 @@ "world.entity.raid.RaidAccessor", "world.entity.raid.RaiderAccessor", "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.BoatAccessor", + "world.entity.vehicle.AbstractBoatAccessor", "world.entity.vehicle.MinecartFurnaceAccessor", "world.food.FoodDataAccessor", "world.inventory.AbstractContainerMenuAccessor", diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/BoatBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/AbstractBoatBridge.java similarity index 97% rename from src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/BoatBridge.java rename to src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/AbstractBoatBridge.java index d39353485f8..a7318718bab 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/BoatBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/vehicle/AbstractBoatBridge.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.bridge.world.entity.vehicle; -public interface BoatBridge { +public interface AbstractBoatBridge { double bridge$getMaxSpeed(); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java index cbd0fae9ef6..d8653cb763d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java @@ -38,9 +38,9 @@ private LockableData() { public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(BaseContainerBlockEntityAccessor.class) - .create(Keys.LOCK_TOKEN) - .get(h -> h.accessor$lockKey().key()) - .set((h, v) -> h.accessor$lockKey(v.isEmpty() ? LockCode.NO_LOCK : new LockCode(v))); + .create(Keys.LOCK_TOKEN);// TODO - Implement Item Predicates +// .get(h -> h.accessor$lockKey().key()) +// .set((h, v) -> h.accessor$lockKey(v.isEmpty() ? LockCode.NO_LOCK : new LockCode(v))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java index 8fd0878b0fb..f5146dd7d27 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java @@ -24,13 +24,13 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.entity.vehicle.Boat; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.persistence.DataContentUpdater; -import org.spongepowered.api.data.type.BoatType; -import org.spongepowered.common.accessor.world.entity.vehicle.BoatAccessor; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.accessor.world.entity.vehicle.AbstractBoatAccessor; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; import org.spongepowered.common.data.ByteToBooleanContentUpdater; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -46,32 +46,29 @@ private BoatData() { // @formatter:off public static void register(final DataProviderRegistrator registrator) { registrator - .asMutable(Boat.class) - .create(Keys.BOAT_TYPE) - .get(h -> ((BoatType) (Object) h.getVariant())) - .set((h, v) -> h.setVariant((Boat.Type) (Object) v)) - .asMutable(BoatAccessor.class) + .asMutable(AbstractBoat.class) + .asMutable(AbstractBoatAccessor.class) .create(Keys.IS_IN_WATER) .get(h -> h.accessor$status() == Boat.Status.IN_WATER) - .asMutable(BoatBridge.class) + .asMutable(AbstractBoatBridge.class) .create(Keys.CAN_MOVE_ON_LAND) - .get(BoatBridge::bridge$getMoveOnLand) - .set(BoatBridge::bridge$setMoveOnLand) - .asMutable(BoatBridge.class) + .get(AbstractBoatBridge::bridge$getMoveOnLand) + .set(AbstractBoatBridge::bridge$setMoveOnLand) + .asMutable(AbstractBoatBridge.class) .create(Keys.OCCUPIED_DECELERATION) - .get(BoatBridge::bridge$getOccupiedDecelerationSpeed) - .set(BoatBridge::bridge$setOccupiedDecelerationSpeed) - .asMutable(BoatBridge.class) + .get(AbstractBoatBridge::bridge$getOccupiedDecelerationSpeed) + .set(AbstractBoatBridge::bridge$setOccupiedDecelerationSpeed) + .asMutable(AbstractBoatBridge.class) .create(Keys.MAX_SPEED) - .get(BoatBridge::bridge$getMaxSpeed) - .set(BoatBridge::bridge$setMaxSpeed) - .asMutable(BoatBridge.class) + .get(AbstractBoatBridge::bridge$getMaxSpeed) + .set(AbstractBoatBridge::bridge$setMaxSpeed) + .asMutable(AbstractBoatBridge.class) .create(Keys.UNOCCUPIED_DECELERATION) - .get(BoatBridge::bridge$getUnoccupiedDecelerationSpeed) - .set(BoatBridge::bridge$setUnoccupiedDecelerationSpeed) + .get(AbstractBoatBridge::bridge$getUnoccupiedDecelerationSpeed) + .set(AbstractBoatBridge::bridge$setUnoccupiedDecelerationSpeed) ; final ResourceKey boatDataStoreKey = ResourceKey.sponge("boat"); - registrator.spongeDataStore(boatDataStoreKey, 2, new DataContentUpdater[]{BoatData.BOAT_UPDATER_BYTE_TO_BOOL_FIX}, BoatBridge.class, + registrator.spongeDataStore(boatDataStoreKey, 2, new DataContentUpdater[]{BoatData.BOAT_UPDATER_BYTE_TO_BOOL_FIX}, AbstractBoatBridge.class, Keys.MAX_SPEED, Keys.CAN_MOVE_ON_LAND, Keys.OCCUPIED_DECELERATION, Keys.UNOCCUPIED_DECELERATION); SpongeDataManager.INSTANCE.registerLegacySpongeData(Constants.Entity.Boat.BOAT_MAX_SPEED, boatDataStoreKey, Keys.MAX_SPEED); SpongeDataManager.INSTANCE.registerLegacySpongeData(Constants.Entity.Boat.BOAT_MOVE_ON_LAND, boatDataStoreKey, Keys.CAN_MOVE_ON_LAND); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PlayerData.java index ba5b59f02f5..745bd8a8c1c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PlayerData.java @@ -60,7 +60,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (HandPreference) (Object) h.getMainArm()) .set((h, v) -> h.setMainArm((HumanoidArm) (Object) v)) .create(Keys.EXHAUSTION) - .get(h -> (double) h.getFoodData().getExhaustionLevel()) + .get(h -> (double) ((FoodDataAccessor) h.getFoodData()).accessor$exhaustionLevel()) .set((h, v) -> ((FoodDataAccessor) h.getFoodData()).accessor$exhaustionLevel(v.floatValue())) .create(Keys.EXPERIENCE) .get(h -> h.totalExperience) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java index bf4a788432b..a87303e42cf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java @@ -52,18 +52,18 @@ public static void register(final DataProviderRegistrator registrator) { return ((DyeColorBlockBridge) block).bridge$getDyeColor().orElse(null); }) .supports(h -> h.getItem() instanceof BlockItem && !(h.getItem() instanceof BannerItem)) - .create(Keys.LOCK_TOKEN) - .get(h -> { - var component = h.getOrDefault(DataComponents.LOCK, LockCode.NO_LOCK); - return component.key().isEmpty() ? null : component.key(); - }) - .set((h, v) -> { - if (v.isEmpty()) { - h.remove(DataComponents.LOCK); - return; - } - h.set(DataComponents.LOCK, new LockCode(v)); - }) + .create(Keys.LOCK_TOKEN) // TODO - Implement Item Predicates +// .get(h -> { +// var component = h.getOrDefault(DataComponents.LOCK, LockCode.NO_LOCK); +// return component.key().isEmpty() ? null : component.key(); +// }) +// .set((h, v) -> { +// if (v.isEmpty()) { +// h.remove(DataComponents.LOCK); +// return; +// } +// h.set(DataComponents.LOCK, new LockCode(v)); +// }) .delete(h -> h.remove(DataComponents.LOCK)) .supports(h -> { if (!(h.getItem() instanceof BlockItem)) { diff --git a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java index d71213c7d9f..93e62b4ed17 100644 --- a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java @@ -29,8 +29,10 @@ import org.spongepowered.api.entity.ai.goal.builtin.creature.AvoidLivingGoal; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.entity.living.PathfinderAgent; +import org.spongepowered.api.world.server.ServerWorld; import java.util.Objects; +import java.util.function.BiPredicate; import java.util.function.Predicate; public final class SpongeAvoidLivingGoalBuilder implements AvoidLivingGoal.Builder { @@ -69,7 +71,7 @@ public AvoidLivingGoal.Builder farRangeSpeed(double speed) { @Override public AvoidLivingGoal.Builder from(AvoidLivingGoal value) { - return this.targetSelector(value.targetSelector()) + return this.targetSelector((e) -> value.targetSelector().test(e, (ServerWorld) e.world())) .searchDistance(value.searchDistance()) .closeRangeSpeed(value.closeRangeSpeed()) .farRangeSpeed(value.farRangeSpeed()); diff --git a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/target/SpongeFindNearestAttackableTargetGoalBuilder.java b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/target/SpongeFindNearestAttackableTargetGoalBuilder.java index a85069f64e2..435b72001e8 100644 --- a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/target/SpongeFindNearestAttackableTargetGoalBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/target/SpongeFindNearestAttackableTargetGoalBuilder.java @@ -28,6 +28,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.targeting.TargetingConditions; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.ai.goal.builtin.creature.target.FindNearestAttackableTargetGoal; import org.spongepowered.api.entity.living.Living; @@ -40,7 +41,7 @@ public final class SpongeFindNearestAttackableTargetGoalBuilder extends SpongeTargetGoalBuilder implements FindNearestAttackableTargetGoal.Builder { - private static final Predicate ALWAYS_TRUE = e -> true; + private static final TargetingConditions.Selector ALWAYS_TRUE = (e, l) -> true; private Class targetClass; private int chance; @@ -94,6 +95,6 @@ public FindNearestAttackableTargetGoal build(PathfinderAgent owner) { Objects.requireNonNull(this.targetClass); return (FindNearestAttackableTargetGoal) new NearestAttackableTargetGoal((PathfinderMob) owner, this.targetClass, this.chance, - this.checkSight, this.checkOnlyNearby, this.predicate == null ? SpongeFindNearestAttackableTargetGoalBuilder.ALWAYS_TRUE : this.predicate); + this.checkSight, this.checkOnlyNearby, this.predicate == null ? SpongeFindNearestAttackableTargetGoalBuilder.ALWAYS_TRUE : (e, l) -> ((Predicate) this.predicate).test(l)); } } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 7b64ad7d24a..b1429318dec 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -503,7 +503,7 @@ public static DestructEntityEvent.Death callDestructEntityEventDeath(final Livin final DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(frame.currentCause(), originalChannel, Optional.of(originalChannel), originalMessage, originalMessage, (Living) entity, - entity.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY), messageCancelled); + ((ServerLevel) entity.level()).getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY), messageCancelled); SpongeCommon.post(event); return event; diff --git a/src/main/java/org/spongepowered/common/event/tracking/IPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/IPhaseState.java index c965ec699c7..4c9a41b9797 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/IPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/IPhaseState.java @@ -61,6 +61,7 @@ import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.World; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.server.TickTaskBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; @@ -160,12 +161,14 @@ default boolean isInteraction() { /** * Performs any necessary custom logic after the provided {@link BlockSnapshot} * {@link Transaction} has taken place. - * @param context The context for information + * + * @param context The context for information + * @param serverWorld * @param blockChange The block change performed - * @param receipt The transaction of the old and new snapshots + * @param receipt The transaction of the old and new snapshots */ default void postBlockTransactionApplication( - final C context, final BlockChange blockChange, + final C context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt receipt ) { } diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java index 9f2aa7307b0..78bc12d574b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseStateProxy.java @@ -53,6 +53,7 @@ import org.spongepowered.api.item.inventory.transaction.SlotTransaction; import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.BlockChangeFlag; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.server.TickTaskBridge; import org.spongepowered.common.bridge.world.TrackedWorldBridge; @@ -102,11 +103,13 @@ default boolean isInteraction() { /** * Performs any necessary custom logic after the provided {@link BlockSnapshot} * {@link Transaction} has taken place. - * @param blockChange The block change performed - * @param receipt The transaction of the old and new snapshots + * + * @param serverWorld + * @param blockChange The block change performed + * @param receipt The transaction of the old and new snapshots */ - default void postBlockTransactionApplication(final BlockChange blockChange, final BlockTransactionReceipt receipt) { - this.getState().postBlockTransactionApplication(this.asContext(), blockChange, receipt); + default void postBlockTransactionApplication(ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt receipt) { + this.getState().postBlockTransactionApplication(this.asContext(), serverWorld, blockChange, receipt); } /** diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/BlockTransactionType.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/BlockTransactionType.java index b8605f062fe..965ea025c85 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/BlockTransactionType.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/BlockTransactionType.java @@ -63,7 +63,7 @@ protected void consumeEventsAndMarker( eventsByWorld.asMap().forEach((key, events) -> { final Optional serverWorld = ((SpongeServer) SpongeCommon.server()).worldManager().world(key); - if (!serverWorld.isPresent()) { + if (serverWorld.isEmpty()) { return; } @@ -85,7 +85,7 @@ protected void consumeEventsAndMarker( final Operation operation = context.getBlockOperation(original, result); final BlockTransactionReceipt eventTransaction = new BlockTransactionReceipt(original, result, operation); transactions.add(eventTransaction); - context.postBlockTransactionApplication(original.blockChange, eventTransaction); + context.postBlockTransactionApplication(serverWorld.get(), original.blockChange, eventTransaction); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java index 43a9b373744..d365efa21f5 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java @@ -35,6 +35,7 @@ import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.event.cause.entity.SpawnTypes; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.entity.PlayerTracker; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -66,7 +67,7 @@ public BiConsumer getFrameMod @Override public void postBlockTransactionApplication( - final CommandPhaseContext context, final BlockChange blockChange, + final CommandPhaseContext context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt transaction ) { // We want to investigate if there is a user on the cause stack diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PacketCommandState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PacketCommandState.java index 30041525395..57d93ca2df8 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PacketCommandState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PacketCommandState.java @@ -37,6 +37,7 @@ import org.spongepowered.api.event.cause.entity.SpawnTypes; import org.spongepowered.api.event.entity.SpawnEntityEvent; import org.spongepowered.api.util.Tuple; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.TrackingUtil; import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; @@ -69,7 +70,7 @@ public BiConsumer getFr @Override public void postBlockTransactionApplication( - final PlayerCommandPhaseContext context, final BlockChange blockChange, + final PlayerCommandPhaseContext context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt transaction ) { // We want to investigate if there is a user on the cause stack diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PlaceBlockPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PlaceBlockPacketState.java index 5ba2f9e9330..660f5ec66da 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PlaceBlockPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/PlaceBlockPacketState.java @@ -87,7 +87,7 @@ public void populateContext(final net.minecraft.server.level.ServerPlayer player @Override public void postBlockTransactionApplication( - final BasicPacketContext context, final BlockChange blockChange, + final BasicPacketContext context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt transaction ) { TrackingUtil.associateTrackerToTarget(blockChange, transaction, ((ServerPlayer) context.getPacketPlayer()).uniqueId()); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/UseItemPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/UseItemPacketState.java index a07ab05571f..887044374d0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/UseItemPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/UseItemPacketState.java @@ -41,6 +41,7 @@ import org.spongepowered.api.event.cause.entity.SpawnTypes; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackSnapshot; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.entity.PlayerTracker; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -91,7 +92,7 @@ public void populateContext( @Override public void postBlockTransactionApplication( - final BasicPacketContext context, final BlockChange blockChange, + final BasicPacketContext context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt transaction ) { final ServerPlayer player = context.getSpongePlayer(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/BlockEventTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/BlockEventTickPhaseState.java index ab67914b419..c0bd38061b6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/BlockEventTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/BlockEventTickPhaseState.java @@ -34,6 +34,7 @@ import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.event.cause.entity.SpawnTypes; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.world.level.TrackableBlockEventDataBridge; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; @@ -84,7 +85,7 @@ public void associateNeighborStateNotifier( @Override public void postBlockTransactionApplication( - final BlockEventTickContext context, final BlockChange blockChange, + final BlockEventTickContext context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt receipt ) { final Block block = (Block) receipt.originalBlock().state().type(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java index 27405e72373..962b8c0cbd2 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java @@ -40,6 +40,7 @@ import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.event.cause.entity.SpawnTypes; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.accessor.world.entity.decoration.ItemFrameAccessor; import org.spongepowered.common.bridge.world.entity.EntityBridge; import org.spongepowered.common.bridge.world.entity.TrackableEntityBridge; @@ -124,7 +125,7 @@ protected EntityTickContext createNewContext(final PhaseTracker tracker) { @Override public void postBlockTransactionApplication( - final EntityTickContext context, final BlockChange blockChange, + final EntityTickContext context, final ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt transaction ) { if (blockChange == BlockChange.BREAK) { @@ -159,12 +160,11 @@ public void postBlockTransactionApplication( return false; }); for (final HangingEntity entityHanging : hangingEntities) { - if (entityHanging instanceof ItemFrame) { - final ItemFrame itemFrame = (ItemFrame) entityHanging; - if (!itemFrame.isRemoved()) { - ((ItemFrameAccessor) itemFrame).invoker$dropItem((net.minecraft.world.entity.Entity) tickingEntity, true); + if (entityHanging instanceof ItemFrame iframe) { + if (!iframe.isRemoved()) { + ((ItemFrameAccessor) iframe).invoker$dropItem((ServerLevel) serverWorld, (net.minecraft.world.entity.Entity) tickingEntity, true); } - itemFrame.remove(net.minecraft.world.entity.Entity.RemovalReason.DISCARDED); + iframe.remove(net.minecraft.world.entity.Entity.RemovalReason.DISCARDED); } } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java index edb6df776fb..c6c59b088f8 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java @@ -35,6 +35,7 @@ import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.world.LocatableBlock; import org.spongepowered.api.world.World; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.level.TrackableBlockEventDataBridge; @@ -122,7 +123,7 @@ public void appendContextPreExplosion(final ExplosionContext explosionContext, f @Override public void postBlockTransactionApplication( - final T context, final BlockChange blockChange, + final T context, ServerWorld serverWorld, final BlockChange blockChange, final BlockTransactionReceipt receipt ) { // If we do not have a notifier at this point then there is no need to attempt to retrieve one from the chunk diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 7fbcc93da10..338da482292 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -166,7 +166,6 @@ private void loadEnumRegistries() { map.put(AttributeModifier.Operation.ADD_MULTIPLIED_BASE, "multiply_base"); map.put(AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL, "multiply_total"); }); - this.automaticName(RegistryTypes.BOAT_TYPE, Boat.Type.values()); this.automaticName(RegistryTypes.CHEST_ATTACHMENT_TYPE, ChestType.values()); this.automaticName(RegistryTypes.COLLISION_RULE, Team.CollisionRule.values()); this.automaticName(RegistryTypes.COMPARATOR_MODE, ComparatorMode.values()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorMixin_API.java index 245d0d91b4f..c4c927d18ff 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorMixin_API.java @@ -28,6 +28,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandCause; @@ -63,7 +64,7 @@ public Collection select(@NonNull final ServerLocation location) throws @Override @NonNull public Collection select(@NonNull final Entity entity) throws IllegalStateException { - return this.api$select(((net.minecraft.world.entity.Entity) entity).createCommandSourceStack()); + return this.api$select(((net.minecraft.world.entity.Entity) entity).createCommandSourceStackForNameResolution(((ServerLevel) ((net.minecraft.world.entity.Entity) entity).level()))); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index ed797b1ede1..63ba4343956 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -32,6 +32,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -98,7 +99,7 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.En @Shadow @Nullable public abstract MinecraftServer shadow$getServer(); @Shadow public abstract boolean shadow$isRemoved(); @Shadow public abstract UUID shadow$getUUID(); - @Shadow public abstract boolean shadow$hurt(DamageSource source, float amount); + @Shadow public abstract boolean shadow$hurtOrSimulate(DamageSource source, float amount); @Shadow protected abstract void shadow$setRot(float yaw, float pitch); @Shadow public abstract net.minecraft.world.phys.AABB shadow$getBoundingBox(); @Shadow public abstract void shadow$setRemoved(Entity.RemovalReason var1); @@ -108,7 +109,6 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.En @Shadow public abstract Level shadow$level(); // @formatter:on - @Override public Source random() { return (Source) this.random; @@ -237,6 +237,8 @@ public boolean isLoaded() { this.shadow$setRemoved(Entity.RemovalReason.DISCARDED); } + + @Override public boolean damage(final double damage, final org.spongepowered.api.event.cause.entity.damage.source.DamageSource damageSource) { if (!(damageSource instanceof DamageSource)) { @@ -244,7 +246,7 @@ public boolean damage(final double damage, final org.spongepowered.api.event.cau return false; } // Causes at this point should already be pushed from plugins before this point with the cause system. - return this.shadow$hurt((DamageSource) damageSource, (float) damage); + return this.shadow$hurtOrSimulate((DamageSource) damageSource, (float) damage); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java index 6b54348d93e..208b9805d88 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java @@ -29,19 +29,21 @@ import org.spongepowered.api.entity.ai.goal.builtin.creature.AvoidLivingGoal; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.entity.living.PathfinderAgent; +import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.accessor.world.entity.ai.targeting.TargetingConditionsAccessor; +import java.util.function.BiPredicate; import java.util.function.Predicate; @SuppressWarnings({"unchecked"}) @Mixin(net.minecraft.world.entity.ai.goal.AvoidEntityGoal.class) public abstract class AvoidEntityGoalMixin_API extends GoalMixin_API implements AvoidLivingGoal { - private static final Predicate ALWAYS_TRUE = e -> true; + private static final BiPredicate ALWAYS_TRUE = (e, l) -> true; // @formatter:off @Shadow @Final @Mutable private double walkSpeedModifier; @@ -51,14 +53,14 @@ public abstract class AvoidEntityGoalMixin_API extends GoalMixin_API targetSelector() { - final Predicate predicate = ((TargetingConditionsAccessor) this.avoidEntityTargeting).accessor$selector(); - return (Predicate) (Object) (predicate == null ? AvoidEntityGoalMixin_API.ALWAYS_TRUE : predicate); + public BiPredicate targetSelector() { + final TargetingConditions.Selector predicate = ((TargetingConditionsAccessor) this.avoidEntityTargeting).accessor$selector(); + return (BiPredicate) (Object) (predicate == null ? AvoidEntityGoalMixin_API.ALWAYS_TRUE : predicate); } @Override - public AvoidLivingGoal setTargetSelector(Predicate predicate) { - this.avoidEntityTargeting.selector((Predicate) (Object) predicate); + public AvoidLivingGoal setTargetSelector(BiPredicate predicate) { + this.avoidEntityTargeting.selector((TargetingConditions.Selector) predicate); return this; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoalMixin_API.java index ed9aa85e4b6..00f45740062 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoalMixin_API.java @@ -74,13 +74,13 @@ public FindNearestAttackableTargetGoal setChance(int chance) { @Override public FindNearestAttackableTargetGoal filter(Predicate predicate) { - this.targetConditions.selector(((Predicate) (Object) predicate)); + this.targetConditions.selector((e, l) -> predicate.test((Living) l)); return this; } @Override public Predicate filter() { - final Predicate predicate = ((TargetingConditionsAccessor) this.targetConditions).accessor$selector(); + final TargetingConditions.Selector predicate = ((TargetingConditionsAccessor) this.targetConditions).accessor$selector(); return (Predicate) (Object) (predicate == null ? NearestAttackableTargetGoalMixin_API.ALWAYS_TRUE : predicate); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireworkRocketEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireworkRocketEntityMixin_API.java index ac21fff7c71..9ef8325893a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireworkRocketEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireworkRocketEntityMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -39,13 +40,15 @@ public abstract class FireworkRocketEntityMixin_API extends ProjectileMixin_API // @formatter:off @Shadow private int life; @Shadow private int lifetime; - @Shadow protected abstract void shadow$explode(); + @Shadow protected abstract void shadow$explode(ServerLevel level); // @formatter:on @Override public void detonate() { this.life = this.lifetime + 1; - this.shadow$explode(); + if (this.shadow$level() instanceof ServerLevel sl) { + this.shadow$explode(sl); + } } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java index 3fcf7053f0b..9fdae239297 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.projectile.LargeFireball; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; @@ -43,8 +44,9 @@ public abstract class LargeFireballMixin_API extends FireballMixin_API implement @Override public void detonate() { - final boolean causesFire = this.shadow$getCommandSenderWorld().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); - ((LargeFireballBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), this.explosionPower, causesFire, Level.ExplosionInteraction.MOB); + if (this.shadow$level() instanceof ServerLevel sl && sl.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + ((LargeFireballBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), this.explosionPower, true, Level.ExplosionInteraction.MOB); + } this.shadow$discard(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/BoatMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/BoatMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java index 2b7e87f7f52..a3c3c926942 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/BoatMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java @@ -34,15 +34,14 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.vehicle.Boat.class) +@Mixin(net.minecraft.world.entity.vehicle.AbstractBoat.class) @Implements(@Interface(iface = Boat.class, prefix = "apiBoat$")) -public abstract class BoatMixin_API extends EntityMixin_API implements Boat { +public abstract class AbstractBoatMixin_API extends EntityMixin_API implements Boat { @Override protected Set> api$getVanillaValues() { final Set> values = super.api$getVanillaValues(); - values.add(this.requireValue(Keys.BOAT_TYPE).asImmutable()); values.add(this.requireValue(Keys.CAN_MOVE_ON_LAND).asImmutable()); values.add(this.requireValue(Keys.IS_IN_WATER).asImmutable()); values.add(this.requireValue(Keys.MAX_SPEED).asImmutable()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/ChestBoatMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/ChestBoatMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java index 1f1abb933dd..ee842169990 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/ChestBoatMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java @@ -30,8 +30,8 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.vehicle.ChestBoat.class) -public abstract class ChestBoatMixin_API extends BoatMixin_API implements ChestBoat { +@Mixin(net.minecraft.world.entity.vehicle.AbstractChestBoat.class) +public abstract class AbstractChestBoatMixin_API extends AbstractBoatMixin_API implements ChestBoat { @Override protected Set> api$getVanillaValues() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java deleted file mode 100644 index 3011507b930..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/Boat_TypeMixin_API.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; - -import net.minecraft.world.entity.vehicle.Boat; -import org.spongepowered.api.data.type.BoatType; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(Boat.Type.class) -public abstract class Boat_TypeMixin_API implements BoatType { - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BaseContainerBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BaseContainerBlockEntityMixin_API.java index 02911fdedda..a5a0fdfbcdb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BaseContainerBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BaseContainerBlockEntityMixin_API.java @@ -54,9 +54,10 @@ public abstract class BaseContainerBlockEntityMixin_API extends BlockEntityMixin @Override public DataContainer toContainer() { final DataContainer container = super.toContainer(); - if (this.lockKey != null) { - container.set(Constants.TileEntity.LOCK_CODE, this.lockKey.key()); - } + // TODO - figure out lock code serialization +// if (this.lockKey != null) { +// container.set(Constants.TileEntity.LOCK_CODE, this.lockKey.key()); +// } final List items = Lists.newArrayList(); for (int i = 0; i < ((Container) this).getContainerSize(); i++) { final ItemStack stack = ((Container) this).getItem(i); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java index ce24f3c9beb..8de4402c106 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java @@ -45,7 +45,6 @@ public interface LevelDataMixin_API extends WorldProperties { // @formatter:off @Shadow long shadow$getGameTime(); @Shadow long shadow$getDayTime(); - @Shadow GameRules shadow$getGameRules(); // @formatter:on @Override @@ -58,48 +57,4 @@ default MinecraftDayTime dayTime() { return new SpongeMinecraftDayTime(this.shadow$getDayTime()); } - @Override - default V gameRule(final GameRule gameRule) { - final GameRules.Value value = this.shadow$getGameRules().getRule((GameRules.Key) (Object) Objects.requireNonNull(gameRule, - "gameRule")); - if (value instanceof GameRules.BooleanValue) { - return (V) Boolean.valueOf(((GameRules.BooleanValue) value).get()); - } else if (value instanceof GameRules.IntegerValue) { - return (V) Integer.valueOf(((GameRules.IntegerValue) value).get()); - } - return null; - } - - @Override - default void setGameRule(final GameRule gameRule, final V value) { - Objects.requireNonNull(gameRule, "gameRule"); - Objects.requireNonNull(value, "value"); - - final GameRules.Value mValue = this.shadow$getGameRules().getRule((GameRules.Key) (Object) gameRule); - ((GameRules_ValueAccessor) mValue).invoker$deserialize(value.toString()); - } - - @Override - default Map, ?> gameRules() { - final Map, GameRules.Value> rules = - ((GameRulesAccessor) this.shadow$getGameRules()).accessor$rules(); - - final Map, Object> apiRules = new HashMap<>(); - for (final Map.Entry, GameRules.Value> rule : rules.entrySet()) { - final GameRule key = (GameRule) (Object) rule.getKey(); - final GameRules.Value mValue = rule.getValue(); - Object value = null; - if (mValue instanceof GameRules.BooleanValue) { - value = ((GameRules.BooleanValue) mValue).get(); - } else if (mValue instanceof GameRules.IntegerValue) { - value = ((GameRules.IntegerValue) mValue).get(); - } - - if (value != null) { - apiRules.put(key, value); - } - } - - return apiRules; - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java index b38594bf530..d9238aab2fc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java @@ -24,20 +24,26 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.storage.ServerLevelData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.trader.WanderingTrader; import org.spongepowered.api.util.MinecraftDayTime; import org.spongepowered.api.util.Ticks; +import org.spongepowered.api.world.gamerule.GameRule; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.api.world.weather.Weather; import org.spongepowered.api.world.weather.WeatherType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.world.level.GameRulesAccessor; +import org.spongepowered.common.accessor.world.level.GameRules_ValueAccessor; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -54,8 +60,55 @@ public interface ServerLevelDataMixin_API extends ServerWorldProperties { @Shadow void shadow$setWanderingTraderId(UUID p_230394_1_); @Shadow @Nullable UUID shadow$getWanderingTraderId(); @Shadow void shadow$setDayTime(long p_76068_1_); + @Shadow GameRules shadow$getGameRules(); // @formatter:on + + @Override + default V gameRule(GameRule gameRule) { + final GameRules.Value value = this.shadow$getGameRules().getRule((GameRules.Key) (Object) Objects.requireNonNull(gameRule, + "gameRule")); + if (value instanceof GameRules.BooleanValue) { + return (V) Boolean.valueOf(((GameRules.BooleanValue) value).get()); + } else if (value instanceof GameRules.IntegerValue) { + return (V) Integer.valueOf(((GameRules.IntegerValue) value).get()); + } + return null; + } + + @Override + default void setGameRule(final GameRule gameRule, final V value) { + Objects.requireNonNull(gameRule, "gameRule"); + Objects.requireNonNull(value, "value"); + + final GameRules.Value mValue = this.shadow$getGameRules().getRule((GameRules.Key) (Object) gameRule); + ((GameRules_ValueAccessor) mValue).invoker$deserialize(value.toString()); + } + + @Override + default Map, ?> gameRules() { + final Map, GameRules.Value> rules = + ((GameRulesAccessor) this.shadow$getGameRules()).accessor$rules(); + + final Map, Object> apiRules = new HashMap<>(); + for (final Map.Entry, GameRules.Value> rule : rules.entrySet()) { + final GameRule key = (GameRule) (Object) rule.getKey(); + final GameRules.Value mValue = rule.getValue(); + Object value = null; + if (mValue instanceof GameRules.BooleanValue) { + value = ((GameRules.BooleanValue) mValue).get(); + } else if (mValue instanceof GameRules.IntegerValue) { + value = ((GameRules.IntegerValue) mValue).get(); + } + + if (value != null) { + apiRules.put(key, value); + } + } + + return apiRules; + } + @Override default void setDayTime(final MinecraftDayTime dayTime) { this.shadow$setDayTime(dayTime.asTicks().ticks()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java index bcb20b4169b..e81e9559941 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java @@ -55,6 +55,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.accessor.commands.CommandSourceStackAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; +import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -116,9 +117,9 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg context.get(EventContextKeys.ROTATION).ifPresent(x -> this.rotation = new Vec2((float) x.x(), (float) x.y())); context.get(EventContextKeys.SUBJECT).ifPresent(x -> { - if (x instanceof EntityAccessor) { - this.permissionLevel = ((EntityAccessor) x).invoker$getPermissionLevel(); - } else if (x instanceof MinecraftServer && !((MinecraftServer) x).isSingleplayer()) { + if (x instanceof PlayerAccessor pa) { + this.permissionLevel = pa.invoker$getPermissionLevel(); + } else if (x instanceof MinecraftServer ms && !ms.isSingleplayer()) { this.permissionLevel = 4; } }); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java index 5edc7f26754..0ef1e4de132 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java @@ -24,14 +24,16 @@ */ package org.spongepowered.common.mixin.core.nbt; +import com.google.common.base.Function; +import com.google.common.collect.Maps; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import org.apache.logging.log4j.Level; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.util.PrettyPrinter; @@ -54,11 +56,10 @@ public abstract class CompoundTagMixin { @Shadow @Final private Map tags; // @formatter:on - @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/Tag;copy()Lnet/minecraft/nbt/Tag;")) - @Nullable - private Tag impl$checkForOverflowOnCopy(Tag inbt) { - try { - return inbt == null ? null : inbt.copy(); + @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;transformValues(Ljava/util/Map;Lcom/google/common/base/Function;)Ljava/util/Map;")) + private Map impl$checkForOverflowOnCopy(Map fromMap, Function function) { + return Maps.transformValues(fromMap, (tag) -> {try { + return tag == null ? null : tag.copy(); } catch (StackOverflowError e) { final PrettyPrinter printer = new PrettyPrinter(60) .add("StackOverflow from trying to copy this compound") @@ -86,22 +87,22 @@ public abstract class CompoundTagMixin { printer.add(); printer.log(SpongeCommon.logger(), Level.ERROR); return null; - } + }}); } - @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;")) - private Tag impl$checkForNullNBTValuesDuringCopy(CompoundTag compound, String key, Tag value) { - if (value == null) { - final IllegalStateException exception = new IllegalStateException("There is a null NBT component in the compound for key: " + key); - SpongeCommon.logger().error("Printing out a stacktrace to catch an exception in performing an NBTTagCompound.copy!\n" - + "If you are seeing this, then Sponge is preventing an exception from being thrown due to unforseen\n" - + "possible bugs in any mods present. Please report this to SpongePowered and/or the relative mod\n" - + "authors for the offending compound data!", exception); - } else { - compound.put(key, value); - } - - return value; + @ModifyArg(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;(Ljava/util/Map;)V")) + private Map impl$checkForNullNBTValuesDuringCopy(Map map) { + return Maps.newHashMap(Maps.filterEntries(map, entry -> { + if (entry.getValue() == null) { + final IllegalStateException exception = new IllegalStateException("There is a null NBT component in the compound for key: " + entry.getKey()); + SpongeCommon.logger().error("Printing out a stacktrace to catch an exception in performing an NBTTagCompound.copy!\n" + + "If you are seeing this, then Sponge is preventing an exception from being thrown due to unforseen\n" + + "possible bugs in any mods present. Please report this to SpongePowered and/or the relative mod\n" + + "authors for the offending compound data!", exception); + return false; + } + return true; + })); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java index c841d31eee9..06440f66c08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java @@ -38,11 +38,11 @@ public abstract class GameRuleCommandMixin { @Redirect(method = "setRule", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getGameRules()Lnet/minecraft/world/level/GameRules;")) private static GameRules impl$usePerWorldGameRules(final MinecraftServer server, final CommandContext context) { - return context.getSource().getLevel().getLevelData().getGameRules(); + return context.getSource().getLevel().getGameRules(); } @Redirect(method = "queryRule", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getGameRules()Lnet/minecraft/world/level/GameRules;")) private static GameRules impl$usePerWorldGameRules(final MinecraftServer server, final CommandSourceStack source) { - return source.getLevel().getLevelData().getGameRules(); + return source.getLevel().getGameRules(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 836cc0e4aa6..06f667ffb7d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -321,7 +321,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Override public boolean bridge$keepInventory() { if (this.impl$keepInventory == null) { - return this.shadow$level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); + return this.shadow$serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); } return this.impl$keepInventory; } @@ -638,7 +638,7 @@ public void die(final DamageSource cause) { } // Sponge end - final var level = this.shadow$level(); + final var level = this.shadow$serverLevel(); final boolean flag = level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES) && !event.isMessageCancelled(); if (flag) { final net.minecraft.network.chat.Component component = this.shadow$getCombatTracker().getDeathMessage(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 238e99fadfa..b542809e3f4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -32,6 +32,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -163,9 +164,9 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract void shadow$setInvisible(boolean invisible); @Shadow public abstract EntityType shadow$getType(); @Shadow public abstract void shadow$teleportTo(double x, double y, double z); - @Shadow public abstract CommandSourceStack shadow$createCommandSourceStack(); + @Shadow public abstract CommandSourceStack shadow$createCommandSourceStackForNameResolution(ServerLevel level); @Shadow public abstract net.minecraft.world.phys.Vec3 shadow$position(); - @Shadow @Nullable public abstract ItemEntity shadow$spawnAtLocation(ItemStack stack, float offsetY); + @Shadow @Nullable public abstract ItemEntity shadow$spawnAtLocation(ServerLevel $$0, ItemStack stack, float offsetY); @Shadow @Nullable public abstract Entity shadow$getVehicle(); @Shadow public abstract AABB shadow$getBoundingBox(); @Shadow @Nullable public abstract PlayerTeam shadow$getTeam(); @@ -176,7 +177,6 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract void shadow$setDeltaMovement(net.minecraft.world.phys.Vec3 motion); @Shadow public abstract void shadow$unRide(); @Shadow protected abstract void shadow$removeAfterChangingDimensions(); - @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract float shadow$getYRot(); @Shadow public abstract float shadow$getXRot(); @Shadow public abstract void shadow$setYRot(final float param0); @@ -420,7 +420,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.shadow$createCommandSourceStack(); + return this.shadow$createCommandSourceStackForNameResolution((ServerLevel) this.shadow$level()); } /** @@ -659,23 +659,20 @@ public void stopRiding() { @Redirect(method = "lavaHurt", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z" + target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z" ) ) - private boolean impl$createLavaBlockDamageSource(final Entity entity, final DamageSource source, final float damage) { - if (this.shadow$level().isClientSide) { // Short circuit - return entity.hurt(source, damage); - } + private boolean impl$createLavaBlockDamageSource(final Entity instance, ServerLevel serverLevel, DamageSource source, float damage) { final AABB bb = this.shadow$getBoundingBox().inflate(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D); - final ServerLocation location = DamageEventUtil.findFirstMatchingBlock((Entity) (Object) this, bb, block -> + final ServerLocation location = DamageEventUtil.findFirstMatchingBlock(instance, bb, block -> block.is(Blocks.LAVA) || block.getBlock() instanceof LavaCauldronBlock); if (location != null) { var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) .block(location.createSnapshot()).build(); - return entity.hurt((DamageSource) blockSource, damage); + return instance.hurtServer(serverLevel, (DamageSource) blockSource, damage); } - return entity.hurt(source, damage); + return instance.hurtServer(serverLevel, source, damage); } @Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;collide(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;")) @@ -765,18 +762,12 @@ public void stopRiding() { } - /** - * @author gabizou - January 4th, 2016 - * @reason gabizou - January 27th, 2016 - Rewrite to a redirect - *

- * This prevents sounds from being sent to the server by entities that are vanished - */ - - @Redirect(method = "playSound", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;isSilent()Z")) - private boolean impl$checkIsSilentOrInvis(final Entity entity) { - return entity.isSilent() || !this.bridge$vanishState().createsSounds(); + @Redirect(method = "isSilent", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/network/syncher/SynchedEntityData;get(Lnet/minecraft/network/syncher/EntityDataAccessor;)Ljava/lang/Object;" + )) + private Object impl$checkIsSilentOrInvis(final SynchedEntityData data, final EntityDataAccessor key) { + return data.get(key) || !this.bridge$vanishState().createsSounds(); } @Redirect(method = "push(Lnet/minecraft/world/entity/Entity;)V", @@ -826,18 +817,18 @@ public void stopRiding() { */ @Inject( - method = "spawnAtLocation(Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", + method = "spawnAtLocation(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("HEAD"), cancellable = true ) public void impl$throwDropItemConstructEvent( - final ItemStack stack, final float offsetY, final CallbackInfoReturnable cir + final ServerLevel serverLevel, ItemStack stack, float offsetY, CallbackInfoReturnable cir ) { if (stack.isEmpty()) { cir.setReturnValue(null); return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + if (((LevelBridge) serverLevel).bridge$isFake()) { return; } // Now the real fun begins. @@ -863,7 +854,7 @@ public void stopRiding() { } final ItemEntity entityitem = new ItemEntity(this.shadow$level(), posX, posY, posZ, item); entityitem.setDefaultPickUpDelay(); - this.shadow$level().addFreshEntity(entityitem); + serverLevel.addFreshEntity(entityitem); cir.setReturnValue(entityitem); } } @@ -946,16 +937,13 @@ public void stopRiding() { @Redirect(method = "thunderHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) private boolean impl$ThrowDamageEventWithLightingSource( - final Entity entity, final DamageSource source, final float damage, + final Entity entity, final ServerLevel serverLevel, final DamageSource source, final float damage, final ServerLevel level, final LightningBolt lightningBolt ) { - if (!this.shadow$level().isClientSide) { - return entity.hurt(source, damage); - } var entitySource = new DamageSource(source.typeHolder(), lightningBolt); - return entity.hurt(entitySource, damage); + return entity.hurtServer(serverLevel, entitySource, damage); } @Inject(method = "getFireImmuneTicks", at = @At(value = "HEAD"), cancellable = true) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java index 0a56467684a..451d8b72663 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ExperienceOrb; @@ -45,9 +46,9 @@ public abstract class ExperienceOrbMixin extends EntityMixin { this.impl$callExpireEntityEvent(); } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ExperienceOrb;markHurt()V")) - private void attackImpl$onAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index fcca3360918..aeec908009f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -104,12 +104,12 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public abstract int shadow$getUseItemRemainingTicks(); @Shadow public abstract float shadow$getHealth(); @Shadow public abstract CombatTracker shadow$getCombatTracker(); - @Shadow public void shadow$kill() { } + @Shadow public void shadow$kill(ServerLevel level) { } @Shadow public abstract InteractionHand shadow$getUsedItemHand(); @Shadow public abstract Optional shadow$getSleepingPos(); @Shadow protected abstract void shadow$spawnItemParticles(ItemStack stack, int count); @Shadow public abstract ItemStack shadow$getItemInHand(InteractionHand hand); - @Shadow protected abstract void shadow$dropEquipment(); + @Shadow protected abstract void shadow$dropEquipment(ServerLevel level); @Shadow protected abstract void shadow$dropAllDeathLoot(ServerLevel level, DamageSource damageSourceIn); @Shadow @Nullable public abstract LivingEntity shadow$getKillCredit(); @Shadow protected abstract void shadow$createWitherRose(@Nullable LivingEntity p_226298_1_); @@ -172,14 +172,14 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;dropEquipment()V" + target = "Lnet/minecraft/world/entity/LivingEntity;dropEquipment(Lnet/minecraft/server/level/ServerLevel;)V" ) ) - private void tracker$dropInventory(final LivingEntity thisEntity) { + private void tracker$dropInventory(final LivingEntity thisEntity, final ServerLevel level) { if (thisEntity instanceof PlayerBridge && ((PlayerBridge) thisEntity).bridge$keepInventory()) { return; } - this.shadow$dropEquipment(); + this.shadow$dropEquipment(level); } @Inject(method = "pushEntities", at = @At("HEAD"), cancellable = true) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 19af0cfbaac..e8c3d229ae9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.stats.Stats; @@ -87,8 +88,8 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Forge onLivingAttack Hook */ - @Inject(method = "hurt", at = @At("HEAD"), cancellable = true) - private void attackImpl$beforeHurt(final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { + @Inject(method = "hurtServer", at = @At("HEAD"), cancellable = true) + private void attackImpl$beforeHurt(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { if (source == null) { new PrettyPrinter(60).centre().add("Null DamageSource").hr() .addWrapped("Sponge has found a null damage source! This should NEVER happen " @@ -110,8 +111,8 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Prepare {@link org.spongepowered.common.util.DamageEventUtil.Hurt} for damage event */ - @Inject(method = "hurt", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I")) - private void attackImpl$preventEarlyBlock1(final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { + @Inject(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I")) + private void attackImpl$preventEarlyBlock1(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { this.attackImpl$hurt = new DamageEventUtil.Hurt($$0, new ArrayList<>()); } @@ -119,7 +120,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * Prevents shield usage before event * Captures the blocked damage as a function */ - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V")) private void attackImpl$preventEarlyBlock1(final LivingEntity instance, final float damageToShield) { // this.hurtCurrentlyUsedShield(damageToShield); this.attackImpl$hurt.functions().add(DamageEventUtil.createShieldFunction(instance)); @@ -128,7 +129,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Prevents shield usage before event */ - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V")) private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final LivingEntity livingDamageSource) { // this.blockUsingShield(livingDamageSource); } @@ -136,8 +137,8 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Capture the bonus freezing damage as a function */ - @Inject(method = "hurt", at = @At(value = "CONSTANT", args = "floatValue=5.0F")) - private void attackImpl$freezingBonus(final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { + @Inject(method = "hurtServer", at = @At(value = "CONSTANT", args = "floatValue=5.0F")) + private void attackImpl$freezingBonus(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { this.attackImpl$hurt.functions().add(DamageEventUtil.createFreezingBonus((LivingEntity) (Object) this, $$0, 5.0F)); } @@ -145,7 +146,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * Prevents {@link #shadow$hurtHelmet} before the event * Captures the hard hat damage reduction as a function */ - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V")) private void attackImpl$hardHat(final LivingEntity instance, final DamageSource $$0, final float $$1) { // this.hurtHelmet($$0, $$1); this.attackImpl$hurt.functions().add(DamageEventUtil.createHardHatModifier(instance.getItemBySlot(EquipmentSlot.HEAD), 0.75F)); @@ -155,21 +156,21 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * Capture the old values to reset if we end up cancelling or blocking. * Also reset {@link #attackImpl$wasInInvulnerableTime} */ - @Inject(method = "hurt", at = @At(value = "FIELD", + @Inject(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;walkAnimation:Lnet/minecraft/world/entity/WalkAnimationState;")) - private void attackImpl$beforeActuallyHurt(final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { + private void attackImpl$beforeActuallyHurt(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { // Save old values this.attackImpl$lastHurt = this.lastHurt; this.attackImpl$InvulnerableTime = this.invulnerableTime; this.attackImpl$actuallyHurtCancelled = false; } - @ModifyArg(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 0)) + @ModifyArg(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 0)) private float attackImp$useBaseDamage1(final float $$0) { return this.attackImpl$baseDamage - this.attackImpl$lastHurt; } - @ModifyArg(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 1)) + @ModifyArg(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 1)) private float attackImp$useBaseDamage2(final float $$0) { return this.attackImpl$baseDamage; } @@ -178,14 +179,13 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * After calling #actuallyHurt (even when invulnerable), if cancelled return early or is still invulnerable * and reset {@link #lastHurt} and {@link #invulnerableTime} */ - @Inject(method = "hurt", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, + @Inject(method = "hurtServer", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, - target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt1(final DamageSource $$0, - final float damageTaken, - final CallbackInfoReturnable cir, - final float dealtDamage, - final boolean isBlocked + target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void attackImpl$afterActuallyHurt1( + final ServerLevel level, final DamageSource source, final float damageTaken, + final CallbackInfoReturnable cir, final float dealtDamage, final boolean isBlocked, + float $$5, boolean wasHurt ) { if (this.attackImpl$actuallyHurtCancelled || damageTaken <= this.lastHurt) { this.invulnerableTime = this.attackImpl$InvulnerableTime; @@ -198,15 +198,10 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * After calling #actuallyHurt, if cancelled return early * Also reset values */ - @Inject(method = "hurt", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, + @Inject(method = "hurtServer",cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 1, - target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt2(final DamageSource $$0, - final float damageTaken, - final CallbackInfoReturnable cir, - final float dealtDamage, - final boolean isBlocked - ) { + target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void attackImpl$afterActuallyHurt2(ServerLevel $$0, DamageSource $$1, float $$2, CallbackInfoReturnable cir) { if (this.attackImpl$actuallyHurtCancelled) { this.invulnerableTime = this.attackImpl$InvulnerableTime; cir.setReturnValue(false); @@ -217,10 +212,10 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Set final damage after #actuallyHurt and lastHurt has been set. */ - @ModifyVariable(method = "hurt", argsOnly = true, + @ModifyVariable(method = "hurtServer", argsOnly = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;getEntity()Lnet/minecraft/world/entity/Entity;"), slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;getEntity()Lnet/minecraft/world/entity/Entity;"))) private float attackImpl$modifyDamageTaken(float damageTaken) { return this.attackImpl$actuallyHurtFinalDamage; @@ -229,7 +224,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin /** * Sets blocked damage after #actuallyHurt */ - @ModifyVariable(method = "hurt", ordinal = 2, + @ModifyVariable(method = "hurtServer", ordinal = 2, at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/damagesource/DamageSource;FFZ)V", shift = At.Shift.AFTER)) @@ -237,14 +232,14 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin return this.attackImpl$actuallyHurtBlockedDamage; } - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) private void attackImpl$onHurtSound(final LivingEntity instance, final DamageSource $$0) { if (this.bridge$vanishState().createsSounds()) { this.shadow$playHurtSound($$0); } } - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) private void attackImpl$onMakeSound(final LivingEntity instance, final SoundEvent $$0) { if (this.bridge$vanishState().createsSounds()) { instance.makeSound($$0); @@ -252,9 +247,10 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin } @Redirect(method = "actuallyHurt", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;isInvulnerableTo(Lnet/minecraft/world/damagesource/DamageSource;)Z")) - public boolean attackImpl$startActuallyHurt(final LivingEntity instance, final DamageSource damageSource, final DamageSource $$0, final float originalDamage) { - if (instance.isInvulnerableTo(damageSource)) { + target = "Lnet/minecraft/world/entity/LivingEntity;isInvulnerableTo(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)Z")) + public boolean attackImpl$startActuallyHurt(final LivingEntity instance, final ServerLevel level, final DamageSource damageSource, + final ServerLevel redundant, final DamageSource redundant2, final float originalDamage) { + if (instance.isInvulnerableTo(level, damageSource)) { return true; } @@ -424,7 +420,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin * also reverts {@link #attackImpl$beforeActuallyHurt} */ @Inject(method = "actuallyHurt", at = @At("RETURN")) - public void attackImpl$cleanupActuallyHurt(final DamageSource $$0, final float $$1, final CallbackInfo ci) { + public void attackImpl$cleanupActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { this.attackImpl$handlePostDamage(); this.attackImpl$actuallyHurt = null; this.attackImpl$actuallyHurtResult = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 9649c89ee30..530c2f8de59 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -27,10 +27,8 @@ import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.ai.control.MoveControl; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.Entity; @@ -69,11 +67,6 @@ public abstract class MobMixin extends LivingEntityMixin { @Shadow protected abstract void shadow$registerGoals(); // @formatter:on - - @Shadow public abstract boolean wantsToPickUp(final ItemStack $$0); - - @Shadow protected MoveControl moveControl; - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;registerGoals()V")) private void impl$registerGoals(final Mob this$0) { this.impl$setupGoalSelectors(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java index 4142c751fad..9de678c164e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java @@ -50,8 +50,8 @@ public abstract class MobMixin_Attack_Impl extends LivingEntityMixin_Attack_Impl } @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - private boolean attackImpl$onCanGrief(final net.minecraft.world.entity.Entity targetEntity, final DamageSource damageSource, final float mcFinalDamage) { + target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private boolean attackImpl$onCanGrief(final net.minecraft.world.entity.Entity targetEntity, final ServerLevel level, final DamageSource damageSource, final float mcFinalDamage) { final var thisEntity = (Mob) (Object) this; float knockbackModifier = this.shadow$getKnockback(targetEntity, damageSource); @@ -65,7 +65,7 @@ public abstract class MobMixin_Attack_Impl extends LivingEntityMixin_Attack_Impl final var event = DamageEventUtil.callMobAttackEvent(attack, knockbackModifier); this.impl$knockbackModifier = event.knockbackModifier(); - return targetEntity.hurt(damageSource, (float) event.finalOutputDamage()); + return targetEntity.hurtServer(level, damageSource, (float) event.finalOutputDamage()); } @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java index dbcf9ecd5af..5ab4f0887be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.ai.sensing; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.sensing.Sensor; import org.spongepowered.asm.mixin.Mixin; @@ -40,7 +41,7 @@ public class SensorMixin { "isEntityAttackable", "isEntityAttackableIgnoringLineOfSight" }, at = @At("HEAD"), cancellable = true) - private static void impl$cancelForVanishedEntities(LivingEntity $$0, LivingEntity $$1, CallbackInfoReturnable cir) { + private static void impl$cancelForVanishedEntities(ServerLevel $$0, LivingEntity $$1, LivingEntity $$2, CallbackInfoReturnable cir) { final var vs = ((VanishableBridge) $$0).bridge$vanishState(); if (vs.invisible() && vs.untargetable()) { cir.setReturnValue(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java index 0bd8e652526..9393f86511b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java @@ -29,6 +29,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.mixin.core.world.entity.MobMixin; @@ -36,11 +37,9 @@ @Mixin(SnowGolem.class) public abstract class SnowGolemMixin extends MobMixin { - @Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;floor(D)I", ordinal = 3), - cancellable = true) - private void impl$onCanGrief(CallbackInfo ci) { - if (!this.shadow$level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !((GrieferBridge) this).bridge$canGrief()) { - ci.cancel(); - } + @Redirect(method = "aiStep()V", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z")) + private boolean impl$checkCanGrief(final GameRules gameRules, final GameRules.Key key) { + return gameRules.getBoolean(key) && ((GrieferBridge) this).bridge$canGrief(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java index 260354e7d87..353999a85f9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.boss.enderdragon; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; @@ -62,16 +63,18 @@ public abstract class EndCrystalMixin extends EntityMixin implements ExplosiveBr this.impl$explosionRadius = radius == null ? Constants.Entity.EnderCrystal.DEFAULT_EXPLOSION_STRENGTH : radius; } - @Redirect(method = "hurt", + @Redirect(method = "hurtServer", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)V" + target = "Lnet/minecraft/server/level/ServerLevel;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)V" ) ) - private void impl$onHurtExplode(final net.minecraft.world.level.Level world, - final Entity entityIn, final DamageSource damageSource, final ExplosionDamageCalculator exDamageCalc, final double xIn, final double yIn, final double zIn, final float explosionRadius, - final boolean fire, final Level.ExplosionInteraction modeIn, final DamageSource causeSource, final float $$1) { - this.bridge$wrappedExplode(xIn, yIn, zIn, damageSource, causeSource); + private void impl$onHurtExplode( + final ServerLevel instance, final Entity entity, final DamageSource damageSource, + final ExplosionDamageCalculator explosionDamageCalculator, final double xIn, double yIn, double zIn, + float v, boolean b, Level.ExplosionInteraction explosionInteraction, final ServerLevel level, + final DamageSource source, final float amount) { + this.bridge$wrappedExplode(xIn, yIn, zIn, damageSource, source); } @Override @@ -87,9 +90,9 @@ public abstract class EndCrystalMixin extends EntityMixin implements ExplosiveBr } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;remove(Lnet/minecraft/world/entity/Entity$RemovalReason;)V")) - private void attackImpl$onAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java index 6c0da06f9dc..59643aef1e1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.boss.enderdragon; +import net.minecraft.tags.TagKey; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.enderdragon.phases.DragonHoverPhase; import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance; @@ -53,23 +54,23 @@ public abstract class EnderDragonMixin extends MobMixin { method = "checkWalls", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;getBlock()Lnet/minecraft/world/level/block/Block;" + target = "Lnet/minecraft/world/level/block/state/BlockState;is(Lnet/minecraft/tags/TagKey;)Z" ), slice = @Slice( from = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;" + value = "FIELD", + target = "Lnet/minecraft/world/level/GameRules;RULE_MOBGRIEFING:Lnet/minecraft/world/level/GameRules$Key;" ), to = @At( - value = "FIELD", - target = "Lnet/minecraft/world/level/material/Material;FIRE:Lnet/minecraft/world/level/material/Material;", + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;removeBlock(Lnet/minecraft/core/BlockPos;Z)Z", opcode = Opcodes.GETSTATIC ) ), require = 0 // Forge rewrites the material request to block.isAir ) - private Block impl$onCanGrief(final BlockState state) { - return ((GrieferBridge) this).bridge$canGrief() ? state.getBlock() : Blocks.AIR; + private boolean impl$onCanGrief(final BlockState state, final TagKey tag) { + return ((GrieferBridge) this).bridge$canGrief() && state.is(tag); } /** diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java index 9e419a6e1e2..d377bb6d48e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java @@ -75,20 +75,20 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { /** * BYPASSES_INVULNERABILITY */ - @Inject(method = "hurt", cancellable = true, + @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;BYPASSES_INVULNERABILITY:Lnet/minecraft/tags/TagKey;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V", ordinal = 0)) - private void impl$fireDamageEventOutOfWorld(final DamageSource source, final float $$1, final CallbackInfoReturnable cir) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V", ordinal = 0)) + private void impl$fireDamageEventOutOfWorld(final ServerLevel level, final DamageSource source, final float $$1, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } /** * IS_EXPLOSION */ - @Inject(method = "hurt", cancellable = true, + @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_EXPLOSION:Lnet/minecraft/tags/TagKey;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByAnything(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$fireDamageEventExplosion(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventExplosion(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } @@ -97,7 +97,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * IGNITES_ARMOR_STANDS + isOnFire * BURNS_ARMOR_STANDS + health > 0.5 */ - @Redirect(method = "hurt", + @Redirect(method = "hurtServer", slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IGNITES_ARMOR_STANDS:Lnet/minecraft/tags/TagKey;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;causeDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) private void impl$fireDamageEventDamage(final ArmorStand self, final ServerLevel level, final DamageSource source, final float amount) { @@ -110,20 +110,20 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { /** * {@link DamageSource#isCreativePlayer()} */ - @Inject(method = "hurt", + @Inject(method = "hurtServer", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;isCreativePlayer()Z")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;playBrokenSound()V"), cancellable = true) - private void impl$fireDamageEventCreativePunch(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventCreativePunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } /** * {@link ArmorStand#lastHit} was not recently */ - @Inject(method = "hurt", cancellable = true, + @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;lastHit:J", opcode = Opcodes.GETFIELD)), at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;broadcastEntityEvent(Lnet/minecraft/world/entity/Entity;B)V")) - private void impl$fireDamageEventFirstPunch(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventFirstPunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { // While this doesn't technically "damage" the armor stand, it feels like damage in other respects, so fire an event. var event = DamageEventUtil.callSimpleDamageEntityEvent(source, (ArmorStand) (Object) this, 0); if (event.isCancelled()) { @@ -131,9 +131,9 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$beforeBrokenByPlayer(final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { + private void impl$beforeBrokenByPlayer(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { if (ShouldFire.DESTRUCT_ENTITY_EVENT && !((LevelBridge) this.shadow$level()).bridge$isFake()) { final var event = SpongeCommonEventFactory.callDestructEntityEventDeath((ArmorStand) (Object) this, null); if (event.isCancelled()) { @@ -143,7 +143,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { } } - @Redirect(method = "hurt", at = @At(value = "INVOKE", + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) public void impl$onBrokenByPlayer(final ArmorStand instance, final ServerLevel $$0, final DamageSource $$1) { @@ -155,9 +155,9 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { /** * {@link ArmorStand#lastHit} was recently */ - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$fireDamageEventSecondPunch(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventSecondPunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } @@ -168,8 +168,8 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * * @param target the killed stand */ - @Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) - private void impl$actuallyKill(final ArmorStand target) { + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V")) + private void impl$actuallyKill(final ArmorStand target, final ServerLevel level) { target.remove(RemovalReason.KILLED); target.gameEvent(GameEvent.ENTITY_DIE); } @@ -181,8 +181,8 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * * @param target the killed stand */ - @Redirect(method = "causeDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) - private void impl$actuallyKill2(final ArmorStand target) { + @Redirect(method = "causeDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V")) + private void impl$actuallyKill2(final ArmorStand target, final ServerLevel level) { target.remove(RemovalReason.KILLED); target.gameEvent(GameEvent.ENTITY_DIE); } @@ -197,7 +197,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * This needs to be reimplemented in {@link #impl$actuallyKill}! */ @Overwrite - public void kill() { - super.shadow$kill(); + public void kill(final ServerLevel level) { + super.shadow$kill(level); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java index 03a8ad46608..763e0ad5bc9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.decoration; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.BlockAttachedEntity; @@ -54,9 +55,9 @@ public abstract class BlockAttachedEntityMixin extends EntityMixin { return this.shadow$survives() && !this.impl$ignorePhysics; } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;kill()V")) - private void attackImpl$postEventOnAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;kill(Lnet/minecraft/server/level/ServerLevel;)V")) + private void attackImpl$postEventOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java index f84c4d54c9b..c09f61c3b90 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.decoration; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; @@ -35,9 +36,10 @@ @Mixin(net.minecraft.world.entity.decoration.ItemFrame.class) public abstract class ItemFrameMixin extends HangingEntityMixin { - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/decoration/ItemFrame;dropItem(Lnet/minecraft/world/entity/Entity;Z)V")) - private void attackImpl$onAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/decoration/ItemFrame;dropItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Z)V")) + private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, + final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index e80443443f2..0dd2ca7b6ad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.item; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; @@ -144,9 +145,10 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;markHurt()V")) - private void attackImpl$onAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, + final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 59860310fb6..976768bf6d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -102,6 +102,7 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri @Shadow @Final public InventoryMenu inventoryMenu; @Shadow @Final private GameProfile gameProfile; @Shadow public abstract boolean shadow$isSpectator(); + @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract int shadow$getXpNeededForNextLevel(); @Shadow @Nullable public abstract ItemEntity shadow$drop(final ItemStack droppedItem, final boolean dropAround, final boolean traceItem); @Shadow public abstract FoodData shadow$getFoodData(); @@ -227,7 +228,6 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri method = { "playSound(Lnet/minecraft/sounds/SoundEvent;FF)V", "giveExperienceLevels(I)V", - "eat(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;" }, at = @At( value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index aacb5281609..b1f5df8e8df 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.player; +import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -195,7 +196,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I @Redirect(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) public boolean attackImpl$onHurt(final Entity targetEntity, final DamageSource damageSource, final float mcDamage) { float knockbackModifier = this.shadow$getKnockback(targetEntity, damageSource) + (this.attackImpl$isStrongSprintAttack ? 1.0F : 0.0F); @@ -214,14 +215,18 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I this.impl$playAttackSound((Player) (Object) this, SoundEvents.PLAYER_ATTACK_KNOCKBACK); } - return targetEntity.hurt(damageSource, (float) this.attackImpl$attackEvent.finalOutputDamage()); + if (targetEntity.level() instanceof ServerLevel sl) { + return targetEntity.hurtServer(sl, damageSource, (float) this.attackImpl$attackEvent.finalOutputDamage()); + } + + return targetEntity.hurtClient(damageSource); } /** * Set enchantment damage with value from event */ @ModifyVariable(method = "attack", ordinal = 1, - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V", ordinal = 0)), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) public float attackImpl$enchentmentDamageFromEvent(final float enchDmg) { @@ -295,7 +300,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I */ @Redirect(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) public void attackImpl$modifyKnockback(final LivingEntity instance, final double $$0, final double $$1, final double $$2) { instance.knockback($$0 * this.attackImpl$attackEvent.knockbackModifier(), $$1, $$2); @@ -317,9 +322,10 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I } @Redirect(method = "actuallyHurt", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;isInvulnerableTo(Lnet/minecraft/world/damagesource/DamageSource;)Z")) - public boolean attackImpl$startActuallyHurt(final Player instance, final DamageSource damageSource, final DamageSource $$0, final float originalDamage) { - if (instance.isInvulnerableTo(damageSource)) { + target = "Lnet/minecraft/world/entity/player/Player;isInvulnerableTo(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)Z")) + public boolean attackImpl$startActuallyHurt(final Player instance, final ServerLevel level, final DamageSource damageSource, + final ServerLevel redundant, final DamageSource ds, final float originalDamage) { + if (instance.isInvulnerableTo(level, damageSource)) { return true; } @@ -362,7 +368,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I * Cleanup */ @Inject(method = "actuallyHurt", at = @At("RETURN")) - public void attackImpl$afterActuallyHurt(final DamageSource $$0, final float $$1, final CallbackInfo ci) { + public void attackImpl$afterActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { this.attackImpl$handlePostDamage(); this.attackImpl$actuallyHurt = null; this.attackImpl$actuallyHurtResult = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java index 6f91c80b19a..b5c3ba26b91 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.projectile; +import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; @@ -91,10 +92,8 @@ private void onProjectileHit(final BlockHitResult hitResult, final CallbackInfo this.impl$getProjectileSource(), hitResult)) { this.shadow$playSound(SoundEvents.ARROW_HIT, 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F)); // Make it almost look like it collided with something - final BlockHitResult blockraytraceresult = (BlockHitResult)hitResult; - final BlockState blockstate = this.shadow$level().getBlockState(blockraytraceresult.getBlockPos()); - this.lastState = blockstate; - final Vec3 vec3d = blockraytraceresult.getLocation().subtract(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ()); + this.lastState = this.shadow$level().getBlockState(hitResult.getBlockPos()); + final Vec3 vec3d = hitResult.getLocation().subtract(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ()); this.shadow$setDeltaMovement(vec3d); final Vec3 vec3d1 = vec3d.normalize().scale(0.05F); this.shadow$setPos(this.shadow$getX() - vec3d1.x, this.shadow$getY() - vec3d1.y, this.shadow$getZ() - vec3d1.z); @@ -138,7 +137,7 @@ private void onProjectileHit(final EntityHitResult hitResult, final CallbackInfo this.life = 0; if (!this.shadow$level().isClientSide && this.shadow$getDeltaMovement().lengthSqr() < 1.0E-7D) { if (this.pickup == AbstractArrow.Pickup.ALLOWED) { - this.shadow$spawnAtLocation(this.shadow$getPickupItem(), 0.1F); + this.shadow$spawnAtLocation((ServerLevel) this.shadow$level(), this.shadow$getPickupItem(), 0.1F); } this.shadow$discard(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java index 174d7c289b5..39706decc33 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.projectile; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.level.Level; @@ -88,15 +89,11 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen this.impl$explosionRadius = radius == null ? Constants.Entity.Firework.DEFAULT_EXPLOSION_RADIUS : radius; } - @Redirect(method = "explode()V", + @Redirect(method = "explode(Lnet/minecraft/server/level/ServerLevel;)V", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;broadcastEntityEvent(Lnet/minecraft/world/entity/Entity;B)V") + target = "Lnet/minecraft/server/level/ServerLevel;broadcastEntityEvent(Lnet/minecraft/world/entity/Entity;B)V") ) - private void impl$useSpongeExplosion(final Level world, final Entity self, final byte state) { - if (this.shadow$level().isClientSide) { - world.broadcastEntityEvent(self, state); - return; - } + private void impl$useSpongeExplosion(final ServerLevel world, final Entity self, final byte state) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { // Fireworks don't typically explode like other explosives, but we'll // post an event regardless and if the radius is zero the explosion diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java index dc90ee08343..3efc4c01c22 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.projectile; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.ShulkerBullet; @@ -50,9 +51,9 @@ private void onBulletHitBlock(final HitResult result, final CallbackInfo ci) { } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ShulkerBullet;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void attackImpl$onAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java index 5286cd530d4..00ec313c112 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java @@ -37,7 +37,7 @@ public abstract class SnowballMixin extends ThrowableProjectileMixin implements private boolean impl$damageSet = false; @ModifyArg(method = "onHitEntity", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")) private float impl$onAttackEntityFromUseCustomDamage(float damage) { return this.impl$damageSet ? (float) this.impl$damageAmount : damage; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java index e94c66d2615..40bebdc1d5b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java @@ -37,7 +37,7 @@ public abstract class ThrownEggMixin extends ThrowableProjectileMixin { @ModifyArg(method = "onHitEntity", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z") + target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V") ) private float onAttackEntityFromUseDamage(final float damage) { return (float) this.impl$damageAmount; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java index f1c466a54de..cf352b54929 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java @@ -44,7 +44,7 @@ public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin { @ModifyArg(method = "onHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + target = "Lnet/minecraft/world/entity/player/Player;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) private float impl$onAttackEntityFromWithDamage(final float damage) { return (float) this.impl$damageAmount; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java index fa4610c95bb..c2661fc7fc3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java @@ -54,7 +54,7 @@ public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin im private boolean impl$damageSet = false; @ModifyArg(method = "onHitEntity", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) private float impl$onAttackEntityFrom(final float amount) { if (this.impl$damageSet) { return this.impl$damage; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/BoatMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/BoatMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java index a7403b7f54e..26b135e677a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/BoatMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java @@ -24,18 +24,18 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import org.spongepowered.api.data.Keys; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.common.bridge.data.SpongeDataHolderBridge; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; import org.spongepowered.common.util.Constants; -@Mixin(Boat.class) -public abstract class BoatMixin extends EntityMixin implements BoatBridge { +@Mixin(AbstractBoat.class) +public abstract class AbstractBoatMixin extends EntityMixin implements AbstractBoatBridge { private float impl$maxSpeed = Constants.Entity.Boat.DEFAULT_MAX_SPEED; private boolean impl$moveOnLand = Constants.Entity.Boat.MOVE_ON_LAND; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java index c89aa2f110d..9844796031e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.phys.Vec3; import org.spongepowered.api.data.Keys; @@ -54,7 +55,7 @@ public abstract class AbstractMinecartMixin extends VehicleEntityMixin implement * @reason Use our custom maximum speed for the Minecart. */ @Overwrite - protected double getMaxSpeed() { + protected double getMaxSpeed(ServerLevel level) { return this.impl$maxSpeed; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java index a2c83ce6104..69ce2149a1a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.vehicle.MinecartFurnace; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -47,9 +48,9 @@ private void onInit(CallbackInfo ci) { */ @Override @Overwrite - protected double getMaxSpeed() { + protected double getMaxSpeed(ServerLevel level) { // Return our custom value from EntityMinecart - return super.getMaxSpeed(); + return super.getMaxSpeed(level); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index 67731871c9a..cfe8bf317e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.vehicle.MinecartTNT; @@ -88,8 +89,9 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements } - @Inject(method = "hurt", at = @At("HEAD")) - private void impl$onAttackSetPrimeCause(final DamageSource damageSource, final float amount, final CallbackInfoReturnable ci) { + @Inject(method = "hurtServer", at = @At("HEAD")) + private void impl$onAttackSetPrimeCause(final ServerLevel level, final DamageSource damageSource, + final float amount, final CallbackInfoReturnable ci) { this.impl$primeCause = damageSource; } @@ -136,9 +138,9 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/MinecartTNT;explode(Lnet/minecraft/world/damagesource/DamageSource;D)V")) - private void attackImpl$postOnAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java index 1fa0a765550..de39fb029c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.vehicle.VehicleEntity; import org.spongepowered.asm.mixin.Mixin; @@ -36,9 +37,10 @@ @Mixin(VehicleEntity.class) public abstract class VehicleEntityMixin extends EntityMixin { - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/VehicleEntity;shouldSourceDestroy(Lnet/minecraft/world/damagesource/DamageSource;)Z")) - private void attackImpl$postOnAttackEntityFrom(final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, + final float amount, final CallbackInfoReturnable cir) { if (DamageEventUtil.callOtherAttackEvent((net.minecraft.world.entity.Entity) (Object) this, source, amount).isCancelled()) { cir.setReturnValue(true); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/food/FoodDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/food/FoodDataMixin.java index 41a0d465762..f2f5b68172c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/food/FoodDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/food/FoodDataMixin.java @@ -91,18 +91,8 @@ public abstract class FoodDataMixin implements FoodDataBridge { this.saturationLevel = this.impl$fireEventAndGetValue(Keys.SATURATION, (double) this.saturationLevel, (double) value).floatValue(); } - @Redirect(method = "setExhaustion", at = @At(value = "FIELD", target = "Lnet/minecraft/world/food/FoodData;exhaustionLevel:F", opcode = Opcodes.PUTFIELD)) - private void impl$setExhaustion(final FoodData self, final float value) { - this.exhaustionLevel = this.impl$fireEventAndGetValue(Keys.EXHAUSTION, (double) this.exhaustionLevel, (double) value).floatValue(); - } - @Redirect(method = "addExhaustion", at = @At(value = "FIELD", target = "Lnet/minecraft/world/food/FoodData;exhaustionLevel:F", opcode = Opcodes.PUTFIELD)) - private void impl$addExhaustion(final FoodData self, final float value) { - this.exhaustionLevel = this.impl$fireEventAndGetValue(Keys.EXHAUSTION, (double) this.exhaustionLevel, (double) value).floatValue(); - } - - @Redirect(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/world/food/FoodData;exhaustionLevel:F", opcode = Opcodes.PUTFIELD)) - private void impl$tickDrainExhaustion(final FoodData self, final float value) { + private void impl$setExhaustion(final FoodData self, final float value) { this.exhaustionLevel = this.impl$fireEventAndGetValue(Keys.EXHAUSTION, (double) this.exhaustionLevel, (double) value).floatValue(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java index e4c25d85225..ad866c991ee 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.level.block; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.level.Explosion; @@ -81,12 +82,12 @@ public abstract class TntBlockMixin extends BlockMixin { @Inject( method = "wasExploded", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), locals = LocalCapture.CAPTURE_FAILSOFT, cancellable = true ) private void impl$CheckIfCanPrimeFromExplosion( - final Level worldIn, final BlockPos pos, final Explosion explosionIn, final CallbackInfo ci, final PrimedTnt tnt) { + final ServerLevel worldIn, final BlockPos pos, final Explosion explosionIn, final CallbackInfo ci, final PrimedTnt tnt) { if (ShouldFire.PRIME_EXPLOSIVE_EVENT_PRE) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.addContext(EventContextKeys.DAMAGE_TYPE, DamageTypes.EXPLOSION); @@ -110,7 +111,7 @@ public abstract class TntBlockMixin extends BlockMixin { return this.impl$onRemove(world, pos, isMoving); } - @Redirect(method = "use", at = @At(value = "INVOKE", + @Redirect(method = "useItemOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) private boolean impl$removeActivated(final Level world, final BlockPos pos, final BlockState state, final int flag) { // Called when player manually ignites TNT diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java index 6cd5a1d20fb..713f2f7eb9c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java @@ -24,6 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.level.block.entity; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; @@ -31,6 +34,10 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import javax.swing.text.html.Option; +import java.util.Optional; +import java.util.function.Function; + @Mixin(BeaconBlockEntity.class) public abstract class BeaconBlockEntityMixin extends BlockEntityMixin { @@ -43,11 +50,13 @@ public abstract class BeaconBlockEntityMixin extends BlockEntityMixin { * @param id The id * @return The potion by id, no validation */ + @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "rawtypes"}) @Redirect(method = "loadEffect", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BeaconBlockEntity;filterEffect(Lnet/minecraft/world/effect/MobEffect;)Lnet/minecraft/world/effect/MobEffect;") + at = @At(value = "INVOKE", target = "Ljava/util/Optional;map(Ljava/util/function/Function;)Ljava/util/Optional;") ) @Nullable - private static MobEffect impl$UsePotionUtilInsteadOfCheckingValidPotions(MobEffect effect) { - return effect; + private static Optional impl$UsePotionUtilInsteadOfCheckingValidPotions( + Optional instance, Function mapper) { + return instance; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index e4bab6e5c82..8c6797c20fc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -169,8 +169,8 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @Redirect(method = "tickFluid(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/material/Fluid;)V", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/material/FluidState;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) - private void tracker$wrapFluidTick(final FluidState fluidState, final net.minecraft.world.level.Level level, final BlockPos pos, final BlockState blockState) { + target = "Lnet/minecraft/world/level/material/FluidState;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V")) + private void tracker$wrapFluidTick(final FluidState fluidState, final ServerLevel level, final BlockPos pos, final BlockState blockState) { TrackingUtil.updateTickFluid(this, fluidState, pos, blockState); } @@ -229,10 +229,10 @@ public void scheduleTick(final BlockPos pos, final Fluid fluid, final int trigge @Redirect(method = "tickChunk(Lnet/minecraft/world/level/chunk/LevelChunk;I)V", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/material/FluidState;randomTick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V" + target = "Lnet/minecraft/world/level/material/FluidState;randomTick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V" ) ) - private void tracker$wrapFluidRandomTick(final FluidState fluidState, final net.minecraft.world.level.Level worldIn, final BlockPos pos, final RandomSource random) { + private void tracker$wrapFluidRandomTick(final FluidState fluidState, final ServerLevel worldIn, final BlockPos pos, final RandomSource random) { TrackingUtil.randomTickFluid(this, fluidState, pos, this.random); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java index 5746dda6774..4647439094d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java @@ -26,6 +26,7 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -88,16 +89,16 @@ public abstract class EntityMixin_Tracker implements DelegatingConfigTrackableBr protected @MonotonicNonNull EffectTransactor tracker$dropsTransactor = null; @Inject( - method = "spawnAtLocation(Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", + method = "spawnAtLocation(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("HEAD") ) - private void tracker$logEntityDropTransactionIfNecessary(final ItemStack stack, final float offsetY, - final CallbackInfoReturnable cir) { + private void tracker$logEntityDropTransactionIfNecessary(final ServerLevel level, final ItemStack stack, final float offsetY, + final CallbackInfoReturnable cir) { final PhaseTracker instance = PhaseTracker.SERVER; if (!instance.onSidedThread()) { return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + if (((LevelBridge) level).bridge$isFake()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index 6f7e33dd68a..43ffb8ba24c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -120,7 +120,7 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { * @reason Instead of inlining the onDeath method with the main mixin, we can "toggle" * the usage of the death state control in the tracker mixin. */ - @Redirect(method = "hurt", + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;die(Lnet/minecraft/world/damagesource/DamageSource;)V" ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java index e393e3ff477..2f25d1db67d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java @@ -74,9 +74,6 @@ public abstract class LevelMixin_Tracker implements LevelBridge, LevelAccessor { @Shadow public abstract FluidState shadow$getFluidState(BlockPos p_204610_1_); // @formatter:on - - @Shadow public abstract GameRules getGameRules(); - /** * We introduce the protected method to be overridden in * {@code org.spongepowered.common.mixin.core.world.server.ServerWorldMixin#tracker$wrapTileEntityTick(ITickableTileEntity)} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 59e3ae2e275..1a65cdb3432 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -303,9 +303,8 @@ "minecraft.world.entity.raid.RaidMixin_API", "minecraft.world.entity.vehicle.AbstractMinecartContainerMixin_API", "minecraft.world.entity.vehicle.AbstractMinecartMixin_API", - "minecraft.world.entity.vehicle.Boat_TypeMixin_API", - "minecraft.world.entity.vehicle.BoatMixin_API", - "minecraft.world.entity.vehicle.ChestBoatMixin_API", + "minecraft.world.entity.vehicle.AbstractBoatMixin_API", + "minecraft.world.entity.vehicle.AbstractChestBoatMixin_API", "minecraft.world.entity.vehicle.MinecartChestMixin_API", "minecraft.world.entity.vehicle.MinecartCommandBlockMixin_API", "minecraft.world.entity.vehicle.MinecartFurnaceMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 6921449e40d..73d62d1ffbd 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -34,6 +34,7 @@ "item.EmptyMapItemMixin", "item.ThrowableInaccurateItemMixin", "item.YeetableInaccurateItemMixin", + "nbt.CompoundTagMixin", "network.ConnectionMixin", "network.PacketEncoderMixin", "network.chat.Component_SerializerMixin", @@ -135,6 +136,7 @@ "world.entity.animal.OcelotMixin", "world.entity.animal.ParrotMixin", "world.entity.animal.Rabbit_RaidGardenGoalMixin", + "world.entity.animal.SnowGolemMixin", "world.entity.animal.WolfMixin", "world.entity.animal.horse.AbstractHorseMixin", "world.entity.boss.enderdragon.EndCrystalMixin", @@ -178,9 +180,9 @@ "world.entity.projectile.ThrownEnderpearlMixin", "world.entity.projectile.ThrownTridentMixin", "world.entity.projectile.WitherSkullMixin", + "world.entity.vehicle.AbstractBoatMixin", "world.entity.vehicle.AbstractMinecartContainerMixin", "world.entity.vehicle.AbstractMinecartMixin", - "world.entity.vehicle.BoatMixin", "world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin", "world.entity.vehicle.MinecartCommandBlockMixin", "world.entity.vehicle.MinecartFurnaceMixin", @@ -235,9 +237,11 @@ "world.level.block.MagmaBlockMixin", "world.level.block.NetherPortalBlockMixin", "world.level.block.NoteBlockMixin", + "world.level.block.TntBlockMixin", "world.level.block.entity.AbstractFurnaceBlockEntityMixin", "world.level.block.entity.BannerBlockEntityMixin", "world.level.block.entity.BaseContainerBlockEntityMixin", + "world.level.block.entity.BeaconBlockEntityMixin", "world.level.block.entity.BellBLockEntityMixin", "world.level.block.entity.BlockEntityMixin", "world.level.block.entity.BrewingStandBlockEntityMixin", @@ -300,5 +304,5 @@ }, "overwrites": { "conformVisibility": true - } + } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 0e03da3251f..718aacee6b9 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -41,18 +41,18 @@ public abstract class LivingEntityMixin_Attack_Impl { @SuppressWarnings("InvalidInjectorMethodSignature") - @ModifyConstant(method = "hurt", constant = @Constant(classValue = Wolf.class, ordinal = 0)) + @ModifyConstant(method = "hurtServer", constant = @Constant(classValue = Wolf.class, ordinal = 0)) private Class attackImpl$onWolfCast(final Object entity, final Class wolf) { return TamableAnimal.class; } - @Redirect(method = "hurt", + @Redirect(method = "hurtServer", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;isTame()Z")) private boolean attackImpl$onWolfIsTame(@Coerce final Object instance) { return ((TamableAnimal)instance).isTame(); } - @Redirect(method = "hurt", + @Redirect(method = "hurtServer", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwner()Lnet/minecraft/world/entity/LivingEntity;")) private LivingEntity attackImpl$onWolfGetOwner(@Coerce final Object instance) { return ((TamableAnimal)instance).getOwner(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/BoatMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java similarity index 89% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/BoatMixin_Vanilla.java rename to vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java index 2e60f5aea1f..693141a973a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/BoatMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java @@ -24,16 +24,16 @@ */ package org.spongepowered.vanilla.mixin.core.world.entity.vehicle; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; -@Mixin(Boat.class) -public abstract class BoatMixin_Vanilla implements BoatBridge { +@Mixin(AbstractBoat.class) +public abstract class AbstractBoatMixin_Vanilla implements AbstractBoatBridge { /** * Forge changes this check to ask the block state for "slipperiness" so we return the check here to Vanilla diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index cbbac4390be..9d391552788 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -39,7 +39,7 @@ "world.entity.LivingEntityMixin_Vanilla", "world.entity.ai.attributes.DefaultAttributesMixin", "world.entity.item.ItemEntityMixin_Vanilla", - "world.entity.vehicle.BoatMixin_Vanilla", + "world.entity.vehicle.AbstractBoatMixin_Vanilla", "world.level.block.FireBlockMixin_Vanilla", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", "world.level.storage.LevelStorageSourceMixin_Vanilla" From 87d71afb57284f5d725ffa88580843b7fc602389 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 3 Oct 2024 00:02:47 -0700 Subject: [PATCH 089/586] chore(update): start update for 24w40a Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- gradle.properties | 2 +- .../common/bridge/world/entity/EntityBridge.java | 4 ++-- .../common/data/provider/item/stack/ItemStackData.java | 2 +- .../inventory/ContainerBasedTransaction.java | 4 ++-- .../inventory/CraftingPreviewTransaction.java | 4 ++-- .../transaction/inventory/PlaceRecipeTransaction.java | 2 +- .../transaction/inventory/SelectTradeTransaction.java | 2 +- .../recipe/crafting/custom/SpongeSpecialRecipe.java | 2 +- .../crafting/shapeless/SpongeShapelessRecipe.java | 2 +- .../recipe/stonecutting/SpongeStonecuttingRecipe.java | 6 +++--- .../world/portal/SpongeCompositePortalLogic.java | 4 ++-- .../common/world/portal/SpongeCustomPortalLogic.java | 10 +++++----- 13 files changed, 23 insertions(+), 23 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 8a9430065c6..144e45c2731 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8a9430065c66c04e7a1f1f3f8e4f96bfb2e62947 +Subproject commit 144e45c2731ea5149feb4844b73ab5b98695047e diff --git a/gradle.properties b/gradle.properties index 0c97c7f9c08..7bb5897a081 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w39a +minecraftVersion=24w40a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java index a8b41003978..038bd18db65 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java @@ -26,7 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.cause.entity.DismountType; import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; @@ -70,7 +70,7 @@ public interface EntityBridge { boolean bridge$dismountRidingEntity(DismountType type); - Entity bridge$changeDimension(DimensionTransition transition); + Entity bridge$changeDimension(TeleportTransition transition); ChangeEntityWorldEvent.Reposition bridge$fireRepositionEvent(org.spongepowered.api.world.server.ServerWorld originalDestinationWorld, org.spongepowered.api.world.server.ServerWorld targetWorld, diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index bff85314924..3346446c7ea 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -108,7 +108,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.BURN_TIME) .get(h -> SpongeCommon.server().fuelValues().burnDuration(h)) .create(Keys.CONTAINER_ITEM) - .get(h -> (ItemType) h.getItem().getCraftingRemainingItem()) + .get(h -> (ItemType) h.getItem().getCraftingRemainder().getItem()) .create(Keys.DISPLAY_NAME) .get(h -> SpongeAdventure.asAdventure(h.getDisplayName())) .create(Keys.CUSTOM_MODEL_DATA) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java index 52811cbb503..3bd55e1b709 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java @@ -284,11 +284,11 @@ private void handleCrafting(final Player player, final ClickContainerEvent event } private void handleCraftingPreview(final Player player, final ClickContainerEvent event) { - if (this.craftingInventory != null) { + if (this.craftingInventory != null && player instanceof ServerPlayer sp) { // TODO push event to cause? // TODO prevent event when there is no preview? final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), event.transactions()); - final var recipe = player.level().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); + final var recipe = sp.serverLevel().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); final CraftItemEvent.Preview previewEvent = SpongeEventFactory.createCraftItemEventPreview(event.cause(), (Container) this.menu, this.craftingInventory, event.cursorTransaction(), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(h -> h.id()).map(ResourceKey.class::cast), Optional.empty(), event.transactions()); SpongeCommon.post(previewEvent); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java index 2fb3bf724e7..80a4fc5c600 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java @@ -71,12 +71,12 @@ public Optional parentAbsorber() { @Override Optional createInventoryEvent(final List slotTransactions, final List entities, final PhaseContext<@NonNull ?> context, final Cause currentCause) { - if (slotTransactions.isEmpty()) { + if (slotTransactions.isEmpty() || !(this.player instanceof ServerPlayer sp)) { return Optional.empty(); } final ItemStackSnapshot cursor = ItemStackUtil.snapshotOf(this.player.containerMenu.getCarried()); final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), slotTransactions); - final var recipe = this.player.level().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, this.craftSlots.asCraftInput(), this.player.level()); + final var recipe = sp.serverLevel().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftSlots.asCraftInput(), this.player.level()); final CraftItemEvent.Preview event = SpongeEventFactory.createCraftItemEventPreview(currentCause, ContainerUtil.fromNative(this.menu), this.craftingInventory, new Transaction<>(cursor, cursor), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java index b64b10b0236..ab486784a6c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java @@ -105,7 +105,7 @@ boolean isContainerEventAllowed(final PhaseContext<@Nullable ?> context) { if (!(context instanceof InventoryPacketContext)) { return false; } - final int containerId = ((InventoryPacketContext) context).getPacket().getContainerId(); + final int containerId = ((InventoryPacketContext) context).getPacket().containerId(); return containerId != this.player.containerMenu.containerId; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SelectTradeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SelectTradeTransaction.java index 8d5f9eaf98e..c5f6a2ad3c1 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SelectTradeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SelectTradeTransaction.java @@ -91,7 +91,7 @@ boolean isContainerEventAllowed(final PhaseContext<@NonNull ?> context) { if (!(context instanceof InventoryPacketContext)) { return false; } - final int containerId = ((InventoryPacketContext) context).getPacket().getContainerId(); + final int containerId = ((InventoryPacketContext) context).getPacket().containerId(); return containerId != this.player.containerMenu.containerId; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index 09531ed46b4..66ffc3e56bd 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -109,7 +109,7 @@ public NonNullList getRemainingItems(final CraftingInput input) { } @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { // Fake special crafting serializer // because of Unknown recipe serializer when using our serializer with a vanilla client // return Registry.RECIPE_SERIALIZER.getOrDefault(this.id()); diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index 59849a785cf..4864e5068e7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -60,7 +60,7 @@ public class SpongeShapelessRecipe extends ShapelessRecipe { public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( $$0 -> $$0.group( Codec.STRING.fieldOf(Constants.Recipe.SPONGE_TYPE).forGetter(t -> "custom"), // important to fail early when decoding vanilla recipes - Codec.STRING.optionalFieldOf("group", "").forGetter(ShapelessRecipe::getGroup), + Codec.STRING.optionalFieldOf("group", "").forGetter(ShapelessRecipe::group), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(ShapelessRecipe::category), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), Ingredient.CODEC.listOf(1,9) diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index 819cf425181..a6791c73274 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -57,9 +57,9 @@ public class SpongeStonecuttingRecipe extends StonecutterRecipe implements Resul public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( $$1 -> $$1.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Codec.STRING.optionalFieldOf("group", "").forGetter(SingleItemRecipe::getGroup), - Ingredient.CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter($$0x -> $$0x.ingredient), - RESULT_CODEC.forGetter($$0x -> $$0x.result), + Codec.STRING.optionalFieldOf("group", "").forGetter(SingleItemRecipe::group), + Ingredient.CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter(SingleItemRecipe::input), + RESULT_CODEC.forGetter($$0x -> $$0x.result()), ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) ) diff --git a/src/main/java/org/spongepowered/common/world/portal/SpongeCompositePortalLogic.java b/src/main/java/org/spongepowered/common/world/portal/SpongeCompositePortalLogic.java index 9e5f9112353..f517ca6991c 100644 --- a/src/main/java/org/spongepowered/common/world/portal/SpongeCompositePortalLogic.java +++ b/src/main/java/org/spongepowered/common/world/portal/SpongeCompositePortalLogic.java @@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.jetbrains.annotations.Nullable; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.portal.Portal; @@ -50,7 +50,7 @@ public SpongeCompositePortalLogic(final List p.getPortalDestination(sourceLevel, entity, portalPos)) .filter(Objects::nonNull) diff --git a/src/main/java/org/spongepowered/common/world/portal/SpongeCustomPortalLogic.java b/src/main/java/org/spongepowered/common/world/portal/SpongeCustomPortalLogic.java index 65bf3c1c70d..7e73377ce5f 100644 --- a/src/main/java/org/spongepowered/common/world/portal/SpongeCustomPortalLogic.java +++ b/src/main/java/org/spongepowered/common/world/portal/SpongeCustomPortalLogic.java @@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.portal.Portal; @@ -60,7 +60,7 @@ public SpongeCustomPortalLogic(final PortalLogic.PortalExitCalculator calulator, } @Nullable @Override - public DimensionTransition getPortalDestination(final ServerLevel fromLevel, final Entity entity, final BlockPos fromPos) { + public TeleportTransition getPortalDestination(final ServerLevel fromLevel, final Entity entity, final BlockPos fromPos) { final var spongeEntity = (org.spongepowered.api.entity.Entity) entity; // Calculate desired portal location // Then find existing portal or generate if not found @@ -70,14 +70,14 @@ public DimensionTransition getPortalDestination(final ServerLevel fromLevel, fin ).orElse(null); } - private static DimensionTransition generateTransition(final Entity entity, final ServerLocation finalExit) { - return new DimensionTransition( + private static TeleportTransition generateTransition(final Entity entity, final ServerLocation finalExit) { + return new TeleportTransition( (ServerLevel) finalExit.world(), VecHelper.toVanillaVector3d(finalExit.position()), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), - DimensionTransition.PLACE_PORTAL_TICKET); + TeleportTransition.PLACE_PORTAL_TICKET); } @Override From f79def5475a662a3375702bac034e92f0b0aa59a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Thu, 3 Oct 2024 18:18:35 +0200 Subject: [PATCH 090/586] fix some recipe --- .../item/recipe/SpongeRecipeRegistration.java | 6 ++++-- .../recipe/cooking/SpongeBlastingRecipe.java | 7 ------- .../cooking/SpongeCampfireCookingRecipe.java | 8 -------- .../recipe/cooking/SpongeSmeltingRecipe.java | 8 -------- .../recipe/cooking/SpongeSmokingRecipe.java | 8 -------- .../crafting/custom/SpongeSpecialRecipe.java | 6 ------ .../crafting/shaped/SpongeShapedRecipe.java | 10 +--------- .../shapeless/SpongeShapelessRecipe.java | 8 -------- .../recipe/smithing/SpongeSmithingRecipe.java | 18 ------------------ .../stonecutting/SpongeStonecuttingRecipe.java | 8 -------- 10 files changed, 5 insertions(+), 82 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java index 372eeb77cda..ceddabfb89a 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java @@ -35,6 +35,7 @@ import net.minecraft.advancements.critereon.RecipeUnlockedTrigger; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; @@ -71,9 +72,10 @@ public SpongeRecipeRegistration(final ResourceLocation key, this.key = key; this.serializer = serializer; this.pack = pack; + var rKey = net.minecraft.resources.ResourceKey.create(Registries.RECIPE, key); this.advancement = Advancement.Builder.advancement() - .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(key)) - .rewards(AdvancementRewards.Builder.recipe(key)) + .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(rKey)) + .rewards(AdvancementRewards.Builder.recipe(rKey)) .build(ResourceLocation.fromNamespaceAndPath(key.getNamespace(), "recipes/" + recipeCategory.getFolderName() + "/" + key.getPath())); this.group = group == null ? "" : group; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java index 6675d43b475..4d3223616b3 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java @@ -59,12 +59,5 @@ public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provid return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { -// if (this.resultFunction != null) { -// return ItemStack.EMPTY; -// } - return super.getResultItem($$1); - } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java index ecce010f0ab..6fd30630776 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java @@ -59,12 +59,4 @@ public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provid return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return ItemStack.EMPTY; - } - return super.getResultItem($$1); - } - } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java index 13e51a37ac7..cdd5b5e9999 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java @@ -59,12 +59,4 @@ public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provid return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return ItemStack.EMPTY; - } - return super.getResultItem($$1); - } - } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java index 5397cad2138..e761bb39b93 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java @@ -59,13 +59,5 @@ public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provid return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return ItemStack.EMPTY; - } - return super.getResultItem($$1); - } - } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index 66ffc3e56bd..2a42fe3fdd2 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -91,12 +91,6 @@ public ItemStack assemble(final CraftingInput input, final HolderLookup.Provider return ItemStackUtil.toNative(this.resultFunction.apply(InventoryUtil.toSponge(input))); } - @OnlyIn(Dist.CLIENT) - @Override - public boolean canCraftInDimensions(int width, int height) { - throw new MissingImplementationException("SpongeSpecialRecipe", "canFit"); - } - @Override public NonNullList getRemainingItems(final CraftingInput input) { if (this.remainingItemsFunction == null) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java index 0dd447c0c7c..6ce7547a3f7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java @@ -48,7 +48,7 @@ public class SpongeShapedRecipe extends ShapedRecipe implements ResultFunctionRe public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( $$0 -> $$0.group( Codec.STRING.fieldOf(Constants.Recipe.SPONGE_TYPE).forGetter(t -> "custom"), // important to fail early when decoding vanilla recipes - Codec.STRING.optionalFieldOf(Constants.Recipe.GROUP, "").forGetter(ShapedRecipe::getGroup), + Codec.STRING.optionalFieldOf(Constants.Recipe.GROUP, "").forGetter(ShapedRecipe::group), CraftingBookCategory.CODEC.fieldOf(Constants.Recipe.CATEGORY).orElse(CraftingBookCategory.MISC).forGetter(ShapedRecipe::category), ShapedRecipePattern.MAP_CODEC.forGetter($$0x -> ((ShapedRecipeBridge) $$0x).bridge$pattern()), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), @@ -118,12 +118,4 @@ public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $ return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$0) { - if (this.resultFunctionId != null) { - return ItemStack.EMPTY; - } - return super.getResultItem($$0); - } - } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index 4864e5068e7..daed310a648 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -135,14 +135,6 @@ public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $ return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { -// if (this.resultFunctionId != null) { -// return ItemStack.EMPTY; -// } - return super.getResultItem($$1); - } - private static boolean matches(List stacks, List ingredients) { final int elements = ingredients.size(); diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index 0626bb76ee4..42e3cf263b2 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -81,25 +81,7 @@ public ItemStack assemble(final SmithingRecipeInput $$0, final HolderLookup.Prov return IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); } - final ItemStack resultItem = this.getResultItem($$1); - if (!resultItem.getComponents().isEmpty()) { - final ItemStack itemStack = resultItem.copy(); - var patch = $$0.getItem(0).getComponentsPatch(); - if (!patch.isEmpty()) { - itemStack.applyComponents(patch); - return itemStack; - } - } return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return ItemStack.EMPTY; - } - return super.getResultItem($$1); - } - - } diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index a6791c73274..7cc74df448e 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -95,12 +95,4 @@ public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provid return super.assemble($$0, $$1); } - @Override - public ItemStack getResultItem(final HolderLookup.Provider $$1) { -// if (this.resultFunctionId != null) { -// return ItemStack.EMPTY; -// } - return super.getResultItem($$1); - } - } From 473958825a0fc0da7f5e0a7874cbcd635e55c986 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 8 Oct 2024 19:01:23 -0700 Subject: [PATCH 091/586] chore(update): update for 1.21.2-pre1 Signed-off-by: Gabriel Harris-Rouquette --- .../vanilla/generator/GeneratorMain.java | 1 - gradle.properties | 2 +- gradle/verification-metadata.xml | 95 ++++ .../TargetingConditionsAccessor.java | 2 - .../inventory/StonecutterMenuAccessor.java | 41 -- .../item/crafting/RecipeMapAccessor.java} | 16 +- .../resources/mixins.sponge.accessors.json | 420 +++++++++--------- .../provider/block/entity/LockableData.java | 1 - .../item/stack/BlockItemStackData.java | 1 - .../effect/particle/SpongeParticleHelper.java | 18 +- .../SpongeAvoidLivingGoalBuilder.java | 1 - .../common/inventory/util/InventoryUtil.java | 3 +- .../crafting/custom/SpongeSpecialRecipe.java | 3 - .../loader/CommandRegistryLoader.java | 2 +- .../loader/VanillaRegistryLoader.java | 1 - .../world/entity/EntityMixin_API.java | 1 - .../ai/goal/AvoidEntityGoalMixin_API.java | 2 - .../minecraft/world/item/ItemMixin_API.java | 4 +- .../AbstractCookingRecipeMixin_API.java | 19 +- .../crafting/CraftingRecipeMixin_API.java | 19 +- .../item/crafting/RecipeManagerMixin_API.java | 25 +- .../world/item/crafting/RecipeMixin_API.java | 12 +- .../crafting/SingleItemRecipeMixin_API.java | 3 +- .../crafting/StonecutterRecipeMixin_API.java | 2 +- .../level/storage/LevelDataMixin_API.java | 7 - .../commands/CommandSourceStackMixin.java | 1 - .../server/commands/TeleportCommandMixin.java | 3 +- .../core/server/level/ServerPlayerMixin.java | 41 +- .../core/server/players/PlayerListMixin.java | 3 +- .../mixin/core/world/entity/EntityMixin.java | 16 +- .../world/entity/PortalProcessorMixin.java | 11 +- .../world/entity/ai/sensing/SensorMixin.java | 4 +- .../world/entity/animal/SnowGolemMixin.java | 2 - .../boss/enderdragon/EnderDragonMixin.java | 1 - .../projectile/FireworkRocketEntityMixin.java | 1 - .../projectile/ThrownEnderpearlMixin.java | 13 +- .../world/inventory/StonecutterMenuMixin.java | 31 +- .../crafting/AbstractCookingRecipeMixin.java | 18 +- ...AbstractCookingRecipeSerializerMixin.java} | 19 +- ....java => CustomRecipeSerializerMixin.java} | 6 +- .../item/crafting/RecipeManagerMixin.java | 37 +- .../item/crafting/SingleItemRecipeMixin.java | 5 +- .../world/level/block/CampfireBlockMixin.java | 15 +- .../level/block/EndPortalBlockMixin.java | 4 +- .../AbstractFurnaceBlockEntityMixin.java | 17 +- .../block/entity/BeaconBlockEntityMixin.java | 5 - .../entity/CampfireBlockEntityMixin.java | 49 +- ...erBlockBlockEntityMixin_Inventory_API.java | 5 +- .../CraftingMenuMixin_Inventory.java | 8 +- .../inventory/ResultSlotMixin_Inventory.java | 22 +- ...MenuMixin_TrackedMenuBridge_Inventory.java | 15 +- ...MenuMixin_TrackedMenuBridge_Inventory.java | 5 +- ...PacketListenerImplMixin_MovementCheck.java | 4 +- .../world/level/LevelMixin_Tracker.java | 1 - src/mixins/resources/mixins.sponge.core.json | 4 +- ...actFurnaceBlockEntityAccessor_Vanilla.java | 3 +- ...erGamePacketListenerImplMixin_Vanilla.java | 16 +- ...stractFurnaceBlockEntityMixin_Vanilla.java | 32 +- 58 files changed, 598 insertions(+), 520 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/inventory/StonecutterMenuAccessor.java rename src/{main/java/org/spongepowered/common/bridge/world/level/block/entity/CampfireBlockEntityBridge.java => accessors/java/org/spongepowered/common/accessor/world/item/crafting/RecipeMapAccessor.java} (73%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/{SimpleCookingSerializerMixin.java => AbstractCookingRecipeSerializerMixin.java} (88%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/{SimpleCraftingRecipeSerializerMixin.java => CustomRecipeSerializerMixin.java} (93%) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index a9000d3d50e..bf7c449a001 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -62,7 +62,6 @@ import net.minecraft.world.entity.animal.horse.Markings; import net.minecraft.world.entity.animal.horse.Variant; import net.minecraft.world.entity.monster.SpellcasterIllager; -import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; diff --git a/gradle.properties b/gradle.properties index 7bb5897a081..7d619435edd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w40a +minecraftVersion=1.21.2-pre1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ad17c5edb2c..5bd3115ef98 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1241,6 +1241,14 @@ + + + + + + + + @@ -1664,6 +1672,14 @@ + + + + + + + + @@ -3788,6 +3804,14 @@ + + + + + + + + @@ -3798,6 +3822,11 @@ + + + + + @@ -3814,6 +3843,14 @@ + + + + + + + + @@ -3830,6 +3867,14 @@ + + + + + + + + @@ -3840,6 +3885,11 @@ + + + + + @@ -4884,6 +4934,11 @@ + + + + + @@ -5630,6 +5685,14 @@ + + + + + + + + @@ -5654,6 +5717,14 @@ + + + + + + + + @@ -5686,6 +5757,14 @@ + + + + + + + + @@ -5723,6 +5802,14 @@ + + + + + + + + @@ -5739,6 +5826,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java index 3a2a459743e..7301d5c9c4c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ai/targeting/TargetingConditionsAccessor.java @@ -24,12 +24,10 @@ */ package org.spongepowered.common.accessor.world.entity.ai.targeting; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.targeting.TargetingConditions; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.function.Predicate; @Mixin(TargetingConditions.class) public interface TargetingConditionsAccessor { diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/StonecutterMenuAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/StonecutterMenuAccessor.java deleted file mode 100644 index 7b6b94afb21..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/StonecutterMenuAccessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.inventory; - -import net.minecraft.world.Container; -import net.minecraft.world.inventory.StonecutterMenu; -import net.minecraft.world.item.crafting.SingleRecipeInput; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; - -@Mixin(StonecutterMenu.class) -public interface StonecutterMenuAccessor { - - @Invoker("createRecipeInput") static SingleRecipeInput invoker$createRecipeInput(Container $$0) { - throw new UntransformedInvokerError(); - } - -} diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/block/entity/CampfireBlockEntityBridge.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/RecipeMapAccessor.java similarity index 73% rename from src/main/java/org/spongepowered/common/bridge/world/level/block/entity/CampfireBlockEntityBridge.java rename to src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/RecipeMapAccessor.java index 39c1a505ab7..f7ed452f1de 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/block/entity/CampfireBlockEntityBridge.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/crafting/RecipeMapAccessor.java @@ -22,12 +22,20 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.bridge.world.level.block.entity; +package org.spongepowered.common.accessor.world.item.crafting; -import net.minecraft.world.item.crafting.CampfireCookingRecipe; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeMap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; -public interface CampfireBlockEntityBridge { +import java.util.Map; - void bridge$placeRecipe(RecipeHolder recipe); +@Mixin(RecipeMap.class) +public interface RecipeMapAccessor { + + @Accessor("byKey") + Map>, RecipeHolder> accessor$byKey(); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index ede87acc68c..6b62d5a2b76 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -1,213 +1,213 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.accessor", - "client": [ - "client.KeyMappingAccessor", - "client.multiplayer.ClientLevelAccessor", - "world.level.entity.TransientEntitySectionManagerAccessor" - ], - "mixins": [ - "ChatFormattingAccessor", - "advancements.CriteriaTriggersAccessor", - "advancements.critereon.MinMaxBounds_DoublesAccessor", - "advancements.critereon.MinMaxBounds_IntsAccessor", - "commands.CommandSourceStackAccessor", - "commands.arguments.DimensionArgumentAccessor", - "commands.arguments.OperationArgumentAccessor", - "commands.arguments.selector.EntitySelectorParserAccessor", - "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", - "commands.arguments.selector.options.EntitySelectorOptionsAccessor", - "core.MappedRegistryAccessor", - "entity.passive.AbstractChestedHorseEntityAccessor", - "network.ConnectionAccessor", - "network.chat.HoverEvent_ItemStackInfoAccessor", - "network.chat.StyleAccessor", - "network.protocol.game.ClientboundAddEntityPacketAccessor", - "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", - "network.protocol.game.ServerboundInteractPacketAccessor", - "network.protocol.game.ServerboundMovePlayerPacketAccessor", - "network.protocol.game.ServerboundMoveVehiclePacketAccessor", - "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.ResourceKeyAccessor", - "server.MinecraftServerAccessor", - "server.level.ChunkMap_TrackedEntityAccessor", - "server.level.ChunkMapAccessor", - "server.level.ServerChunkCacheAccessor", - "server.level.ServerLevelAccessor", - "server.level.ServerPlayer_ContainerListenerAccessor", - "server.level.ServerPlayerAccessor", - "server.level.ServerPlayerGameModeAccessor", - "server.level.TicketAccessor", - "server.level.TicketTypeAccessor", - "server.network.ServerCommonPacketListenerImplAccessor", - "server.network.ServerGamePacketListenerImplAccessor", - "server.network.ServerLoginPacketListenerImplAccessor", - "server.players.GameProfileCache_GameProfileInfoAccessor", - "server.players.IpBanListAccessor", - "server.players.PlayerListAccessor", - "server.players.StoredUserEntryAccessor", - "server.players.StoredUserListAccessor", - "server.rcon.thread.RconClientAccessor", - "sounds.SoundEventAccessor", - "stats.StatsCounterAccessor", - "util.datafix.schemas.V100Accessor", - "world.CompoundContainerAccessor", - "world.damagesource.CombatTrackerAccessor", - "world.entity.AgableMobAccessor", - "world.entity.AreaEffectCloudAccessor", - "world.entity.Display_BlockDisplayAccessor", - "world.entity.Display_ItemDisplayAccessor", - "world.entity.Display_TextDisplayAccessor", - "world.entity.DisplayAccessor", - "world.entity.EntityAccessor", - "world.entity.EntityTypeAccessor", - "world.entity.ExperienceOrbAccessor", - "world.entity.LightningBoltAccessor", - "world.entity.LivingEntityAccessor", - "world.entity.MobAccessor", - "world.entity.PortalProcessorAccessor", - "world.entity.ai.targeting.TargetingConditionsAccessor", - "world.entity.animal.AnimalAccessor", - "world.entity.animal.CatAccessor", - "world.entity.animal.FoxAccessor", - "world.entity.animal.OcelotAccessor", - "world.entity.animal.PandaAccessor", - "world.entity.animal.PigAccessor", - "world.entity.animal.PufferfishAccessor", - "world.entity.animal.SheepAccessor", - "world.entity.animal.TropicalFishAccessor", - "world.entity.animal.TurtleAccessor", - "world.entity.animal.WolfAccessor", - "world.entity.animal.horse.HorseAccessor", - "world.entity.animal.horse.LlamaAccessor", - "world.entity.animal.horse.TraderLlamaAccessor", - "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", - "world.entity.boss.wither.WitherBossAccessor", - "world.entity.decoration.ArmorStandAccessor", - "world.entity.decoration.HangingEntityAccessor", - "world.entity.decoration.ItemFrameAccessor", - "world.entity.item.FallingBlockEntityAccessor", - "world.entity.item.PrimedTntAccessor", - "world.entity.monster.BlazeAccessor", - "world.entity.monster.CreeperAccessor", - "world.entity.monster.EnderManAccessor", - "world.entity.monster.EndermiteAccessor", - "world.entity.monster.EvokerAccessor", - "world.entity.monster.GuardianAccessor", - "world.entity.monster.PatrollingMonsterAccessor", - "world.entity.monster.PhantomAccessor", - "world.entity.monster.PillagerAccessor", - "world.entity.monster.RavagerAccessor", - "world.entity.monster.SlimeAccessor", - "world.entity.monster.SpellcasterIllagerAccessor", - "world.entity.monster.VexAccessor", - "world.entity.monster.VindicatorAccessor", - "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.npc.AbstractVillagerAccessor", - "world.entity.player.AbilitiesAccessor", - "world.entity.player.PlayerAccessor", - "world.entity.projectile.ArrowAccessor", - "world.entity.projectile.EyeOfEnderAccessor", - "world.entity.projectile.FireworkRocketEntityAccessor", - "world.entity.projectile.FishingHookAccessor", - "world.entity.projectile.ProjectileAccessor", - "world.entity.projectile.ShulkerBulletAccessor", - "world.entity.raid.RaidAccessor", - "world.entity.raid.RaiderAccessor", - "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.AbstractBoatAccessor", - "world.entity.vehicle.MinecartFurnaceAccessor", - "world.food.FoodDataAccessor", - "world.inventory.AbstractContainerMenuAccessor", - "world.inventory.AbstractFurnaceMenuAccessor", - "world.inventory.BeaconMenuAccessor", - "world.inventory.BrewingStandMenuAccessor", - "world.inventory.AbstractCraftingMenuAccessor", - "world.inventory.DispenserMenuAccessor", - "world.inventory.HopperMenuAccessor", - "world.inventory.HorseInventoryMenuAccessor", - "world.inventory.ItemCombinerMenuAccessor", - "world.inventory.MerchantMenuAccessor", - "world.inventory.ResultSlotAccessor", - "world.inventory.SlotAccessor", - "world.inventory.SmithingMenuAccessor", - "world.inventory.StonecutterMenuAccessor", - "world.item.AdventureModePredicateAccessor", - "world.item.ItemCooldowns_CooldownInstanceAccessor", - "world.item.component.CustomDataAccessor", - "world.item.crafting.ShapelessRecipeAccessor", - "world.item.enchantment.ItemEnchantmentsAccessor", - "world.item.trading.MerchantOfferAccessor", - "world.level.BaseCommandBlockAccessor", - "world.level.BaseSpawnerAccessor", - "world.level.ServerExplosionAccessor", - "world.level.GameRules_ValueAccessor", - "world.level.GameRulesAccessor", - "world.level.LevelAccessor", - "world.level.LevelSettingsAccessor", - "world.level.NaturalSpawner_SpawnStateAccessor", - "world.level.NaturalSpawnerAccessor", - "world.level.biome.Biome_ClimateSettingsAccessor", - "world.level.biome.BiomeAccessor", - "world.level.biome.MobSpawnSettingsAccessor", - "world.level.biome.MultiNoiseBiomeSourceAccessor", - "world.level.biome.OverworldBiomeBuilderAccessor", - "world.level.biome.TheEndBiomeSourceAccessor", - "world.level.block.AbstractSkullBlockAccessor", - "world.level.block.BaseFireBlockAccessor", - "world.level.block.BedBlockAccessor", - "world.level.block.CrafterBlockAccessor", - "world.level.block.CropBlockAccessor", - "world.level.block.DispenserBlockAccessor", - "world.level.block.EnderChestBlockAccessor", - "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", - "world.level.block.entity.BaseContainerBlockEntityAccessor", - "world.level.block.entity.BeaconBlockEntityAccessor", - "world.level.block.entity.BlockEntityAccessor", - "world.level.block.entity.BrewingStandBlockEntityAccessor", - "world.level.block.entity.ConduitBlockEntityAccessor", - "world.level.block.entity.CrafterBlockEntityAccessor", - "world.level.block.entity.EnchantingTableBlockEntityAccessor", - "world.level.block.entity.HopperBlockEntityAccessor", - "world.level.block.entity.LecternBlockEntity_Accessor", - "world.level.block.entity.SkullBlockEntityAccessor", - "world.level.block.entity.SpawnerBlockEntityAccessor", - "world.level.block.entity.StructureBlockEntityAccessor", - "world.level.block.entity.TheEndGatewayBlockEntityAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", - "world.level.block.piston.PistonBaseBlockAccessor", - "world.level.block.state.BlockBehaviour_PropertiesAccessor", - "world.level.block.state.BlockBehaviourAccessor", - "world.level.block.state.StateHolderAccessor", - "world.level.border.WorldBorder_SettingsAccessor", - "world.level.border.WorldBorderAccessor", - "world.level.chunk.ChunkAccessAccessor", - "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", - "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", - "world.level.chunk.LevelChunkAccessor", - "world.level.chunk.storage.ChunkStorageAccessor", - "world.level.chunk.storage.IOWorker$PendingStoreAccessor", - "world.level.chunk.storage.RegionFileAccessor", - "world.level.chunk.storage.SimpleRegionStorageAccessor", - "world.level.dimension.DimensionTypeAccessor", - "world.level.dimension.end.EndDragonFightAccessor", - "world.level.entity.EntityTickListAccessor", - "world.level.entity.PersistentEntitySectionManagerAccessor", - "world.level.levelgen.NoiseSettingsAccessor", - "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", - "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", - "world.level.saveddata.maps.MapItemSavedDataAccessor", - "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", - "world.level.storage.PlayerDataStorageAccessor", - "world.phys.AABBAccessor", - "world.scores.PlayerTeamAccessor", - "world.scores.ScoreboardAccessor" - ], - "server": [ - "server.dedicated.DedicatedServerAccessor" + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.accessor", + "client": [ + "client.KeyMappingAccessor", + "client.multiplayer.ClientLevelAccessor", + "world.level.entity.TransientEntitySectionManagerAccessor" + ], + "mixins": [ + "ChatFormattingAccessor", + "advancements.CriteriaTriggersAccessor", + "advancements.critereon.MinMaxBounds_DoublesAccessor", + "advancements.critereon.MinMaxBounds_IntsAccessor", + "commands.CommandSourceStackAccessor", + "commands.arguments.DimensionArgumentAccessor", + "commands.arguments.OperationArgumentAccessor", + "commands.arguments.selector.EntitySelectorParserAccessor", + "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", + "commands.arguments.selector.options.EntitySelectorOptionsAccessor", + "core.MappedRegistryAccessor", + "entity.passive.AbstractChestedHorseEntityAccessor", + "network.ConnectionAccessor", + "network.chat.HoverEvent_ItemStackInfoAccessor", + "network.chat.StyleAccessor", + "network.protocol.game.ClientboundAddEntityPacketAccessor", + "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", + "network.protocol.game.ServerboundInteractPacketAccessor", + "network.protocol.game.ServerboundMovePlayerPacketAccessor", + "network.protocol.game.ServerboundMoveVehiclePacketAccessor", + "network.protocol.handshake.ClientIntentionPacketAccessor", + "resources.ResourceKeyAccessor", + "server.MinecraftServerAccessor", + "server.level.ChunkMap_TrackedEntityAccessor", + "server.level.ChunkMapAccessor", + "server.level.ServerChunkCacheAccessor", + "server.level.ServerLevelAccessor", + "server.level.ServerPlayer_ContainerListenerAccessor", + "server.level.ServerPlayerAccessor", + "server.level.ServerPlayerGameModeAccessor", + "server.level.TicketAccessor", + "server.level.TicketTypeAccessor", + "server.network.ServerCommonPacketListenerImplAccessor", + "server.network.ServerGamePacketListenerImplAccessor", + "server.network.ServerLoginPacketListenerImplAccessor", + "server.players.GameProfileCache_GameProfileInfoAccessor", + "server.players.IpBanListAccessor", + "server.players.PlayerListAccessor", + "server.players.StoredUserEntryAccessor", + "server.players.StoredUserListAccessor", + "server.rcon.thread.RconClientAccessor", + "sounds.SoundEventAccessor", + "stats.StatsCounterAccessor", + "util.datafix.schemas.V100Accessor", + "world.CompoundContainerAccessor", + "world.damagesource.CombatTrackerAccessor", + "world.entity.AgableMobAccessor", + "world.entity.AreaEffectCloudAccessor", + "world.entity.Display_BlockDisplayAccessor", + "world.entity.Display_ItemDisplayAccessor", + "world.entity.Display_TextDisplayAccessor", + "world.entity.DisplayAccessor", + "world.entity.EntityAccessor", + "world.entity.EntityTypeAccessor", + "world.entity.ExperienceOrbAccessor", + "world.entity.LightningBoltAccessor", + "world.entity.LivingEntityAccessor", + "world.entity.MobAccessor", + "world.entity.PortalProcessorAccessor", + "world.entity.ai.targeting.TargetingConditionsAccessor", + "world.entity.animal.AnimalAccessor", + "world.entity.animal.CatAccessor", + "world.entity.animal.FoxAccessor", + "world.entity.animal.OcelotAccessor", + "world.entity.animal.PandaAccessor", + "world.entity.animal.PigAccessor", + "world.entity.animal.PufferfishAccessor", + "world.entity.animal.SheepAccessor", + "world.entity.animal.TropicalFishAccessor", + "world.entity.animal.TurtleAccessor", + "world.entity.animal.WolfAccessor", + "world.entity.animal.horse.HorseAccessor", + "world.entity.animal.horse.LlamaAccessor", + "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", + "world.entity.boss.wither.WitherBossAccessor", + "world.entity.decoration.ArmorStandAccessor", + "world.entity.decoration.HangingEntityAccessor", + "world.entity.decoration.ItemFrameAccessor", + "world.entity.item.FallingBlockEntityAccessor", + "world.entity.item.PrimedTntAccessor", + "world.entity.monster.BlazeAccessor", + "world.entity.monster.CreeperAccessor", + "world.entity.monster.EnderManAccessor", + "world.entity.monster.EndermiteAccessor", + "world.entity.monster.EvokerAccessor", + "world.entity.monster.GuardianAccessor", + "world.entity.monster.PatrollingMonsterAccessor", + "world.entity.monster.PhantomAccessor", + "world.entity.monster.PillagerAccessor", + "world.entity.monster.RavagerAccessor", + "world.entity.monster.SlimeAccessor", + "world.entity.monster.SpellcasterIllagerAccessor", + "world.entity.monster.VexAccessor", + "world.entity.monster.VindicatorAccessor", + "world.entity.monster.ZombifiedPiglinAccessor", + "world.entity.npc.AbstractVillagerAccessor", + "world.entity.player.AbilitiesAccessor", + "world.entity.player.PlayerAccessor", + "world.entity.projectile.ArrowAccessor", + "world.entity.projectile.EyeOfEnderAccessor", + "world.entity.projectile.FireworkRocketEntityAccessor", + "world.entity.projectile.FishingHookAccessor", + "world.entity.projectile.ProjectileAccessor", + "world.entity.projectile.ShulkerBulletAccessor", + "world.entity.raid.RaidAccessor", + "world.entity.raid.RaiderAccessor", + "world.entity.raid.RaidsAccessor", + "world.entity.vehicle.AbstractBoatAccessor", + "world.entity.vehicle.MinecartFurnaceAccessor", + "world.food.FoodDataAccessor", + "world.inventory.AbstractContainerMenuAccessor", + "world.inventory.AbstractCraftingMenuAccessor", + "world.inventory.AbstractFurnaceMenuAccessor", + "world.inventory.BeaconMenuAccessor", + "world.inventory.BrewingStandMenuAccessor", + "world.inventory.DispenserMenuAccessor", + "world.inventory.HopperMenuAccessor", + "world.inventory.HorseInventoryMenuAccessor", + "world.inventory.ItemCombinerMenuAccessor", + "world.inventory.MerchantMenuAccessor", + "world.inventory.ResultSlotAccessor", + "world.inventory.SlotAccessor", + "world.inventory.SmithingMenuAccessor", + "world.item.AdventureModePredicateAccessor", + "world.item.ItemCooldowns_CooldownInstanceAccessor", + "world.item.component.CustomDataAccessor", + "world.item.crafting.RecipeMapAccessor", + "world.item.crafting.ShapelessRecipeAccessor", + "world.item.enchantment.ItemEnchantmentsAccessor", + "world.item.trading.MerchantOfferAccessor", + "world.level.BaseCommandBlockAccessor", + "world.level.BaseSpawnerAccessor", + "world.level.GameRules_ValueAccessor", + "world.level.GameRulesAccessor", + "world.level.LevelAccessor", + "world.level.LevelSettingsAccessor", + "world.level.NaturalSpawner_SpawnStateAccessor", + "world.level.NaturalSpawnerAccessor", + "world.level.ServerExplosionAccessor", + "world.level.biome.Biome_ClimateSettingsAccessor", + "world.level.biome.BiomeAccessor", + "world.level.biome.MobSpawnSettingsAccessor", + "world.level.biome.MultiNoiseBiomeSourceAccessor", + "world.level.biome.OverworldBiomeBuilderAccessor", + "world.level.biome.TheEndBiomeSourceAccessor", + "world.level.block.AbstractSkullBlockAccessor", + "world.level.block.BaseFireBlockAccessor", + "world.level.block.BedBlockAccessor", + "world.level.block.CrafterBlockAccessor", + "world.level.block.CropBlockAccessor", + "world.level.block.DispenserBlockAccessor", + "world.level.block.EnderChestBlockAccessor", + "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", + "world.level.block.entity.BaseContainerBlockEntityAccessor", + "world.level.block.entity.BeaconBlockEntityAccessor", + "world.level.block.entity.BlockEntityAccessor", + "world.level.block.entity.BrewingStandBlockEntityAccessor", + "world.level.block.entity.ConduitBlockEntityAccessor", + "world.level.block.entity.CrafterBlockEntityAccessor", + "world.level.block.entity.EnchantingTableBlockEntityAccessor", + "world.level.block.entity.HopperBlockEntityAccessor", + "world.level.block.entity.LecternBlockEntity_Accessor", + "world.level.block.entity.SkullBlockEntityAccessor", + "world.level.block.entity.SpawnerBlockEntityAccessor", + "world.level.block.entity.StructureBlockEntityAccessor", + "world.level.block.entity.TheEndGatewayBlockEntityAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", + "world.level.block.piston.PistonBaseBlockAccessor", + "world.level.block.state.BlockBehaviour_PropertiesAccessor", + "world.level.block.state.BlockBehaviourAccessor", + "world.level.block.state.StateHolderAccessor", + "world.level.border.WorldBorder_SettingsAccessor", + "world.level.border.WorldBorderAccessor", + "world.level.chunk.ChunkAccessAccessor", + "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", + "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", + "world.level.chunk.LevelChunkAccessor", + "world.level.chunk.storage.ChunkStorageAccessor", + "world.level.chunk.storage.IOWorker$PendingStoreAccessor", + "world.level.chunk.storage.RegionFileAccessor", + "world.level.chunk.storage.SimpleRegionStorageAccessor", + "world.level.dimension.DimensionTypeAccessor", + "world.level.dimension.end.EndDragonFightAccessor", + "world.level.entity.EntityTickListAccessor", + "world.level.entity.PersistentEntitySectionManagerAccessor", + "world.level.levelgen.NoiseSettingsAccessor", + "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", + "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", + "world.level.saveddata.maps.MapItemSavedDataAccessor", + "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", + "world.level.storage.PlayerDataStorageAccessor", + "world.phys.AABBAccessor", + "world.scores.PlayerTeamAccessor", + "world.scores.ScoreboardAccessor" + ], + "server": [ + "server.dedicated.DedicatedServerAccessor" ] } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java index d8653cb763d..cdbbb388550 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/LockableData.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.data.provider.block.entity; -import net.minecraft.world.LockCode; import org.spongepowered.api.data.Keys; import org.spongepowered.common.accessor.world.level.block.entity.BaseContainerBlockEntityAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java index a87303e42cf..1c281273d53 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockItemStackData.java @@ -25,7 +25,6 @@ package org.spongepowered.common.data.provider.item.stack; import net.minecraft.core.component.DataComponents; -import net.minecraft.world.LockCode; import net.minecraft.world.item.BannerItem; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java index c9782b4f606..c09654d2ca8 100644 --- a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java +++ b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java @@ -108,27 +108,15 @@ private static CachedParticlePacket getNamedPacket(final ParticleEffect effect, final Color toColor = effect.optionOrDefault(ParticleOptions.TO_COLOR).get(); final double scale = effect.optionOrDefault(ParticleOptions.SCALE).get(); final DustColorTransitionOptions particleData = new DustColorTransitionOptions( - new org.joml.Vector3f( - (float) color.red() / 255, - (float) color.green() / 255, - (float) color.blue() / 255 - ), - new org.joml.Vector3f( - (float) toColor.red() / 255, - (float) toColor.green() / 255, - (float) toColor.blue() / 255 - ), + ARGB.color(color.red(), color.green(), color.blue()), + ARGB.color(toColor.red(), toColor.green(), toColor.blue()), (float) scale); return new NamedCachedPacket(particleData, offset, quantity, velocity); } else if (internalType == ParticleTypes.DUST) { //This particle type supports a color option. final Color color = effect.optionOrDefault(ParticleOptions.COLOR).get(); final double scale = effect.optionOrDefault(ParticleOptions.SCALE).get(); - final DustParticleOptions particleData = new DustParticleOptions(new org.joml.Vector3f( - (float) color.red() / 255, - (float) color.green() / 255, - (float) color.blue() / 255), - (float) scale); + final DustParticleOptions particleData = new DustParticleOptions(ARGB.color(color.red(), color.green(), color.blue()), (float) scale); return new NamedCachedPacket(particleData, offset, quantity, velocity); } else if (internalType == ParticleTypes.ITEM) { //This particle type supports an item option. diff --git a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java index 93e62b4ed17..a075bb4af60 100644 --- a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/SpongeAvoidLivingGoalBuilder.java @@ -32,7 +32,6 @@ import org.spongepowered.api.world.server.ServerWorld; import java.util.Objects; -import java.util.function.BiPredicate; import java.util.function.Predicate; public final class SpongeAvoidLivingGoalBuilder implements AvoidLivingGoal.Builder { diff --git a/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java b/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java index f58776c355a..dbdcfcdbe12 100644 --- a/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java +++ b/src/main/java/org/spongepowered/common/inventory/util/InventoryUtil.java @@ -53,7 +53,6 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.inventory.AbstractCraftingMenuAccessor; import org.spongepowered.common.accessor.world.inventory.SmithingMenuAccessor; -import org.spongepowered.common.accessor.world.inventory.StonecutterMenuAccessor; import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; import org.spongepowered.common.entity.player.SpongeUserData; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; @@ -99,7 +98,7 @@ public static Optional toCraftingInput(final Invent .map(SingleRecipeInput::new).orElse(null); case AbstractCraftingMenuAccessor menu -> menu.accessor$craftSlots().asCraftInput(); case InventoryMenu menu -> menu.getCraftSlots().asCraftInput(); - case StonecutterMenu menu -> StonecutterMenuAccessor.invoker$createRecipeInput(menu.container); + case StonecutterMenu menu -> new SingleRecipeInput(menu.container.getItem(0)); case SmithingMenuAccessor menu -> menu.invoker$createRecipeInput(); default -> null; }; diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index 2a42fe3fdd2..bc2ec36d749 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -36,14 +36,11 @@ import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.Constants; -import org.spongepowered.common.util.MissingImplementationException; import java.util.List; import java.util.function.BiPredicate; diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index 63d3a85e769..f0c4ab3d9c8 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -217,7 +217,7 @@ public static RegistryLoader clientCompletionType() { public static RegistryLoader clientSuggestionProvider() { return RegistryLoader.of(l -> { // TODO based on SuggestionProviders.PROVIDERS_BY_NAME instead - l.add(CommandCompletionProviders.ALL_RECIPES, k -> (CommandCompletionProvider) SuggestionProviders.ALL_RECIPES); +// l.add(CommandCompletionProviders.ALL_RECIPES, k -> (CommandCompletionProvider) SuggestionProviders.ALL_RECIPES); l.add(CommandCompletionProviders.AVAILABLE_SOUNDS, k -> (CommandCompletionProvider) SuggestionProviders.AVAILABLE_SOUNDS); l.add(CommandCompletionProviders.SUMMONABLE_ENTITIES, k -> (CommandCompletionProvider) SuggestionProviders.SUMMONABLE_ENTITIES); }); diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 338da482292..8a2491cc8d2 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -54,7 +54,6 @@ import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.raid.Raid; -import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index 63ba4343956..4d9768d9c26 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -32,7 +32,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java index 208b9805d88..48acc27bbe2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/goal/AvoidEntityGoalMixin_API.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.ai.goal; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.targeting.TargetingConditions; import org.spongepowered.api.entity.ai.goal.builtin.creature.AvoidLivingGoal; import org.spongepowered.api.entity.living.Living; @@ -37,7 +36,6 @@ import org.spongepowered.common.accessor.world.entity.ai.targeting.TargetingConditionsAccessor; import java.util.function.BiPredicate; -import java.util.function.Predicate; @SuppressWarnings({"unchecked"}) @Mixin(net.minecraft.world.entity.ai.goal.AvoidEntityGoal.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java index 557d19c5177..e0e6f7f20c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java @@ -56,7 +56,7 @@ public abstract class ItemMixin_API implements ItemType, SpongeImmutableDataHold @Shadow @Final private DataComponentMap components; @Shadow public abstract String shadow$getDescriptionId(); - @Shadow @Nullable public abstract Item shadow$getCraftingRemainingItem(); + @Shadow @Final @Nullable private Item craftingRemainingItem; @Shadow public abstract int shadow$getDefaultMaxStackSize(); // @formatter:on @@ -111,7 +111,7 @@ public boolean is(Tag tag) { @Override public Optional container() { - final Item craftingRemainingItem = this.shadow$getCraftingRemainingItem(); + final @Nullable Item craftingRemainingItem = this.craftingRemainingItem; return Optional.ofNullable((ItemType) craftingRemainingItem); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java index 609b3a7dba5..bb8dc2dd723 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java @@ -25,12 +25,10 @@ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; import net.minecraft.world.item.crafting.AbstractCookingRecipe; -import net.minecraft.world.item.crafting.Ingredient; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.recipe.cooking.CookingRecipe; import org.spongepowered.api.item.recipe.cooking.CookingResult; import org.spongepowered.api.util.Ticks; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; @@ -40,39 +38,38 @@ import java.util.Optional; @Mixin(AbstractCookingRecipe.class) -public abstract class AbstractCookingRecipeMixin_API implements CookingRecipe { +public abstract class AbstractCookingRecipeMixin_API extends SingleItemRecipeMixin_API implements CookingRecipe { // @formatter:off - @Shadow @Final protected Ingredient ingredient; - @Shadow public abstract float shadow$getExperience(); - @Shadow public abstract int shadow$getCookingTime(); + @Shadow public abstract float shadow$experience(); + @Shadow public abstract int shadow$cookingTime(); // @formatter:on @Override public org.spongepowered.api.item.recipe.crafting.Ingredient ingredient() { - return IngredientUtil.fromNative(this.ingredient); + return IngredientUtil.fromNative(this.shadow$input()); } @Override public boolean isValid(final ItemStackSnapshot ingredient) { - return this.ingredient.test(ItemStackUtil.fromSnapshotToNative(ingredient)); + return this.shadow$input().test(ItemStackUtil.fromSnapshotToNative(ingredient)); } @Override public Optional result(final ItemStackSnapshot ingredient) { if (this.isValid(ingredient)) { - return Optional.of(new CookingResult(this.exemplaryResult(), this.shadow$getExperience())); + return Optional.of(new CookingResult(this.exemplaryResult(), this.shadow$experience())); } return Optional.empty(); } @Override public Ticks cookingTime() { - return SpongeTicks.ticksOrInfinite(this.shadow$getCookingTime()); + return SpongeTicks.ticksOrInfinite(this.shadow$cookingTime()); } @Override public float experience() { - return this.shadow$getExperience(); + return this.shadow$experience(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/CraftingRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/CraftingRecipeMixin_API.java index c5c25ee36c3..c11308717b6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/CraftingRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/CraftingRecipeMixin_API.java @@ -24,13 +24,20 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; +import net.minecraft.core.NonNullList; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapelessRecipe; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.recipe.RecipeType; import org.spongepowered.api.item.recipe.crafting.CraftingRecipe; +import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.util.ItemStackUtil; +import java.util.List; import java.util.Optional; @Mixin(net.minecraft.world.item.crafting.CraftingRecipe.class) @@ -38,8 +45,16 @@ public interface CraftingRecipeMixin_API extends CraftingRecipe { // @formatter:off @Shadow net.minecraft.world.item.crafting.RecipeType shadow$getType(); + @Shadow NonNullList shadow$getRemainingItems(CraftingInput $$0); // @formatter:on + @Override + default List remainingItems(RecipeInput.Crafting inventory) { + return this.shadow$getRemainingItems((CraftingInput) inventory).stream() + .map(ItemStackUtil::snapshotOf) + .toList(); + } + default RecipeType type() { return (RecipeType) this.shadow$getType(); } @@ -47,10 +62,10 @@ default RecipeType type() { default Optional group() { String group = ""; if (this instanceof ShapedRecipe sr) { - group = sr.getGroup(); + group = sr.group(); } if (this instanceof ShapelessRecipe sr) { - group = sr.getGroup(); + group = sr.group(); } if (group.isEmpty()) { return Optional.empty(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java index efa6d8b2734..e82ad955f7d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java @@ -24,11 +24,12 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeInput; import net.minecraft.world.item.crafting.RecipeManager.CachedCheck; +import net.minecraft.world.item.crafting.RecipeMap; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.Level; import org.spongepowered.api.ResourceKey; @@ -40,6 +41,7 @@ import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.world.item.crafting.RecipeMapAccessor; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.util.ItemStackUtil; @@ -52,17 +54,24 @@ public abstract class RecipeManagerMixin_API implements RecipeManager { // @formatter:off - @Shadow public abstract Optional> shadow$byKey(ResourceLocation recipeId); - @Shadow protected abstract > Collection> shadow$byType(net.minecraft.world.item.crafting.RecipeType recipeTypeIn); @Shadow public abstract Collection> shadow$getRecipes(); - @Shadow public abstract > Optional shadow$getRecipeFor(net.minecraft.world.item.crafting.RecipeType recipeTypeIn, I inventoryIn, net.minecraft.world.level.Level worldIn); + @Shadow public abstract > Optional shadow$getRecipeFor(net.minecraft.world.item.crafting.RecipeType recipeTypeIn, I inventoryIn, Level worldIn); // @formatter:on + @Shadow + private RecipeMap recipes; + @Override public Optional> byKey(final ResourceKey key) { Objects.requireNonNull(key); - return this.shadow$byKey((ResourceLocation) (Object) key).map(Recipe.class::cast); + // TODO - figure out how to do this better + for (var entry : ((RecipeMapAccessor) this.recipes).accessor$byKey().entrySet()) { + if (entry.getKey().location().equals(key)) { + return Optional.of(entry.getValue()).map(Recipe.class::cast); + } + } + return Optional.empty(); } @Override @@ -75,7 +84,7 @@ public Collection> all() { @SuppressWarnings(value = {"unchecked", "rawtypes"}) public > Collection allOfType(final RecipeType type) { Objects.requireNonNull(type); - return this.shadow$byType((net.minecraft.world.item.crafting.RecipeType)type); + return this.recipes.byType((net.minecraft.world.item.crafting.RecipeType)type); } @Override @@ -99,12 +108,12 @@ public RecipeManagerMixin_API.impl$getRecipe(level, checker, in)); } - private static > Optional> impl$getRecipe(final Level level, final CachedCheck checker, final I input) { + private static > Optional> impl$getRecipe(final ServerLevel level, final CachedCheck checker, final I input) { return checker.getRecipeFor(input, level).map(RecipeHolder::value).map(Recipe.class::cast); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java index 7ed649e48ae..a0a73960da9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java @@ -27,7 +27,6 @@ import static org.spongepowered.common.inventory.util.InventoryUtil.toCraftingInputOrThrow; import net.minecraft.core.HolderLookup; -import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeInput; import org.checkerframework.checker.nullness.qual.NonNull; @@ -41,24 +40,22 @@ import org.spongepowered.common.item.util.ItemStackUtil; import java.util.List; -import java.util.stream.Collectors; @Mixin(net.minecraft.world.item.crafting.Recipe.class) public interface RecipeMixin_API extends Recipe { // @formatter:off @Shadow ItemStack shadow$assemble(I inv, HolderLookup.Provider registryAccess); - @Shadow net.minecraft.world.item.ItemStack shadow$getResultItem(HolderLookup.Provider registryAccess); @Shadow boolean shadow$isSpecial(); @Shadow boolean shadow$matches(I inv, net.minecraft.world.level.Level worldIn); - @Shadow NonNullList shadow$getRemainingItems(I inv); @Shadow net.minecraft.world.item.crafting.RecipeType shadow$getType(); // @formatter:on @NonNull @Override default ItemStackSnapshot exemplaryResult() { - return ItemStackUtil.snapshotOf(this.shadow$getResultItem(SpongeCommon.server().registryAccess())); + // TODO - Do we want to start exposing slot displays in some way? + return ItemStackSnapshot.empty(); } @Override @@ -75,10 +72,7 @@ default ItemStackSnapshot result(@NonNull final I2 inv) { @NonNull @Override default List remainingItems(@NonNull final I2 inv) { - final var nonNullList = this.shadow$getRemainingItems((I) toCraftingInputOrThrow(inv)); - return nonNullList.stream() - .map(ItemStackUtil::snapshotOf) - .collect(Collectors.toList()); + return List.of(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java index 4623309db0d..d7233ca9379 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SingleItemRecipeMixin_API.java @@ -26,7 +26,6 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleItemRecipe; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -34,7 +33,7 @@ public abstract class SingleItemRecipeMixin_API { // @formatter:off - @Shadow @Final protected Ingredient ingredient; + @Shadow public abstract Ingredient shadow$input(); // @formatter:on } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java index 7cbfc0a5447..63a38f12cb6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/StonecutterRecipeMixin_API.java @@ -34,7 +34,7 @@ public abstract class StonecutterRecipeMixin_API extends SingleItemRecipeMixin_A @Override public org.spongepowered.api.item.recipe.crafting.Ingredient ingredient() { - return IngredientUtil.fromNative(this.ingredient); + return IngredientUtil.fromNative(this.shadow$input()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java index 8de4402c106..cc207d515f5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java @@ -24,20 +24,13 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.storage.LevelData; import org.spongepowered.api.util.MinecraftDayTime; -import org.spongepowered.api.world.gamerule.GameRule; import org.spongepowered.api.world.storage.WorldProperties; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.accessor.world.level.GameRulesAccessor; -import org.spongepowered.common.accessor.world.level.GameRules_ValueAccessor; import org.spongepowered.common.util.SpongeMinecraftDayTime; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; @Mixin(LevelData.class) public interface LevelDataMixin_API extends WorldProperties { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java index e81e9559941..7a651e6e2c2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java @@ -54,7 +54,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.accessor.commands.CommandSourceStackAccessor; -import org.spongepowered.common.accessor.world.entity.EntityAccessor; import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index 55155b24cd4..1b6676593a7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -26,6 +26,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; +import net.minecraft.server.commands.LookAt; import net.minecraft.server.commands.TeleportCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -70,7 +71,7 @@ public abstract class TeleportCommandMixin { @Overwrite // TODO check if this is still correct - check if we can get rid of the overwrite private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, - Set relativeList, float yaw, float pitch, TeleportCommand.@Nullable LookAt facing) { + Set relativeList, float yaw, float pitch, @Nullable LookAt facing) { double actualX = x; double actualY = y; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 06f667ffb7d..7f5bb335570 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -75,7 +75,7 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; @@ -238,8 +238,8 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr this.connection.teleport(new PositionMoveRotation(VecHelper.toVanillaVector3d(pos), Vec3.ZERO, this.shadow$getYRot(), this.shadow$getXRot()), new HashSet<>()); this.connection.resetPosition(); } else { - this.bridge$changeDimension(new DimensionTransition(level, VecHelper.toVanillaVector3d(pos), thisPlayer.getKnownMovement(), - this.shadow$getYRot(), this.shadow$getXRot(), DimensionTransition.DO_NOTHING)); + this.bridge$changeDimension(new TeleportTransition(level, VecHelper.toVanillaVector3d(pos), thisPlayer.getKnownMovement(), + this.shadow$getYRot(), this.shadow$getXRot(), TeleportTransition.DO_NOTHING)); } return true; } @@ -424,7 +424,7 @@ public boolean teleportTo(final ServerLevel world, } final var thisPlayer = (net.minecraft.server.level.ServerPlayer) (Object) this; - return this.bridge$changeDimension(new DimensionTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, + return this.bridge$changeDimension(new TeleportTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, e -> world.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, e.chunkPosition(), 1, thisPlayer.getId()))) != null; } } @@ -439,7 +439,7 @@ public boolean teleportTo(final ServerLevel world, * @return The {@link Entity} that is either this one, or replaces this one */ @Override - public @Nullable Entity bridge$changeDimension(final DimensionTransition originalTransition) { + public @Nullable Entity bridge$changeDimension(final TeleportTransition originalTransition) { if (this.shadow$isRemoved()) { return null; } @@ -464,7 +464,7 @@ public boolean teleportTo(final ServerLevel world, if (newLevel.dimension() == oldLevel.dimension()) { // actually no dimension change this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); this.connection.resetPosition(); - transition.postDimensionTransition().onTransition(thisPlayer); + transition.postTeleportTransition().onTransition(thisPlayer); // TODO setYHeadRot after would rotate event result return thisPlayer; } @@ -496,7 +496,7 @@ public boolean teleportTo(final ServerLevel world, playerList.sendLevelInfo(thisPlayer, newLevel); playerList.sendAllPlayerInfo(thisPlayer); playerList.sendActivePlayerEffects(thisPlayer); - transition.postDimensionTransition().onTransition(thisPlayer); + transition.postTeleportTransition().onTransition(thisPlayer); // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic called bridge$getBossBarManager().onPlayerDisconnect(player); on both worlds // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic closed player.closeContainer(); when open this.lastSentExp = -1; @@ -517,7 +517,7 @@ public boolean teleportTo(final ServerLevel world, } @Nullable - private DimensionTransition impl$fireDimensionTransitionEvents(final DimensionTransition originalTransition, + private TeleportTransition impl$fireDimensionTransitionEvents(final TeleportTransition originalTransition, final net.minecraft.server.level.ServerPlayer thisPlayer) { var transition = originalTransition; var isDimensionChange = transition.newLevel() != thisPlayer.serverLevel(); @@ -545,13 +545,14 @@ public boolean teleportTo(final ServerLevel world, return null; } if (preEvent.destinationWorld() != preEvent.originalDestinationWorld()) { - transition = new DimensionTransition((ServerLevel) preEvent.destinationWorld(), + transition = new TeleportTransition((ServerLevel) preEvent.destinationWorld(), transition.position(), transition.deltaMovement(), transition.yRot(), transition.xRot(), transition.missingRespawnBlock(), - EnumSet.noneOf(Relative.class), - transition.postDimensionTransition()); + transition.asPassenger(), + EnumSet.noneOf(Relative.class), + transition.postTeleportTransition()); } } @@ -572,13 +573,14 @@ public boolean teleportTo(final ServerLevel world, } if (newDest != originalDest) { // if changed override the DimensionTransition - transition = new DimensionTransition(transition.newLevel(), + transition = new TeleportTransition(transition.newLevel(), VecHelper.toVanillaVector3d(newDest), transition.deltaMovement(), transition.yRot(), transition.xRot(), transition.missingRespawnBlock(), + transition.asPassenger(), EnumSet.noneOf(Relative.class), - transition.postDimensionTransition()); + transition.postTeleportTransition()); } final Vector3d toRot = new Vector3d(transition.xRot(), transition.yRot(), 0); @@ -589,13 +591,14 @@ public boolean teleportTo(final ServerLevel world, newToRot = fromRot; // Cancelled Rotate - Reset to original rotation } if (toRot != newToRot) { - transition = new DimensionTransition(transition.newLevel(), + transition = new TeleportTransition(transition.newLevel(), transition.position(), transition.deltaMovement(), (float) newToRot.y(), (float) newToRot.x(), transition.missingRespawnBlock(), - EnumSet.noneOf(Relative.class), - transition.postDimensionTransition()); + transition.asPassenger(), + EnumSet.noneOf(Relative.class), + transition.postTeleportTransition()); } } @@ -929,8 +932,12 @@ private boolean isPvpAllowed() { return ((ServerWorld) this.shadow$serverLevel()).properties().pvp(); } + /** + * @author gabizou - 1.21.2-pre1 + * @reason We route all teleportation through sponge's bridge for handling events + */ @Overwrite - public Entity changeDimension(final DimensionTransition transition) { + public @Nullable Entity teleport(final TeleportTransition transition) { return this.bridge$changeDimension(transition); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 305949406bb..a63a366f125 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -482,10 +482,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { ((SpongeServer) this.shadow$getServer()).getPlayerDataManager().readPlayerData(compound, entity.getUUID(), null); } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @Inject(method = "respawn", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;findRespawnPositionAndUseSpawnBlock(ZLnet/minecraft/world/level/portal/DimensionTransition$PostDimensionTransition;)Lnet/minecraft/world/level/portal/DimensionTransition;" + target = "Lnet/minecraft/server/level/ServerPlayer;findRespawnPositionAndUseSpawnBlock(ZLnet/minecraft/world/level/portal/TeleportTransition$PostTeleportTransition;)Lnet/minecraft/world/level/portal/TeleportTransition;" ) ) private void impl$flagIfRespawnPositionIsGameMechanic(final net.minecraft.server.level.ServerPlayer $$0, final boolean $$1, diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index b542809e3f4..50f98456499 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -58,7 +58,7 @@ import net.minecraft.world.level.block.Portal; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; @@ -430,7 +430,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, * TODO we may need to separate into Vanilla and Forge again */ @Overwrite - public Entity changeDimension(final DimensionTransition transition) { + public Entity teleport(final TeleportTransition transition) { return this.bridge$changeDimension(transition); } @@ -471,8 +471,8 @@ public Entity changeDimension(final DimensionTransition transition) { * See {@link PortalProcessorMixin#impl$onGetPortalDestination} for portal events */ @Redirect(method = "handlePortal", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;changeDimension(Lnet/minecraft/world/level/portal/DimensionTransition;)Lnet/minecraft/world/entity/Entity;")) - public Entity impl$onChangeDimension(final Entity instance, final DimensionTransition transition) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleport(Lnet/minecraft/world/level/portal/TeleportTransition;)Lnet/minecraft/world/entity/Entity;")) + public Entity impl$onChangeDimension(final Entity instance, final TeleportTransition transition) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.pushCause(this); var be = this.shadow$level().getBlockEntity(this.portalProcess.getEntryPosition()); @@ -487,7 +487,7 @@ public Entity changeDimension(final DimensionTransition transition) { // TODO frame.addContext(EventContextKeys.PORTAL, transition); // TODO 2-dim portal? this.impl$moveEventsFired = true; - return instance.changeDimension(transition); + return instance.teleport(transition); } finally { this.impl$moveEventsFired = false; } @@ -500,7 +500,7 @@ public Entity changeDimension(final DimensionTransition transition) { */ @SuppressWarnings("ConstantConditions") @Nullable - public Entity bridge$changeDimension(final DimensionTransition transition) { + public Entity bridge$changeDimension(final TeleportTransition transition) { final Entity thisEntity = (Entity) (Object) this; if (!(thisEntity.level() instanceof ServerLevel oldLevel) || this.shadow$isRemoved()) { // Sponge inverted check return null; @@ -512,7 +512,7 @@ public Entity changeDimension(final DimensionTransition transition) { List recreatedPassengers = new ArrayList<>(); this.shadow$unRide(); for (final Entity passenger : passengers) { - var recreatedPassenger = passenger.changeDimension(transition); + var recreatedPassenger = passenger.teleport(transition); if (recreatedPassenger != null) { recreatedPassengers.add(recreatedPassenger); } @@ -540,7 +540,7 @@ public Entity changeDimension(final DimensionTransition transition) { oldLevel.resetEmptyTime(); newLevel.resetEmptyTime(); - transition.postDimensionTransition().onTransition(newEntity); + transition.postTeleportTransition().onTransition(newEntity); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java index 4b86c61d707..231f732397a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java @@ -33,7 +33,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Portal; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.SpongeEventFactory; @@ -76,8 +76,8 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { @Redirect(method = "getPortalDestination", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Portal;getPortalDestination(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/portal/DimensionTransition;")) - public DimensionTransition impl$onGetPortalDestination(final Portal instance, final ServerLevel serverLevel, final Entity entity, final BlockPos blockPos) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Portal;getPortalDestination(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/portal/TeleportTransition;")) + public TeleportTransition impl$onGetPortalDestination(final Portal instance, final ServerLevel serverLevel, final Entity entity, final BlockPos blockPos) { final var spongEntity = (org.spongepowered.api.entity.Entity) entity; var finalPortal = instance; @@ -142,14 +142,15 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { } // modify transition after event - return new DimensionTransition((ServerLevel) tpEvent.destinationWorld(), + return new TeleportTransition((ServerLevel) tpEvent.destinationWorld(), VecHelper.toVanillaVector3d(tpEvent.destinationPosition()), VecHelper.toVanillaVector3d(tpEvent.exitSpeed()), (float) tpEvent.toRotation().x(), (float) tpEvent.toRotation().y(), transition.missingRespawnBlock(), + transition.asPassenger(), EnumSet.noneOf(Relative.class), - transition.postDimensionTransition()); + transition.postTeleportTransition()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java index 5ab4f0887be..8c032e63cea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/sensing/SensorMixin.java @@ -42,11 +42,11 @@ public class SensorMixin { "isEntityAttackableIgnoringLineOfSight" }, at = @At("HEAD"), cancellable = true) private static void impl$cancelForVanishedEntities(ServerLevel $$0, LivingEntity $$1, LivingEntity $$2, CallbackInfoReturnable cir) { - final var vs = ((VanishableBridge) $$0).bridge$vanishState(); + final var vs = ((VanishableBridge) $$1).bridge$vanishState(); if (vs.invisible() && vs.untargetable()) { cir.setReturnValue(false); } - final var vsOther = ((VanishableBridge) $$1).bridge$vanishState(); + final var vsOther = ((VanishableBridge) $$2).bridge$vanishState(); if (vsOther.invisible() && vsOther.untargetable()) { cir.setReturnValue(false); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java index 9393f86511b..2cd0432ea5e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java @@ -28,9 +28,7 @@ import net.minecraft.world.level.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.mixin.core.world.entity.MobMixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java index 59643aef1e1..3661568aab3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java @@ -29,7 +29,6 @@ import net.minecraft.world.entity.boss.enderdragon.phases.DragonHoverPhase; import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java index 39706decc33..f892b641d95 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java @@ -27,7 +27,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.FireworkRocketEntity; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.projectile.explosive.FireworkRocket; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java index cf352b54929..04682400380 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java @@ -26,7 +26,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.ThrownEnderpearl; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.cause.entity.MovementTypes; @@ -44,21 +44,20 @@ public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin { @ModifyArg(method = "onHit", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + target = "Lnet/minecraft/server/level/ServerPlayer;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) private float impl$onAttackEntityFromWithDamage(final float damage) { return (float) this.impl$damageAmount; } @Redirect(method = "onHit", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;changeDimension(Lnet/minecraft/world/level/portal/DimensionTransition;)Lnet/minecraft/world/entity/Entity;") + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleport(Lnet/minecraft/world/level/portal/TeleportTransition;)Lnet/minecraft/world/entity/Entity;") ) - private Entity impl$callMoveEntityEventForThrower(final Entity instance, final DimensionTransition $$0) { - final Entity entity = this.shadow$getOwner(); + private Entity impl$callMoveEntityEventForThrower(final Entity instance, final TeleportTransition $$0) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { - frame.pushCause(entity); + frame.pushCause(instance); frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.ENDER_PEARL); - return instance.changeDimension($$0); + return instance.teleport($$0); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/inventory/StonecutterMenuMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/inventory/StonecutterMenuMixin.java index be21fd71df1..6464a420aee 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/inventory/StonecutterMenuMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/inventory/StonecutterMenuMixin.java @@ -26,10 +26,10 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerListener; -import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.inventory.Slot; import net.minecraft.world.inventory.StonecutterMenu; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.StonecutterRecipe; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -37,28 +37,33 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.accessor.world.inventory.AbstractContainerMenuAccessor; import org.spongepowered.common.item.recipe.stonecutting.SpongeStonecuttingRecipe; -import java.util.List; +import java.util.Optional; @Mixin(StonecutterMenu.class) public abstract class StonecutterMenuMixin { // @formatter:off @Shadow @Final Slot resultSlot; - @Shadow private List recipes; - @Shadow @Final private DataSlot selectedRecipeIndex; // @formatter:on - @Inject(method = "setupResultSlot", at = @At(value = "RETURN")) - private void impl$updateRecipeResultSlot(final CallbackInfo ci) { - if (!this.recipes.isEmpty() && this.recipes.get(this.selectedRecipeIndex.get()) instanceof SpongeStonecuttingRecipe) { - // For SpongeStonecuttingRecipe resend the output slot in case the actual crafting result differs from the exemplary result - final ItemStack stack = this.resultSlot.getItem(); - for (final ContainerListener listener : ((AbstractContainerMenuAccessor) this).accessor$containerListeners()) { - listener.slotChanged((AbstractContainerMenu) (Object) this, 1, stack); - } - } + @Inject(method = "setupResultSlot", + at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresentOrElse(Ljava/util/function/Consumer;Ljava/lang/Runnable;)V", shift = At.Shift.AFTER), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void impl$updateRecipeResultSlot( + final int $$0, final CallbackInfo ci, + final Optional> recipe) { + recipe.filter(e -> e.value() instanceof SpongeStonecuttingRecipe) + .ifPresent(e -> { + // For SpongeStonecuttingRecipe resend the output slot in case the actual crafting result differs from the exemplary result + final ItemStack stack = this.resultSlot.getItem(); + for (final ContainerListener listener : ((AbstractContainerMenuAccessor) this).accessor$containerListeners()) { + listener.slotChanged((AbstractContainerMenu) (Object) this, 1, stack); + } + }); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java index f154a0bc0cb..b0bf7289762 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeMixin.java @@ -24,30 +24,16 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.Ingredient; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.item.crafting.CookingRecipeBridge; @Mixin(AbstractCookingRecipe.class) -public abstract class AbstractCookingRecipeMixin implements CookingRecipeBridge { - - // @formatter=off - @Shadow @Final protected ItemStack result; - @Shadow @Final protected Ingredient ingredient; - - // @formatter=on - - @Override - public ItemStack bridge$result() { - return this.result; - } +public abstract class AbstractCookingRecipeMixin extends SingleItemRecipeMixin implements CookingRecipeBridge { @Override public Ingredient bridge$ingredient() { - return this.ingredient; + return this.shadow$input(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java similarity index 88% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java index c3e0ddf42c2..99fbd9f1af7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCookingSerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java @@ -38,7 +38,6 @@ import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.SimpleCookingSerializer; import net.minecraft.world.item.crafting.SmeltingRecipe; import net.minecraft.world.item.crafting.SmokingRecipe; import org.spongepowered.asm.mixin.Mixin; @@ -56,8 +55,8 @@ import java.util.function.Function; -@Mixin(SimpleCookingSerializer.class) -public abstract class SimpleCookingSerializerMixin { +@Mixin(AbstractCookingRecipe.Serializer.class) +public abstract class AbstractCookingRecipeSerializerMixin { @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) @@ -69,7 +68,7 @@ public abstract class SimpleCookingSerializerMixin to.map(si -> (T) si, i -> i), fr -> { if (fr instanceof SpongeBlastingRecipe si) { @@ -80,7 +79,7 @@ public abstract class SimpleCookingSerializerMixin to.map(si -> (T) si, i -> i), fr -> { if (fr instanceof SpongeCampfireCookingRecipe si) { @@ -92,7 +91,7 @@ public abstract class SimpleCookingSerializerMixin to.map(si -> (T) si, i -> i), fr -> { if (fr instanceof SpongeSmeltingRecipe si) { @@ -105,7 +104,7 @@ public abstract class SimpleCookingSerializerMixin to.map(si -> (T) si, i -> i), fr -> { if (fr instanceof SpongeSmokingRecipe si) { @@ -124,12 +123,12 @@ public abstract class SimpleCookingSerializerMixin $$2.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Codec.STRING.optionalFieldOf("group", "").forGetter(AbstractCookingRecipe::getGroup), + Codec.STRING.optionalFieldOf("group", "").forGetter(AbstractCookingRecipe::group), CookingBookCategory.CODEC.fieldOf("category").orElse(CookingBookCategory.MISC).forGetter(AbstractCookingRecipe::category), Ingredient.CODEC.fieldOf(Constants.Recipe.COOKING_INGREDIENT).forGetter($$0x -> ((CookingRecipeBridge) $$0x).bridge$ingredient()), BuiltInRegistries.ITEM.byNameCodec().xmap(ItemStack::new, ItemStack::getItem).fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), - Codec.FLOAT.fieldOf(Constants.Recipe.COOKING_EXP).orElse(0.0F).forGetter(AbstractCookingRecipe::getExperience), - Codec.INT.fieldOf(Constants.Recipe.COOKING_TIME).orElse(defaultCookingTime).forGetter(AbstractCookingRecipe::getCookingTime), + Codec.FLOAT.fieldOf(Constants.Recipe.COOKING_EXP).orElse(0.0F).forGetter(AbstractCookingRecipe::experience), + Codec.INT.fieldOf(Constants.Recipe.COOKING_TIME).orElse(defaultCookingTime).forGetter(AbstractCookingRecipe::cookingTime), ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), Codec.STRING.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCraftingRecipeSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCraftingRecipeSerializerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java index 9defd9d4e6b..c29e4b941b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SimpleCraftingRecipeSerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java @@ -30,7 +30,7 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; +import net.minecraft.world.item.crafting.CustomRecipe; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -38,8 +38,8 @@ import java.util.function.Function; -@Mixin(SimpleCraftingRecipeSerializer.class) -public abstract class SimpleCraftingRecipeSerializerMixin { +@Mixin(CustomRecipe.Serializer.class) +public abstract class CustomRecipeSerializerMixin { @Redirect(method = "", at = @At(value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java index 15ca24ce109..6a88a92d0e8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java @@ -24,10 +24,12 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; +import com.google.gson.JsonObject; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.HolderLookup; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; import org.spongepowered.asm.mixin.Mixin; @@ -37,20 +39,25 @@ @Mixin(RecipeManager.class) public abstract class RecipeManagerMixin { -@Redirect(method = "fromJson", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;parse(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;")) - private static DataResult> impl$onParseRecipe(final Codec> instance, final DynamicOps dynamicOps, final T element, final ResourceLocation $$0) -{ - final DataResult> parsed; - try { - parsed = instance.parse(dynamicOps, element); - } catch (Exception e) { - SpongeCommon.logger().error("Could not parse recipe {}", $$0, e); - throw new RuntimeException(e); + @Redirect(method = "fromJson", at = @At( + value = "INVOKE", + target = "Lcom/mojang/serialization/Codec;parse(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;" + )) + private static DataResult> impl$onParseRecipe( + final Codec> instance, final DynamicOps dynamicOps, final T element, + ResourceKey> $$0, JsonObject $$1, HolderLookup.Provider $$2 + ) { + final DataResult> parsed; + try { + parsed = instance.parse(dynamicOps, element); + } catch (Exception e) { + SpongeCommon.logger().error("Could not parse recipe {}", $$0, e); + throw new RuntimeException(e); + } + if (parsed.error().isPresent()) { + SpongeCommon.logger().error("Could not parse recipe {} {}", $$0, parsed.error().get().message()); + } + return parsed; } - if (parsed.error().isPresent()) { - SpongeCommon.logger().error("Could not parse recipe {} {}", $$0, parsed.error().get().message()); - } - return parsed; -} } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java index e53ce088d5a..b0925a42a67 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.item.crafting; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleItemRecipe; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -38,8 +39,8 @@ public abstract class SingleItemRecipeMixin implements RecipeResultBridge { // @formatter=off - @Shadow @Final protected ItemStack result; - + @Shadow @Final private ItemStack result; + @Shadow public abstract Ingredient shadow$input(); // @formatter=on diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java index 8837646fa7d..fec121c03e4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java @@ -28,18 +28,15 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.CampfireBlock; -import net.minecraft.world.level.block.entity.CampfireBlockEntity; import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.level.block.entity.CampfireBlockEntityBridge; import org.spongepowered.common.mixin.core.block.BlockMixin; @Mixin(CampfireBlock.class) @@ -56,17 +53,9 @@ public abstract class CampfireBlockMixin extends BlockMixin { final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) + .type(DamageTypes.CAMPFIRE) .block(location.createSnapshot()).build(); return (DamageSource) blockSource; } - @Redirect(method = "useItemOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/CampfireBlockEntity;placeFood(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;I)Z")) - public boolean impl$placeFood(final CampfireBlockEntity instance, final LivingEntity player, final ItemStack item, final int cookingTime) { - if (instance.placeFood(player, item, cookingTime)) { - ((CampfireBlockEntityBridge) instance).bridge$placeRecipe(instance.getCookableRecipe(item).get()); - return true; - } - return false; - } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java index 5a7c0c28ba3..c331e66722d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java @@ -30,7 +30,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EndPortalBlock; import net.minecraft.world.level.levelgen.feature.EndPlatformFeature; -import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.level.portal.TeleportTransition; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.portal.Portal; @@ -66,7 +66,7 @@ public abstract class EndPortalBlockMixin implements PortalBlockBridge { } if (entity instanceof ServerPlayer player) { - var transition = player.findRespawnPositionAndUseSpawnBlock(false, DimensionTransition.DO_NOTHING); + var transition = player.findRespawnPositionAndUseSpawnBlock(false, TeleportTransition.DO_NOTHING); return ServerLocation.of((ServerWorld) transition.newLevel(), VecHelper.toVector3d(transition.position())); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 38afcfe57dc..0312655e337 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -26,12 +26,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.objectweb.asm.Opcodes; @@ -74,7 +74,9 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock // Shrink Fuel @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) - private static void impl$throwFuelEventIfOrShrink(final ItemStack itemStack, final int quantity, final Level var0, final BlockPos var1, final BlockState var2, final AbstractFurnaceBlockEntity entity) { + private static void impl$throwFuelEventIfOrShrink( + final ItemStack itemStack, final int quantity, final ServerLevel var0, final BlockPos var1, + final BlockState var2, final AbstractFurnaceBlockEntity entity) { final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(itemStack); @@ -103,8 +105,11 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock @Override public Optional> bridge$getCurrentRecipe() { + if (!(this.level instanceof ServerLevel se)) { + return Optional.empty(); + } var recipeInpuit = new SingleRecipeInput(this.items.get(0)); - return this.quickCheck.getRecipeFor(recipeInpuit, this.level); + return this.quickCheck.getRecipeFor(recipeInpuit, se); } // Interrupt-Active - e.g. a player removing the currently smelting item @@ -112,7 +117,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock method = "setItem", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" ) ) private void impl$interruptSmelt(final CallbackInfo ci) { @@ -130,7 +135,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock slice = @Slice( from = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;I)Z" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z" ), to = @At( value = "INVOKE", @@ -138,7 +143,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock ) ) ) - private static void impl$onResetCookTimePassive(final Level level, final BlockPos pos, final BlockState state, + private static void impl$onResetCookTimePassive(final ServerLevel level, final BlockPos pos, final BlockState state, @Coerce final AbstractFurnaceBlockEntityMixin entity, final CallbackInfo ci) { entity.impl$callInteruptSmeltEvent(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java index 713f2f7eb9c..6bfb95f10fd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java @@ -24,17 +24,12 @@ */ package org.spongepowered.common.mixin.core.world.level.block.entity; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.effect.MobEffect; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import javax.swing.text.html.Option; import java.util.Optional; import java.util.function.Function; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java index 0447f14ca14..bc7261ca253 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java @@ -26,12 +26,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.CampfireBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.api.ResourceKey; @@ -49,10 +51,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.MixinTargetHelper; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.bridge.world.level.block.entity.CampfireBlockEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; @@ -62,7 +64,7 @@ import java.util.Optional; @Mixin(CampfireBlockEntity.class) -public abstract class CampfireBlockEntityMixin implements CampfireBlockEntityBridge { +public abstract class CampfireBlockEntityMixin { // @Formatter:off @Shadow @Final private NonNullList items; @@ -77,8 +79,9 @@ public abstract class CampfireBlockEntityMixin implements CampfireBlockEntityBri // Tick up @Inject(method = "cookTick", locals = LocalCapture.CAPTURE_FAILEXCEPTION, at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/entity/CampfireBlockEntity;cookingProgress:[I", ordinal = 1)) - private static void impl$canCook(final Level level, final BlockPos pos, final BlockState state, final CampfireBlockEntity self, - final CallbackInfo ci, final boolean hasChanged, final int i, final ItemStack itemStack) { + private static void impl$canCook(final ServerLevel level, final BlockPos pos, final BlockState state, final CampfireBlockEntity self, + final RecipeManager.CachedCheck check, + final CallbackInfo ci, final boolean hasChanged, final int i, final ItemStack itemStack) { ((CampfireBlockEntityMixin) (Object) self).impl$currentIndex = i; final boolean isEmpty = itemStack.isEmpty(); if (!isEmpty) { @@ -98,8 +101,9 @@ public abstract class CampfireBlockEntityMixin implements CampfireBlockEntityBri @Inject(method = "cookTick", locals = LocalCapture.CAPTURE_FAILEXCEPTION, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/Containers;dropItemStack(Lnet/minecraft/world/level/Level;DDDLnet/minecraft/world/item/ItemStack;)V")) - private static void impl$assembleCampfireResult(final Level level, final BlockPos pos, final BlockState state, - final CampfireBlockEntity self, final CallbackInfo ci, final boolean hasChanged, final int i, + private static void impl$assembleCampfireResult(final ServerLevel level, final BlockPos pos, final BlockState state, + final CampfireBlockEntity self, final RecipeManager.CachedCheck check, + final CallbackInfo ci, final boolean hasChanged, final int i, final ItemStack itemStack, final SingleRecipeInput recipeInput, final ItemStack itemStack1) { final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); final CampfireBlockEntityMixin mixinSelf = MixinTargetHelper.cast(self); @@ -113,27 +117,32 @@ public abstract class CampfireBlockEntityMixin implements CampfireBlockEntityBri mixinSelf.impl$pendingSlotTransaction = transaction; } - @Inject(method = "cookTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;sendBlockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;I)V")) - private static void impl$setCookingEventFinishResult(final Level $$0, final BlockPos $$1, final BlockState $$2, final CampfireBlockEntity $$3, final CallbackInfo ci) { - final CampfireBlockEntityMixin mixinSelf = MixinTargetHelper.cast($$3); + @Inject(method = "cookTick", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;sendBlockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;I)V" + ), locals = LocalCapture.CAPTURE_FAILEXCEPTION) + private static void impl$setCookingEventFinishResult( + final ServerLevel level, final BlockPos pos, final BlockState state, + final CampfireBlockEntity self, final RecipeManager.CachedCheck $$4, + final CallbackInfo ci, final boolean $$5, final int $$6, final ItemStack $$7, final SingleRecipeInput $$8, + final ItemStack $$9 + ) { + final CampfireBlockEntityMixin mixinSelf = MixinTargetHelper.cast(self); mixinSelf.impl$pendingSlotTransaction.custom().ifPresent(item -> mixinSelf.items.set(((SlotAdapter) mixinSelf.impl$pendingSlotTransaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); mixinSelf.impl$pendingSlotTransaction = null; } - @Override - public void bridge$placeRecipe(final RecipeHolder recipe) { - for(int i = 0; i < this.items.size(); ++i) { - final ItemStack itemstack = this.items.get(i); - if (itemstack.isEmpty()) { - this.impl$cookingRecipe[i] = recipe; - return; - } - } + @Inject(method = "placeFood", at = @At(value = "INVOKE", target = "Ljava/util/Optional;get()Ljava/lang/Object;"), + locals = LocalCapture.CAPTURE_FAILHARD) + private void impl$captureRecipeUsage( + final ServerLevel $$0, final LivingEntity $$1, final ItemStack $$2, final CallbackInfoReturnable cir, + final int i, final ItemStack stack, final Optional> recipeOptional) { + // We know that the crafting recipe will exist because mojang checked for us + this.impl$cookingRecipe[i] = recipeOptional.get(); } @Redirect(method = "cookTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isItemEnabled(Lnet/minecraft/world/flag/FeatureFlagSet;)Z")) - private static boolean impl$checkInfiniteCookingTime(final ItemStack instance, final FeatureFlagSet featureFlagSet, final Level level, final BlockPos blockPos, + private static boolean impl$checkInfiniteCookingTime(final ItemStack instance, final FeatureFlagSet featureFlagSet, final ServerLevel level, final BlockPos blockPos, final BlockState state, final CampfireBlockEntity self) { final int cookingTime = ((CampfireBlockEntityMixin) (Object) self).cookingTime[((CampfireBlockEntityMixin) (Object) self).impl$currentIndex]; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java index a0ca6cfd4ed..09a74c9bb08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java @@ -70,8 +70,11 @@ public GridInventory asGrid() { */ @Override public boolean craftItem() { + if (!(this.level instanceof ServerLevel sl)) { + return false; + } final var input = ((CraftingContainer) this).asCraftInput(); - final var potentialResults = CrafterBlock.getPotentialResults(this.level, input); + final var potentialResults = CrafterBlock.getPotentialResults(sl, input); if (potentialResults.isEmpty()) { return false; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java index bf57192d81a..3b173f8ebbe 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.event.world.inventory; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -31,7 +32,6 @@ import net.minecraft.world.inventory.CraftingMenu; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.crafting.CraftingInventory; @@ -50,8 +50,10 @@ public abstract class CraftingMenuMixin_Inventory { // Crafting Preview @Redirect(method = "slotChangedCraftingGrid", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V")) - private static void beforeSlotChangedCraftingGrid(final ResultContainer resultContainer, final int slotId, final ItemStack itemStack, - final AbstractContainerMenu param0, final Level param1, final Player player, final CraftingContainer craftingContainer, final ResultContainer resultcontainer) { + private static void beforeSlotChangedCraftingGrid( + final ResultContainer resultContainer, final int slotId, final ItemStack itemStack, + final AbstractContainerMenu param0, final ServerLevel param1, final Player player, + final CraftingContainer craftingContainer, final ResultContainer resultcontainer) { resultContainer.setItem(slotId, itemStack); final Inventory inv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java index 65ac8c43f99..7a43a4977ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java @@ -26,6 +26,7 @@ import net.minecraft.core.NonNullList; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; @@ -33,11 +34,11 @@ import net.minecraft.world.inventory.ResultSlot; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeInput; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.item.inventory.Inventory; @@ -64,6 +65,10 @@ public abstract class ResultSlotMixin_Inventory extends Slot { @Shadow @Final private net.minecraft.world.inventory.CraftingContainer craftSlots; + @Shadow private NonNullList shadow$getRemainingItems(CraftingInput input, Level level) { + throw new IllegalStateException("Untransformed shadow method!"); + } + public ResultSlotMixin_Inventory(final Container inventoryIn, final int index, final int xPosition, final int yPosition) { super(inventoryIn, index, xPosition, yPosition); } @@ -87,8 +92,11 @@ public void set(@Nullable final ItemStack stack) { @Inject(method = "onTake", at = @At("HEAD")) private void impl$beforeTake(final Player thePlayer, final ItemStack stack, final CallbackInfo ci) { + if (!(thePlayer.level() instanceof ServerLevel sl)) { + return; + } if (this.impl$onTakeRecipe == null || !this.impl$onTakeRecipe.value().matches(this.craftSlots.asCraftInput(), thePlayer.level())) { - final RecipeManager manager = thePlayer.level().getRecipeManager(); + final RecipeManager manager = sl.recipeAccess(); this.impl$onTakeRecipe = manager.getRecipeFor(RecipeType.CRAFTING, this.craftSlots.asCraftInput(), thePlayer.level()).orElse(null); } @@ -105,12 +113,12 @@ public void set(@Nullable final ItemStack stack) { stack.shrink(1); } - @Redirect(method = "onTake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/RecipeManager;getRemainingItemsFor(Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/world/item/crafting/RecipeInput;Lnet/minecraft/world/level/Level;)Lnet/minecraft/core/NonNullList;")) - private > NonNullList impl$onGetRemainingItems(final RecipeManager recipeManager, final RecipeType recipeTypeIn, final I recipeInput, final net.minecraft.world.level.Level worldIn) { + @Redirect(method = "onTake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultSlot;getRemainingItems(Lnet/minecraft/world/item/crafting/CraftingInput;Lnet/minecraft/world/level/Level;)Lnet/minecraft/core/NonNullList;")) + private NonNullList impl$onGetRemainingItems(ResultSlot instance, CraftingInput $$0, Level $$1) { if (this.impl$onTakeRecipe == null) { - return NonNullList.withSize(recipeInput.size(), ItemStack.EMPTY); + return NonNullList.withSize($$0.size(), ItemStack.EMPTY); } - return worldIn.getRecipeManager().getRemainingItemsFor(recipeTypeIn, recipeInput, worldIn); + return this.shadow$getRemainingItems($$0, $$1); } @Inject(method = "onTake", cancellable = true, at = @At("RETURN")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java index 4d405bf7779..155b32b5a54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.impl.world.inventory; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -41,14 +42,18 @@ @Mixin(AbstractFurnaceMenu.class) public abstract class AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory { - @Inject(method = "(Lnet/minecraft/world/inventory/MenuType;Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/world/inventory/RecipeBookType;ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", at = @At("RETURN")) - private void inventory$attachContainerMenu(final MenuType $$0, final RecipeType $$1, final RecipeBookType $$2, final int $$3, final Inventory $$4, - final Container $$5, final ContainerData $$6, final CallbackInfo ci) { - if ($$4 instanceof final TrackedMenuBridge trackedMenu) { + @Inject( + method = "(Lnet/minecraft/world/inventory/MenuType;Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/inventory/RecipeBookType;ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", + at = @At("RETURN")) + private void inventory$attachContainerMenu( + final MenuType $$0, final RecipeType $$1, final ResourceKey $$2, + final RecipeBookType $$3, final int $$4, final Inventory inventory, final Container container, final ContainerData $$7, + final CallbackInfo ci) { + if (inventory instanceof final TrackedMenuBridge trackedMenu) { trackedMenu.bridge$trackContainerMenu((AbstractContainerMenu) (Object) this); } - if ($$5 instanceof final TrackedMenuBridge trackedMenu) { + if (container instanceof final TrackedMenuBridge trackedMenu) { trackedMenu.bridge$trackContainerMenu((AbstractContainerMenu) (Object) this); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/ItemCombinerMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/ItemCombinerMenuMixin_TrackedMenuBridge_Inventory.java index d5ac16172a7..d24d110bd99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/ItemCombinerMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/ItemCombinerMenuMixin_TrackedMenuBridge_Inventory.java @@ -29,9 +29,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.ItemCombinerMenu; +import net.minecraft.world.inventory.ItemCombinerMenuSlotDefinition; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.ResultContainer; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -49,7 +49,8 @@ public abstract class ItemCombinerMenuMixin_TrackedMenuBridge_Inventory { // @formatter:on @Inject(method = "", at = @At("RETURN")) - private void inventory$attachContainerMenu(final @Nullable MenuType $$0, final int $$1, final Inventory $$2, final ContainerLevelAccess $$3, final CallbackInfo ci) { + private void inventory$attachContainerMenu( + MenuType $$0, int $$1, Inventory $$2, ContainerLevelAccess $$3, ItemCombinerMenuSlotDefinition $$4, CallbackInfo ci) { if ($$2 instanceof final TrackedMenuBridge trackedMenu) { trackedMenu.bridge$trackContainerMenu((AbstractContainerMenu) (Object) this); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java b/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java index 33baee1c932..acb2835c33a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java +++ b/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java @@ -42,7 +42,7 @@ public abstract class ServerGamePacketListenerImplMixin_MovementCheck { @ModifyConstant(method = "handleMovePlayer", constant = @Constant(floatValue = 100.0F, ordinal = 0), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isFallFlying()Z", ordinal = 0), - to = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;isSingleplayerOwner()Z", ordinal = 0) + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getBoundingBox()Lnet/minecraft/world/phys/AABB;", ordinal = 0) ) ) private float movementCheck$onMovedTooQuickly(final float value) { @@ -55,7 +55,7 @@ public abstract class ServerGamePacketListenerImplMixin_MovementCheck { @ModifyConstant(method = "handleMovePlayer", constant = @Constant(doubleValue = 0.0625D, ordinal = 0), slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isChangingDimension()Z", ordinal = 1), + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isChangingDimension()Z", ordinal = 0), to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isSleeping()Z", ordinal = 1) ) ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java index 2f25d1db67d..8a4441d0352 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/LevelMixin_Tracker.java @@ -27,7 +27,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 73d62d1ffbd..206b7aa0d19 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -208,8 +208,8 @@ "world.item.crafting.ShapedRecipeMixin", "world.item.crafting.ShapelessRecipe_SerializerMixin", "world.item.crafting.ShapelessRecipeMixin", - "world.item.crafting.SimpleCookingSerializerMixin", - "world.item.crafting.SimpleCraftingRecipeSerializerMixin", + "world.item.crafting.AbstractCookingRecipeSerializerMixin", + "world.item.crafting.CustomRecipeSerializerMixin", "world.item.crafting.SingleItemRecipeMixin", "world.item.crafting.SmithingTransformRecipe_SerializerMixin", "world.item.crafting.SmithingTransformRecipeMixin", diff --git a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java b/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java index 58380316c81..86fdaf869e4 100644 --- a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java +++ b/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java @@ -28,6 +28,7 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -38,7 +39,7 @@ public interface AbstractFurnaceBlockEntityAccessor_Vanilla { @Invoker("canBurn") - static boolean invoker$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder var0, final NonNullList var1, final int var2) { + static boolean invoker$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { throw new UntransformedInvokerError(); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java index c4fcf2bf993..8ae0fb39d1e 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java @@ -26,6 +26,7 @@ import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.game.ServerGamePacketListener; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.inventory.RecipeBookMenu; @@ -53,22 +54,25 @@ public abstract class ServerGamePacketListenerImplMixin_Vanilla extends ServerCommonPacketListenerImplMixin_Vanilla implements ServerGamePacketListener { @SuppressWarnings({"unchecked", "rawtypes"}) - @Redirect(method = "lambda$handlePlaceRecipe$10", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) - private RecipeBookMenu.PostPlaceAction vanilla$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean creative, final RecipeHolder recipe, final net.minecraft.world.entity.player.Inventory playerInventory) { - final var player = playerInventory.player; + @Redirect(method = "handlePlaceRecipe", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) + private RecipeBookMenu.PostPlaceAction vanilla$onPlaceRecipe( + final RecipeBookMenu instance, final boolean shift, final boolean creative, + final RecipeHolder recipe, final ServerLevel serverLevel, + final net.minecraft.world.entity.player.Inventory inventory) { + final var player = inventory.player; final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); if (!(craftInv instanceof CraftingInventory)) { - final var postPlaceAction = recipeBookMenu.handlePlacement(shift, creative, recipe, playerInventory); + final var postPlaceAction = instance.handlePlacement(shift, creative, recipe, serverLevel, inventory); SpongeCommon.logger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire."); return postPlaceAction; } try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, (RecipeHolder) recipe, (ServerPlayer) player, (CraftingInventory) craftInv)) { - final var postPlaceAction = recipeBookMenu.handlePlacement(shift, creative, recipe, playerInventory); + final var postPlaceAction = instance.handlePlacement(shift, creative, recipe, serverLevel, inventory); player.containerMenu.broadcastChanges(); return postPlaceAction; } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 17c1a96221a..9e397f1b87a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -27,10 +27,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.Level; +import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.checkerframework.checker.nullness.qual.Nullable; @@ -77,10 +79,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // Tick up and Start @Redirect(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;I)Z", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", ordinal = 1)) - private static boolean vanillaImpl$checkIfCanSmelt(final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final Level level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entity) { - if (!AbstractFurnaceBlockEntityAccessor_Vanilla.invoker$canBurn(registryAccess, recipe, slots, maxStackSize)) { + private static boolean vanillaImpl$checkIfCanSmelt( + final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final SingleRecipeInput input, + final NonNullList slots, final int maxStackSize, final ServerLevel level, final BlockPos entityPos, + final BlockState state, final AbstractFurnaceBlockEntity entity) { + if (!AbstractFurnaceBlockEntityAccessor_Vanilla.invoker$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { return false; } @@ -103,8 +108,10 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) - private static int vanillaImpl$resetCookTimeIfCancelled(final int newCookTime, final int zero, final int totalCookTime, - final Level level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entity) { + private static int vanillaImpl$resetCookTimeIfCancelled( + final int newCookTime, final int zero, final int totalCookTime, + final ServerLevel level, final BlockPos entityPos, final BlockState state, + final AbstractFurnaceBlockEntity entity) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(((AbstractFurnaceBlockEntityMixin_Vanilla) (Object) entity).items.get(1)); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); @@ -125,7 +132,10 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai slice = @Slice( from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) )) - private static void vanilla$captureBucketFill(final RegistryAccess $$0, final RecipeHolder $$1, final NonNullList $$2, final int $$3, final CallbackInfoReturnable cir) { + private static void vanilla$captureBucketFill( + final RegistryAccess $$0, final RecipeHolder $$1, + final SingleRecipeInput input, final NonNullList $$2, final int $$3, + final CallbackInfoReturnable cir) { final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); @@ -134,9 +144,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai } @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", shift = At.Shift.AFTER)) - private static void vanillaImpl$afterSmeltItem(final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int var2, final CallbackInfoReturnable cir) { + // final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int var2, final CallbackInfoReturnable cir + private static void vanillaImpl$afterSmeltItem( + final RegistryAccess registryAccess, final RecipeHolder recipe, + final SingleRecipeInput input, final NonNullList slots, final int $$4, + final CallbackInfoReturnable cir) { final ItemStack itemIn = slots.get(0); - final ItemStack recipeResult = recipe.value().getResultItem(registryAccess); + final ItemStack recipeResult = recipe.value().assemble(input, registryAccess); final ItemStack itemOut = slots.get(2); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); From 2d5bfca62d593439a3891b7e7cc74777be3f9dff Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 9 Oct 2024 18:47:21 -0700 Subject: [PATCH 092/586] chore(ci): enable publishing vanilla jars for update branches Signed-off-by: Gabriel Harris-Rouquette --- .github/workflows/common-run-build.yaml | 38 ++++++++++++++++--------- .github/workflows/deploy.yaml | 25 ++++++++++++++-- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 027975557b0..c3dbfe08a8d 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -11,15 +11,30 @@ jobs: # Only run on PRs if the source branch is on someone else's repo if: "${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}" runs-on: ubuntu-22.04 + strategy: + matrix: + project: + - vanilla + - forge + - neoforge + include: + - project: vanilla + gradleProject: SpongeVanilla + - project: forge + gradleProject: SpongeForge + - project: neoforge + gradleProject: SpongeNeo steps: - name: setup id: setup uses: SpongePowered/.github/.github/actions/setup-java-env@master + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" with: runtime_version: 21 publishing_branch_regex: 'api-\d+' - name: setup / cache minecraft dependencies uses: "actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9" # v4.0.2 + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" with: path: | ${{ github.workspace}}/buildSrc/.gradle/ @@ -28,15 +43,18 @@ jobs: restore-keys: | ${{ runner.os }}-minecraft-${{ env.CACHE_REV }}- - name: setup / environment + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" run: | echo "GIT_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV echo "GIT_BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - name: build with Gradle - run: ./gradlew -Pprojects=vanilla,forge,neoforge,testplugins build --stacktrace + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" + run: ./gradlew -Pprojects=${{ matrix.project }},testplugins build --stacktrace env: CI_SYSTEM: Github Actions - name: Archive artifacts for build + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 with: name: Sponge Jars @@ -46,22 +64,14 @@ jobs: ${{ github.workspace }}/vanilla/build/libs/*.jar ${{ github.workspace }}/forge/build/libs/*.jar ${{ github.workspace }}/neoforge/build/libs/*.jar - - name: SpongeVanilla Production Jar + - name: ${{ matrix.gradleProject }} Production Jar + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 with: - name: SpongeVanilla Production Jar - path: "${{ github.workspace }}/vanilla/build/libs/*-universal.jar" - - name: SpongeForge Production Jar - uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 - with: - name: SpongeForge Production Jar - path: "${{ github.workspace }}/forge/build/libs/*-universal.jar" - - name: SpongeNeo Production Jar - uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 - with: - name: SpongeNeo Production Jar - path: "${{ github.workspace }}/neoforge/build/libs/*-universal.jar" + name: ${{ matrix.gradleProject }} Production Jar + path: "${{ github.workspace }}/${{ matrix.project }}/build/libs/*-universal.jar" - name: SpongeVanilla libraries + if: "matrix.project == 'vanilla'" uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 with: name: SpongeVanilla installer libraries diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 1ddb706d534..82311bfe60c 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -5,7 +5,9 @@ name: Build and Deploy on: push: - branches: [ 'api-*' ] + branches: + - 'api-*' + - 'update/*' tags-ignore: [ '**' ] env: @@ -22,13 +24,30 @@ jobs: publish: needs: integrationTest runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + project: + - vanilla + - forge + - neoforge + include: + - project: vanilla + gradleProject: SpongeVanilla + - project: forge + gradleProject: SpongeForge + - project: neoforge + gradleProject: SpongeNeo steps: - name: setup + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" id: setup uses: SpongePowered/.github/.github/actions/setup-java-env@master with: runtime_version: 21 + publishing_branch_regex: '' - name: setup / minecraft cache + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" uses: "actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9" # v4.0.2 with: path: | @@ -39,12 +58,14 @@ jobs: ${{ runner.os }}-minecraft-${{ env.CACHE_REV }}- # We don't need to run tests again, so we just publish - name: setup / workspace + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" run: | echo "GIT_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV echo "GIT_BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - name: Publish to Sponge Maven & GitHub Packages - run: ./gradlew -s -Pprojects=vanilla,forge,neoforge :publish :SpongeVanilla:publish :SpongeForge:publish :SpongeNeo:publish + if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" + run: ./gradlew -s -Pprojects=vanilla,${{ matrix.project }} :${{ matrix.gradleProject }}:publish env: CI_SYSTEM: Github Actions GITHUB_USERNAME: "${{ github.actor }}" From 411f9f55ce25e9048551640679f256addaa0e2ab Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 9 Oct 2024 19:06:28 -0700 Subject: [PATCH 093/586] fix: update for incorrect api removal Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../main/java/org/spongepowered/test/recipe/RecipeTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 2e777ef7211..2a43df043f1 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 2e777ef7211a991de6eb73e2a3fb7e50cedea475 +Subproject commit 2a43df043f11843eac7cc2fa45677bc62afa0f80 diff --git a/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java b/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java index 2fb84f4a299..491fa5c59e3 100644 --- a/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java @@ -42,6 +42,7 @@ import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.query.QueryTypes; import org.spongepowered.api.item.recipe.RecipeRegistration; @@ -254,7 +255,7 @@ private void onRecipeRegistry(final RegisterDataPackValueEvent hardnessPredicate = stack -> stack.type().block().map(b -> b.defaultState().get(Keys.DESTROY_SPEED).orElse(0d) > 20).orElse(false); // e.g. obsidian + final Predicate hardnessPredicate = stack -> stack.type().block().map(b -> b.defaultState().get(Keys.DESTROY_SPEED).orElse(0d) > 20).orElse(false); // e.g. obsidian final Ingredient hardBlock = Ingredient.of(ResourceKey.of(this.plugin, "hardblock"), hardnessPredicate, ItemStack.of(ItemTypes.OBSIDIAN)); final RecipeRegistration hardblockToWool = ShapelessCraftingRecipe.builder().addIngredients(hardBlock).result(ItemStack.of(ItemTypes.WHITE_WOOL)) From 805eb43318767fa1d3924cdc90e23fc9cb15a71c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 9 Oct 2024 19:58:48 -0700 Subject: [PATCH 094/586] fix: potentially fix recipe api implementation Signed-off-by: Gabriel Harris-Rouquette --- .../item/recipe/crafting/RecipeUtil.java | 54 +++++++++++++++++++ .../world/item/crafting/RecipeMixin_API.java | 33 +++++++++--- 2 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/item/recipe/crafting/RecipeUtil.java diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/RecipeUtil.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/RecipeUtil.java new file mode 100644 index 00000000000..180026731e4 --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/RecipeUtil.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item.recipe.crafting; + +import net.minecraft.util.context.ContextMap; +import net.minecraft.world.item.crafting.display.DisplayContentsFactory; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; +import org.spongepowered.api.Sponge; +import org.spongepowered.common.SpongeCommon; + +import java.util.List; + +public final class RecipeUtil { + + public static ContextMap serverBasedContextMap() { + if (!Sponge.isServerAvailable()) { + return new ContextMap.Builder().create(SlotDisplayContext.CONTEXT); + } + final var server = SpongeCommon.server(); + return new ContextMap.Builder() + .withParameter(SlotDisplayContext.FUEL_VALUES, server.fuelValues()) + .withParameter(SlotDisplayContext.REGISTRIES, server.registryAccess()) + .create(SlotDisplayContext.CONTEXT); + } + + public class RemainderResolver implements DisplayContentsFactory.ForRemainders { + @Override + public T addRemainder(T var1, List var2) { + return null; + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java index a0a73960da9..8b19f11b424 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; -import static org.spongepowered.common.inventory.util.InventoryUtil.toCraftingInputOrThrow; - import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeInput; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.recipe.Recipe; @@ -37,9 +37,12 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.inventory.util.InventoryUtil; +import org.spongepowered.common.item.recipe.crafting.RecipeUtil; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.List; +import java.util.function.Predicate; @Mixin(net.minecraft.world.item.crafting.Recipe.class) public interface RecipeMixin_API extends Recipe { @@ -49,30 +52,44 @@ public interface RecipeMixin_API shadow$getType(); - // @formatter:on + @Shadow List shadow$display(); +// @formatter:on @NonNull @Override default ItemStackSnapshot exemplaryResult() { - // TODO - Do we want to start exposing slot displays in some way? - return ItemStackSnapshot.empty(); + return this.shadow$display().stream() + .map(RecipeDisplay::result) + .map(sd -> sd.resolveForFirstStack(RecipeUtil.serverBasedContextMap())) + .filter(Predicate.not(ItemStack::isEmpty)) + .map(ItemStackUtil::snapshotOf) + .findFirst() + .orElseGet(ItemStackSnapshot::empty); } @Override default boolean isValid(@NonNull final I2 inv, @NonNull final ServerWorld world) { - return this.shadow$matches((I) toCraftingInputOrThrow(inv), (net.minecraft.world.level.Level) world); + return this.shadow$matches((I) InventoryUtil.toCraftingInputOrThrow(inv), (net.minecraft.world.level.Level) world); } @NonNull @Override default ItemStackSnapshot result(@NonNull final I2 inv) { - return ItemStackUtil.snapshotOf(this.shadow$assemble((I) toCraftingInputOrThrow(inv), SpongeCommon.server().registryAccess())); + return ItemStackUtil.snapshotOf(this.shadow$assemble((I) InventoryUtil.toCraftingInputOrThrow(inv), SpongeCommon.server().registryAccess())); } @NonNull @Override default List remainingItems(@NonNull final I2 inv) { - return List.of(); + return this.shadow$display().stream() + .map(RecipeDisplay::result) + .filter(sd -> sd instanceof SlotDisplay.WithRemainder) + .map(SlotDisplay.WithRemainder.class::cast) + .map(SlotDisplay.WithRemainder::remainder) + .map(sd -> sd.resolveForFirstStack(RecipeUtil.serverBasedContextMap())) + .filter(Predicate.not(ItemStack::isEmpty)) + .map(ItemStackUtil::snapshotOf) + .toList(); } @Override From c588b3d7078ad9f0e258d9247f25af0acfeb0253 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 12 Oct 2024 10:39:32 -0700 Subject: [PATCH 095/586] chore: update to 1.21.2-pre3 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- .../common/effect/sound/SpongeSoundBuilder.java | 2 +- .../common/event/SpongeCommonEventFactory.java | 4 ++-- .../transaction/effect/ChunkChangeCompleteEffect.java | 2 +- .../event/tracking/phase/tick/BlockTickPhaseState.java | 8 ++++---- .../common/world/biome/SpongeBiomeTemplate.java | 2 +- .../world/biome/ambient/SpongeSoundConfigFactory.java | 6 +++--- .../common/world/volume/VolumeStreamUtils.java | 2 +- .../api/minecraft/block/BlockSoundGroupMixin_API.java | 10 +++++----- .../mixin/api/minecraft/sounds/MusicMixin_API.java | 2 +- .../api/minecraft/world/item/JukeboxSongMixin_API.java | 2 +- .../minecraft/world/level/LevelAccessorMixin_API.java | 2 +- .../level/biome/AmbientAdditionsSettingsMixin_API.java | 2 +- .../level/biome/AmbientMoodSettingsMixin_API.java | 2 +- .../state/properties/NoteBlockInstrumentMixin_API.java | 2 +- .../world/level/chunk/ChunkAccessMixin_API.java | 4 ++-- .../world/level/chunk/LevelChunkMixin_API.java | 2 +- .../mixin/core/server/level/ServerLevelMixin.java | 2 +- .../common/mixin/core/world/entity/EntityMixin.java | 2 +- .../world/entity/projectile/AbstractArrowMixin.java | 6 +++--- .../mixin/core/world/level/chunk/LevelChunkMixin.java | 10 ++++++---- 21 files changed, 39 insertions(+), 37 deletions(-) diff --git a/gradle.properties b/gradle.properties index 7d619435edd..a51d9f41d21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.2-pre1 +minecraftVersion=1.21.2-pre3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java b/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java index d6f6dbb9a6a..9b99d2bfb6c 100644 --- a/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java +++ b/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java @@ -33,6 +33,6 @@ public final class SpongeSoundBuilder extends AbstractResourceKeyedBuilder registry = ((Level) phaseContext.world).registryAccess().registryOrThrow(Registries.BLOCK); - final @Nullable Block fruitBlock = registry.get(((StemBlockAccessor) stemBlock).accessor$fruit()); - final @Nullable Block attachedStemBlock = registry.get(((StemBlockAccessor) stemBlock).accessor$attachedStem()); + final Registry registry = ((ServerLevel) phaseContext.world).registryAccess().lookupOrThrow(Registries.BLOCK); + final @Nullable Block fruitBlock = registry.getValue(((StemBlockAccessor) stemBlock).accessor$fruit()); + final @Nullable Block attachedStemBlock = registry.getValue(((StemBlockAccessor) stemBlock).accessor$attachedStem()); if (newBlock == fruitBlock || newBlock == attachedStemBlock) { return BlockChange.GROW; } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java index 9849bc7e832..481ed65a69c 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java @@ -195,7 +195,7 @@ protected BiomeTemplate build0() { foliageColor.ifPresent(c -> effectsBuilder.foliageColorOverride(c.rgb())); grassColor.ifPresent(c -> effectsBuilder.grassColorOverride(c.rgb())); particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) ps)); - ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) s))); + ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) m)); additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) s)); backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) m)); diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java index 425d535c24c..286d309f889 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java @@ -36,16 +36,16 @@ public class SpongeSoundConfigFactory implements SoundConfig.Factory { @Override public SoundConfig.Mood ofAmbientMood(final SoundType sound, final int tickDelay, final int searchRadius, final double distanceModifier) { - return (SoundConfig.Mood) new AmbientMoodSettings(Holder.direct((SoundEvent) sound), tickDelay, searchRadius, distanceModifier); + return (SoundConfig.Mood) new AmbientMoodSettings(Holder.direct((SoundEvent) (Object) sound), tickDelay, searchRadius, distanceModifier); } @Override public SoundConfig.Additional ofAdditional(final SoundType sound, final double tickChance) { - return (SoundConfig.Additional) new AmbientAdditionsSettings(Holder.direct((SoundEvent) sound), tickChance); + return (SoundConfig.Additional) new AmbientAdditionsSettings(Holder.direct((SoundEvent) (Object) sound), tickChance); } @Override public SoundConfig.BackgroundMusic ofBackroundMusic(final SoundType sound, final int minDelay, final int maxDelay, final boolean replacesCurrent) { - return (SoundConfig.BackgroundMusic) new Music(Holder.direct((SoundEvent) sound), minDelay, maxDelay, replacesCurrent); + return (SoundConfig.BackgroundMusic) new Music(Holder.direct((SoundEvent) (Object) sound), minDelay, maxDelay, replacesCurrent); } } diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index e76db24809d..d611184cbdb 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -321,7 +321,7 @@ public static boolean setBiome(final ChunkAccess chunk, final int x, final int y ) { final boolean result = VolumeStreamUtils.setBiome(chunk.getSection(chunk.getSectionIndex(y)), x, y, z, biome); if (result) { - chunk.setUnsaved(true); + chunk.markUnsaved(); } return result; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockSoundGroupMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockSoundGroupMixin_API.java index 69aa244b41b..8c72f740ca9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockSoundGroupMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockSoundGroupMixin_API.java @@ -56,26 +56,26 @@ public double pitch() { @Override public org.spongepowered.api.effect.sound.SoundType breakSound() { - return (org.spongepowered.api.effect.sound.SoundType) this.breakSound; + return (org.spongepowered.api.effect.sound.SoundType) (Object) this.breakSound; } @Override public org.spongepowered.api.effect.sound.SoundType stepSound() { - return (org.spongepowered.api.effect.sound.SoundType) this.stepSound; + return (org.spongepowered.api.effect.sound.SoundType) (Object) this.stepSound; } @Override public org.spongepowered.api.effect.sound.SoundType placeSound() { - return (org.spongepowered.api.effect.sound.SoundType) this.placeSound; + return (org.spongepowered.api.effect.sound.SoundType) (Object) this.placeSound; } @Override public org.spongepowered.api.effect.sound.SoundType hitSound() { - return (org.spongepowered.api.effect.sound.SoundType) this.hitSound; + return (org.spongepowered.api.effect.sound.SoundType) (Object) this.hitSound; } @Override public org.spongepowered.api.effect.sound.SoundType fallSound() { - return (org.spongepowered.api.effect.sound.SoundType) this.fallSound; + return (org.spongepowered.api.effect.sound.SoundType) (Object) this.fallSound; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java index 102078cbe50..55c04b7c5d3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java @@ -45,7 +45,7 @@ public abstract class MusicMixin_API implements SoundConfig.BackgroundMusic { @Override public SoundType sound() { - return (SoundType) this.event.value(); + return (SoundType) (Object) this.event.value(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/JukeboxSongMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/JukeboxSongMixin_API.java index 7b7fa4a636a..1ac5dd00437 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/JukeboxSongMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/JukeboxSongMixin_API.java @@ -40,6 +40,6 @@ public abstract class JukeboxSongMixin_API implements MusicDisc { @Override public SoundType sound() { - return (SoundType) this.soundEvent.value(); + return (SoundType) (Object) this.soundEvent.value(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java index 7e88eb2b746..8b51058fdbd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java @@ -98,7 +98,7 @@ default boolean setBiome(final int x, final int y, final int z, final org.sponge return false; } - return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> iChunk.getSection(iChunk.getSectionIndex(y)), () -> iChunk.setUnsaved(true)); + return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> iChunk.getSection(iChunk.getSectionIndex(y)), iChunk::markUnsaved); } // Volume diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java index d7be89e3af2..5aecb500911 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java @@ -43,7 +43,7 @@ public abstract class AmbientAdditionsSettingsMixin_API implements SoundConfig.A @Override public SoundType sound() { - return (SoundType) this.soundEvent.value(); + return (SoundType) (Object) this.soundEvent.value(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java index e047a72155d..4b93d6398b0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java @@ -45,7 +45,7 @@ public abstract class AmbientMoodSettingsMixin_API implements SoundConfig.Mood { @Override public SoundType sound() { - return (SoundType) this.soundEvent.value(); + return (SoundType) (Object) this.soundEvent.value(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/NoteBlockInstrumentMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/NoteBlockInstrumentMixin_API.java index 5686585dcdb..ae1a8fae1be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/NoteBlockInstrumentMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/NoteBlockInstrumentMixin_API.java @@ -41,6 +41,6 @@ public abstract class NoteBlockInstrumentMixin_API implements InstrumentType { @Override public SoundType sound() { - return (SoundType) this.shadow$getSoundEvent().value(); + return (SoundType) (Object) this.shadow$getSoundEvent().value(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java index 8d124e6d6b5..f1ea1749899 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java @@ -67,7 +67,7 @@ public abstract class ChunkAccessMixin_API

> implements Chunk< @Shadow public abstract ChunkPos shadow$getPos(); @Shadow public abstract int shadow$getHeight(Heightmap.Types var1, int var2, int var3); @Shadow public abstract LevelChunkSection shadow$getSection(int p_187657_); - @Shadow public abstract void shadow$setUnsaved(boolean p_62094_); + @Shadow public abstract void shadow$markUnsaved(); // @formatter:on @SuppressWarnings("unchecked") @Override @@ -96,7 +96,7 @@ public boolean isEmpty() { @Override public boolean setBiome(final int x, final int y, final int z, final Biome biome) { - return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> this.shadow$getSection(this.getSectionIndex(y)), () -> this.shadow$setUnsaved(true)); + return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> this.shadow$getSection(this.getSectionIndex(y)), this::shadow$markUnsaved); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index cbd945278b9..29080211aac 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -143,7 +143,7 @@ public Biome biome(final int x, final int y, final int z) { @Override public boolean setBiome(final int x, final int y, final int z, final Biome biome) { - return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> this.getSection(this.getSectionIndex(y)), () -> this.setUnsaved(true)); + return VolumeStreamUtils.setBiomeOnNativeChunk(x, y, z, biome, () -> this.getSection(this.getSectionIndex(y)), this::markUnsaved); } @Intrinsic diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 814729115da..5a96da6bd3c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -515,7 +515,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, } } - @Redirect(method = "lambda$onBlockStateChange$13", + @Redirect(method = "lambda$onBlockStateChange$14", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;add(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;)V" diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 50f98456499..971e4b85784 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -743,7 +743,7 @@ public void stopRiding() { } - @Redirect(method = "applyEffectsFromBlocks(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;)V", + @Redirect(method = "checkInsideBlocks(Ljava/util/List;Ljava/util/Set;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java index b5c3ba26b91..7dde827bfc2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java @@ -51,7 +51,6 @@ public abstract class AbstractArrowMixin extends ProjectileMixin implements Abst // @formatter:off @Shadow private int life; - @Shadow protected boolean inGround; @Shadow public int shakeTime; @Shadow public AbstractArrow.Pickup pickup; @Shadow @Nullable private BlockState lastState; @@ -60,9 +59,10 @@ public abstract class AbstractArrowMixin extends ProjectileMixin implements Abst @Shadow public abstract void shadow$setPierceLevel(byte level); @Shadow protected abstract ItemStack shadow$getPickupItem(); @Shadow protected abstract void resetPiercedEntities(); - + @Shadow protected abstract void shadow$setInGround(boolean $$0); // @formatter:on + @Nullable private Double impl$customKnockback; // Not all ProjectileSources are entities (e.g. BlockProjectileSource). @@ -97,7 +97,7 @@ private void onProjectileHit(final BlockHitResult hitResult, final CallbackInfo this.shadow$setDeltaMovement(vec3d); final Vec3 vec3d1 = vec3d.normalize().scale(0.05F); this.shadow$setPos(this.shadow$getX() - vec3d1.x, this.shadow$getY() - vec3d1.y, this.shadow$getZ() - vec3d1.z); - this.inGround = true; + this.shadow$setInGround(true); this.shakeTime = 7; this.shadow$setCritArrow(false); this.shadow$setPierceLevel((byte)0); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java index 07a4474a29c..7a6618479d1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java @@ -92,7 +92,9 @@ public abstract class LevelChunkMixin extends ChunkAccess implements LevelChunkB @Shadow @Nullable public abstract BlockEntity shadow$getBlockEntity(BlockPos pos, net.minecraft.world.level.chunk.LevelChunk.EntityCreationType p_177424_2_); @Shadow public abstract BlockState shadow$getBlockState(BlockPos pos); @Shadow public abstract void shadow$addEntity(net.minecraft.world.entity.Entity param0); - // @formatter:on + @Shadow public abstract void shadow$markUnsaved(); +// @formatter:on + private long impl$scheduledForUnload = -1; // delay chunk unloads private boolean impl$persistedChunk = false; @@ -130,7 +132,7 @@ public LevelChunkMixin( @Override public void bridge$markChunkDirty() { - this.unsaved = true; + this.shadow$markUnsaved(); } @Override @@ -399,14 +401,14 @@ public String toString() { @Override public DataTransactionResult bridge$offer(final Key<@NonNull ? extends Value> key, final E value) { final DataTransactionResult result = DataHolderProcessor.bridge$offer(this, key, value); - this.unsaved = true; + this.shadow$markUnsaved(); return result; } @Override public DataTransactionResult bridge$remove(final Key<@NonNull ? extends Value> key) { final DataTransactionResult result = DataHolderProcessor.bridge$remove(this, key); - this.unsaved = true; + this.shadow$markUnsaved(); return result; } From 20c98f2f45a0c6f12b0184f941d55b45c48481fe Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 12 Oct 2024 16:03:33 -0700 Subject: [PATCH 096/586] wip: update Generator for api content updates --- .../vanilla/generator/GeneratorMain.java | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index bf7c449a001..9df502ce99f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -33,19 +33,19 @@ import net.minecraft.Util; import net.minecraft.advancements.AdvancementType; import net.minecraft.commands.Commands.CommandSelection; +import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.resources.RegistryDataLoader; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.Bootstrap; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.RegistryLayer; -import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.*; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.ServerPacksSource; import net.minecraft.server.packs.resources.CloseableResourceManager; import net.minecraft.server.packs.resources.MultiPackResourceManager; +import net.minecraft.tags.TagLoader; import net.minecraft.world.Difficulty; import net.minecraft.world.damagesource.DamageEffects; import net.minecraft.world.damagesource.DamageScaling; @@ -69,6 +69,7 @@ import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.WorldDataConfiguration; +import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; import net.minecraft.world.level.block.state.properties.DripstoneThickness; @@ -90,6 +91,7 @@ import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A generator that will output source code containing constants used in Minecraft: Java Edition. @@ -160,25 +162,28 @@ private static Pair loadVanill // We don't currently try to load any datapacks here final var packRepository = ServerPacksSource.createVanillaTrustedRepository(); MinecraftServer.configurePackRepository(packRepository, WorldDataConfiguration.DEFAULT, /* safeMode = */ false, true); - final CloseableResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, packRepository.openAllSelected()); + final CloseableResourceManager rm = new MultiPackResourceManager(PackType.SERVER_DATA, packRepository.openAllSelected()); // WorldLoader.load final LayeredRegistryAccess staticRegistries = RegistryLayer.createRegistryAccess(); - final LayeredRegistryAccess withWorldgen = staticRegistries.replaceFrom( - RegistryLayer.WORLDGEN, - RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN).listRegistries().toList(), RegistryDataLoader.WORLDGEN_REGISTRIES) - ); - final LayeredRegistryAccess withDimensions = withWorldgen.replaceFrom( - RegistryLayer.DIMENSIONS, - RegistryDataLoader.load(resourceManager, staticRegistries.getAccessForLoading(RegistryLayer.DIMENSIONS).listRegistries().toList(), RegistryDataLoader.DIMENSION_REGISTRIES) - ); - + List> pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.STATIC)); + final var wga = staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN); + List> tl = TagLoader.buildUpdatedLookups(wga, pendingTags); + RegistryAccess.Frozen wgr = RegistryDataLoader.load(rm, tl, RegistryDataLoader.WORLDGEN_REGISTRIES); + tl = TagLoader.buildUpdatedLookups(wgr, pendingTags); + List> cl = Stream.concat(tl.stream(), wgr.listRegistries()).toList(); + final LayeredRegistryAccess withWorldGen = staticRegistries.replaceFrom(RegistryLayer.WORLDGEN, wgr); + pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.WORLDGEN)); + RegistryAccess.Frozen da = RegistryDataLoader.load(rm, cl, RegistryDataLoader.DIMENSION_REGISTRIES); + TagLoader.buildUpdatedLookups(da, pendingTags); + final LayeredRegistryAccess withDimensions = withWorldGen.replaceFrom(RegistryLayer.DIMENSIONS, da); + pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.DIMENSIONS)); final RegistryAccess.Frozen compositeRegistries = withDimensions.getAccessForLoading(RegistryLayer.RELOADABLE); final var resourcesFuture = ReloadableServerResources.loadResources( - resourceManager, + rm, withDimensions, - List.of(), + pendingTags, packRepository.getRequestedFeatureFlags(), CommandSelection.ALL, 2, // functionPermissionLevel @@ -186,7 +191,7 @@ private static Pair loadVanill Runnable::run // applyExecutor ).whenComplete((result, ex) -> { if (ex != null) { - resourceManager.close(); + rm.close(); } }).thenApply(resources -> { resources.updateStaticRegistryTags(); @@ -245,6 +250,13 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), + new EnumEntriesValidator<>( + "data.type", + "CreakingHearts", + CreakingHeartBlock.CreakingHeartState.class, + "getSerializedName", + "sponge" + ), new RegistryEntriesGenerator<>( "map.decoration", "MapDecorationTypes", From d36a5a86ac6626848783da57e92202b5a0cd2bc0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 14 Oct 2024 20:28:47 -0700 Subject: [PATCH 097/586] chore: update api data types for 1.21.2 content Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../BlockStatePropertiesGenerator.java | 2 ++ .../BlockStatePropertyKeysGenerator.java | 2 ++ .../generator/EnumEntriesValidator.java | 6 +++++- .../vanilla/generator/GeneratorMain.java | 7 ++----- .../generator/RegistryEntriesGenerator.java | 18 +++++++++++------- .../org/spongepowered/test/data/DataTest.java | 2 +- 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index f42a8a8a443..7f4b70ea4c9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit f42a8a8a44309e2230e05b081736ac28cdfa2511 +Subproject commit 7f4b70ea4c9738df9069df51ca0bd36b44f9e329 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 202e77ae676..fbcf5ea6048 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -32,6 +32,7 @@ import net.minecraft.core.FrontAndTop; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -131,6 +132,7 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(StructureMode.class, BlockStatePropertiesGenerator.inDataTypePkg("StructureMode")); vanillaEnumTypeMapping.put(PistonType.class, BlockStatePropertiesGenerator.inDataTypePkg("PistonType")); vanillaEnumTypeMapping.put(BambooLeaves.class, BlockStatePropertiesGenerator.inDataTypePkg("BambooLeavesType")); + vanillaEnumTypeMapping.put(CreakingHeartBlock.CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeart")); vanillaEnumTypeMapping.put(WallSide.class, BlockStatePropertiesGenerator.inDataTypePkg("WallConnectionState")); vanillaEnumTypeMapping.put(RailShape.class, BlockStatePropertiesGenerator.inDataTypePkg("RailDirection")); vanillaEnumTypeMapping.put(AttachFace.class, BlockStatePropertiesGenerator.inDataTypePkg("AttachmentSurface")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index d00816a08ce..8e269ac5864 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -33,6 +33,7 @@ import com.squareup.javapoet.TypeVariableName; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; +import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -129,6 +130,7 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(StructureMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("StructureMode")); vanillaEnumTypeMapping.put(PistonType.class, BlockStatePropertyKeysGenerator.inDataTypePkg("PistonType")); vanillaEnumTypeMapping.put(BambooLeaves.class, BlockStatePropertyKeysGenerator.inDataTypePkg("BambooLeavesType")); + vanillaEnumTypeMapping.put(CreakingHeartBlock.CreakingHeartState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CreakingHeart")); vanillaEnumTypeMapping.put(WallSide.class, BlockStatePropertyKeysGenerator.inDataTypePkg("WallConnectionState")); vanillaEnumTypeMapping.put(RailShape.class, BlockStatePropertyKeysGenerator.inDataTypePkg("RailDirection")); vanillaEnumTypeMapping.put(AttachFace.class, BlockStatePropertyKeysGenerator.inDataTypePkg("AttachmentSurface")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java index 27618ec8527..78acf6a1f41 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java @@ -136,7 +136,11 @@ public void generate(final Context ctx) { // Sort field entries and add them back to the class processedFields.sort(Comparator.comparing(field -> field.getVariable(0).getNameAsString())); - primaryTypeDeclaration.getMembers().addAll(lastNonFieldIndex, processedFields); + var indextoAddAt = lastNonFieldIndex; + if (indextoAddAt == -1) { + indextoAddAt = 0; + } + primaryTypeDeclaration.getMembers().addAll(indextoAddAt, processedFields); if (!added.isEmpty()) { Logger.info("Added {} entries to {} that will require manual action to implement: {}", added.size(), this.targetClassSimpleName, added); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 9df502ce99f..fa239231a98 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -170,14 +170,11 @@ private static Pair loadVanill final var wga = staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN); List> tl = TagLoader.buildUpdatedLookups(wga, pendingTags); RegistryAccess.Frozen wgr = RegistryDataLoader.load(rm, tl, RegistryDataLoader.WORLDGEN_REGISTRIES); - tl = TagLoader.buildUpdatedLookups(wgr, pendingTags); List> cl = Stream.concat(tl.stream(), wgr.listRegistries()).toList(); final LayeredRegistryAccess withWorldGen = staticRegistries.replaceFrom(RegistryLayer.WORLDGEN, wgr); - pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.WORLDGEN)); RegistryAccess.Frozen da = RegistryDataLoader.load(rm, cl, RegistryDataLoader.DIMENSION_REGISTRIES); - TagLoader.buildUpdatedLookups(da, pendingTags); final LayeredRegistryAccess withDimensions = withWorldGen.replaceFrom(RegistryLayer.DIMENSIONS, da); - pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.DIMENSIONS)); + TagLoader.loadTagsForExistingRegistries(rm, withDimensions.getLayer(RegistryLayer.WORLDGEN)); final RegistryAccess.Frozen compositeRegistries = withDimensions.getAccessForLoading(RegistryLayer.RELOADABLE); final var resourcesFuture = ReloadableServerResources.loadResources( @@ -378,7 +375,7 @@ private static List generators(final Context context) { ), new EnumEntriesValidator<>( "world.explosion", - "BlockInteractions", + "ExplosionBlockInteractions", Explosion.BlockInteraction.class, "name", "sponge" diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index 72abbf31d06..753594ccfeb 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -24,10 +24,13 @@ */ package org.spongepowered.vanilla.generator; +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; @@ -35,6 +38,7 @@ import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; +import org.jetbrains.annotations.ApiStatus; import java.io.IOException; import java.util.Comparator; @@ -121,7 +125,7 @@ public void generate(final Context ctx) throws IOException { clazz.addAnnotation(Types.suppressWarnings("unused")); final RegistryScope scopeType; - Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()).orElse(null); + Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()).map(Holder.Reference::value).orElse(null); if (registry == null) { registry = ctx.registries().lookup(this.registry).orElse(null); if (registry == null) { @@ -160,12 +164,12 @@ private FieldSpec makeField(final String ownType, final TypeName fieldType, fina if (!featureFlagSet.isSubsetOf(FeatureFlags.VANILLA_SET)) { final var flags = FeatureFlags.REGISTRY.toNames(featureFlagSet).stream().map(rl -> rl.getNamespace().equals("minecraft") ? rl.getPath() : rl.getNamespace() + ":" + rl.getPath()).toArray(); // Use this when new feature flags are introduced -// if (featureFlagSet.contains(FeatureFlags.UPDATE_1_20)) { -// var annotation = AnnotationSpec.builder(ClassName.get("org.spongepowered.api.util.annotation", "Experimental")) -// .addMember("value", "$S", flags).build(); -// builder.addAnnotation(annotation).build(); -// builder.addAnnotation(ApiStatus.Experimental.class).build(); -// } + if (featureFlagSet.contains(FeatureFlags.WINTER_DROP)) { + var annotation = AnnotationSpec.builder(ClassName.get("org.spongepowered.api.util.annotation", "Experimental")) + .addMember("value", "$S", flags).build(); + builder.addAnnotation(annotation).build(); + builder.addAnnotation(ApiStatus.Experimental.class).build(); + } } diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 92460049d70..5a732f206ce 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -373,7 +373,7 @@ public void testData(final ServerPlayer player) { this.checkOfferData(ravager, Keys.CAN_JOIN_RAID, true); this.checkOfferData(ravager, Keys.CAN_JOIN_RAID, false); - final Entity boat = world.createEntity(EntityTypes.BOAT.get(), position); + final Entity boat = world.createEntity(EntityTypes.OAK_BOAT.get(), position); this.checkOfferData(boat, Keys.CAN_MOVE_ON_LAND, true); this.checkOfferData(boat, Keys.CAN_MOVE_ON_LAND, false); From 146836e580af4a48b24cc679f62deb5bf009c2b9 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 14 Oct 2024 22:11:35 -0700 Subject: [PATCH 098/586] feat: add creaking data Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../creaking/CreakingTransientAccessor.java | 39 ++ .../resources/mixins.sponge.accessors.json | 425 +++++++++--------- .../data/provider/entity/CreakingData.java | 50 +++ .../provider/entity/EntityDataProviders.java | 1 + 5 files changed, 304 insertions(+), 213 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java diff --git a/SpongeAPI b/SpongeAPI index 7f4b70ea4c9..43c7dd04b6e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 7f4b70ea4c9738df9069df51ca0bd36b44f9e329 +Subproject commit 43c7dd04b6e78c7493259537036cafb0a59ae8f6 diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java new file mode 100644 index 00000000000..a3a80e54d1a --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.monster.creaking; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.monster.creaking.CreakingTransient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(CreakingTransient.class) +public interface CreakingTransientAccessor { + + @Accessor("homePos") BlockPos accessor$homePos(); + + @Accessor("homePos") void accessor$setHomePos(BlockPos pos); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 8773c4e9e3c..12b09545f3f 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -1,214 +1,215 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.accessor", - "client": [ - "client.KeyMappingAccessor", - "client.multiplayer.ClientLevelAccessor", - "world.level.entity.TransientEntitySectionManagerAccessor" - ], - "mixins": [ - "ChatFormattingAccessor", - "advancements.CriteriaTriggersAccessor", - "advancements.critereon.MinMaxBounds_DoublesAccessor", - "advancements.critereon.MinMaxBounds_IntsAccessor", - "commands.CommandSourceStackAccessor", - "commands.arguments.DimensionArgumentAccessor", - "commands.arguments.OperationArgumentAccessor", - "commands.arguments.selector.EntitySelectorParserAccessor", - "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", - "commands.arguments.selector.options.EntitySelectorOptionsAccessor", - "core.MappedRegistryAccessor", - "entity.passive.AbstractChestedHorseEntityAccessor", - "network.ConnectionAccessor", - "network.chat.HoverEvent_ItemStackInfoAccessor", - "network.chat.StyleAccessor", - "network.protocol.game.ClientboundAddEntityPacketAccessor", - "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", - "network.protocol.game.ServerboundInteractPacketAccessor", - "network.protocol.game.ServerboundMovePlayerPacketAccessor", - "network.protocol.game.ServerboundMoveVehiclePacketAccessor", - "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.ResourceKeyAccessor", - "server.MinecraftServerAccessor", - "server.level.ChunkMap_TrackedEntityAccessor", - "server.level.ChunkMapAccessor", - "server.level.ServerChunkCacheAccessor", - "server.level.ServerLevelAccessor", - "server.level.ServerPlayer_ContainerListenerAccessor", - "server.level.ServerPlayerAccessor", - "server.level.ServerPlayerGameModeAccessor", - "server.level.TicketAccessor", - "server.level.TicketTypeAccessor", - "server.network.ServerCommonPacketListenerImplAccessor", - "server.network.ServerGamePacketListenerImplAccessor", - "server.network.ServerLoginPacketListenerImplAccessor", - "server.players.GameProfileCache_GameProfileInfoAccessor", - "server.players.IpBanListAccessor", - "server.players.PlayerListAccessor", - "server.players.StoredUserEntryAccessor", - "server.players.StoredUserListAccessor", - "server.rcon.thread.RconClientAccessor", - "sounds.SoundEventAccessor", - "stats.StatsCounterAccessor", - "util.datafix.schemas.V100Accessor", - "world.CompoundContainerAccessor", - "world.damagesource.CombatTrackerAccessor", - "world.entity.AgableMobAccessor", - "world.entity.AreaEffectCloudAccessor", - "world.entity.Display_BlockDisplayAccessor", - "world.entity.Display_ItemDisplayAccessor", - "world.entity.Display_TextDisplayAccessor", - "world.entity.DisplayAccessor", - "world.entity.EntityAccessor", - "world.entity.EntityTypeAccessor", - "world.entity.ExperienceOrbAccessor", - "world.entity.LightningBoltAccessor", - "world.entity.LivingEntityAccessor", - "world.entity.MobAccessor", - "world.entity.PortalProcessorAccessor", - "world.entity.ai.targeting.TargetingConditionsAccessor", - "world.entity.animal.AnimalAccessor", - "world.entity.animal.CatAccessor", - "world.entity.animal.FoxAccessor", - "world.entity.animal.OcelotAccessor", - "world.entity.animal.PandaAccessor", - "world.entity.animal.PigAccessor", - "world.entity.animal.PufferfishAccessor", - "world.entity.animal.SheepAccessor", - "world.entity.animal.TropicalFishAccessor", - "world.entity.animal.TurtleAccessor", - "world.entity.animal.WolfAccessor", - "world.entity.animal.horse.HorseAccessor", - "world.entity.animal.horse.LlamaAccessor", - "world.entity.animal.horse.TraderLlamaAccessor", - "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", - "world.entity.boss.wither.WitherBossAccessor", - "world.entity.decoration.ArmorStandAccessor", - "world.entity.decoration.HangingEntityAccessor", - "world.entity.decoration.ItemFrameAccessor", - "world.entity.item.FallingBlockEntityAccessor", - "world.entity.item.PrimedTntAccessor", - "world.entity.monster.BlazeAccessor", - "world.entity.monster.CreeperAccessor", - "world.entity.monster.EnderManAccessor", - "world.entity.monster.EndermiteAccessor", - "world.entity.monster.EvokerAccessor", - "world.entity.monster.GuardianAccessor", - "world.entity.monster.PatrollingMonsterAccessor", - "world.entity.monster.PhantomAccessor", - "world.entity.monster.PillagerAccessor", - "world.entity.monster.RavagerAccessor", - "world.entity.monster.SlimeAccessor", - "world.entity.monster.SpellcasterIllagerAccessor", - "world.entity.monster.VexAccessor", - "world.entity.monster.VindicatorAccessor", - "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.npc.AbstractVillagerAccessor", - "world.entity.player.AbilitiesAccessor", - "world.entity.player.PlayerAccessor", - "world.entity.projectile.ArrowAccessor", - "world.entity.projectile.EyeOfEnderAccessor", - "world.entity.projectile.FireworkRocketEntityAccessor", - "world.entity.projectile.FishingHookAccessor", - "world.entity.projectile.ProjectileAccessor", - "world.entity.projectile.ShulkerBulletAccessor", - "world.entity.raid.RaidAccessor", - "world.entity.raid.RaiderAccessor", - "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.AbstractBoatAccessor", - "world.entity.vehicle.MinecartFurnaceAccessor", - "world.food.FoodDataAccessor", - "world.inventory.AbstractContainerMenuAccessor", - "world.inventory.AbstractCraftingMenuAccessor", - "world.inventory.AbstractFurnaceMenuAccessor", - "world.inventory.BeaconMenuAccessor", - "world.inventory.BrewingStandMenuAccessor", - "world.inventory.DispenserMenuAccessor", - "world.inventory.HopperMenuAccessor", - "world.inventory.HorseInventoryMenuAccessor", - "world.inventory.ItemCombinerMenuAccessor", - "world.inventory.MerchantMenuAccessor", - "world.inventory.ResultSlotAccessor", - "world.inventory.SlotAccessor", - "world.inventory.SmithingMenuAccessor", - "world.item.AdventureModePredicateAccessor", - "world.item.ItemCooldowns_CooldownInstanceAccessor", - "world.item.component.CustomDataAccessor", - "world.item.crafting.RecipeMapAccessor", - "world.item.crafting.ShapelessRecipeAccessor", - "world.item.enchantment.ItemEnchantmentsAccessor", - "world.item.trading.MerchantOfferAccessor", - "world.level.BaseCommandBlockAccessor", - "world.level.BaseSpawnerAccessor", - "world.level.GameRules_ValueAccessor", - "world.level.GameRulesAccessor", - "world.level.LevelAccessor", - "world.level.LevelSettingsAccessor", - "world.level.NaturalSpawner_SpawnStateAccessor", - "world.level.NaturalSpawnerAccessor", - "world.level.ServerExplosionAccessor", - "world.level.biome.Biome_ClimateSettingsAccessor", - "world.level.biome.BiomeAccessor", - "world.level.biome.MobSpawnSettingsAccessor", - "world.level.biome.MultiNoiseBiomeSourceAccessor", - "world.level.biome.OverworldBiomeBuilderAccessor", - "world.level.biome.TheEndBiomeSourceAccessor", - "world.level.block.AbstractSkullBlockAccessor", - "world.level.block.BaseFireBlockAccessor", - "world.level.block.BedBlockAccessor", - "world.level.block.CrafterBlockAccessor", - "world.level.block.CropBlockAccessor", - "world.level.block.DispenserBlockAccessor", - "world.level.block.EnderChestBlockAccessor", - "world.level.block.StemBlockAccessor", - "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", - "world.level.block.entity.BaseContainerBlockEntityAccessor", - "world.level.block.entity.BeaconBlockEntityAccessor", - "world.level.block.entity.BlockEntityAccessor", - "world.level.block.entity.BrewingStandBlockEntityAccessor", - "world.level.block.entity.ConduitBlockEntityAccessor", - "world.level.block.entity.CrafterBlockEntityAccessor", - "world.level.block.entity.EnchantingTableBlockEntityAccessor", - "world.level.block.entity.HopperBlockEntityAccessor", - "world.level.block.entity.LecternBlockEntity_Accessor", - "world.level.block.entity.SkullBlockEntityAccessor", - "world.level.block.entity.SpawnerBlockEntityAccessor", - "world.level.block.entity.StructureBlockEntityAccessor", - "world.level.block.entity.TheEndGatewayBlockEntityAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", - "world.level.block.piston.PistonBaseBlockAccessor", - "world.level.block.state.BlockBehaviour_PropertiesAccessor", - "world.level.block.state.BlockBehaviourAccessor", - "world.level.block.state.StateHolderAccessor", - "world.level.border.WorldBorder_SettingsAccessor", - "world.level.border.WorldBorderAccessor", - "world.level.chunk.ChunkAccessAccessor", - "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", - "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", - "world.level.chunk.LevelChunkAccessor", - "world.level.chunk.storage.ChunkStorageAccessor", - "world.level.chunk.storage.IOWorker$PendingStoreAccessor", - "world.level.chunk.storage.RegionFileAccessor", - "world.level.chunk.storage.SimpleRegionStorageAccessor", - "world.level.dimension.DimensionTypeAccessor", - "world.level.dimension.end.EndDragonFightAccessor", - "world.level.entity.EntityTickListAccessor", - "world.level.entity.PersistentEntitySectionManagerAccessor", - "world.level.levelgen.NoiseSettingsAccessor", - "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", - "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", - "world.level.saveddata.maps.MapItemSavedDataAccessor", - "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", - "world.level.storage.PlayerDataStorageAccessor", - "world.phys.AABBAccessor", - "world.scores.PlayerTeamAccessor", - "world.scores.ScoreboardAccessor" - ], - "server": [ - "server.dedicated.DedicatedServerAccessor" - ] + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.accessor", + "client": [ + "client.KeyMappingAccessor", + "client.multiplayer.ClientLevelAccessor", + "world.level.entity.TransientEntitySectionManagerAccessor" + ], + "mixins": [ + "ChatFormattingAccessor", + "advancements.CriteriaTriggersAccessor", + "advancements.critereon.MinMaxBounds_DoublesAccessor", + "advancements.critereon.MinMaxBounds_IntsAccessor", + "commands.CommandSourceStackAccessor", + "commands.arguments.DimensionArgumentAccessor", + "commands.arguments.OperationArgumentAccessor", + "commands.arguments.selector.EntitySelectorParserAccessor", + "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", + "commands.arguments.selector.options.EntitySelectorOptionsAccessor", + "core.MappedRegistryAccessor", + "entity.passive.AbstractChestedHorseEntityAccessor", + "network.ConnectionAccessor", + "network.chat.HoverEvent_ItemStackInfoAccessor", + "network.chat.StyleAccessor", + "network.protocol.game.ClientboundAddEntityPacketAccessor", + "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", + "network.protocol.game.ServerboundInteractPacketAccessor", + "network.protocol.game.ServerboundMovePlayerPacketAccessor", + "network.protocol.game.ServerboundMoveVehiclePacketAccessor", + "network.protocol.handshake.ClientIntentionPacketAccessor", + "resources.ResourceKeyAccessor", + "server.MinecraftServerAccessor", + "server.level.ChunkMap_TrackedEntityAccessor", + "server.level.ChunkMapAccessor", + "server.level.ServerChunkCacheAccessor", + "server.level.ServerLevelAccessor", + "server.level.ServerPlayer_ContainerListenerAccessor", + "server.level.ServerPlayerAccessor", + "server.level.ServerPlayerGameModeAccessor", + "server.level.TicketAccessor", + "server.level.TicketTypeAccessor", + "server.network.ServerCommonPacketListenerImplAccessor", + "server.network.ServerGamePacketListenerImplAccessor", + "server.network.ServerLoginPacketListenerImplAccessor", + "server.players.GameProfileCache_GameProfileInfoAccessor", + "server.players.IpBanListAccessor", + "server.players.PlayerListAccessor", + "server.players.StoredUserEntryAccessor", + "server.players.StoredUserListAccessor", + "server.rcon.thread.RconClientAccessor", + "sounds.SoundEventAccessor", + "stats.StatsCounterAccessor", + "util.datafix.schemas.V100Accessor", + "world.CompoundContainerAccessor", + "world.damagesource.CombatTrackerAccessor", + "world.entity.AgableMobAccessor", + "world.entity.AreaEffectCloudAccessor", + "world.entity.Display_BlockDisplayAccessor", + "world.entity.Display_ItemDisplayAccessor", + "world.entity.Display_TextDisplayAccessor", + "world.entity.DisplayAccessor", + "world.entity.EntityAccessor", + "world.entity.EntityTypeAccessor", + "world.entity.ExperienceOrbAccessor", + "world.entity.LightningBoltAccessor", + "world.entity.LivingEntityAccessor", + "world.entity.MobAccessor", + "world.entity.PortalProcessorAccessor", + "world.entity.ai.targeting.TargetingConditionsAccessor", + "world.entity.animal.AnimalAccessor", + "world.entity.animal.CatAccessor", + "world.entity.animal.FoxAccessor", + "world.entity.animal.OcelotAccessor", + "world.entity.animal.PandaAccessor", + "world.entity.animal.PigAccessor", + "world.entity.animal.PufferfishAccessor", + "world.entity.animal.SheepAccessor", + "world.entity.animal.TropicalFishAccessor", + "world.entity.animal.TurtleAccessor", + "world.entity.animal.WolfAccessor", + "world.entity.animal.horse.HorseAccessor", + "world.entity.animal.horse.LlamaAccessor", + "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", + "world.entity.boss.wither.WitherBossAccessor", + "world.entity.decoration.ArmorStandAccessor", + "world.entity.decoration.HangingEntityAccessor", + "world.entity.decoration.ItemFrameAccessor", + "world.entity.item.FallingBlockEntityAccessor", + "world.entity.item.PrimedTntAccessor", + "world.entity.monster.BlazeAccessor", + "world.entity.monster.CreeperAccessor", + "world.entity.monster.EnderManAccessor", + "world.entity.monster.EndermiteAccessor", + "world.entity.monster.EvokerAccessor", + "world.entity.monster.GuardianAccessor", + "world.entity.monster.PatrollingMonsterAccessor", + "world.entity.monster.PhantomAccessor", + "world.entity.monster.PillagerAccessor", + "world.entity.monster.RavagerAccessor", + "world.entity.monster.SlimeAccessor", + "world.entity.monster.SpellcasterIllagerAccessor", + "world.entity.monster.VexAccessor", + "world.entity.monster.VindicatorAccessor", + "world.entity.monster.ZombifiedPiglinAccessor", + "world.entity.monster.creaking.CreakingTransientAccessor", + "world.entity.npc.AbstractVillagerAccessor", + "world.entity.player.AbilitiesAccessor", + "world.entity.player.PlayerAccessor", + "world.entity.projectile.ArrowAccessor", + "world.entity.projectile.EyeOfEnderAccessor", + "world.entity.projectile.FireworkRocketEntityAccessor", + "world.entity.projectile.FishingHookAccessor", + "world.entity.projectile.ProjectileAccessor", + "world.entity.projectile.ShulkerBulletAccessor", + "world.entity.raid.RaidAccessor", + "world.entity.raid.RaiderAccessor", + "world.entity.raid.RaidsAccessor", + "world.entity.vehicle.AbstractBoatAccessor", + "world.entity.vehicle.MinecartFurnaceAccessor", + "world.food.FoodDataAccessor", + "world.inventory.AbstractContainerMenuAccessor", + "world.inventory.AbstractCraftingMenuAccessor", + "world.inventory.AbstractFurnaceMenuAccessor", + "world.inventory.BeaconMenuAccessor", + "world.inventory.BrewingStandMenuAccessor", + "world.inventory.DispenserMenuAccessor", + "world.inventory.HopperMenuAccessor", + "world.inventory.HorseInventoryMenuAccessor", + "world.inventory.ItemCombinerMenuAccessor", + "world.inventory.MerchantMenuAccessor", + "world.inventory.ResultSlotAccessor", + "world.inventory.SlotAccessor", + "world.inventory.SmithingMenuAccessor", + "world.item.AdventureModePredicateAccessor", + "world.item.ItemCooldowns_CooldownInstanceAccessor", + "world.item.component.CustomDataAccessor", + "world.item.crafting.RecipeMapAccessor", + "world.item.crafting.ShapelessRecipeAccessor", + "world.item.enchantment.ItemEnchantmentsAccessor", + "world.item.trading.MerchantOfferAccessor", + "world.level.BaseCommandBlockAccessor", + "world.level.BaseSpawnerAccessor", + "world.level.GameRules_ValueAccessor", + "world.level.GameRulesAccessor", + "world.level.LevelAccessor", + "world.level.LevelSettingsAccessor", + "world.level.NaturalSpawner_SpawnStateAccessor", + "world.level.NaturalSpawnerAccessor", + "world.level.ServerExplosionAccessor", + "world.level.biome.Biome_ClimateSettingsAccessor", + "world.level.biome.BiomeAccessor", + "world.level.biome.MobSpawnSettingsAccessor", + "world.level.biome.MultiNoiseBiomeSourceAccessor", + "world.level.biome.OverworldBiomeBuilderAccessor", + "world.level.biome.TheEndBiomeSourceAccessor", + "world.level.block.AbstractSkullBlockAccessor", + "world.level.block.BaseFireBlockAccessor", + "world.level.block.BedBlockAccessor", + "world.level.block.CrafterBlockAccessor", + "world.level.block.CropBlockAccessor", + "world.level.block.DispenserBlockAccessor", + "world.level.block.EnderChestBlockAccessor", + "world.level.block.StemBlockAccessor", + "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", + "world.level.block.entity.BaseContainerBlockEntityAccessor", + "world.level.block.entity.BeaconBlockEntityAccessor", + "world.level.block.entity.BlockEntityAccessor", + "world.level.block.entity.BrewingStandBlockEntityAccessor", + "world.level.block.entity.ConduitBlockEntityAccessor", + "world.level.block.entity.CrafterBlockEntityAccessor", + "world.level.block.entity.EnchantingTableBlockEntityAccessor", + "world.level.block.entity.HopperBlockEntityAccessor", + "world.level.block.entity.LecternBlockEntity_Accessor", + "world.level.block.entity.SkullBlockEntityAccessor", + "world.level.block.entity.SpawnerBlockEntityAccessor", + "world.level.block.entity.StructureBlockEntityAccessor", + "world.level.block.entity.TheEndGatewayBlockEntityAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", + "world.level.block.piston.PistonBaseBlockAccessor", + "world.level.block.state.BlockBehaviour_PropertiesAccessor", + "world.level.block.state.BlockBehaviourAccessor", + "world.level.block.state.StateHolderAccessor", + "world.level.border.WorldBorder_SettingsAccessor", + "world.level.border.WorldBorderAccessor", + "world.level.chunk.ChunkAccessAccessor", + "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", + "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", + "world.level.chunk.LevelChunkAccessor", + "world.level.chunk.storage.ChunkStorageAccessor", + "world.level.chunk.storage.IOWorker$PendingStoreAccessor", + "world.level.chunk.storage.RegionFileAccessor", + "world.level.chunk.storage.SimpleRegionStorageAccessor", + "world.level.dimension.DimensionTypeAccessor", + "world.level.dimension.end.EndDragonFightAccessor", + "world.level.entity.EntityTickListAccessor", + "world.level.entity.PersistentEntitySectionManagerAccessor", + "world.level.levelgen.NoiseSettingsAccessor", + "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", + "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", + "world.level.saveddata.maps.MapItemSavedDataAccessor", + "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", + "world.level.storage.PlayerDataStorageAccessor", + "world.phys.AABBAccessor", + "world.scores.PlayerTeamAccessor", + "world.scores.ScoreboardAccessor" + ], + "server": [ + "server.dedicated.DedicatedServerAccessor" + ] } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java new file mode 100644 index 00000000000..7bec37c48c6 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.monster.creaking.Creaking; +import net.minecraft.world.entity.monster.creaking.CreakingTransient; +import org.spongepowered.api.data.Keys; +import org.spongepowered.common.accessor.world.entity.monster.creaking.CreakingTransientAccessor; +import org.spongepowered.common.data.provider.DataProviderRegistrator; +import org.spongepowered.common.util.VecHelper; + +public final class CreakingData { + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asImmutable(Creaking.class) + .create(Keys.CREAKING_IS_LINKED) + .get(e -> e instanceof CreakingTransient); + registrator + .asMutable(CreakingTransient.class) + .create(Keys.CREAKING_HOME_POSITION) + .get(h -> VecHelper.toVector3i(((CreakingTransientAccessor) h).accessor$homePos())) + .set((h, v) -> ((CreakingTransientAccessor) h).accessor$setHomePos(VecHelper.toBlockPos(v))); + ; + } + // @formatter:on +} diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index facac285ef6..0741cb7dadb 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -49,6 +49,7 @@ public void registerProviders() { CatData.register(this.registrator); ChickenData.register(this.registrator); CommandBlockMinecartData.register(this.registrator); + CreakingData.register(this.registrator); CreeperData.register(this.registrator); DamagingProjectileData.register(this.registrator); DolphinData.register(this.registrator); From 960a47b0bf337648e28f982047d3b9874feed71f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 15 Oct 2024 20:25:44 -0700 Subject: [PATCH 099/586] chore: bump to next major version Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 43c7dd04b6e..173e7d48cb3 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 43c7dd04b6e78c7493259537036cafb0a59ae8f6 +Subproject commit 173e7d48cb3d3efa6414552f69406efe1ceed199 From 218bac8bc045a1e9c377b789cff9eb10c4c9e390 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 15 Oct 2024 20:35:46 -0700 Subject: [PATCH 100/586] feat: enable cooldown group data keys Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../provider/item/stack/ItemStackData.java | 71 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 173e7d48cb3..8e1c091ecea 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 173e7d48cb3d3efa6414552f69406efe1ceed199 +Subproject commit 8e1c091ecea15b3e81c3c491a3efca270d0574d0 diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 3346446c7ea..4b991d5a3ca 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -30,6 +30,7 @@ import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; @@ -46,6 +47,7 @@ import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; +import net.minecraft.world.item.component.UseCooldown; import net.minecraft.world.item.component.UseRemainder; import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; @@ -55,7 +57,10 @@ import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Platform; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.data.DataTransactionResult; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.Inventory; @@ -67,6 +72,7 @@ import org.spongepowered.common.item.util.ItemStackUtil; import java.util.List; +import java.util.Optional; @SuppressWarnings({"unchecked", "UnstableApiUsage"}) public final class ItemStackData { @@ -276,7 +282,56 @@ public static void register(final DataProviderRegistrator registrator) { }) .set((h, value) -> h.set(DataComponents.ITEM_NAME, SpongeAdventure.asVanillaMutable(value))) .delete(stack -> stack.remove(DataComponents.ITEM_NAME)) - ; + .create(Keys.COOLDOWN_GROUP) + .get(h -> { + final @Nullable UseCooldown cooldown = h.get(DataComponents.USE_COOLDOWN); + if (cooldown == null) { + return null; + } + return (ResourceKey) (Object) cooldown.cooldownGroup().orElse(null); + }) + .set((h, value) -> { + if (value == null) { + h.remove(DataComponents.USE_COOLDOWN); + return; + } + h.set(DataComponents.USE_COOLDOWN, new UseCooldown(1, Optional.of((ResourceLocation) (Object) value))); + }) + .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) + .create(Keys.COOLDOWN) + .get(h -> { + final @Nullable UseCooldown cooldown = h.get(DataComponents.USE_COOLDOWN); + if (cooldown == null) { + return null; + } + return Ticks.of(cooldown.ticks()); + }) + .setAndGet((h, value) -> { + if (value == null) { + return ItemStackData.deleteAndTransactUseCooldown(h); + } + final var existing = h.get(DataComponents.USE_COOLDOWN); + var builder = DataTransactionResult.builder() + .success(Value.immutableOf(Keys.COOLDOWN, value)); + if (existing != null) { + h.set(DataComponents.USE_COOLDOWN, new UseCooldown(value.ticks(), existing.cooldownGroup())); + builder.replace(existing.cooldownGroup().map(ResourceKey.class::cast) + .map(group -> + List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(existing.ticks())), + Value.immutableOf(Keys.COOLDOWN_GROUP, group) + ) + ) + .orElseGet(() -> List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(existing.ticks())) + ))); + } else { + h.set(DataComponents.USE_COOLDOWN, new UseCooldown(value.ticks(), Optional.empty())); + } + return builder.build(); + }) + .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) + ; } // @formatter:on @@ -303,4 +358,18 @@ private static void setIsUnbrekable(final ItemStack stack, final Boolean value) } } + private static DataTransactionResult deleteAndTransactUseCooldown(final ItemStack stack) { + final @Nullable UseCooldown cooldown = stack.remove(DataComponents.USE_COOLDOWN); + if (cooldown == null) { + return DataTransactionResult.successNoData(); + } + return cooldown.cooldownGroup() + .map(group -> DataTransactionResult.successRemove(List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())), + Value.immutableOf(Keys.COOLDOWN_GROUP, (ResourceKey) (Object) group) + ))).orElseGet(() -> DataTransactionResult.successRemove(List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())) + ))); + } + } From 22c156c48b6b0127424ee43ffe748686ff648110 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 17 Oct 2024 17:34:04 -0700 Subject: [PATCH 101/586] chore: update to 1.21.2-rc1 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a51d9f41d21..4293bf607ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.2-pre3 +minecraftVersion=1.21.2-rc1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From e97464579de3f0f06cef57bd2e1677541752764c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 21 Oct 2024 20:04:07 -0700 Subject: [PATCH 102/586] chore: update to 1.21.2-rc2 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4293bf607ef..650da30265c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.2-rc1 +minecraftVersion=1.21.2-rc2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From e370c98a3d17f9150ddbabaae9f6fcec8b4e7997 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 11:44:34 -0700 Subject: [PATCH 103/586] chore: update to 1.21.2 release Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 650da30265c..98a69614149 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.2-rc2 +minecraftVersion=1.21.2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From ebdd4c25fafd45854ab76447268859d9dd07f52c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 11:49:59 -0700 Subject: [PATCH 104/586] chore(ci): enable concurrent builds to continue even as others fail Occasionally we run into an update issue that some platforms aren't available yet. Signed-off-by: Gabriel Harris-Rouquette --- .github/workflows/common-run-build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index c3dbfe08a8d..2fa2d2e25b0 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -12,6 +12,7 @@ jobs: if: "${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}" runs-on: ubuntu-22.04 strategy: + fail-fast: false matrix: project: - vanilla From c5c0c6e25ea0c0923ff1edab53bdbd8cfca71e95 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 20:26:10 -0700 Subject: [PATCH 105/586] chore: update neo to 1.21.2 Signed-off-by: Gabriel Harris-Rouquette --- gradle/verification-metadata.xml | 80 +++++++++++++++++ neoforge/gradle.properties | 2 +- ...bstractFurnaceBlockEntityAccessor_Neo.java | 23 +++++ .../resources/mixins.spongeneo.accessors.json | 13 +-- .../spongepowered/neoforge/SpongeNeoMod.java | 4 +- .../server/level/ServerPlayerMixin_Neo.java | 1 + ...ServerGamePacketListenerImplMixin_Neo.java | 23 +++-- .../core/world/entity/EntityMixin_Neo.java | 29 +++++++ .../world/entity/LivingEntityMixin_Neo.java | 2 +- .../entity/animal/SnowGolemMixin_Neo.java | 23 +++++ ...in_Neo.java => AbstractBoatMixin_Neo.java} | 8 +- .../AbstractFurnaceBlockEntityMixin_Neo.java | 45 +++++++--- .../state/BlockBehaviorMixin_Neo_Tracker.java | 2 +- .../resources/mixins.spongeneo.core.json | 4 +- .../context/transaction/TransactionSink.java | 2 +- .../inventory/PlaceRecipeTransaction.java | 4 +- .../mixin/core/world/entity/EntityMixin.java | 12 --- .../world/entity/animal/SnowGolemMixin.java | 43 --------- src/mixins/resources/mixins.sponge.core.json | 1 - .../world/entity/EntityMixin_Vanilla.java | 20 +++++ .../entity/animal/SnowGolemMixin_Vanilla.java | 19 ++++ .../resources/mixins.spongevanilla.core.json | 87 ++++++++++--------- 22 files changed, 310 insertions(+), 137 deletions(-) create mode 100644 neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java rename neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/{BoatMixin_Neo.java => AbstractBoatMixin_Neo.java} (90%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 131ded4b65f..5d6ec566280 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -322,6 +322,9 @@ + + + @@ -349,6 +352,9 @@ + + + @@ -365,6 +371,9 @@ + + + @@ -1219,6 +1228,9 @@ + + + @@ -1293,6 +1305,9 @@ + + + @@ -1331,6 +1346,9 @@ + + + @@ -2211,6 +2229,14 @@ + + + + + + + + @@ -3530,6 +3556,14 @@ + + + + + + + + @@ -3578,6 +3612,14 @@ + + + + + + + + @@ -3611,6 +3653,20 @@ + + + + + + + + + + + + + + @@ -3619,6 +3675,14 @@ + + + + + + + + @@ -3643,6 +3707,14 @@ + + + + + + + + @@ -3651,6 +3723,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index bc3c1bdd502..5cd3f2b2b63 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.1.35 +neoForgeVersion=21.2.0-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file diff --git a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java new file mode 100644 index 00000000000..7930b01544b --- /dev/null +++ b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java @@ -0,0 +1,23 @@ +package org.spongepowered.neoforge.accessor.world.level.block.entity; + + +import net.minecraft.core.NonNullList; +import net.minecraft.core.RegistryAccess; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.SingleRecipeInput; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.common.UntransformedInvokerError; + +@Mixin(AbstractFurnaceBlockEntity.class) +public interface AbstractFurnaceBlockEntityAccessor_Neo { + + @Invoker("canBurn") + static boolean invoker$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { + throw new UntransformedInvokerError(); + } +} + diff --git a/neoforge/src/accessors/resources/mixins.spongeneo.accessors.json b/neoforge/src/accessors/resources/mixins.spongeneo.accessors.json index 92a1833be67..206c76d1fec 100644 --- a/neoforge/src/accessors/resources/mixins.spongeneo.accessors.json +++ b/neoforge/src/accessors/resources/mixins.spongeneo.accessors.json @@ -1,8 +1,9 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.neoforge.accessor", - "mixins": [ - "neoforge.registries.RegistrySnapshotAccessor_Neo" - ] + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.neoforge.accessor", + "mixins": [ + "neoforge.registries.RegistrySnapshotAccessor_Neo", + "world.level.block.entity.AbstractFurnaceBlockEntityAccessor_Neo" + ] } \ No newline at end of file diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java index d176a538dd7..d5280aa47e9 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java @@ -26,6 +26,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.neoforged.bus.api.IEventBus; @@ -139,7 +141,7 @@ public void onRegister(RegisterEvent event) { .sized(0.6F, 1.8F) .clientTrackingRange(org.spongepowered.common.util.Constants.Entity.Player.TRACKING_RANGE) .updateInterval(2) - .build("sponge:human"); + .build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.parse("sponge:human"))); event.register(Registries.ENTITY_TYPE, helper -> helper.register(HumanEntity.KEY, SpongeEntityTypes.HUMAN)); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java index a3e3bd1629e..4191e405300 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java @@ -26,6 +26,7 @@ import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java index a3eeb6fa173..ef2000360bf 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java @@ -25,6 +25,8 @@ package org.spongepowered.neoforge.mixin.core.server.network; import net.minecraft.network.protocol.game.ServerGamePacketListener; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.RecipeHolder; @@ -33,6 +35,7 @@ import org.spongepowered.api.item.inventory.crafting.CraftingInventory; import org.spongepowered.api.item.inventory.query.QueryTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; @@ -44,23 +47,29 @@ @Mixin(ServerGamePacketListenerImpl.class) public abstract class ServerGamePacketListenerImplMixin_Neo implements ServerGamePacketListener { - @SuppressWarnings({"unchecked", "rawtypes"}) - @Redirect(method = "lambda$handlePlaceRecipe$10", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerPlayer;)V")) - private void neo$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final RecipeHolder recipe, final net.minecraft.server.level.ServerPlayer player) { + @Shadow public ServerPlayer player; + + @Redirect(method = "handlePlaceRecipe", + at = @At(value = "INVOKE", target = "net/minecraft/world/inventory/RecipeBookMenu.handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) + private RecipeBookMenu.PostPlaceAction neo$onPlaceRecipe( + final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, + final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); + final var player = this.player; final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); + final RecipeBookMenu.PostPlaceAction result; if (!(craftInv instanceof CraftingInventory)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); SpongeCommon.logger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire."); - return; + return result; } try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, recipe, player, (CraftingInventory) craftInv)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); player.containerMenu.broadcastChanges(); } + return result; } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java new file mode 100644 index 00000000000..d70fe4738ad --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java @@ -0,0 +1,29 @@ +package org.spongepowered.neoforge.mixin.core.world.entity; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageSources; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LightningBolt; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Entity.class) +public class EntityMixin_Neo { + + @Redirect(method = "thunderHit", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/damagesource/DamageSources;lightningBolt()Lnet/minecraft/world/damagesource/DamageSource;")) + private DamageSource vanilla$ThrowDamageEventWithLightingSource(final DamageSources sources, + final ServerLevel level, final LightningBolt lightningBolt + ) { + final var originalLightning = sources.lightningBolt(); + final var entitySource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() + .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) originalLightning) + .entity((org.spongepowered.api.entity.Entity) lightningBolt) + .build(); + return (DamageSource) (Object) entitySource; + } + +} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java index cd25627c003..f0ab5d9c54c 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java @@ -37,7 +37,7 @@ public abstract class LivingEntityMixin_Neo { method = "updateFallFlying", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;elytraFlightTick(Lnet/minecraft/world/entity/LivingEntity;I)Z", + target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", shift = At.Shift.AFTER ) ) diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java new file mode 100644 index 00000000000..0246eff009a --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java @@ -0,0 +1,23 @@ +package org.spongepowered.neoforge.mixin.core.world.entity.animal; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.animal.SnowGolem; +import net.neoforged.neoforge.event.EventHooks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.world.entity.GrieferBridge; + +@Mixin(SnowGolem.class) +public abstract class SnowGolemMixin_Neo { + + @Redirect(method = "aiStep()V", at = @At( + value = "INVOKE", target = "Lnet/neoforged/neoforge/event/EventHooks;canEntityGrief(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;)Z")) + private boolean impl$checkCanGrief(ServerLevel level, Entity entity) { + if (!((GrieferBridge) this).bridge$canGrief()) { + return false; + } + return EventHooks.canEntityGrief(level, entity); + } +} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/BoatMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java similarity index 90% rename from neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/BoatMixin_Neo.java rename to neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java index 542343f5564..0be84dc6caf 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/BoatMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java @@ -26,17 +26,17 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; -@Mixin(Boat.class) -public abstract class BoatMixin_Neo implements BoatBridge { +@Mixin(AbstractBoat.class) +public abstract class AbstractBoatMixin_Neo implements AbstractBoatBridge { @Redirect(method = "getGroundFriction", at = @At( value = "INVOKE", diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index b2f8d270b99..f2fb8c24da7 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -27,9 +27,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -56,6 +59,7 @@ import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.mixin.core.world.level.block.entity.BaseContainerBlockEntityMixin; +import org.spongepowered.neoforge.accessor.world.level.block.entity.AbstractFurnaceBlockEntityAccessor_Neo; import java.util.ArrayList; import java.util.Collections; @@ -68,9 +72,6 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // @formatter:off @Shadow protected NonNullList items; @Shadow int cookingProgress; - @Shadow private static boolean shadow$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final AbstractFurnaceBlockEntity furnace) { - throw new UnsupportedOperationException("Shadowed canBurn"); - } // @formatter:on private boolean neo$filledWaterBucket; @@ -78,10 +79,14 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // Tick up and Start @Redirect(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;ILnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)Z", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", ordinal = 1)) - private static boolean neo$checkIfCanSmelt(final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final AbstractFurnaceBlockEntity entityIn) { - if (!AbstractFurnaceBlockEntityMixin_Neo.shadow$canBurn(registryAccess, recipe, slots, maxStackSize, entityIn)) { + private static boolean neo$checkIfCanSmelt( + final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final SingleRecipeInput input, + final NonNullList slots, final int maxStackSize, final ServerLevel level, final BlockPos entityPos, + final BlockState state, final AbstractFurnaceBlockEntity entityIn + ) { + if (!AbstractFurnaceBlockEntityAccessor_Neo.invoker$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { return false; } @@ -105,8 +110,11 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) - private static int neo$resetCookTimeIfCancelled(final int newCookTime, final int zero, final int totalCookTime, - final Level level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { + private static int neo$resetCookTimeIfCancelled( + final int newCookTime, final int zero, final int totalCookTime, + final ServerLevel level, final BlockPos entityPos, final BlockState state, + final AbstractFurnaceBlockEntity entityIn + ) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Neo) (Object) entityIn; final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); @@ -128,18 +136,29 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB slice = @Slice( from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) )) - private static void neo$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final AbstractFurnaceBlockEntity entityIn, final CallbackInfoReturnable cir) { - ((AbstractFurnaceBlockEntityMixin_Neo) (Object) entityIn).neo$filledWaterBucket = true; + private static void neo$captureBucketFill( + final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput arg3, + final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir + ) { + final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); + final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) + .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); + ((AbstractFurnaceBlockEntityMixin_Neo) entity).neo$filledWaterBucket = true; } @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", shift = At.Shift.AFTER)) - private static void neo$afterSmeltItem(final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final AbstractFurnaceBlockEntity entityIn, final CallbackInfoReturnable cir) { + private static void neo$afterSmeltItem( + final RegistryAccess registryAccess, final RecipeHolder recipe, + final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, + final CallbackInfoReturnable cir + ) { final ItemStack itemIn = slots.get(0); - final ItemStack recipeResult = recipe.value().getResultItem(registryAccess); + final ItemStack recipeResult = recipe.value().assemble(input, registryAccess); final ItemStack itemOut = slots.get(2); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); - final FurnaceBlockEntity entity = (FurnaceBlockEntity) entityIn; + final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) + .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); final List transactions = new ArrayList<>(); itemIn.grow(1); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java index 16ed44d3f87..7f7eaf032b2 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java @@ -42,7 +42,7 @@ public abstract class BlockBehaviorMixin_Neo_Tracker { method = "getLootTable", at = @At( value = "FIELD", - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;lootTableSupplier:Ljava/util/function/Supplier;", + target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;drops:Ljava/util/Optional;", remap = false ) ) diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index 0bef1de107f..40f3495d5e5 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -23,12 +23,14 @@ "server.level.ServerEntityMixin_Neo", "server.level.ServerPlayerMixin_Neo", "server.network.ServerGamePacketListenerImplMixin_Neo", + "world.entity.EntityMixin_Neo", "world.entity.LivingEntityMixin_Neo", "world.entity.LivingEntityMixin_Neo_Attack_Impl", + "world.entity.animal.SnowGolemMixin_Neo", "world.entity.item.ItemEntityMixin_Neo", "world.entity.player.PlayerMixin_Neo_Attack_Impl", "world.entity.projectile.FishingHookMixin_Neo", - "world.entity.vehicle.BoatMixin_Neo", + "world.entity.vehicle.AbstractBoatMixin_Neo", "world.level.block.FireBlockMixin_Neo", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" ], diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index da8863ac6b2..c84d43fc6d4 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -379,7 +379,7 @@ default EffectTransactor logCloseInventory(final Player player, final boolean cl return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); } - default EffectTransactor logPlaceRecipe(final boolean shift, final RecipeHolder> recipe, final ServerPlayer player, final CraftingInventory craftInv) { + default EffectTransactor logPlaceRecipe(final boolean shift, final RecipeHolder recipe, final ServerPlayer player, final CraftingInventory craftInv) { final PlaceRecipeTransaction transaction = new PlaceRecipeTransaction(player, shift, recipe, craftInv); this.logTransaction(transaction); return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java index ab486784a6c..99f9aa3d22d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java @@ -53,10 +53,10 @@ public class PlaceRecipeTransaction extends ContainerBasedTransaction { private final ServerPlayer player; private final ItemStackSnapshot originalCursor; private boolean shift; - private RecipeHolder> recipe; + private RecipeHolder recipe; private CraftingInventory craftingInventory; - public PlaceRecipeTransaction(final ServerPlayer player, final boolean shift, final RecipeHolder> recipe, CraftingInventory craftingInventory) { + public PlaceRecipeTransaction(final ServerPlayer player, final boolean shift, final RecipeHolder recipe, CraftingInventory craftingInventory) { super(player.containerMenu); this.player = player; this.originalCursor = ItemStackUtil.snapshotOf(player.containerMenu.getCarried()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 971e4b85784..6464acc9c2c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -934,18 +934,6 @@ public void stopRiding() { return !this.impl$transient; } - - @Redirect(method = "thunderHit", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - private boolean impl$ThrowDamageEventWithLightingSource( - final Entity entity, final ServerLevel serverLevel, final DamageSource source, final float damage, - final ServerLevel level, final LightningBolt lightningBolt - ) { - var entitySource = new DamageSource(source.typeHolder(), lightningBolt); - return entity.hurtServer(serverLevel, entitySource, damage); - } - @Inject(method = "getFireImmuneTicks", at = @At(value = "HEAD"), cancellable = true) private void impl$getFireImmuneTicks(final CallbackInfoReturnable ci) { if (this.impl$hasCustomFireImmuneTicks) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java deleted file mode 100644 index 2cd0432ea5e..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/SnowGolemMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.entity.animal; - -import net.minecraft.world.entity.animal.SnowGolem; -import net.minecraft.world.level.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.entity.GrieferBridge; -import org.spongepowered.common.mixin.core.world.entity.MobMixin; - -@Mixin(SnowGolem.class) -public abstract class SnowGolemMixin extends MobMixin { - - @Redirect(method = "aiStep()V", at = @At( - value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z")) - private boolean impl$checkCanGrief(final GameRules gameRules, final GameRules.Key key) { - return gameRules.getBoolean(key) && ((GrieferBridge) this).bridge$canGrief(); - } -} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 8c102eed091..97fef9308ee 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -140,7 +140,6 @@ "world.entity.animal.OcelotMixin", "world.entity.animal.ParrotMixin", "world.entity.animal.Rabbit_RaidGardenGoalMixin", - "world.entity.animal.SnowGolemMixin", "world.entity.animal.WolfMixin", "world.entity.animal.horse.AbstractHorseMixin", "world.entity.boss.enderdragon.EndCrystalMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityMixin_Vanilla.java index 2b76a635ef3..5631ca6b23e 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityMixin_Vanilla.java @@ -24,10 +24,16 @@ */ package org.spongepowered.vanilla.mixin.core.world.entity; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.world.entity.EntityBridge; @Mixin(Entity.class) @@ -37,4 +43,18 @@ public abstract class EntityMixin_Vanilla implements EntityBridge { @Shadow public abstract Level shadow$level(); // @formatter:on + @Redirect(method = "thunderHit", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/damagesource/DamageSources;lightningBolt()Lnet/minecraft/world/damagesource/DamageSource;")) + private DamageSource vanilla$ThrowDamageEventWithLightingSource(final DamageSources sources, + final ServerLevel level, final LightningBolt lightningBolt + ) { + final var originalLightning = sources.lightningBolt(); + final var entitySource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() + .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) originalLightning) + .entity((org.spongepowered.api.entity.Entity) lightningBolt) + .build(); + return (DamageSource) (Object) entitySource; + } + } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java new file mode 100644 index 00000000000..1c88bc99c25 --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java @@ -0,0 +1,19 @@ +package org.spongepowered.vanilla.mixin.core.world.entity.animal; + + +import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.level.GameRules; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.world.entity.GrieferBridge; + +@Mixin(SnowGolem.class) +public abstract class SnowGolemMixin_Vanilla { + + @Redirect(method = "aiStep()V", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z")) + private boolean impl$checkCanGrief(final GameRules gameRules, final GameRules.Key key) { + return gameRules.getBoolean(key) && ((GrieferBridge) this).bridge$canGrief(); + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index d59b474243c..dd3af254426 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -1,45 +1,46 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.vanilla.mixin.core", - "priority": 1301, - "client": [ - "client.ClientBrandRetrieverMixin_Vanilla", - "client.MinecraftMixin_Vanilla", - "client.gui.screens.TitleScreenMixin_Vanilla", - "client.renderer.entity.EntityRenderDispatcherMixin_Vanilla", - "client.server.IntegratedServerMixin_Vanilla" - ], - "server": [ - "server.dedicated.DedicatedServer_1_Mixin_Vanilla", - "server.dedicated.DedicatedServerMixin_Vanilla" - ], - "mixins": [ - "CrashReportMixin_Vanilla", - "brigadier.exceptions.CommandSyntaxExceptionMixin_Vanilla", - "commands.CommandsMixin_Vanilla", - "network.ConnectionMixin_Vanilla", - "network.protocol.common.ClientboundCustomPayloadPacketMixin_Vanilla", - "network.protocol.common.ServerboundCustomPayloadPacketMixin_Vanilla", - "server.BootstrapMixin_Vanilla", - "server.MinecraftServerMixin_Vanilla", - "server.commands.SpreadPlayersCommandMixin_Vanilla", - "server.level.ServerPlayerMixin_Vanilla", - "server.network.ServerGamePacketListenerImplMixin_Vanilla", - "server.packs.repository.PackRepositoryMixin_Vanilla", - "world.entity.EntityMixin_Vanilla", - "world.entity.EntityTypeMixin_Vanilla", - "world.entity.LivingEntityMixin_Attack_Impl", - "world.entity.LivingEntityMixin_Vanilla", - "world.entity.ai.attributes.DefaultAttributesMixin", - "world.entity.item.ItemEntityMixin_Vanilla", - "world.entity.player.PlayerMixin_Vanilla_Attack_Impl", - "world.entity.vehicle.AbstractBoatMixin_Vanilla", - "world.level.block.FireBlockMixin_Vanilla", - "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", - "world.level.storage.LevelStorageSourceMixin_Vanilla" - ], - "overwrites": { - "conformVisibility": true - } + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.vanilla.mixin.core", + "priority": 1301, + "client": [ + "client.ClientBrandRetrieverMixin_Vanilla", + "client.MinecraftMixin_Vanilla", + "client.gui.screens.TitleScreenMixin_Vanilla", + "client.renderer.entity.EntityRenderDispatcherMixin_Vanilla", + "client.server.IntegratedServerMixin_Vanilla" + ], + "server": [ + "server.dedicated.DedicatedServer_1_Mixin_Vanilla", + "server.dedicated.DedicatedServerMixin_Vanilla" + ], + "mixins": [ + "CrashReportMixin_Vanilla", + "brigadier.exceptions.CommandSyntaxExceptionMixin_Vanilla", + "commands.CommandsMixin_Vanilla", + "network.ConnectionMixin_Vanilla", + "network.protocol.common.ClientboundCustomPayloadPacketMixin_Vanilla", + "network.protocol.common.ServerboundCustomPayloadPacketMixin_Vanilla", + "server.BootstrapMixin_Vanilla", + "server.MinecraftServerMixin_Vanilla", + "server.commands.SpreadPlayersCommandMixin_Vanilla", + "server.level.ServerPlayerMixin_Vanilla", + "server.network.ServerGamePacketListenerImplMixin_Vanilla", + "server.packs.repository.PackRepositoryMixin_Vanilla", + "world.entity.EntityMixin_Vanilla", + "world.entity.EntityTypeMixin_Vanilla", + "world.entity.LivingEntityMixin_Attack_Impl", + "world.entity.LivingEntityMixin_Vanilla", + "world.entity.ai.attributes.DefaultAttributesMixin", + "world.entity.animal.SnowGolemMixin_Vanilla", + "world.entity.item.ItemEntityMixin_Vanilla", + "world.entity.player.PlayerMixin_Vanilla_Attack_Impl", + "world.entity.vehicle.AbstractBoatMixin_Vanilla", + "world.level.block.FireBlockMixin_Vanilla", + "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", + "world.level.storage.LevelStorageSourceMixin_Vanilla" + ], + "overwrites": { + "conformVisibility": true + } } \ No newline at end of file From b7be0b9b632a4708bb91192f3a73d462b0c3167d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 20:27:24 -0700 Subject: [PATCH 106/586] chore: disable forge until 1.21.2 update is ready SpongeVanilla and SpongeNeo should be available --- .github/workflows/common-run-build.yaml | 6 +++--- .github/workflows/deploy.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 2fa2d2e25b0..1489e320505 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -16,13 +16,13 @@ jobs: matrix: project: - vanilla - - forge +# - forge - neoforge include: - project: vanilla gradleProject: SpongeVanilla - - project: forge - gradleProject: SpongeForge +# - project: forge +# gradleProject: SpongeForge - project: neoforge gradleProject: SpongeNeo steps: diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 82311bfe60c..19e1759793d 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -29,13 +29,13 @@ jobs: matrix: project: - vanilla - - forge +# - forge - neoforge include: - project: vanilla gradleProject: SpongeVanilla - - project: forge - gradleProject: SpongeForge +# - project: forge +# gradleProject: SpongeForge - project: neoforge gradleProject: SpongeNeo steps: From f1f9b7943eb62eb293498fc562672639893650c7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 20:32:01 -0700 Subject: [PATCH 107/586] chore: fix licenses --- ...bstractFurnaceBlockEntityAccessor_Neo.java | 25 ++++++++++++++++++- .../server/level/ServerPlayerMixin_Neo.java | 1 - .../core/world/entity/EntityMixin_Neo.java | 24 ++++++++++++++++++ .../entity/animal/SnowGolemMixin_Neo.java | 24 ++++++++++++++++++ .../AbstractFurnaceBlockEntityMixin_Neo.java | 1 - .../context/transaction/TransactionSink.java | 1 - .../inventory/PlaceRecipeTransaction.java | 1 - .../mixin/core/world/entity/EntityMixin.java | 1 - .../entity/animal/SnowGolemMixin_Vanilla.java | 24 ++++++++++++++++++ 9 files changed, 96 insertions(+), 6 deletions(-) diff --git a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java index 7930b01544b..72cf95cded1 100644 --- a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java +++ b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.neoforge.accessor.world.level.block.entity; @@ -20,4 +44,3 @@ public interface AbstractFurnaceBlockEntityAccessor_Neo { throw new UntransformedInvokerError(); } } - diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java index 4191e405300..a3e3bd1629e 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java @@ -26,7 +26,6 @@ import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java index d70fe4738ad..4db1c7d6257 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/EntityMixin_Neo.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.neoforge.mixin.core.world.entity; import net.minecraft.server.level.ServerLevel; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java index 0246eff009a..564bae8e0e1 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.neoforge.mixin.core.world.entity.animal; import net.minecraft.server.level.ServerLevel; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index f2fb8c24da7..13e9b1fcd28 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -33,7 +33,6 @@ import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index c84d43fc6d4..3d16c60548f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -35,7 +35,6 @@ import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java index 99f9aa3d22d..569eac4d821 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java @@ -26,7 +26,6 @@ import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 6464acc9c2c..2e6241aa51b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -46,7 +46,6 @@ import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java index 1c88bc99c25..4e290a570d6 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.vanilla.mixin.core.world.entity.animal; From db09b6932022954b6ffb3e842dcb9444f2338bf4 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 20:41:56 -0700 Subject: [PATCH 108/586] chore(neo): fix accesswideners --- src/main/resources/common.accesswidener | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index c370b151d43..216dbb883d7 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -10,11 +10,10 @@ accessible class net/minecraft/world/entity/animal/TropicalFish$Pattern accessible class net/minecraft/world/entity/raid/Raid$RaidStatus accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State extendable method net/minecraft/server/players/IpBanList getIpFromAddress (Ljava/net/SocketAddress;)Ljava/lang/String; -accessible class net/minecraft/server/commands/TeleportCommand$LookAt extendable class net/minecraft/world/item/crafting/Ingredient extendable method net/minecraft/world/item/crafting/Ingredient (Lnet/minecraft/core/HolderSet;)V accessible field net/minecraft/world/item/crafting/Ingredient values Lnet/minecraft/core/HolderSet; -accessible method net/minecraft/world/level/biome/Biome getTemperature (Lnet/minecraft/core/BlockPos;)F +accessible method net/minecraft/world/level/biome/Biome getTemperature (Lnet/minecraft/core/BlockPos;I)F accessible class net/minecraft/server/level/ServerLevel$EntityCallbacks accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$Action accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$ActionType From d838daff1c7f89dd92203dd8b19eb13bc217803c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 22 Oct 2024 20:49:46 -0700 Subject: [PATCH 109/586] chore(ci): persist matrix project artifacts separately --- .github/workflows/common-run-build.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 1489e320505..52f9e692f81 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -58,13 +58,11 @@ jobs: if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 with: - name: Sponge Jars + name: Sponge ${{ matrix.project }} Jars path: | ${{ github.workspace }}/SpongeAPI/build/libs/*.jar ${{ github.workspace }}/build/libs/*.jar - ${{ github.workspace }}/vanilla/build/libs/*.jar - ${{ github.workspace }}/forge/build/libs/*.jar - ${{ github.workspace }}/neoforge/build/libs/*.jar + ${{ github.workspace }}/${{ matrix.project }}/build/libs/*.jar - name: ${{ matrix.gradleProject }} Production Jar if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" uses: "actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3" # v4.3.1 From 0d3b9ee9ee1a4454f550648ff321f1436eb4e707 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 24 Oct 2024 00:45:55 -0700 Subject: [PATCH 110/586] chore: update to 1.21.3 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- gradle/verification-metadata.xml | 30 ++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 98a69614149..eb71a3a0c71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.2 +minecraftVersion=1.21.3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5d6ec566280..85dd6ac66e6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2237,6 +2237,14 @@ + + + + + + + + @@ -3667,6 +3675,20 @@ + + + + + + + + + + + + + + @@ -3683,6 +3705,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 5cd3f2b2b63..42d6f02f9fc 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.2.0-beta +neoForgeVersion=21.3.0-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file From 55579e64bbab56f1af16d395b63feb800c2e1600 Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 25 Oct 2024 18:48:56 +0300 Subject: [PATCH 111/586] Change WorldManager#worldDirectory to always return valid location --- SpongeAPI | 2 +- .../common/world/server/SpongeWorldManager.java | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 5afbdb156d8..bde75c74b7f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 5afbdb156d848df52c0363ed39a4e68ac540bdaa +Subproject commit bde75c74b7fd037468f173fbec0715ed355b6806 diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 2ded515fb9b..5e3588b38ef 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -163,14 +163,9 @@ public Optional world(final ResourceKey key) { } @Override - public Optional worldDirectory(final ResourceKey key) { + public Path worldDirectory(final ResourceKey key) { Objects.requireNonNull(key, "key"); - - Path directory = this.getDirectory(key); - if (Files.notExists(directory)) { - return Optional.empty(); - } - return Optional.of(directory); + return this.getDirectory(key); } @Override From cf689beaca9bb217815b884afe0ebc944a14752c Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 6 Nov 2024 23:41:59 +0200 Subject: [PATCH 112/586] spotlessApply --- .../src/main/java/org/spongepowered/test/data/DataTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index ffa12e744e0..76aa88949ef 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -46,7 +46,6 @@ import org.spongepowered.api.data.Key; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.meta.BannerPatternLayer; -import org.spongepowered.api.data.type.ArmorMaterials; import org.spongepowered.api.data.type.AttachmentSurfaces; import org.spongepowered.api.data.type.BannerPatternShapes; import org.spongepowered.api.data.type.BoatTypes; From 8e39e2bfcdddfbfc31c511db6a41c11192e1d240 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 6 Nov 2024 23:46:20 +0200 Subject: [PATCH 113/586] Fix recipe events --- .../transaction/inventory/ContainerBasedTransaction.java | 4 ++-- .../transaction/inventory/CraftingPreviewTransaction.java | 2 +- .../transaction/inventory/PlaceRecipeTransaction.java | 4 ++-- .../block/entity/AbstractFurnaceBlockEntityMixin.java | 4 ++-- .../level/block/entity/CampfireBlockEntityMixin.java | 4 ++-- .../entity/AbstractFurnaceBlockEntityMixin_Vanilla.java | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java index 3bd55e1b709..2a41a47fa14 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java @@ -273,7 +273,7 @@ private void handleCrafting(final Player player, final ClickContainerEvent event SpongeEventFactory.createCraftItemEventCraft(PhaseTracker.getCauseStackManager().currentCause(), ContainerUtil.fromNative(this.menu), craftedItem, this.craftingInventory, event.cursorTransaction(), Optional.ofNullable(this.onTakeRecipe).map(r -> (CraftingRecipe) r.value()), - Optional.ofNullable(this.onTakeRecipe).map(r -> (ResourceKey) (Object) r.id()), + Optional.ofNullable(this.onTakeRecipe).map(r -> (ResourceKey) (Object) r.id().location()), Optional.of(this.craftingInventory.result()), event.transactions()); SpongeCommon.post(craftEvent); this.handleEventResults(player, craftEvent); @@ -290,7 +290,7 @@ private void handleCraftingPreview(final Player player, final ClickContainerEven final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), event.transactions()); final var recipe = sp.serverLevel().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); final CraftItemEvent.Preview previewEvent = SpongeEventFactory.createCraftItemEventPreview(event.cause(), (Container) this.menu, this.craftingInventory, event.cursorTransaction(), previewTransaction, - recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(h -> h.id()).map(ResourceKey.class::cast), Optional.empty(), event.transactions()); + recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), event.transactions()); SpongeCommon.post(previewEvent); this.handleEventResults(player, previewEvent); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java index 80a4fc5c600..f244054dca7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java @@ -80,7 +80,7 @@ Optional createInventoryEvent(final List s final CraftItemEvent.Preview event = SpongeEventFactory.createCraftItemEventPreview(currentCause, ContainerUtil.fromNative(this.menu), this.craftingInventory, new Transaction<>(cursor, cursor), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), - recipe.map(RecipeHolder::id).map(ResourceKey.class::cast), + recipe.map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), slotTransactions); return Optional.of(event); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java index 569eac4d821..58be64b551a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java @@ -77,13 +77,13 @@ Optional createInventoryEvent( event = SpongeEventFactory.createClickContainerEventRecipeAll(cause, (Container) this.menu, this.craftingInventory, cursorTransaction, preview, Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(RecipeHolder::id).map(ResourceKey.class::cast), + Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), slotTransactions); } else { event = SpongeEventFactory.createClickContainerEventRecipeSingle(cause, (Container) this.menu, this.craftingInventory, cursorTransaction, preview, Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(RecipeHolder::id).map(ResourceKey.class::cast), + Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), slotTransactions); } return Optional.of(event); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 0312655e337..37dbda079b0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -85,7 +85,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock final SlotTransaction transaction = new SlotTransaction(((FurnaceBlockEntity) entity).inventory().slot(1).get(), fuel, shrinkedFuel); final var recipe = ((AbstractFurnaceBlockEntityMixin) (Object) entity).bridge$getCurrentRecipe(); final CookingEvent.ConsumeFuel event = SpongeEventFactory.createCookingEventConsumeFuel(cause, (FurnaceBlockEntity) entity, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id()), Collections.singletonList(transaction)); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location()), Collections.singletonList(transaction)); SpongeCommon.post(event); if (event.isCancelled()) { ((AbstractFurnaceBlockEntityMixin) (Object) entity).cookingTotalTime = 0; @@ -154,7 +154,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); final var recipe = this.bridge$getCurrentRecipe(); final CookingEvent.Interrupt event = SpongeEventFactory.createCookingEventInterrupt(cause, (FurnaceBlockEntity) this, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java index 54891998d30..35e60c55eea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java @@ -89,7 +89,7 @@ public abstract class CampfireBlockEntityMixin { final ItemStackSnapshot stack = ItemStackUtil.snapshotOf(mixinSelf.items.get(i)); final RecipeHolder recipe = mixinSelf.impl$cookingRecipe[i]; final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (Campfire) self, stack, Optional.empty(), - Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id())); + Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); if (event.isCancelled()) { mixinSelf.cookingProgress[i]--; @@ -109,7 +109,7 @@ public abstract class CampfireBlockEntityMixin { final SlotTransaction transaction = new SlotTransaction(((Campfire) self).inventory().slot(i).get(), ItemStackUtil.snapshotOf(itemStack1), ItemStackSnapshot.empty()); final RecipeHolder recipe = mixinSelf.impl$cookingRecipe[i]; final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, (Campfire) self, - Optional.empty(), Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id()), + Optional.empty(), Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().location()), Collections.singletonList(transaction)); SpongeCommon.post(event); mixinSelf.impl$cookingRecipe[i] = null; diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 675a242248b..24ac7f4ffd7 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -94,13 +94,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); if (entity.cookingProgress == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -119,7 +119,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingProgress; // dont tick down @@ -179,7 +179,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { From 1b07a5eff7b607f0b3e7bfee0de6e6545f6c6492 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 6 Nov 2024 23:54:41 +0200 Subject: [PATCH 114/586] Adjust PhaseTracker to support multithreaded levels --- .../common/block/SpongeBlockSnapshot.java | 2 +- .../network/chat/SpongeChatDecorator.java | 2 +- .../GenericMutableDataProviderBase.java | 3 +- .../inventory/InventoryEventFactory.java | 13 +- .../common/event/tracking/PhaseContext.java | 9 +- .../common/event/tracking/PhaseTracker.java | 55 +++++++-- .../event/tracking/PooledPhaseState.java | 8 +- .../common/event/tracking/TrackingUtil.java | 48 ++++---- .../phase/packet/PacketPhaseUtil.java | 8 +- .../common/hooks/GeneralHooks.java | 3 +- .../common/scheduler/ServerScheduler.java | 2 +- .../archetype/SpongeArchetypeVolume.java | 3 +- .../world/entity/EntityMixin_API.java | 3 +- .../world/level/LevelAccessorMixin_API.java | 2 +- .../mixin/core/client/MinecraftMixin.java | 2 +- .../core/server/MinecraftServerMixin.java | 2 +- .../core/server/level/ServerLevelMixin.java | 7 +- .../core/server/level/ServerPlayerMixin.java | 9 +- .../core/server/players/PlayerListMixin.java | 7 +- .../mixin/core/world/entity/EntityMixin.java | 14 ++- .../core/world/entity/LivingEntityMixin.java | 9 +- .../entity/LivingEntityMixin_Attack_Impl.java | 2 +- .../entity/decoration/ArmorStandMixin.java | 2 +- .../world/entity/item/ItemEntityMixin.java | 2 +- .../player/PlayerMixin_Attack_Impl.java | 2 +- .../projectile/ProjectileUtilMixin.java | 3 +- .../PersistentEntitySectionManagerMixin.java | 3 +- .../ServerPlayerMixin_Inventory_API.java | 2 +- .../level/ServerPlayerMixin_Inventory.java | 20 ++-- .../ServerPlayerMixin_Shared_Inventory.java | 13 +- ...GamePacketListenerImplMixin_Inventory.java | 16 +-- .../AbstractContainerMenuMixin_Inventory.java | 22 ++-- .../inventory/AnvilMenuMixin_Inventory.java | 2 +- .../CraftingMenuMixin_Inventory.java | 2 +- .../inventory/ResultSlotMixin_Inventory.java | 2 +- .../world/inventory/SlotMixin_Inventory.java | 5 +- .../HopperBlockEntityMixin_Inventory.java | 4 +- .../server/MinecraftServerMixin_Tracker.java | 10 +- .../server/level/ChunkMapMixin_Tracker.java | 7 +- .../level/ChunkStatusTasksMixin_Tracker.java | 14 ++- .../level/ServerChunkCacheMixin_Tracker.java | 4 +- .../level/ServerLevelMixin_Tracker.java | 41 ++++--- .../ServerPlayerGameModeMixin_Tracker.java | 8 +- ...erGamePacketListenerImplMixin_Tracker.java | 2 +- .../players/PlayerListMixin_Tracker.java | 6 +- .../world/entity/EntityMixin_Tracker.java | 12 +- .../entity/LivingEntityMixin_Tracker.java | 15 +-- .../world/item/BoneMealItemMixin_Tracker.java | 5 +- .../world/item/ItemStackMixin_Tracker.java | 3 +- .../world/level/block/BlockMixin_Tracker.java | 111 +++++++++++++----- .../block/DispenserBlockMixin_Tracker.java | 2 +- .../level/block/LeavesBlockMixin_Tracker.java | 2 +- .../block/SaplingBlockMixin_Tracker.java | 7 +- .../level/chunk/LevelChunkMixin_Tracker.java | 12 +- .../end/EndDragonFightMixin_Tracker.java | 9 +- .../NeighborUpdaterMixin_Tracker.java | 2 +- .../world/ticks/LevelTicksMixin_Tracker.java | 2 +- .../level/ServerPlayerMixin_Vanilla.java | 8 +- ...erGamePacketListenerImplMixin_Vanilla.java | 2 +- ...erPlayerGameModeMixin_Vanilla_Tracker.java | 3 +- 60 files changed, 379 insertions(+), 221 deletions(-) diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index 5fd5dee4143..b508e0bab40 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -177,7 +177,7 @@ public boolean restore(final boolean force, final BlockChangeFlag flag) { final ServerLevel world = optionalWorld.get(); // We need to deterministically define the context as nullable if we don't need to enter. // this way we guarantee an exit. - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(world))) { context.buildAndSwitch(); final BlockPos pos = VecHelper.toBlockPos(this.pos); if (!world.isInWorldBounds(pos)) { // Invalid position. Inline this check diff --git a/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java b/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java index 4fc27bc7dfe..ead45659749 100644 --- a/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java +++ b/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java @@ -42,7 +42,7 @@ public class SpongeChatDecorator implements ChatDecorator { @Override public Component decorate(@Nullable final ServerPlayer player, final Component message) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getServerInstanceExplicitly().pushCauseFrame()) { if (player != null) { frame.pushCause(player); } diff --git a/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java b/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java index e6b66c94410..0056806ef64 100644 --- a/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java +++ b/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider; import io.leangen.geantyref.GenericTypeReflector; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.entity.EntityInLevelCallback; import org.spongepowered.api.data.DataHolder; import org.spongepowered.api.data.DataTransactionResult; @@ -260,7 +261,7 @@ private Optional> callReplacementEvent( .result(DataTransactionResult.Type.SUCCESS); originalValue.ifPresent(transaction::replace); final ChangeDataHolderEvent.ValueChange valueChange = SpongeEventFactory.createChangeDataHolderEventValueChange( - PhaseTracker.SERVER.currentCause(), + PhaseTracker.getWorldInstance((ServerLevel) entity.world()).currentCause(), transaction.build(), dataHolder); if (SpongeCommon.post(valueChange)) { diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index 8bbf9b9fd43..0abee380cbd 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.event.inventory; import net.kyori.adventure.text.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; @@ -91,9 +92,10 @@ public class InventoryEventFactory { public static boolean callPlayerInventoryPickupEvent(final Player player, final ItemEntity itemToPickup) { final ItemStack stack = itemToPickup.getItem(); final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) player.level()); final ChangeInventoryEvent.Pickup.Pre event = SpongeEventFactory.createChangeInventoryEventPickupPre( - PhaseTracker.getCauseStackManager().currentCause(), + phaseTracker.currentCause(), Optional.empty(), Collections.singletonList(snapshot), ((Inventory) player.containerMenu), (Item) itemToPickup, snapshot); SpongeCommon.post(event); if (event.isCancelled()) { @@ -106,7 +108,7 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final return true; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.PICKUP)) { for (final ItemStackSnapshot item : list) { @@ -126,7 +128,7 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final stack.setCount(0); return true; } else { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final boolean added; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.PICKUP)) { @@ -141,7 +143,8 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final } public static ItemStack callHopperInventoryPickupEvent(final Container inventory, final ItemEntity item, final ItemStack stack) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) item.level()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(inventory); final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); @@ -227,7 +230,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(player.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(ItemStackSnapshot.empty(), newCursor); final InteractContainerEvent.Open event = - SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getCauseStackManager().currentCause(), + SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getWorldInstance(player.serverLevel()).currentCause(), (org.spongepowered.api.item.inventory.Container) player.containerMenu, cursorTransaction); SpongeCommon.post(event); if (event.isCancelled()) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java index 02aa5b19a3a..e655e457281 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java @@ -160,7 +160,7 @@ public P buildAndSwitch() { if (SpongeConfigs.getCommon().get().phaseTracker.generateStackTracePerPhase) { this.stackTrace = new Exception("Debug Trace").getStackTrace(); } - PhaseTracker.getInstance().switchToPhase(this.state, this); + this.createdTracker.switchToPhase(this.state, this); return (P) this; } @@ -321,16 +321,15 @@ public void close() { // Should never throw an exception this.state, this, new IllegalStateException("Closing empty phase context")); return; } - final PhaseTracker instance = PhaseTracker.getInstance(); - instance.completePhase(this); + this.createdTracker.completePhase(this); if (this.usedFrame != null) { - this.usedFrame.iterator().forEachRemaining(instance::popCauseFrame); + this.usedFrame.iterator().forEachRemaining(this.createdTracker::popCauseFrame); this.usedFrame = null; } else if (this.shouldProvideModifiers()) { // So, this part is interesting... Since the used frame is null, that means // the cause stack manager still has the reference of this context/phase, we have // to "pop off" the list. - instance.popFrameMutator(this); + this.createdTracker.popFrameMutator(this); } this.reset(); this.isCompleted = false; diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index b5258e55a14..383dc92de14 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -32,6 +32,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -88,7 +89,7 @@ public final class PhaseTracker implements CauseStackManager { public static final PhaseTracker CLIENT = new PhaseTracker(); - public static final PhaseTracker SERVER = new PhaseTracker(); + private static final PhaseTracker SERVER = new PhaseTracker(); public static final Logger LOGGER = LogManager.getLogger(PhaseTracker.class); static final CopyOnWriteArrayList ASYNC_CAPTURED_ENTITIES = new CopyOnWriteArrayList<>(); private static final Map SPINOFF_TRACKERS = new MapMaker().weakKeys().concurrencyLevel(8).makeMap(); @@ -118,6 +119,44 @@ public static PhaseTracker getInstance() { }); } + /** + * The server phase tracker should be used for actions + * that are not tied to any specific {@link ServerLevel}. + * + *

For actions that are specific to a {@link ServerLevel}, + * the {@link #getWorldInstance(ServerLevel)} should be + * preferred.

+ * + *

For actions that could be performed inside a world + * generation thread, the {@link #getWorldInstance(LevelAccessor)} + * should be used instead.

+ * + *

If the current world instance is unknown, the + * implementation can perform more expensive lookup + * using the parameterless {@link #getWorldInstance}.

+ */ + public static PhaseTracker getServerInstanceExplicitly() { + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance() { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance(final LevelAccessor level) { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance(final ServerLevel level) { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + public static CauseStackManager getCauseStackManager() { return PhaseTracker.getInstance(); } @@ -231,7 +270,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world } public void init() { - if (this != PhaseTracker.SERVER) { + if (this == PhaseTracker.CLIENT) { return; } if (this.hasRun) { @@ -302,14 +341,14 @@ public boolean onSidedThread() { // ----------------- SIMPLE GETTERS -------------------------------------- public IPhaseState getCurrentState() { - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new UnsupportedOperationException("Cannot access the PhaseTracker off-thread, please use the respective PhaseTracker for their proper thread."); } return this.stack.peekState(); } public PhaseContext getPhaseContext() { - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new UnsupportedOperationException("Cannot access the PhaseTracker off-thread, please use the respective PhaseTracker for their proper thread."); } return this.stack.peekContext(); @@ -322,7 +361,7 @@ public PhaseContext getPhaseContext() { // ----------------- STATE ACCESS ---------------------------------- void switchToPhase(final IPhaseState state, final PhaseContext phaseContext) { - if (phaseContext.createdTracker != this && Thread.currentThread() != this.getSidedThread()) { + if (phaseContext.createdTracker != this && !this.onSidedThread()) { // lol no, report the block change properly new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr() .addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS) @@ -335,7 +374,7 @@ void switchToPhase(final IPhaseState state, final PhaseContext phaseContex Objects.requireNonNull(state, "State cannot be null!"); Objects.requireNonNull(phaseContext, "PhaseContext cannot be null!"); Preconditions.checkArgument(phaseContext.isComplete(), "PhaseContext must be complete!"); - if (this == PhaseTracker.SERVER && SpongeConfigs.getCommon().get().phaseTracker.verbose) { + if (this != PhaseTracker.CLIENT && SpongeConfigs.getCommon().get().phaseTracker.verbose) { if (this.stack.size() > 6) { if (this.stack.checkForRunaways(state, phaseContext)) { PhasePrinter.printRunawayPhase(this.stack, state, phaseContext); @@ -352,7 +391,7 @@ void switchToPhase(final IPhaseState state, final PhaseContext phaseContex @SuppressWarnings({"rawtypes", "unused", "try"}) void completePhase(final PhaseContext context) { - if (context.createdTracker != this && Thread.currentThread() != this.getSidedThread()) { + if (context.createdTracker != this && !this.onSidedThread()) { // lol no, report the block change properly new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr() .addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS) @@ -741,7 +780,7 @@ public Optional removeContext(final EventContextKey key) { private void enforceMainThread() { // On clients, this may not be available immediately, we can't bomb out that early. - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new IllegalStateException(String.format( "CauseStackManager called from off main thread (current='%s', expected='%s')!", ThreadUtil.getDescription(Thread.currentThread()), diff --git a/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java index 24e8ddce470..59b1ecb2a87 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java @@ -38,11 +38,11 @@ protected PooledPhaseState() { @Override public final C createPhaseContext(final PhaseTracker tracker) { - if (Thread.currentThread() != tracker.getSidedThread()) { + if (!tracker.onSidedThread()) { throw new IllegalStateException("Asynchronous Thread Access to PhaseTracker: " + tracker); } - if (tracker == PhaseTracker.SERVER) { + if (tracker == PhaseTracker.getServerInstanceExplicitly()) { if (this.serverCached != null) { final C cached = this.serverCached; this.serverCached = null; @@ -64,10 +64,10 @@ public final C createPhaseContext(final PhaseTracker tracker) { final void releaseContextFromPool(final C context) { final PhaseTracker createdTracker = context.createdTracker; - if (Thread.currentThread() != createdTracker.getSidedThread()) { + if (!createdTracker.onSidedThread()) { throw new IllegalStateException("Asynchronous Thread Access to PhaseTracker: " + createdTracker); } - if (createdTracker == PhaseTracker.SERVER) { + if (createdTracker == PhaseTracker.getServerInstanceExplicitly()) { if (this.serverCached == null) { this.serverCached = context; return; diff --git a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java index 67a35d5fa35..f240e990292 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java @@ -110,7 +110,8 @@ public static void tickEntity(final Consumer return; } - final EntityTickContext tickContext = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.SERVER).source(entity); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) entity.level()); + final EntityTickContext tickContext = TickPhase.Tick.ENTITY.createPhaseContext(phaseTracker).source(entity); try (final EntityTickContext context = tickContext) { if (entity instanceof CreatorTrackedBridge) { ((CreatorTrackedBridge) entity).tracker$getNotifierUUID().ifPresent(context::notifier); @@ -126,7 +127,7 @@ public static void tickEntity(final Consumer SpongeCommonEventFactory.callNaturalRotateEntityEvent(entity); } } catch (final Exception e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, tickContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, tickContext); } } @@ -163,7 +164,8 @@ public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, fin ((ActiveChunkReferantBridge) blockEntity).bridge$setActiveChunk((TrackedLevelChunkBridge) blockEntity.getLevel().getChunkAt(blockEntity.getBlockPos())); } - final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(PhaseTracker.SERVER).source(mixinTileEntity); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) blockEntity.getLevel()); + final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(phaseTracker).source(mixinTileEntity); try (final PhaseContext<@NonNull ?> phaseContext = context) { if (blockEntity instanceof CreatorTrackedBridge) { @@ -191,7 +193,7 @@ public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, fin } } catch (final Exception e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, context); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, context); } // We delay clearing active chunk if TE is invalidated during tick so we must remove it after if (blockEntity.isRemoved()) { @@ -204,10 +206,11 @@ public static void updateTickBlock( final TrackedWorldBridge mixinWorld, final net.minecraft.world.level.block.state.BlockState block, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot snapshot = mixinWorld.bridge$createSnapshot(block, pos, BlockChangeFlags.NONE); - final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(PhaseTracker.getCauseStackManager().currentCause(), snapshot); + final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(phaseTracker.currentCause(), snapshot); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -215,10 +218,10 @@ public static void updateTickBlock( } final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world(apiWorld).position(pos.getX(), pos.getY(), pos.getZ()).state((BlockState)block).build(); - final BlockTickContext phaseContext = TickPhase.Tick.BLOCK.createPhaseContext(PhaseTracker.SERVER).source(locatable); + final BlockTickContext phaseContext = TickPhase.Tick.BLOCK.createPhaseContext(phaseTracker).source(locatable); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase @@ -227,7 +230,7 @@ public static void updateTickBlock( PhaseTracker.LOGGER.trace(TrackingUtil.BLOCK_TICK, () -> "Wrapping Block Tick: " + block.toString()); block.tick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -236,10 +239,11 @@ public static void updateTickFluid( final TrackedWorldBridge mixinWorld, final FluidState fluidState, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState blockState) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot snapshot = mixinWorld.bridge$createSnapshot(blockState, pos, BlockChangeFlags.NONE); - final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(PhaseTracker.getCauseStackManager().currentCause(), snapshot); + final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(phaseTracker.currentCause(), snapshot); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -247,12 +251,12 @@ public static void updateTickFluid( } final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world(apiWorld).position(pos.getX(), pos.getY(), pos.getZ()).state((BlockState) blockState).build(); - final FluidTickContext phaseContext = TickPhase.Tick.FLUID.createPhaseContext(PhaseTracker.SERVER) + final FluidTickContext phaseContext = TickPhase.Tick.FLUID.createPhaseContext(phaseTracker) .source(locatable) .fluid(fluidState); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase @@ -261,7 +265,7 @@ public static void updateTickFluid( PhaseTracker.LOGGER.trace(TrackingUtil.FLUID_TICK, () -> "Wrapping Fluid Tick: " + fluidState.toString()); fluidState.tick(world, pos, blockState); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -271,12 +275,13 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, final net.minecraft.world.level.block.state.BlockState state, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot currentTickBlock = mixinWorld.bridge$createSnapshot(state, pos, BlockChangeFlags.NONE); final TickBlockEvent event = - SpongeEventFactory.createTickBlockEventRandom(PhaseTracker.getCauseStackManager().currentCause(), currentTickBlock); + SpongeEventFactory.createTickBlockEventRandom(phaseTracker.currentCause(), currentTickBlock); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -288,10 +293,10 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, .position(pos.getX(), pos.getY(), pos.getZ()) .state((BlockState) state) .build(); - final BlockTickContext phaseContext = TickPhase.Tick.RANDOM_BLOCK.createPhaseContext(PhaseTracker.SERVER).source(locatable); + final BlockTickContext phaseContext = TickPhase.Tick.RANDOM_BLOCK.createPhaseContext(phaseTracker).source(locatable); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase try (final PhaseContext<@NonNull ?> context = phaseContext) { @@ -299,7 +304,7 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, PhaseTracker.LOGGER.trace(TrackingUtil.BLOCK_TICK, "Wrapping Random Block Tick: {}", state); state.randomTick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @SuppressWarnings("rawtypes") @@ -307,12 +312,13 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, final FluidState state, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot currentTickBlock = mixinWorld.bridge$createSnapshot(state.createLegacyBlock(), pos, BlockChangeFlags.NONE); final TickBlockEvent event = - SpongeEventFactory.createTickBlockEventRandom(PhaseTracker.getCauseStackManager().currentCause(), currentTickBlock); + SpongeEventFactory.createTickBlockEventRandom(phaseTracker.currentCause(), currentTickBlock); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -324,13 +330,13 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, .position(pos.getX(), pos.getY(), pos.getZ()) .state((BlockState) state.createLegacyBlock()) .build(); - final FluidTickContext phaseContext = TickPhase.Tick.RANDOM_FLUID.createPhaseContext(PhaseTracker.SERVER) + final FluidTickContext phaseContext = TickPhase.Tick.RANDOM_FLUID.createPhaseContext(phaseTracker) .source(locatable) .fluid(state); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase try (final PhaseContext<@NonNull ?> context = phaseContext) { @@ -338,7 +344,7 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, PhaseTracker.LOGGER.trace(TrackingUtil.FLUID_TICK, () -> "Wrapping Random Fluid Tick: " + state.toString()); state.randomTick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -351,7 +357,7 @@ public static boolean fireMinecraftBlockEvent(final ServerLevel worldIn, final B // No source present which means we are ignoring the phase state return currentState.triggerEvent(worldIn, event.pos(), event.paramA(), event.paramB()); } - final BlockEventTickContext phaseContext = TickPhase.Tick.BLOCK_EVENT.createPhaseContext(PhaseTracker.SERVER); + final BlockEventTickContext phaseContext = TickPhase.Tick.BLOCK_EVENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)); phaseContext.source(source); final UUID user = ((TrackableBlockEventDataBridge) (Object) event).bridge$getSourceUserUUID(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 7e2013123b9..4b398bf6b44 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; @@ -82,7 +83,10 @@ public final class PacketPhaseUtil { @SuppressWarnings("removal") public static void handleSlotRestore(@Nullable final Player player, final @Nullable AbstractContainerMenu containerMenu, final List slotTransactions, final boolean eventCancelled) { - try (PhaseContext<@NonNull ?> ignored = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).buildAndSwitch()) { + final PhaseTracker phaseTracker = player != null + ? PhaseTracker.getWorldInstance((ServerLevel) player.level()) + : PhaseTracker.getWorldInstance(); + try (PhaseContext<@NonNull ?> ignored = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(phaseTracker).buildAndSwitch()) { boolean restoredAny = false; for (final SlotTransaction slotTransaction : slotTransactions) { @@ -252,7 +256,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n } else { final IPhaseState> packetState = PacketPhase.getInstance().getStateForPacket(packetIn); // At the very least make an unknown packet state case. - final PacketContext context = packetState.createPhaseContext(PhaseTracker.SERVER); + final PacketContext context = packetState.createPhaseContext(PhaseTracker.getWorldInstance(packetPlayer.serverLevel())); context.source(packetPlayer) .packetPlayer(packetPlayer) .packet(packetIn); diff --git a/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java b/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java index f0d91d4c46b..1932195b812 100644 --- a/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java @@ -27,6 +27,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.status.ServerStatus; import org.spongepowered.api.Sponge; +import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.Optional; @@ -36,7 +37,7 @@ default boolean onServerThread() { // Return true when the server isn't yet initialized, this means on a client // that the game is still being loaded. This is needed to support initialization // events with cause tracking. - return !Sponge.isServerAvailable() || Sponge.server().onMainThread(); + return !Sponge.isServerAvailable() || PhaseTracker.getWorldInstance().onSidedThread(); } default ServerStatus createServerStatus(ServerStatus originalStatus, Component description, Optional players, Optional version, Optional favicon) { diff --git a/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java b/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java index 76f8599ed66..be1b41179ce 100644 --- a/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java +++ b/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java @@ -41,7 +41,7 @@ public void tick() { super.tick(); Sponge.server().streamOnlinePlayers().forEach(player -> { - try (final EntityTickContext context = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.SERVER).source(player)) { + try (final EntityTickContext context = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.getServerInstanceExplicitly()).source(player)) { context.buildAndSwitch(); // Detect Changes on PlayerInventories marked as dirty. ((PlayerInventoryBridge) ((net.minecraft.world.entity.player.Player) player).getInventory()).bridge$cleanupDirty(); diff --git a/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java b/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java index ac0577f93b7..4f7d26d1780 100644 --- a/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java +++ b/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.world.volume.buffer.archetype; +import net.minecraft.server.level.ServerLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockState; @@ -276,7 +277,7 @@ public void applyToWorld( Objects.requireNonNull(target, "Target world cannot be null"); Objects.requireNonNull(placement, "Target position cannot be null"); try (final PhaseContext<@NonNull ?> context = PluginPhase.State.VOLUME_STREAM_APPLICATION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) target)) .spawnType(spawnContext) .source(this)) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index cfe05e7ba24..ae8d346c17d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -32,6 +32,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -165,7 +166,7 @@ public Transform transform() { @Override public boolean setTransform(final Transform transform) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).onSidedThread()) { return false; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java index 8b51058fdbd..d09d59cc265 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java @@ -171,7 +171,7 @@ default boolean setBlock(final int x, final int y, final int z, final org.sponge if (!((Level) this).isInWorldBounds(new BlockPos(x, y, z))) { throw new PositionOutOfBoundsException(new Vector3i(x, y, z), Constants.World.BLOCK_MIN, Constants.World.BLOCK_MAX); } - try (final @Nullable PhaseContext<@NonNull ?> context = PluginPhase.State.BLOCK_WORKER.switchIfNecessary(PhaseTracker.SERVER)) { + try (final @Nullable PhaseContext<@NonNull ?> context = PluginPhase.State.BLOCK_WORKER.switchIfNecessary(PhaseTracker.getWorldInstance((LevelAccessor) this))) { if (context != null) { context.buildAndSwitch(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index 9bf069259f9..ce0fb5a032c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -116,7 +116,7 @@ public MinecraftMixin(String param0) { private void impl$nullServerRefAndPhaseTracker(Screen screenIn, CallbackInfo ci) { ((MinecraftBridge) this).bridge$setTemporaryIntegratedServer(null); try { - PhaseTracker.SERVER.setThread(null); + PhaseTracker.getServerInstanceExplicitly().setThread(null); } catch (IllegalAccessException ignore) { } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 00401bb7d4d..a701c9d68db 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -154,7 +154,7 @@ public Subject subject() { final AtomicReference atomicReference, final Thread thread) { try { - PhaseTracker.SERVER.setThread(thread); + PhaseTracker.getServerInstanceExplicitly().setThread(thread); } catch (final IllegalAccessException e) { throw new RuntimeException("Could not initialize the server PhaseTracker!"); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index a6520bddc20..3f7af4b2ea8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -235,8 +235,9 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Override public void bridge$triggerExplosion(Explosion explosion) { // Set up the pre event + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); if (ShouldFire.EXPLOSION_EVENT_PRE) { - final var cause = PhaseTracker.getCauseStackManager().currentCause(); + final var cause = phaseTracker.currentCause(); final ExplosionEvent.Pre event = SpongeEventFactory.createExplosionEventPre(cause, explosion, (ServerWorld) this); if (SpongeCommon.post(event)) { return; @@ -246,7 +247,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final ServerExplosion mcExplosion = (ServerExplosion) explosion; - try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker) .explosion(mcExplosion) .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { ignored.buildAndSwitch(); @@ -474,7 +475,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, @Inject(method = "globalLevelEvent", at = @At("HEAD"), cancellable = true) private void impl$throwBroadcastGlobalEvent(int effectID, BlockPos pos, int pitch, CallbackInfo ci) { if (!this.bridge$isFake() && ShouldFire.PLAY_SOUND_EVENT_BROADCAST) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).pushCauseFrame()) { final PlaySoundEvent.Broadcast event = SpongeCommonEventFactory.callPlaySoundBroadcastEvent(frame, this, pos, effectID); if (event != null && event.isCancelled()) { ci.cancel(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 7f5bb335570..6de6a633dad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -523,11 +523,12 @@ public boolean teleportTo(final ServerLevel world, var isDimensionChange = transition.newLevel() != thisPlayer.serverLevel(); if (!this.impl$moveEventsFired) { - final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(PhaseTracker.getInstance()).worldChange() + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(thisPlayer.serverLevel()); + final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange() .player(); - final boolean hasMovementContext = PhaseTracker.SERVER.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); + final boolean hasMovementContext = phaseTracker.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); try (final TeleportContext context = contextToSwitchTo.buildAndSwitch(); - final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(thisPlayer); if (!hasMovementContext) { // TODO we should be able to detect normal plugin code though @@ -563,7 +564,7 @@ public boolean teleportTo(final ServerLevel world, newDest = reposition.destinationPosition(); } else { if (ShouldFire.MOVE_ENTITY_EVENT) { // TODO move into impl$fireMoveEvent? - newDest = this.impl$fireMoveEvent(PhaseTracker.SERVER, originalDest); + newDest = this.impl$fireMoveEvent(phaseTracker, originalDest); if (newDest == null) { return null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index a0a538b1aa2..1a3ff1df7ab 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -444,8 +444,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { ((ServerPlayerBridge) mcPlayer).bridge$setConnectionMessageToSend(null); - final PhaseContext context = PhaseTracker.SERVER.getPhaseContext(); - PhaseTracker.SERVER.pushCause(event); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(mcPlayer.serverLevel()); + final PhaseContext context = phaseTracker.getPhaseContext(); + phaseTracker.pushCause(event); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logPlayerInventoryChange(mcPlayer, PlayerInventoryTransaction.EventCreator.STANDARD); try (final EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(transactor)) { @@ -642,7 +643,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final Predicate filter; ChatType.Bound boundChatType; - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getServerInstanceExplicitly().pushCauseFrame()) { if ($$2 != null) { frame.pushCause($$2); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 2e6241aa51b..fff2eb84924 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -240,10 +240,11 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, return false; } - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final ServerLevel originalWorld = (ServerLevel) this.shadow$level(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(originalWorld); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - final ServerLevel originalWorld = (ServerLevel) this.shadow$level(); final ServerLevel originalDestinationWorld = (ServerLevel) location.world(); final ServerLevel destinationWorld; final @org.checkerframework.checker.nullness.qual.Nullable Vector3d destinationPosition; @@ -265,7 +266,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, destinationPosition = repositionEvent.destinationPosition(); } else { destinationWorld = (ServerLevel) this.shadow$level(); - destinationPosition = this.impl$fireMoveEvent(PhaseTracker.SERVER, location.position()); + destinationPosition = this.impl$fireMoveEvent(phaseTracker, location.position()); if (destinationPosition == null) { return false; } @@ -275,7 +276,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, if (isChangeOfWorld) { Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost( - PhaseTracker.getCauseStackManager().currentCause(), + phaseTracker.currentCause(), (org.spongepowered.api.entity.Entity) this, (ServerWorld) originalWorld, (ServerWorld) originalDestinationWorld, @@ -875,7 +876,8 @@ public void stopRiding() { this.remainingFireTicks < 1 && ticks >= Constants.Entity.MINIMUM_FIRE_TICKS && this.impl$canCallIgniteEntityEvent()) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) entity.level()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(((org.spongepowered.api.entity.Entity) this).location().world()); final IgniteEntityEvent event = SpongeEventFactory. @@ -892,7 +894,7 @@ public void stopRiding() { .build(); final ChangeDataHolderEvent.ValueChange valueChange = SpongeEventFactory.createChangeDataHolderEventValueChange( - PhaseTracker.SERVER.currentCause(), + phaseTracker.currentCause(), transaction, (DataHolder.Mutable) this); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index fff8bd381fb..994a4510d38 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -146,7 +146,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "die", at = @At("HEAD"), cancellable = true) private void impl$throwDestructEntityDeath(final DamageSource cause, final CallbackInfo ci) { - final boolean throwEvent = !((LevelBridge) this.shadow$level()).bridge$isFake() && Sponge.isServerAvailable() && Sponge.server().onMainThread(); + final boolean throwEvent = !((LevelBridge) this.shadow$level()).bridge$isFake() && Sponge.isServerAvailable() && PhaseTracker.getWorldInstance().onSidedThread(); if (!this.dead) { // isDead should be set later on in this method so we aren't re-throwing the events. if (throwEvent && this.impl$deathEventsPosted <= Constants.Sponge.MAX_DEATH_EVENTS_BEFORE_GIVING_UP) { // ignore because some moron is not resetting the entity. @@ -454,17 +454,18 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt stack.releaseUsing(world, self, duration); return; } - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) world); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); final HandType handType = (HandType) (Object) this.shadow$getUsedItemHand(); this.impl$addSelfToFrame(frame, snapshot, handType); final Ticks ticksDuration = SpongeTicks.ticksOrInfinite(duration); - if (!SpongeCommon.post(SpongeEventFactory.createUseItemStackEventStop(PhaseTracker.getCauseStackManager().currentCause(), + if (!SpongeCommon.post(SpongeEventFactory.createUseItemStackEventStop(phaseTracker.currentCause(), ticksDuration, ticksDuration, snapshot))) { stack.releaseUsing(world, self, duration); if (self instanceof ServerPlayer) { // Log Change and capture SlotTransactions - PhaseTracker.SERVER.getPhaseContext().getTransactor().logPlayerInventoryChange(((ServerPlayer) self), PlayerInventoryTransaction.EventCreator.STANDARD); + phaseTracker.getPhaseContext().getTransactor().logPlayerInventoryChange(((ServerPlayer) self), PlayerInventoryTransaction.EventCreator.STANDARD); ((ServerPlayer) self).inventoryMenu.broadcastChanges(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index dd36c767846..8bce4b1a806 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -373,7 +373,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen result.damageToHelmet().isPresent() || result.damageToArmor().isPresent()) && (Object) this instanceof Player player) { - PhaseTracker.SERVER.getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); + PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); player.inventoryMenu.broadcastChanges(); // capture } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java index d377bb6d48e..7ca9cfd76d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java @@ -147,7 +147,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) public void impl$onBrokenByPlayer(final ArmorStand instance, final ServerLevel $$0, final DamageSource $$1) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance($$0).getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { this.shadow$brokenByPlayer($$0, $$1); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index 0dd2ca7b6ad..199d69d5742 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -123,7 +123,7 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB ) ) private void impl$fireExpireEntityEventTargetItem(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread() || this.shadow$getItem().isEmpty()) { + if (!PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).onSidedThread() || this.shadow$getItem().isEmpty()) { // In the rare case the first if block is actually at the end of the method instruction list, we don't want to // erroneously be calling this twice. return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index 07a49e1163f..50c8b1c2238 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -291,7 +291,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I instance.setItemInHand(interactionHand, stack); // Capture... - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logPlayerInventoryChange(instance, PlayerInventoryTransaction.EventCreator.STANDARD); this.inventoryMenu.broadcastChanges(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java index 0e8674220a6..6f786188ad6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java @@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.ProjectileUtil; import net.minecraft.world.level.Level; @@ -84,7 +85,7 @@ public abstract class ProjectileUtilMixin { return ProjectileUtil.getEntityHitResult($$0, $$1, $$2, $$3, $$4, $$5, $$6); } try (final PhaseContext<@NonNull ?> context = EntityPhase.State.COLLISION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) $$0)) .source($$1) ) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java index 2759957ff5d..f3b9c8b2fb3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.level.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.entity.EntityAccess; import net.minecraft.world.level.entity.PersistentEntitySectionManager; @@ -73,7 +74,7 @@ public class PersistentEntitySectionManagerMixin { final ServerLocation location = ServerLocation.of(sw, position.x(), position.y(), position.z()); final Vec2 rotationVector = mcEntity.getRotationVector(); final Vector3d rotation = new Vector3d(rotationVector.x, rotationVector.y, 0); - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance((ServerLevel) sw).pushCauseFrame()) { frame.pushCause(entity); final Event construct = SpongeEventFactory.createConstructEntityEventPost(frame.currentCause(), (org.spongepowered.api.entity.Entity) entity, location, rotation, ((EntityType) mcEntity.getType())); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java index 3c4711ab9f7..8bbb25f2918 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java @@ -72,7 +72,7 @@ public boolean closeInventory() throws IllegalArgumentException { } // Create Close_Window to capture item drops final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; - try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())) .source(this) .packetPlayer(player) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 2e300ee4b00..9e01385102d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.Entity; @@ -45,6 +46,7 @@ import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -72,9 +74,13 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory { + // @formatter:off @Nullable private EffectTransactor inventory$effectTransactor = null; @Nullable private Object inventory$menuProvider; + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + // Ignore ServerPlayerMixin_Inventory(final EntityType param0, final Level param1) { super(param0, param1); @@ -84,7 +90,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void impl$beforeSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final PlayerInventoryTransaction.EventCreator eventCreator = context.getState() instanceof SwapHandItemsState ? PlayerInventoryTransaction.EventCreator.SWAP_HAND : PlayerInventoryTransaction.EventCreator.STANDARD; @@ -103,7 +109,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Inject(method = "drop(Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;removeFromSelected(Z)Lnet/minecraft/world/item/ItemStack;")) protected void impl$beforeRemoveItem(final boolean param0, final CallbackInfoReturnable cir) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); this.inventory$effectTransactor = transactor.logDropFromPlayerInventory((ServerPlayer) (Object) this, param0); } @@ -127,7 +133,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory } final ServerPlayer serverPlayer = (ServerPlayer) player; - try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.getWorldInstance(this.shadow$serverLevel())) .source(serverPlayer) .packetPlayer(serverPlayer) ) { @@ -150,7 +156,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory entity.playerTouch(player); return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); try (final EffectTransactor ignored = context.getTransactor().logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { entity.playerTouch(player); this.inventoryMenu.broadcastChanges(); // capture @@ -165,7 +171,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void inventory$onUpdateUsingItem(final LivingEntity thisPlayer) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect((ServerPlayer) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD)) { this.shadow$completeUsingItem(); @@ -184,7 +190,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory ) ) private void impl$afterOpenHorseInventory(final AbstractHorse $$0, final Container $$1, final CallbackInfo ci) { - PhaseTracker.SERVER.getPhaseContext() + PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logContainerSet((ServerPlayer) (Object) this); } @@ -223,7 +229,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory private HorseInventoryMenu impl$transactHorseInventoryMenuCreationWithEffect( final int $$0, final net.minecraft.world.entity.player.Inventory $$1, final Container $$2, final AbstractHorse $$3, final int $$4 ) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext() + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logOpenInventory((ServerPlayer) (Object) this) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java index 82ec70039e9..377ea19010a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; @@ -31,6 +32,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -42,7 +44,12 @@ // Forge and Vanilla @Mixin(ServerPlayer.class) -public class ServerPlayerMixin_Shared_Inventory { +public abstract class ServerPlayerMixin_Shared_Inventory { + + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + @Nullable private Object inventory$menuProvider; @Inject( @@ -55,7 +62,7 @@ public class ServerPlayerMixin_Shared_Inventory { ) ) private void impl$afterOpenMenu(final CallbackInfoReturnable cir) { - PhaseTracker.SERVER.getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); + PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); } @Inject(method = "openMenu", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initMenu(Lnet/minecraft/world/inventory/AbstractContainerMenu;)V")) @@ -74,7 +81,7 @@ public class ServerPlayerMixin_Shared_Inventory { final MenuProvider menuProvider, final int containerCounter, final net.minecraft.world.entity.player.Inventory inventory, final Player player ) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext() + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logOpenInventory((ServerPlayer) (Object) this) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index c95c646d4f6..6866a22f93b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -66,7 +66,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/InventoryMenu;broadcastChanges()V")) private void impl$onBroadcastCreativeActionResult(final InventoryMenu inventoryMenu, final ServerboundSetCreativeModeSlotPacket packetIn) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final ItemStack itemstack = packetIn.itemStack(); @@ -79,7 +79,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Lnet/minecraft/world/item/ItemStack;Z)Lnet/minecraft/world/entity/item/ItemEntity;")) private ItemEntity impl$onBroadcastCreativeActionResult(final ServerPlayer serverPlayer, final ItemStack stack, final boolean param1) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCreativeClickContainer(-1, ItemStackUtil.snapshotOf(stack), this.player)) { return serverPlayer.drop(stack, param1); @@ -92,7 +92,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;stopUsingItem()V")) ) private void impl$onHandleSetCarriedItem(final ServerboundSetCarriedItemPacket packet, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final int slotIdx = packet.getSlot(); transactor.logPlayerCarriedItem(this.player, slotIdx); @@ -101,7 +101,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleContainerClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;sendAllDataToRemote()V")) private void impl$onSpectatorClick(final AbstractContainerMenu menu, final ServerboundContainerClickPacket packet) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player @@ -120,7 +120,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItem(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) private InteractionResult impl$onHandleUseItem(final ServerPlayerGameMode serverPlayerGameMode, final ServerPlayer param0, final Level param1, final ItemStack param2, final InteractionHand param3) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(this.player, PlayerInventoryTransaction.EventCreator.STANDARD)) { final InteractionResult result = serverPlayerGameMode.useItem(param0, param1, param2, param3); @@ -133,7 +133,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleContainerClose", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;doCloseContainer()V")) private void impl$onHandleContainerClose(final ServerPlayer player) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCloseInventory(player, true)) { this.player.containerMenu.removed(player); @@ -144,7 +144,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleRenameItem(Lnet/minecraft/network/protocol/game/ServerboundRenameItemPacket;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AnvilMenu;setItemName(Ljava/lang/String;)Z")) private boolean impl$onHandleRenameItem(final AnvilMenu menu, final String name) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final var ignored = transactor.logIgnoredInventory(this.player.containerMenu)) { return menu.setItemName(name); @@ -154,7 +154,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Inject(method = "handleSelectTrade", at = @At("RETURN")) private void impl$onHandleSelectTrade(final ServerboundSelectTradePacket param0, final CallbackInfo ci) { if (this.player.containerMenu instanceof MerchantMenu) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logSelectTrade(this.player, param0.getItem()); this.player.containerMenu.broadcastChanges(); // capture diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index b530cc8df35..d8db0a26fbb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.inventory.event.world.inventory; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -114,7 +115,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ) ) private void impl$handleUnviewedSlotSwap(final Inventory inv, final int index, final ItemStack newStack) { - if (!PhaseTracker.SERVER.onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { + if (!PhaseTracker.getWorldInstance().onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { inv.setItem(index, newStack); } else { final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(inv.getItem(index)); @@ -139,7 +140,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ) private ItemStack impl$handleUnviewedSlotSwap2(final ItemStack origin, final int splitOff, int $$0, int index, ClickType $$2, Player $$3) { Inventory inv = $$3.getInventory(); - if (!PhaseTracker.SERVER.onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { + if (!PhaseTracker.getWorldInstance().onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { return origin.split(splitOff); } else { final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(origin); @@ -188,7 +189,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon return result; } this.bridge$detectAndSendChanges(true, true); - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) player.level()).getPhaseContext(); TrackingUtil.processBlockCaptures(context); // ClickContainerEvent -> CraftEvent -> PreviewEvent // result is modified by the ClickMenuTransaction return result; @@ -207,7 +208,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon this.shadow$doClick(slotId, dragType, clickType, player); return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logClickContainer(menu, slotId, dragType, clickType, player)) { this.impl$isClicking = true; @@ -222,7 +223,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon @Inject(method = "broadcastFullState", at = @At("HEAD"), cancellable = true) private void impl$broadcastFullStateWithTransactions(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance().onSidedThread()) { return; } this.bridge$detectAndSendChanges(false, false); @@ -243,7 +244,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon */ @Inject(method = "broadcastChanges", at = @At("HEAD"), cancellable = true) private void impl$broadcastChangesWithTransactions(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance().onSidedThread()) { return; } this.bridge$detectAndSendChanges(false, true); @@ -256,7 +257,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon public void bridge$detectAndSendChanges(final boolean capture, final boolean synchronize) { // Code-Flow changed from vanilla completely! - final PhaseContext phaseContext = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext phaseContext = PhaseTracker.getWorldInstance().getPhaseContext(); if (phaseContext.captureModifiedContainer((AbstractContainerMenu) (Object) this)) { return; } @@ -342,8 +343,9 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon } private void impl$capture(final Integer index, final ItemStack newStack, final ItemStack oldStack) { - final PhaseContext phaseContext = PhaseTracker.SERVER.getPhaseContext(); - if (PhaseTracker.SERVER.onSidedThread() && + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(); + final PhaseContext phaseContext = phaseTracker.getPhaseContext(); + if (phaseTracker.onSidedThread() && !(phaseContext.isRestoring() // do not capture when block restoring & initial sync on inventory open || phaseContext instanceof TileEntityTickContext)) { // do not capture for open inventories when ticking BlockEntities final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(oldStack); @@ -359,7 +361,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon } private void impl$captureSwap(int index, Inventory inv, ItemStackSnapshot oldItem, ItemStackSnapshot newItem) { - final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getWorldInstance().getPhaseContext(); final TransactionalCaptureSupplier transactor = phaseContext.getTransactor(); final org.spongepowered.api.item.inventory.Slot adapter = ((InventoryAdapter) inv.player.getInventory()).inventoryAdapter$getSlot(index).get(); final SlotTransaction newTransaction = new SlotTransaction(adapter, oldItem, newItem); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java index 2d5f4c7aa4e..a081fce9f6a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java @@ -49,7 +49,7 @@ public abstract class AnvilMenuMixin_Inventory extends ItemCombinerMenuMixin_Inv @Inject(method = "createResult", at = @At(value = "RETURN")) private void impl$throwUpdateAnvilEvent(final CallbackInfo ci) { - if (!ShouldFire.UPDATE_ANVIL_EVENT || !PhaseTracker.SERVER.onSidedThread()) { + if (!ShouldFire.UPDATE_ANVIL_EVENT || !PhaseTracker.getWorldInstance().onSidedThread()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java index 3b173f8ebbe..4e7bf87dcb6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java @@ -62,7 +62,7 @@ private static void beforeSlotChangedCraftingGrid( return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance().getPhaseContext(); if (!context.isRestoring()) { final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logCraftingPreview((ServerPlayer) player, (CraftingInventory) inv, craftingContainer); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java index 7a43a4977ea..80c4c55a145 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java @@ -134,7 +134,7 @@ public void set(@Nullable final ItemStack stack) { return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance().getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logCrafting(thePlayer, this.impl$craftedStack, (CraftingInventory) craftInv, this.impl$onTakeRecipe); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java index db84f046d84..f71309dd8f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java @@ -47,8 +47,9 @@ public abstract class SlotMixin_Inventory { @Inject(method = "onQuickCraft(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD")) private void inventory$onQuickCraft(final ItemStack slotStack, final ItemStack stackTaken, final CallbackInfo ci) { - if (PhaseTracker.SERVER.onSidedThread()) { - final PhaseContext<@NonNull ?> ctx = PhaseTracker.SERVER.getPhaseContext(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(); + if (phaseTracker.onSidedThread()) { + final PhaseContext<@NonNull ?> ctx = phaseTracker.getPhaseContext(); ctx.getTransactor().logShiftCraftingResult((Slot) (Object) this, stackTaken); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java index 658609e9705..1ffd6924c48 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java @@ -121,7 +121,7 @@ public abstract class HopperBlockEntityMixin_Inventory { // Ignore all container transactions in affected inventories if (hopper instanceof final ViewableInventoryBridge bridge) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance())) { context.buildAndSwitch(); for (final ServerPlayer player : bridge.viewableBridge$getViewers()) { player.containerMenu.broadcastChanges(); @@ -129,7 +129,7 @@ public abstract class HopperBlockEntityMixin_Inventory { } } if (iInventory instanceof final ViewableInventoryBridge bridge) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance())) { context.buildAndSwitch(); for (final ServerPlayer player : bridge.viewableBridge$getViewers()) { player.containerMenu.broadcastChanges(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java index acc316eb42e..0f583e1fe05 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java @@ -63,7 +63,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix @Inject(method = "tickServer", at = @At("RETURN")) private void tracker$ensurePhaseTrackerEmpty(final BooleanSupplier hasTimeLeft, final CallbackInfo ci) { - PhaseTracker.SERVER.ensureEmpty(); + PhaseTracker.getServerInstanceExplicitly().ensureEmpty(); } @Redirect( @@ -76,7 +76,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix private void tracker$wrapUpdateTimeLightAndEntities(final MinecraftServer minecraftServer, final BooleanSupplier hasTimeLeft) { try ( final PhaseContext<@NonNull ?> context = TickPhase.Tick.SERVER_TICK - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getServerInstanceExplicitly()) .server(minecraftServer) ) { context.buildAndSwitch(); @@ -94,7 +94,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix private void tracker$wrapWorldTick(final ServerLevel serverWorld, final BooleanSupplier hasTimeLeft) { try ( final PhaseContext<@NonNull ?> context = TickPhase.Tick.WORLD_TICK - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld) ) { context.buildAndSwitch(); @@ -104,7 +104,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix @Inject(method = "wrapRunnable(Ljava/lang/Runnable;)Lnet/minecraft/server/TickTask;", at = @At("RETURN")) private void tracker$associatePhaseContextWithWrappedTask(final Runnable runnable, final CallbackInfoReturnable cir) { final TickTask returnValue = cir.getReturnValue(); - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getServerInstanceExplicitly().onSidedThread()) { final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); if (phaseContext.isEmpty()) { return; @@ -122,7 +122,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix ) @SuppressWarnings("unchecked") private void tracker$wrapAndPerformContextSwitch(final ReentrantBlockableEventLoop thisServer, final Runnable runnable) { - try (final PhaseContext<@NonNull ?> context = PluginPhase.State.DELAYED_TASK.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = PluginPhase.State.DELAYED_TASK.createPhaseContext(PhaseTracker.getServerInstanceExplicitly()) .source(runnable) .setDelayedContextPopulator(((TickTaskBridge) runnable).bridge$getFrameModifier().orElse(null)) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java index 894d7e8a63d..a009abaa2ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java @@ -63,7 +63,8 @@ public abstract class ChunkMapMixin_Tracker { @Redirect(method = "lambda$prepareTickingChunk$25", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;startTickingChunk(Lnet/minecraft/world/level/chunk/LevelChunk;)V")) private void tracker$wrapUnpackTicks(final ServerLevel level, final LevelChunk chunk) { - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(level); + if (!phaseTracker.onSidedThread()) { new PrettyPrinter(60).add("Illegal Async Chunk Unpacking").centre().hr() .addWrapped("Someone is attempting to unpack chunk scheduled updates while off the main thread, this is" + "generally unsupported and Sponge would appreciate a report about this. Please attach " + @@ -76,10 +77,10 @@ public abstract class ChunkMapMixin_Tracker { .log(SpongeCommon.logger(), Level.ERROR); return; } - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_LOADING) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_LOADING) { return; } - try (final PhaseContext<@NonNull ?> ctx = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()) + try (final PhaseContext<@NonNull ?> ctx = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .source(chunk) .world(level) .chunk(chunk)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java index ea2d4ed8e56..6e26bad1ab8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java @@ -60,7 +60,8 @@ public abstract class ChunkStatusTasksMixin_Tracker { if (isFake) { return; } - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) chunk.getLevel()); + if (!phaseTracker.onSidedThread()) { new PrettyPrinter(60).add("Illegal Async Chunk Load").centre().hr() .addWrapped("Sponge relies on knowing when chunks are being loaded as chunks add entities" + " to the parented world for management. These operations are generally not" @@ -73,10 +74,10 @@ public abstract class ChunkStatusTasksMixin_Tracker { .log(SpongeCommon.logger(), Level.ERROR); return; } - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { return; } - GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()) + GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .source(chunk) .world((ServerLevel) chunk.getLevel()) .chunk(chunk) @@ -92,12 +93,13 @@ public abstract class ChunkStatusTasksMixin_Tracker { ) private static void tracker$endLoad(final ChunkAccess $$0x, final WorldGenContext $$1x, final GenerationChunkHolder $$2x, final CallbackInfoReturnable cir) { - if (!((LevelBridge) $$1x.level()).bridge$isFake() && PhaseTracker.SERVER.onSidedThread()) { - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance($$1x.level()); + if (!((LevelBridge) $$1x.level()).bridge$isFake() && phaseTracker.onSidedThread()) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { return; } // IF we're not on the main thread, - PhaseTracker.getInstance().getPhaseContext().close(); + phaseTracker.getPhaseContext().close(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java index 4551170d435..bdcf5b3f7ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java @@ -55,7 +55,7 @@ public abstract class ServerChunkCacheMixin_Tracker { final NaturalSpawner.SpawnState spawnState, final List mobCategories ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); NaturalSpawner.spawnForChunk(serverWorld, targetChunk, spawnState, mobCategories); @@ -74,7 +74,7 @@ public abstract class ServerChunkCacheMixin_Tracker { final boolean spawnHostileMobs, final boolean spawnPeacefulMobs ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); serverWorld.tickCustomSpawners(spawnHostileMobs, spawnPeacefulMobs); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index e37bc495c69..cdb68aa0138 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -135,7 +135,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem private void tracker$wrapNormalEntityTick(final ServerLevel level, final Consumer entityUpdateConsumer, final Entity entity ) { - final PhaseContext<@NonNull ?> currentState = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> currentState = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); TrackingUtil.tickEntity(entityUpdateConsumer, entity); } @@ -204,7 +204,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem ) ) private void tracker$startWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.SERVER) + TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) (Object) this)) .buildAndSwitch(); } @@ -217,7 +217,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem ) ) private void tracker$closeWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); if (context.getState() != TickPhase.Tick.WEATHER) { throw new IllegalStateException("Expected to be in a Weather ticking state, but we aren't."); } @@ -242,7 +242,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final ObjectLinkedOpenHashSet list, final Object data, final BlockPos pos, final Block blockIn, final int eventID, final int eventParam ) { - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); final BlockEventData blockEventData = (BlockEventData) data; final TrackableBlockEventDataBridge blockEvent = (TrackableBlockEventDataBridge) (Object) blockEventData; // Short circuit phase states who do not track during block events @@ -323,7 +323,8 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final var explosionBuilder = org.spongepowered.api.world.explosion.Explosion.builder().from((org.spongepowered.api.world.explosion.Explosion) mcExplosion); Explosive apiExplosive = (Explosive) entity; - final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(PhaseTracker.getCauseStackManager().currentCause(), + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(phaseTracker.currentCause(), explosionBuilder, apiExplosive, (org.spongepowered.api.world.explosion.Explosion) instance); if (Sponge.eventManager().post(detonateEvent)) { this.tracker$cancelExplosionEffects(entity); @@ -340,7 +341,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem if (ShouldFire.EXPLOSION_EVENT_PRE) { // Set up the pre event final ExplosionEvent.Pre event = - SpongeEventFactory.createExplosionEventPre(PhaseTracker.SERVER.currentCause(), apiExplosion, thisWorld); + SpongeEventFactory.createExplosionEventPre(phaseTracker.currentCause(), apiExplosion, thisWorld); if (SpongeCommon.post(event)) { this.tracker$cancelExplosionEffects(entity); return; @@ -358,7 +359,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem } } - try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER).explosion(mcExplosion) + try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker).explosion(mcExplosion) .source(((Optional) apiExplosion.sourceExplosive()).orElse(this))) { ctx.buildAndSwitch(); @@ -404,8 +405,8 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem if (this.bridge$isFake()) { return Optional.empty(); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags); @@ -466,8 +467,8 @@ public boolean setBlock(final BlockPos pos, final net.minecraft.world.level.bloc if (this.bridge$isFake()) { return super.setBlock(pos, newState, flags, limit); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags); @@ -499,8 +500,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return super.destroyBlock(pos, doDrops, p_241212_3_, limit); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final FluidState fluidstate = this.shadow$getFluidState(pos); @@ -592,7 +593,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (tileentity == null) { return; } - if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (this.bridge$isFake() || !phaseTracker.onSidedThread()) { // If we're fake or not on the server thread, well, we could effectively call // out whoever is trying to remove tile entities asynchronously.... super.shadow$removeBlockEntity(immutable); @@ -601,7 +603,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable // Otherwise, let's go on and check if we're recording transactions, // and if so, log the tile entity removal (may associate with an existing transaction, // or create a new transaction. - final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); if (current.getTransactor().logTileRemoval(tileentity, () -> (ServerLevel) (Object) this)) { final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(RemoveTileEntityFromChunkEffect.getInstance()) @@ -616,7 +618,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public void shadow$setBlockEntity(final net.minecraft.world.level.block.entity.BlockEntity proposed) { final BlockPos immutable = proposed.getBlockPos().immutable(); - if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (this.bridge$isFake() || !phaseTracker.onSidedThread()) { // If we're fake or not on the server thread, well, we could effectively call // out whoever is trying to remove tile entities asynchronously.... super.shadow$setBlockEntity(proposed); @@ -630,7 +633,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable // Otherwise, let's go on and check if we're recording transactions, // and if so, log the tile entity removal (may associate with an existing transaction, // or create a new transaction. - final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); if (current.doesBlockEventTracking()) { final net.minecraft.world.level.block.entity.@Nullable BlockEntity existing = this.shadow$getChunkAt(immutable).getBlockEntity(immutable); if (current.getTransactor().logTileReplacement(immutable, existing, proposed, () -> (ServerLevel) (Object) this)) { @@ -657,8 +660,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return; } - final PhaseTracker tracker = PhaseTracker.SERVER; - if (tracker.getSidedThread() != Thread.currentThread()) { + final PhaseTracker tracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!tracker.onSidedThread()) { // TODO - async entity spawn logging return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 06fb1b321cc..1a01fd029a5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -26,6 +26,7 @@ import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; @@ -112,6 +113,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl player.inventoryMenu.sendAllDataToRemote(); return InteractionResult.FAIL; } + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); // Sponge end if (this.gameModeForPlayer == GameType.SPECTATOR) { final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); @@ -119,7 +121,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl playerIn.openMenu(inamedcontainerprovider); final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(playerIn); frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld)(worldIn)).createSnapshot(pos)); ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); @@ -151,7 +153,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(playerIn); frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos)); ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); @@ -184,7 +186,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl } else { result = stackIn.useOn(itemusecontext); // Sponge start - log change in hand - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); if (!transactor.isEmpty()) { //TODO: Add effect to attach the transaction to be the child of the parents try (final EffectTransactor ignored = context.getTransactor().pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()))) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java index 5a3e28c562c..2fb2e423001 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java @@ -61,7 +61,7 @@ public abstract class ServerGamePacketListenerImplMixin_Tracker { player.doTick(); return; } - try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.SERVER).source(player)) { + try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.getWorldInstance(this.player.serverLevel())).source(player)) { context.buildAndSwitch(); PhaseTracker.LOGGER.trace(TrackingUtil.PLAYER_TICK, () -> "Wrapping Player Tick: " + player.toString()); player.doTick(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java index a552b3ff9de..06b0b047334 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java @@ -47,7 +47,7 @@ public class PlayerListMixin_Tracker { final Entity.RemovalReason reason ) { try (final GeneralizedContext context = PlayerPhase.State.PLAYER_LOGOUT - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance(world)) .source(player)) { context.buildAndSwitch(); world.removePlayerImmediately(player, reason); @@ -57,7 +57,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onPlaceNewPlayerInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } @@ -66,7 +66,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onRespawnInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java index 4647439094d..96005a33810 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java @@ -94,11 +94,11 @@ public abstract class EntityMixin_Tracker implements DelegatingConfigTrackableBr ) private void tracker$logEntityDropTransactionIfNecessary(final ServerLevel level, final ItemStack stack, final float offsetY, final CallbackInfoReturnable cir) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) level).bridge$isFake()) { return; } - if (((LevelBridge) level).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance(level); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); @@ -112,11 +112,11 @@ public abstract class EntityMixin_Tracker implements DelegatingConfigTrackableBr @Inject(method = "setRemoved(Lnet/minecraft/world/entity/Entity$RemovalReason;)V", at = @At("RETURN")) private void tracker$ensureDropEffectCompleted(final Entity.RemovalReason reason, final CallbackInfo ci) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index 43ffb8ba24c..cfaee3f54c7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.tracker.world.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.CombatEntry; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; @@ -96,12 +97,12 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;tickDeath()V")) private void tracker$enterDeathPhase(final LivingEntity livingEntity) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { this.shadow$tickDeath(); return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) livingEntity.level()); + if (!instance.onSidedThread()) { this.shadow$tickDeath(); return; } @@ -127,11 +128,11 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { ) private void tracker$wrapOnDeathWithState(final LivingEntity thisEntity, final DamageSource cause) { // Sponge Start - notify the cause tracker - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) thisEntity.level()); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); @@ -156,7 +157,7 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { return; } try (final PhaseContext<@NonNull ?> context = EntityPhase.State.COLLISION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) livingEntity.level())) .source(livingEntity) ) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java index c38e4b355d1..14f8d2e9bde 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java @@ -79,11 +79,12 @@ public abstract class BoneMealItemMixin_Tracker { return; } - final PhaseContext<@NonNull ?> current = PhaseTracker.getInstance().getPhaseContext(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(worldIn); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); final boolean doesEvent = current.doesBlockEventTracking(); if (doesEvent) { // We can enter the new phase state. - try (final GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(PhaseTracker.SERVER) + try (final GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(phaseTracker) .provideItem(stack) .world(worldIn) .block(state) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java index 71009642869..f981aa4e7fb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.tracker.world.item; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -55,7 +56,7 @@ public abstract class ItemStackMixin_Tracker { final LivingEntity player, final Level levelIn, final BlockState stateIn, final BlockPos posIn, final Player playerIn ) { final boolean isServerLevel = !((LevelBridge) level).bridge$isFake(); - final PhaseContext<@NonNull ?> context = isServerLevel ? PhaseTracker.SERVER.getPhaseContext() : null; + final PhaseContext<@NonNull ?> context = isServerLevel ? PhaseTracker.getWorldInstance((ServerLevel) level).getPhaseContext() : null; try { if (isServerLevel) { context.capturePlayerUsingStackToBreakBlock((ServerPlayer) playerIn); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java index 093ad2e886a..1041962e966 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -73,19 +74,43 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist * @param ci The callback info */ @Inject( - method = { - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V" - }, + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", + at = @At("HEAD"), + cancellable = true + ) + private static void tracker$cancelOnBlockRestoration(final BlockState state, final Level worldIn, + final BlockPos pos, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); + } + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", at = @At("HEAD"), cancellable = true ) - private static void tracker$cancelOnBlockRestoration(final CallbackInfo ci) { - if (Thread.currentThread() == PhaseTracker.SERVER.getSidedThread()) { - if (PhaseTracker.SERVER.getPhaseContext().isRestoring()) { - ci.cancel(); - } + private static void tracker$cancelOnBlockRestoration( + final BlockState state, final LevelAccessor worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); + } + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V", + at = @At("HEAD"), + cancellable = true + ) + private static void tracker$cancelOnBlockRestoration(final BlockState state, final Level worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, + final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); } } @@ -95,11 +120,11 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist ) private static void tracker$captureBlockProposedToBeSpawningDrops(final BlockState state, final Level worldIn, final BlockPos pos, final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops(worldIn, pos, state, null); } @@ -115,11 +140,11 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist if (!(worldIn instanceof Level)) { return; // In the name of my father, and his father before him, I cast you out! } - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops((Level) worldIn, pos, state, tileEntity); } @@ -131,30 +156,60 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist private static void tracker$captureBlockProposedToBeSpawningDrops(final BlockState state, final Level worldIn, final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops(worldIn, pos, state, tileEntity); } @Inject( - method = { - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V" - }, + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", + at = @At("TAIL") + ) + private static void tracker$closeEffectIfCapturing(final BlockState state, final Level worldIn, + final BlockPos pos, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { + return; + } + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); + context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); + BlockMixin_Tracker.tracker$effectTransactorForDrops = null; + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", + at = @At("TAIL") + ) + private static void tracker$closeEffectIfCapturing( + final BlockState state, final LevelAccessor worldIn, final BlockPos pos, + final @Nullable BlockEntity tileEntity, final CallbackInfo ci + ) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { + return; + } + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); + context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); + BlockMixin_Tracker.tracker$effectTransactorForDrops = null; + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V", at = @At("TAIL") ) - private static void tracker$closeEffectIfCapturing(final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + private static void tracker$closeEffectIfCapturing(final BlockState state, final Level worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, + final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); BlockMixin_Tracker.tracker$effectTransactorForDrops = null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java index 1efbbc0112a..b3174cc508d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java @@ -67,7 +67,7 @@ public abstract class DispenserBlockMixin_Tracker { private void tracker$createContextOnDispensing(final ServerLevel worldIn, final BlockState state, final BlockPos pos, final CallbackInfo ci) { final SpongeBlockSnapshot spongeBlockSnapshot = ((TrackedWorldBridge) worldIn).bridge$createSnapshot(state, pos, BlockChangeFlags.ALL); final LevelChunkBridge mixinChunk = (LevelChunkBridge) worldIn.getChunkAt(pos); - this.tracker$context = BlockPhase.State.DISPENSE.createPhaseContext(PhaseTracker.SERVER) + this.tracker$context = BlockPhase.State.DISPENSE.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)) .source(spongeBlockSnapshot) .creator(() -> mixinChunk.bridge$getBlockCreatorUUID(pos)) .notifier(() -> mixinChunk.bridge$getBlockNotifierUUID(pos)) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java index bf8920550a0..7490c140490 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java @@ -90,7 +90,7 @@ public void randomTick(final net.minecraft.world.level.block.state.BlockState st if (this.shadow$decaying(state)) { // Sponge Start - PhaseTracker checks and phase entry if (!((LevelBridge) worldIn).bridge$isFake()) { - try (final PhaseContext<@NonNull ?> context = BlockPhase.State.BLOCK_DECAY.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = BlockPhase.State.BLOCK_DECAY.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)) .source(new SpongeLocatableBlockBuilder() .world((ServerWorld) worldIn) .position(pos.getX(), pos.getY(), pos.getZ()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java index f2bf8151a03..605c5f04a62 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java @@ -57,11 +57,12 @@ public class SaplingBlockMixin_Tracker { return instance.growTree(level, generator, pos, state, random); } - if (PhaseTracker.getInstance().getPhaseContext() instanceof GrowablePhaseContext) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(level); + if (phaseTracker.getPhaseContext() instanceof GrowablePhaseContext) { instance.growTree(level, generator, pos, state, random); - } else if (PhaseTracker.getInstance().getPhaseContext().doesBlockEventTracking()) { + } else if (phaseTracker.getPhaseContext().doesBlockEventTracking()) { // We can enter the new phase state. - try (GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(PhaseTracker.SERVER) + try (GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(phaseTracker) .world(level) .block(state) .pos(pos)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java index 1aa4d23ee8a..266ada0ee0e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java @@ -130,7 +130,7 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i } // Sponge Start - Build out the BlockTransaction - final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) this.level).getPhaseContext(); final @Nullable BlockEntity existing = this.shadow$getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); // Build a transaction maybe? final WeakReference ref = new WeakReference<>((ServerLevel) this.level); @@ -165,11 +165,12 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i @Inject(method = "postProcessGeneration", at = @At("HEAD")) private void tracker$startChunkPostProcess(final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.level); if (this.tracker$postProcessContext != null) { - PhasePrinter.printMessageWithCaughtException(PhaseTracker.SERVER, "Expected to not have a chunk post process", "Chunk Post Process has not completed!", GenerationPhase.State.CHUNK_LOADING, this.tracker$postProcessContext, new NullPointerException("spongecommon.ChunkMixin_Tracker:tracker$postProcessContext is Null")); + PhasePrinter.printMessageWithCaughtException(phaseTracker, "Expected to not have a chunk post process", "Chunk Post Process has not completed!", GenerationPhase.State.CHUNK_LOADING, this.tracker$postProcessContext, new NullPointerException("spongecommon.ChunkMixin_Tracker:tracker$postProcessContext is Null")); this.tracker$postProcessContext.close(); } - this.tracker$postProcessContext = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.SERVER) + this.tracker$postProcessContext = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .chunk((LevelChunk) (Object) this) .world((ServerLevel) this.level) .buildAndSwitch(); @@ -205,10 +206,11 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i @SuppressWarnings({"rawtypes", "unchecked"}) @Redirect(method = "unpackTicks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/ticks/LevelChunkTicks;unpack(J)V")) private void tracker$wrapRescheduledTicks(final LevelChunkTicks instance, final long $$0) { - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.level); + if (!phaseTracker.onSidedThread()) { return; } - try (final ChunkLoadContext context = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.SERVER)) { + try (final ChunkLoadContext context = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker)) { context.chunk((LevelChunk) (Object) this); context.buildAndSwitch(); instance.unpack($$0); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java index b0ebcce7ac3..de559780be2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java @@ -34,6 +34,7 @@ import net.minecraft.world.level.dimension.end.DragonRespawnAnimation; import net.minecraft.world.level.dimension.end.EndDragonFight; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -50,6 +51,8 @@ public abstract class EndDragonFightMixin_Tracker { // @formatter:off + @Shadow @Final private ServerLevel level; + @Shadow protected abstract EnderDragon shadow$createNewDragon(); // @formatter:on @@ -59,7 +62,7 @@ public abstract class EndDragonFightMixin_Tracker { final RandomSource rand, final BlockPos pos ) { - try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.SERVER)) { + try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn.getLevel()))) { context .world((ServerLevel) worldIn) .generator(generator) @@ -75,7 +78,7 @@ public abstract class EndDragonFightMixin_Tracker { @Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/DragonRespawnAnimation;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/dimension/end/EndDragonFight;Ljava/util/List;ILnet/minecraft/core/BlockPos;)V")) private void tracker$switchToSpawnDragonState(final DragonRespawnAnimation dragonSpawnState, final ServerLevel worldIn, final EndDragonFight manager, final List crystals, int respawnStateTicks, final BlockPos exitPortalLocation) { - try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.SERVER)) { + try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(worldIn))) { context .manager(manager) .setIsRespawn(true) @@ -88,7 +91,7 @@ public abstract class EndDragonFightMixin_Tracker { @Redirect(method = "findOrCreateDragon", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/EndDragonFight;createNewDragon()Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;")) private EnderDragon tracker$switchToSpawnDragonState(final EndDragonFight manager) { - try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.SERVER)) { + try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(this.level))) { context .manager(manager) .setIsRespawn(false) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java index 05776e94678..f34827ef39d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java @@ -58,11 +58,11 @@ public interface NeighborUpdaterMixin_Tracker { )) private static void tracker$wrapNeighborUpdateInSideEffect(Level level, BlockState targetState, BlockPos targetPos, Block fromBlock, @Nullable Orientation orientation, boolean movement, CallbackInfo ci) { // Sponge start - prepare notification - final PhaseContext<@NonNull ?> peek = PhaseTracker.getInstance().getPhaseContext(); if (!(level instanceof ServerLevel serverLevel)) { return; } + final PhaseContext<@NonNull ?> peek = PhaseTracker.getWorldInstance(serverLevel).getPhaseContext(); final var targetChunk = serverLevel.getChunkAt(targetPos); final Supplier worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier(serverLevel, "ServerWorld"); final net.minecraft.world.level.block.entity.@Nullable BlockEntity existingTile = targetChunk.getBlockEntity( diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java index 8b878f94796..e37721c2337 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java @@ -70,7 +70,7 @@ public abstract class LevelTicksMixin_Tracker { final var thisScheduledTick = this.alreadyRunThisTick.get(this.alreadyRunThisTick.size() - 1); if (((ScheduledTickBridge) (Object) thisScheduledTick).bridge$isPartOfWorldGeneration()) { try (final var context = GenerationPhase.State.DEFERRED_SCHEDULED_UPDATE.createPhaseContext( - PhaseTracker.SERVER) + PhaseTracker.getWorldInstance()) .source(this) .scheduledUpdate((BlockPos) blockPos, ticking) ) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java index 0718cf4e114..d1bd9c40e2b 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java @@ -24,8 +24,10 @@ */ package org.spongepowered.vanilla.mixin.core.server.level; +import net.minecraft.server.level.ServerLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.server.level.ServerPlayerBridge; import org.spongepowered.common.event.tracking.PhaseContext; @@ -38,10 +40,14 @@ @Mixin(net.minecraft.server.level.ServerPlayer.class) public abstract class ServerPlayerMixin_Vanilla extends LivingEntityMixin_Vanilla implements ServerPlayerBridge { + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + // override from LivingEntityMixin_Vanilla @Override protected void vanilla$onElytraUse(final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java index 78e63b13177..6b8ab1f5b59 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java @@ -54,7 +54,7 @@ public abstract class ServerGamePacketListenerImplMixin_Vanilla implements Serve final RecipeHolder recipe, final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { final var player = inventory.player; - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(serverLevel).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java index 54d359b533e..477a99368df 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java @@ -25,6 +25,7 @@ package org.spongepowered.vanilla.mixin.tracker.server.level; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.entity.player.Player; @@ -55,7 +56,7 @@ public abstract class ServerPlayerGameModeMixin_Vanilla_Tracker { @Redirect(method = "destroyBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;mineBlock(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)V")) public void vanillaTracker$onMineBlock(final ItemStack itemStack, final Level param0, final BlockState param1, final BlockPos param2, final Player param3) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) param0).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); itemStack.mineBlock(param0, param1, param2, param3); // Needs to get logged as a sideeffect under the BlockChange From e11e9df2dab53a82aeef0ce6bb6b028c9b671d64 Mon Sep 17 00:00:00 2001 From: aromaa Date: Thu, 7 Nov 2024 00:12:12 +0200 Subject: [PATCH 115/586] Fix missed phase tracker changes in the Neo module --- .../core/server/level/ServerPlayerMixin_Neo.java | 8 +++++++- .../ServerGamePacketListenerImplMixin_Neo.java | 2 +- .../level/ServerPlayerMixin_Inventory_Neo.java | 13 ++++++++++--- .../ServerPlayerGameModeMixin_Neo_Tracker.java | 2 +- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java index a3e3bd1629e..20edf213fbe 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java @@ -24,8 +24,10 @@ */ package org.spongepowered.neoforge.mixin.core.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -37,10 +39,14 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Neo extends LivingEntityMixin_Neo { + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + // override from LivingEntityMixin_Neo @Override protected void neo$onElytraUse(final CallbackInfo ci) { - final PhaseContext context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java index ef2000360bf..665f8bc25d7 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java @@ -54,7 +54,7 @@ public abstract class ServerGamePacketListenerImplMixin_Neo implements ServerGam private RecipeBookMenu.PostPlaceAction neo$onPlaceRecipe( final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final var player = this.player; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java index 89551943e50..28309aa5e48 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java @@ -25,6 +25,7 @@ package org.spongepowered.neoforge.mixin.inventory.event.server.level; import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; @@ -32,6 +33,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -43,7 +45,12 @@ import java.util.function.Consumer; @Mixin(ServerPlayer.class) -public class ServerPlayerMixin_Inventory_Neo { +public abstract class ServerPlayerMixin_Inventory_Neo { + + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + @Nullable private Object inventory$menuProvider; @Inject( @@ -56,7 +63,7 @@ public class ServerPlayerMixin_Inventory_Neo { ) ) private void impl$afterOpenMenu(final CallbackInfoReturnable cir) { - PhaseTracker.SERVER.getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); + PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); } @Inject(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initMenu(Lnet/minecraft/world/inventory/AbstractContainerMenu;)V")) @@ -75,7 +82,7 @@ public class ServerPlayerMixin_Inventory_Neo { final MenuProvider menuProvider, final int containerCounter, final net.minecraft.world.entity.player.Inventory inventory, final Player player ) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext() + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logOpenInventory((ServerPlayer) (Object) this) ) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java index 915e707ea5d..089f212ea2d 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java @@ -63,7 +63,7 @@ public abstract class ServerPlayerGameModeMixin_Neo_Tracker { final ItemStack itemStack, final Level level, final BlockState state, final BlockPos pos, final Player player ) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); // Log the prepare drops here because Forge rewrites // this method to call mine block before calling destroy block From c0cf9cd1e8fbec7bd99aee422e6a9d3d642e916f Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 8 Nov 2024 22:49:55 +0200 Subject: [PATCH 116/586] Fix item tier registry --- .../registry/loader/VanillaRegistryLoader.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 8a2491cc8d2..6a04310d6d7 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -57,6 +57,7 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.ToolMaterial; import net.minecraft.world.item.component.FireworkExplosion; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameType; @@ -93,6 +94,8 @@ import net.minecraft.world.scores.criteria.ObjectiveCriteria; import net.minecraft.world.ticks.TickPriority; import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.data.type.ItemTier; +import org.spongepowered.api.data.type.ItemTiers; import org.spongepowered.api.item.FireworkShape; import org.spongepowered.api.item.FireworkShapes; import org.spongepowered.api.registry.Registry; @@ -153,6 +156,7 @@ private void loadInstanceRegistries() { // // this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); this.knownName(RegistryTypes.GAME_RULE, GameRulesAccessor.accessor$GAME_RULE_TYPES().keySet(), rule -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, rule.getId())); + this.holder.createRegistry(RegistryTypes.ITEM_TIER, VanillaRegistryLoader.itemTier()); } private void loadEnumRegistries() { @@ -180,8 +184,6 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.HAND_TYPE, InteractionHand.values()); this.automaticName(RegistryTypes.INSTRUMENT_TYPE, NoteBlockInstrument.values()); this.automaticName(RegistryTypes.ITEM_RARITY, Rarity.values()); - // TODO - Figure out if we should make a registry - Snapshot 24w34a -// this.automaticName(RegistryTypes.ITEM_TIER, ToolMaterial.values()); this.automaticName(RegistryTypes.JIGSAW_BLOCK_ORIENTATION, FrontAndTop.values()); this.automaticName(RegistryTypes.MOOSHROOM_TYPE, MushroomCow.Variant.values()); this.automaticName(RegistryTypes.OBJECTIVE_DISPLAY_MODE, ObjectiveCriteria.RenderType.values()); @@ -257,6 +259,16 @@ private static RegistryLoader fireworkShape() { }); } + private static RegistryLoader itemTier() { + return RegistryLoader.of(l -> { + l.add(ItemTiers.DIAMOND, k -> (ItemTier) (Object) ToolMaterial.DIAMOND); + l.add(ItemTiers.GOLD, k -> (ItemTier) (Object) ToolMaterial.GOLD); + l.add(ItemTiers.IRON, k -> (ItemTier) (Object) ToolMaterial.IRON); + l.add(ItemTiers.NETHERITE, k -> (ItemTier) (Object) ToolMaterial.NETHERITE); + l.add(ItemTiers.STONE, k -> (ItemTier) (Object) ToolMaterial.STONE); + l.add(ItemTiers.WOOD, k -> (ItemTier) (Object) ToolMaterial.WOOD); + }); + } // The following methods are named for clarity above. From bcdde69657685915790c27a3c56c4bd3b542d3cf Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 9 Nov 2024 18:49:57 +0200 Subject: [PATCH 117/586] Hot fix wind charges Explosions are in general busted and requires new API changes. We aren't even correctly handling normal explosives --- .../tracker/server/level/ServerLevelMixin_Tracker.java | 6 +++++- .../tracker/world/level/ServerExplosionMixin_Tracker.java | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index cdb68aa0138..e1766cb999a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -322,7 +322,11 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final var explosionBuilder = org.spongepowered.api.world.explosion.Explosion.builder().from((org.spongepowered.api.world.explosion.Explosion) mcExplosion); - Explosive apiExplosive = (Explosive) entity; + if (!(entity instanceof final Explosive apiExplosive)) { + mcExplosion.explode(); + this.tracker$apiExplosion = explosionBuilder.build(); + return; + } final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(phaseTracker.currentCause(), explosionBuilder, apiExplosive, (org.spongepowered.api.world.explosion.Explosion) instance); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java index 5f5f71eebca..b0fc776e835 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/ServerExplosionMixin_Tracker.java @@ -67,6 +67,10 @@ public abstract class ServerExplosionMixin_Tracker { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;onExplosionHit(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/Explosion;Ljava/util/function/BiConsumer;)V")) private void tracker$onExplosionHit(final BlockState instance, final ServerLevel serverLevel, final BlockPos blockPos, final Explosion explosion, final BiConsumer biConsumer) { + if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK) { + instance.onExplosionHit(serverLevel, blockPos, explosion, biConsumer); + return; + } // this.level.getBlockState($$2).onExplosionHit(this.level, $$2, this, ($$1x, $$2x) -> addOrAppendStack($$1, $$1x, $$2x)); // TODO addOrAppendStack? ItemStack pre merging From e207758b93a354c4b05820749061347bacf4a931 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 9 Nov 2024 21:53:38 +0200 Subject: [PATCH 118/586] Fix furnaces --- .../world/item/crafting/AbstractCookingRecipeMixin_API.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java index 98c6879dd5c..22499c29de5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/AbstractCookingRecipeMixin_API.java @@ -67,9 +67,4 @@ public Optional result(final ItemStackLike ingredient) { public Ticks cookingTime() { return SpongeTicks.ticksOrInfinite(this.shadow$cookingTime()); } - - @Override - public float experience() { - return this.shadow$experience(); - } } From d94ab6b7637e45a6cbaa421611065722ea1c9762 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 10 Nov 2024 02:13:33 +0200 Subject: [PATCH 119/586] More fixes to explosions --- .../common/mixin/core/world/level/ServerExplosionMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java index dcde1d3930a..87cc5812fae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java @@ -56,6 +56,7 @@ import java.util.List; import java.util.Map; import java.util.StringJoiner; +import java.util.stream.Collectors; @Mixin(net.minecraft.world.level.ServerExplosion.class) public abstract class ServerExplosionMixin implements ExplosionBridge { @@ -133,7 +134,7 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { return Collections.emptyList(); // no entities affected } if (this.shadow$interactsWithBlocks()) { - this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).toList(); + this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); } if (this.impl$shouldDamageEntities) { return event.entities().stream().map(Entity.class::cast).toList(); From 7b1d7f45812d8dc5057b7376b22a5b28542bde9b Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 10 Nov 2024 02:14:44 +0200 Subject: [PATCH 120/586] Fix ServerPlayer#teleport overwrite signature --- .../common/mixin/core/server/level/ServerPlayerMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 813326a28e3..6d21338b8a8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -441,7 +441,7 @@ public boolean teleportTo(final ServerLevel world, * @return The {@link Entity} that is either this one, or replaces this one */ @Override - public @Nullable Entity bridge$changeDimension(final TeleportTransition originalTransition) { + public net.minecraft.server.level.@Nullable ServerPlayer bridge$changeDimension(final TeleportTransition originalTransition) { if (this.shadow$isRemoved()) { return null; } @@ -940,7 +940,7 @@ private boolean isPvpAllowed() { * @reason We route all teleportation through sponge's bridge for handling events */ @Overwrite - public @Nullable Entity teleport(final TeleportTransition transition) { + public net.minecraft.server.level.@Nullable ServerPlayer teleport(final TeleportTransition transition) { return this.bridge$changeDimension(transition); } From b666fd341c5a266551b20c8cc7c10a3a3a8140d4 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 10 Nov 2024 02:15:07 +0200 Subject: [PATCH 121/586] Fix recipe item type predicate --- .../common/item/recipe/ingredient/SpongeIngredient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index bbb97b5c596..681ad55e969 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -98,7 +98,8 @@ public class SpongeIngredient extends Ingredient { return DataResult.success(new SpongeRawIngredient(spongeIngredient.type, stacks, Optional.empty())); } case SpongePredicateItemList.TYPE_PREDICATE -> { - return DataResult.success(new SpongeRawIngredient(spongeIngredient.type, List.of(), Optional.ofNullable(spongeIngredient.predicateId))); + final var stacks = Arrays.asList(spongeIngredient.itemList.stacks); + return DataResult.success(new SpongeRawIngredient(spongeIngredient.type, stacks, Optional.ofNullable(spongeIngredient.predicateId))); } } throw new NotImplementedException("Serializing SpongeIngredient is not implemented yet."); From 64bec579a52f098fda968e1c7356a5ed446b6c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:01:25 +0200 Subject: [PATCH 122/586] Add key for item model (#4147) --- SpongeAPI | 2 +- .../common/data/provider/item/stack/ItemStackData.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 3e5a2ce6632..d4641e160e8 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3e5a2ce6632f6eeae1461630ac0149cacdf6e8db +Subproject commit d4641e160e878274d3ac3599d27fc6f583f33acd diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 4b991d5a3ca..5fbc6f83717 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -183,6 +183,9 @@ public static void register(final DataProviderRegistrator registrator) { return true; }) .supports(h -> !h.has(DataComponents.MAX_DAMAGE)) + .create(Keys.MODEL) + .get(stack -> (ResourceKey) (Object) stack.get(DataComponents.ITEM_MODEL)) + .set((stack, model) -> stack.set(DataComponents.ITEM_MODEL, (ResourceLocation) (Object) model)) .create(Keys.ITEM_DURABILITY) .get(stack -> stack.getMaxDamage() - stack.getDamageValue()) .set((stack, durability) -> stack.setDamageValue(stack.getMaxDamage() - durability)) From 34d90f92a8fb1203f22223eb82781663243eb06e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 13 Nov 2024 19:07:10 -0800 Subject: [PATCH 123/586] chore: start update to 24w45a A couple of changes: - There's a new shadow styling for chat - PlayerList items can have 'showHat' - ItemModel custom data is totally broken - Structures got an added registry access for placement - Chunk Region tickets lost POST_TELEPORT entirely, this might be worth looking into a functional replacement or not - Client menu changes, needs fixing --- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++ .../accessor/network/chat/StyleAccessor.java | 12 +++--- .../ServerboundMoveVehiclePacketAccessor.java | 7 +--- .../item/stack/ArmorItemStackData.java | 2 +- .../provider/item/stack/ItemStackData.java | 8 ++-- .../effect/particle/SpongeParticleHelper.java | 2 + .../entity/living/human/HumanEntity.java | 2 +- .../entity/player/tab/SpongeTabList.java | 2 +- .../entity/projectile/ProjectileUtil.java | 2 +- .../structure/StructureMixin_API.java | 18 ++++++++- .../adventure/text/format/StyleImplMixin.java | 1 + .../server/commands/TeleportCommandMixin.java | 2 +- .../core/server/level/ServerPlayerMixin.java | 7 ++-- .../ServerGamePacketListenerImplMixin.java | 16 ++++---- .../core/world/entity/LivingEntityMixin.java | 1 - .../entity/LivingEntityMixin_Attack_Impl.java | 38 +++++++++++-------- .../core/world/item/FishingRodItemMixin.java | 4 +- .../gui/widget/list/FilterableList.java | 11 ++---- .../entity/LivingEntityMixin_Attack_Impl.java | 6 +-- 20 files changed, 87 insertions(+), 64 deletions(-) diff --git a/gradle.properties b/gradle.properties index eb71a3a0c71..a907ce2d34b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.3 +minecraftVersion=24w45a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4046353e1be..fb9c7fed25e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1232,6 +1232,14 @@
+ + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java index ede074bb8f8..d45e749941e 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java @@ -29,20 +29,22 @@ import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; import net.minecraft.resources.ResourceLocation; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; +import javax.annotation.Nullable; +import java.util.Optional; + @Mixin(Style.class) public interface StyleAccessor { @Invoker("") - static Style invoker$new(final @Nullable TextColor color, final @Nullable Boolean bold, final @Nullable Boolean italic, - final @Nullable Boolean underlined, final @Nullable Boolean strikethrough, final @Nullable Boolean obfuscated, - final @Nullable ClickEvent clickEvent, final @Nullable HoverEvent hoverEvent, final @Nullable String insertion, - final @Nullable ResourceLocation font) { + static Style invoker$new(final @Nullable TextColor color, final @Nullable Integer shadowColor, final @Nullable Boolean bold, final @Nullable Boolean italic, + final @Nullable Boolean underlined, final @Nullable Boolean strikethrough, final @Nullable Boolean obfuscated, + final @Nullable ClickEvent clickEvent, final @Nullable HoverEvent hoverEvent, final @Nullable String insertion, + final @Nullable ResourceLocation font) { throw new UntransformedInvokerError(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundMoveVehiclePacketAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundMoveVehiclePacketAccessor.java index c506173e7d3..a0865d608f4 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundMoveVehiclePacketAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundMoveVehiclePacketAccessor.java @@ -25,6 +25,7 @@ package org.spongepowered.common.accessor.network.protocol.game; import net.minecraft.network.protocol.game.ServerboundMoveVehiclePacket; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; @@ -32,11 +33,7 @@ @Mixin(ServerboundMoveVehiclePacket.class) public interface ServerboundMoveVehiclePacketAccessor { - @Accessor("x") @Mutable void accessor$x(final double x); - - @Accessor("y") @Mutable void accessor$y(final double y); - - @Accessor("z") @Mutable void accessor$z(final double z); + @Accessor("position") @Mutable void accessor$position(final Vec3 position); @Accessor("yRot") @Mutable void accessor$yRot(final float yRot); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index 80e8198b33e..45679626783 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { if (equippable == null) { return null; } - return equippable.model() + return equippable.assetId() .map(rl -> (ResourceKey) (Object) rl) .flatMap(rk -> RegistryTypes.ARMOR_MATERIAL.get().findEntry(rk)) .map(RegistryEntry::value) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 4b991d5a3ca..c32e212194e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -117,10 +117,10 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (ItemType) h.getItem().getCraftingRemainder().getItem()) .create(Keys.DISPLAY_NAME) .get(h -> SpongeAdventure.asAdventure(h.getDisplayName())) - .create(Keys.CUSTOM_MODEL_DATA) - .get(h -> h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.DEFAULT).value()) - .set((h, v) -> h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(v))) - .delete(h -> h.remove(DataComponents.CUSTOM_MODEL_DATA)) +// .create(Keys.CUSTOM_MODEL_DATA) +// .get(h -> h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY)) +// .set((h, v) -> h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(v))) +// .delete(h -> h.remove(DataComponents.CUSTOM_MODEL_DATA)) .create(Keys.CUSTOM_NAME) .get(h -> { if (h.has(DataComponents.CUSTOM_NAME)) { diff --git a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java index c09654d2ca8..79d7f2da8f5 100644 --- a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java +++ b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java @@ -243,6 +243,7 @@ public void process(final double x, final double y, final double z, final List

createProjectile(final LivingEntity source, fina @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { if (source instanceof Player) { - final FishingHook hook = new FishingHook((Player) source, source.level(), 0, 0, new ItemStack(Items.FISHING_ROD)); + final FishingHook hook = new FishingHook((Player) source, source.level(), 0, 0); hook.setPos(loc.x(), loc.y(), loc.z()); return ProjectileUtil.doLaunch(loc.world(), (FishingBobber) hook); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java index 349ad7f4869..6d790982a78 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java @@ -30,7 +30,9 @@ import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.SectionPos; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.MobCategory; @@ -73,8 +75,20 @@ public boolean place(final ServerWorld world, final Vector3i pos) { // see PlaceCommand#placeStructure final ServerLevel level = (ServerLevel) world; final ServerChunkCache chunkSource = level.getChunkSource(); - final StructureStart start = ((Structure) (Object) this).generate(level.registryAccess(), chunkSource.getGenerator(), chunkSource.getGenerator().getBiomeSource(), - chunkSource.randomState(), level.getStructureManager(), level.getSeed(), new ChunkPos(VecHelper.toBlockPos(pos)), 0, level, b -> true); + final var key = level.registryAccess().lookupOrThrow(Registries.STRUCTURE).wrapAsHolder((Structure) (Object) this); + final StructureStart start = ((Structure) (Object) this).generate( + key, + level.dimension(), + level.registryAccess(), + chunkSource.getGenerator(), + chunkSource.getGenerator().getBiomeSource(), + chunkSource.randomState(), + level.getStructureManager(), + level.getSeed(), + new ChunkPos(VecHelper.toBlockPos(pos)), + 0, + level, + ignored -> true); if (!start.isValid()) { return false; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java index eee014e0b73..ca7a8065c0d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java @@ -47,6 +47,7 @@ public abstract class StyleImplMixin implements StyleBridge { this.bridge$vanilla = StyleAccessor.invoker$new( // color SpongeAdventure.asVanillaNullable($this.color()), + null, // decorations SpongeAdventure.asVanillaNullable($this.decoration(TextDecoration.BOLD)), SpongeAdventure.asVanillaNullable($this.decoration(TextDecoration.ITALIC)), diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index 1b6676593a7..a08d031d170 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -118,7 +118,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, if (entityIn instanceof ServerPlayer sp) { ChunkPos chunkpos = new ChunkPos(new BlockPos((int) actualX, (int) actualY, (int) actualZ)); - worldIn.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, entityIn.getId()); + worldIn.getChunkSource().addRegionTicket(TicketType.FORCED, chunkpos, 1, chunkpos); entityIn.stopRiding(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 6d21338b8a8..2ba773f469c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -229,7 +229,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr final var thisPlayer = ((net.minecraft.server.level.ServerPlayer) (Object) this); final ChunkPos chunkPos = new ChunkPos(VecHelper.toBlockPos(pos)); - level.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, thisPlayer.getId()); + level.getChunkSource().addRegionTicket(TicketType.FORCED, chunkPos, 1, chunkPos); thisPlayer.stopRiding(); if (thisPlayer.isSleeping()) { @@ -425,9 +425,8 @@ public boolean teleportTo(final ServerLevel world, frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); } - final var thisPlayer = (net.minecraft.server.level.ServerPlayer) (Object) this; return this.bridge$changeDimension(new TeleportTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, - e -> world.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, e.chunkPosition(), 1, thisPlayer.getId()))) != null; + e -> world.getChunkSource().addRegionTicket(TicketType.FORCED, e.chunkPosition(), 1, e.chunkPosition()))) != null; } } @@ -698,7 +697,7 @@ public void die(final DamageSource cause) { final LivingEntity livingentity = this.shadow$getKillCredit(); if (livingentity != null) { this.shadow$awardStat(Stats.ENTITY_KILLED_BY.get(livingentity.getType())); - livingentity.awardKillScore((net.minecraft.server.level.ServerPlayer) (Object) this, this.deathScore, cause); + livingentity.awardKillScore((net.minecraft.server.level.ServerPlayer) (Object) this, cause); this.shadow$createWitherRose(livingentity); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 58c4741603f..244357dfd85 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -293,7 +293,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getControllingPassenger()Lnet/minecraft/world/entity/LivingEntity;") ) private void impl$handleVehicleMoveEvent(final ServerboundMoveVehiclePacket param0, final CallbackInfo ci) { - final ServerboundMoveVehiclePacketAccessor packet = (ServerboundMoveVehiclePacketAccessor) param0; + final ServerboundMoveVehiclePacketAccessor packet = (ServerboundMoveVehiclePacketAccessor) (Object) param0; final Entity rootVehicle = this.player.getRootVehicle(); final Vector3d fromRotation = new Vector3d(rootVehicle.getYRot(), rootVehicle.getXRot(), 0); @@ -301,8 +301,9 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // We need this because we ignore very small position changes as to not spam as many move events. final Vector3d fromPosition = VecHelper.toVector3d(rootVehicle.position()); - final Vector3d originalToPosition = new Vector3d(param0.getX(), param0.getY(), param0.getZ()); - final Vector3d originalToRotation = new Vector3d(param0.getYRot(), param0.getXRot(), 0); + final var position = param0.position(); + final Vector3d originalToPosition = new Vector3d(position.x, position.y(), position.z()); + final Vector3d originalToRotation = new Vector3d(param0.yRot(), param0.xRot(), 0); // common checks and throws are done here. final @Nullable Vector3d toPosition = SpongeCommonEventFactory.callMoveEvent( @@ -325,7 +326,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack if (!fromRotation.equals(toRotation)) { rootVehicle.absMoveTo(rootVehicle.getX(), rootVehicle.getY(), rootVehicle.getZ(), (float) toRotation.y(), (float) toRotation.x()); } - this.connection.send(new ClientboundMoveVehiclePacket(rootVehicle)); + this.connection.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); ci.cancel(); return; } @@ -333,12 +334,11 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack if (!toPosition.equals(originalToPosition) || !toRotation.equals(originalToRotation)) { // notify the client about the new position rootVehicle.absMoveTo(toPosition.x(), toPosition.y(), toPosition.z(), (float) toRotation.y(), (float) toRotation.x()); - this.connection.send(new ClientboundMoveVehiclePacket(rootVehicle)); + this.connection.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); // update the packet, let MC take care of the rest. - packet.accessor$x(toPosition.x()); - packet.accessor$y(toPosition.y()); - packet.accessor$z(toPosition.z()); + final var newPos = VecHelper.toVanillaVector3d(toPosition); + packet.accessor$position(newPos); packet.accessor$yRot((float) toRotation.x()); packet.accessor$xRot((float) toRotation.y()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 994a4510d38..1eeb8e3757c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -92,7 +92,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt // @formatter:off @Shadow protected int useItemRemaining; @Shadow protected boolean dead; - @Shadow protected int deathScore; @Shadow protected ItemStack useItem; @Shadow @Nullable private DamageSource lastDamageSource; @Shadow private long lastDamageStamp; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 8bce4b1a806..73899de7437 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -189,7 +189,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * After calling #actuallyHurt, if cancelled return early * Also reset values */ - @Inject(method = "hurtServer",cancellable = true, + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 1, target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) private void attackImpl$afterActuallyHurt2(ServerLevel $$0, DamageSource $$1, float $$2, CallbackInfoReturnable cir) { @@ -212,32 +212,38 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen return this.attackImpl$actuallyHurtFinalDamage; } - /** - * Sets blocked damage after #actuallyHurt - */ - @ModifyVariable(method = "hurtServer", ordinal = 2, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/damagesource/DamageSource;FFZ)V", - shift = At.Shift.AFTER)) - private float attackImpl$modifyBlockedDamage(float damageBlocked) { - return this.attackImpl$actuallyHurtBlockedDamage; - } - - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) + // TODO - Pending on a Mixin bug: https://github.com/SpongePowered/Mixin/issues/684 +// /** +// * Sets blocked damage after #actuallyHurt +// */ +// @ModifyVariable(method = "hurtServer", ordinal = 1, +// at = @At(value = "INVOKE", +// target = "Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/damagesource/DamageSource;FFZ)V", +// shift = At.Shift.AFTER +// ), +// slice = @Slice( +// from = @At(value = "FIELD", target = "Lnet/minecraft/advancements/CriteriaTriggers;ENTITY_HURT_PLAYER:Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;"), +// to = @At(value = "FIELD", target = "Lnet/minecraft/stats/Stats;DAMAGE_BLOCKED_BY_SHIELD:Lnet/minecraft/resources/ResourceLocation;") +// )) +// private float attackImpl$modifyBlockedDamage(float damageBlocked) { +// return this.attackImpl$actuallyHurtBlockedDamage; +// } + + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) private void attackImpl$onHurtSound(final LivingEntity instance, final DamageSource $$0) { if (this.bridge$vanishState().createsSounds()) { this.shadow$playHurtSound($$0); } } - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) private void attackImpl$onMakeSound(final LivingEntity instance, final SoundEvent $$0) { if (this.bridge$vanishState().createsSounds()) { instance.makeSound($$0); } } - @Inject(method = "actuallyHurt", at = @At(value = "INVOKE",target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F")) + @Inject(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F")) public void attackImpl$startActuallyHurt(final ServerLevel level, final DamageSource damageSource, final float originalDamage, final CallbackInfo ci) { // TODO check for direct call? @@ -341,7 +347,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * {@link #shadow$hurtArmor} * {@link ServerPlayer#awardStat} for {@link Stats#DAMAGE_RESISTED} and {@link Stats#DAMAGE_DEALT} * from {@link LivingEntity#hurt} and #actuallyHurt - * + *

* And capture inventory changes if needed */ protected void attackImpl$handlePostDamage() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java index 6b53414d803..da7ae4469ed 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java @@ -71,7 +71,7 @@ private void onThrowEvent(Level level, Player player, InteractionHand hand, Call if (level instanceof ServerLevel serverLevel) { int $$6 = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemstack, player) * 20.0F); int $$7 = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemstack, player); - FishingHook fishHook = new FishingHook(player, level, $$7, $$6, itemstack); + FishingHook fishHook = new FishingHook(player, level, $$7, $$6); PhaseTracker.getCauseStackManager().pushCause(player); if (SpongeCommon.post(SpongeEventFactory.createFishingEventStart(PhaseTracker.getCauseStackManager().currentCause(), (FishingBobber) fishHook))) { @@ -85,7 +85,7 @@ private void onThrowEvent(Level level, Player player, InteractionHand hand, Call } @Redirect(method = "use", at = @At(value = "NEW", target = "net/minecraft/world/entity/projectile/FishingHook")) - private FishingHook onNewEntityFishHook(final Player $$0, final Level $$1, final int $$2, final int $$3, final ItemStack $$4) { + private FishingHook onNewEntityFishHook(final Player $$0, final Level $$1, final int $$2, final int $$3) { // Use the fish hook we created for the event FishingHook fishHook = this.impl$fishHook; this.impl$fishHook = null; diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java index 3522d2607aa..7ebcc9ef51e 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java @@ -122,11 +122,6 @@ public int getRowLeft() { return this.getX() + 4; } - @Override - protected int getScrollbarPosition() { - return this.getX() + this.width - 6; - } - @Override public void setSelected(@Nullable final E entry) { if (this.selectConsumer != null) { @@ -138,7 +133,7 @@ public void setSelected(@Nullable final E entry) { @Override public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_) { - this.updateScrollingState(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); + this.updateScrolling(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); if (!this.isMouseOver(p_mouseClicked_1_, p_mouseClicked_3_)) { return false; } else { @@ -150,8 +145,8 @@ public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouse return true; } } else if (p_mouseClicked_5_ == 0) { - this.clickedHeader((int) (p_mouseClicked_1_ - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), - (int) (p_mouseClicked_3_ - (double) this.getY()) + (int) this.getScrollAmount() - 4); + this.onClick((int) (p_mouseClicked_1_ - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), + (int) (p_mouseClicked_3_ - (double) this.getY()) + (int) this.scrollAmount() - 4); return true; } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 718aacee6b9..ccb7d33c84a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -41,18 +41,18 @@ public abstract class LivingEntityMixin_Attack_Impl { @SuppressWarnings("InvalidInjectorMethodSignature") - @ModifyConstant(method = "hurtServer", constant = @Constant(classValue = Wolf.class, ordinal = 0)) + @ModifyConstant(method = "resolvePlayerResponsibleForDamage", constant = @Constant(classValue = Wolf.class, ordinal = 0)) private Class attackImpl$onWolfCast(final Object entity, final Class wolf) { return TamableAnimal.class; } - @Redirect(method = "hurtServer", + @Redirect(method = "resolvePlayerResponsibleForDamage", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;isTame()Z")) private boolean attackImpl$onWolfIsTame(@Coerce final Object instance) { return ((TamableAnimal)instance).isTame(); } - @Redirect(method = "hurtServer", + @Redirect(method = "resolvePlayerResponsibleForDamage", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwner()Lnet/minecraft/world/entity/LivingEntity;")) private LivingEntity attackImpl$onWolfGetOwner(@Coerce final Object instance) { return ((TamableAnimal)instance).getOwner(); From 7f50cece93b9cbc4e4f69aeded675f8eac5861e2 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 13 Nov 2024 22:21:19 -0800 Subject: [PATCH 124/586] chore: update to 24w46a - Creaking no longer has a transient entity type - API types are updated - FeatureFlag winterdrop is gone --- SpongeAPI | 2 +- .../generator/BlockStatePropertiesGenerator.java | 5 +---- .../generator/BlockStatePropertyKeysGenerator.java | 5 +---- .../vanilla/generator/GeneratorMain.java | 7 ------- .../vanilla/generator/RegistryEntriesGenerator.java | 12 ++++++------ gradle.properties | 2 +- ...gTransientAccessor.java => CreakingAccessor.java} | 8 +++----- src/accessors/resources/mixins.sponge.accessors.json | 2 +- .../common/data/provider/entity/CreakingData.java | 11 +++++------ 9 files changed, 19 insertions(+), 35 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/{CreakingTransientAccessor.java => CreakingAccessor.java} (87%) diff --git a/SpongeAPI b/SpongeAPI index 3e5a2ce6632..15e9b4d0827 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3e5a2ce6632f6eeae1461630ac0149cacdf6e8db +Subproject commit 15e9b4d0827896bf6639baa23647c63d7001ca98 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index fbcf5ea6048..b20d1a0c357 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -32,7 +32,6 @@ import net.minecraft.core.FrontAndTop; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -63,6 +62,7 @@ import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; +import javax.lang.model.element.Modifier; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; @@ -70,8 +70,6 @@ import java.util.Map; import java.util.TreeMap; -import javax.lang.model.element.Modifier; - /** * Generates catalog classes for {@link BlockState} properties. */ @@ -132,7 +130,6 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(StructureMode.class, BlockStatePropertiesGenerator.inDataTypePkg("StructureMode")); vanillaEnumTypeMapping.put(PistonType.class, BlockStatePropertiesGenerator.inDataTypePkg("PistonType")); vanillaEnumTypeMapping.put(BambooLeaves.class, BlockStatePropertiesGenerator.inDataTypePkg("BambooLeavesType")); - vanillaEnumTypeMapping.put(CreakingHeartBlock.CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeart")); vanillaEnumTypeMapping.put(WallSide.class, BlockStatePropertiesGenerator.inDataTypePkg("WallConnectionState")); vanillaEnumTypeMapping.put(RailShape.class, BlockStatePropertiesGenerator.inDataTypePkg("RailDirection")); vanillaEnumTypeMapping.put(AttachFace.class, BlockStatePropertiesGenerator.inDataTypePkg("AttachmentSurface")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index 8e269ac5864..80a2d6685b6 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -33,7 +33,6 @@ import com.squareup.javapoet.TypeVariableName; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; -import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -64,6 +63,7 @@ import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; +import javax.lang.model.element.Modifier; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; @@ -71,8 +71,6 @@ import java.util.TreeMap; import java.util.function.Function; -import javax.lang.model.element.Modifier; - /** * Generates catalog classes for {@link BlockState} properties. */ @@ -130,7 +128,6 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(StructureMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("StructureMode")); vanillaEnumTypeMapping.put(PistonType.class, BlockStatePropertyKeysGenerator.inDataTypePkg("PistonType")); vanillaEnumTypeMapping.put(BambooLeaves.class, BlockStatePropertyKeysGenerator.inDataTypePkg("BambooLeavesType")); - vanillaEnumTypeMapping.put(CreakingHeartBlock.CreakingHeartState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CreakingHeart")); vanillaEnumTypeMapping.put(WallSide.class, BlockStatePropertyKeysGenerator.inDataTypePkg("WallConnectionState")); vanillaEnumTypeMapping.put(RailShape.class, BlockStatePropertyKeysGenerator.inDataTypePkg("RailDirection")); vanillaEnumTypeMapping.put(AttachFace.class, BlockStatePropertyKeysGenerator.inDataTypePkg("AttachmentSurface")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index aa8df42e4e4..01d1c00cd60 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -247,13 +247,6 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), - new EnumEntriesValidator<>( - "data.type", - "CreakingHearts", - CreakingHeartBlock.CreakingHeartState.class, - "getSerializedName", - "sponge" - ), new RegistryEntriesGenerator<>( "map.decoration", "MapDecorationTypes", diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index 753594ccfeb..73ea1f9a0ee 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -164,12 +164,12 @@ private FieldSpec makeField(final String ownType, final TypeName fieldType, fina if (!featureFlagSet.isSubsetOf(FeatureFlags.VANILLA_SET)) { final var flags = FeatureFlags.REGISTRY.toNames(featureFlagSet).stream().map(rl -> rl.getNamespace().equals("minecraft") ? rl.getPath() : rl.getNamespace() + ":" + rl.getPath()).toArray(); // Use this when new feature flags are introduced - if (featureFlagSet.contains(FeatureFlags.WINTER_DROP)) { - var annotation = AnnotationSpec.builder(ClassName.get("org.spongepowered.api.util.annotation", "Experimental")) - .addMember("value", "$S", flags).build(); - builder.addAnnotation(annotation).build(); - builder.addAnnotation(ApiStatus.Experimental.class).build(); - } +// if (featureFlagSet.contains(FeatureFlags.WINTER_DROP)) { +// var annotation = AnnotationSpec.builder(ClassName.get("org.spongepowered.api.util.annotation", "Experimental")) +// .addMember("value", "$S", flags).build(); +// builder.addAnnotation(annotation).build(); +// builder.addAnnotation(ApiStatus.Experimental.class).build(); +// } } diff --git a/gradle.properties b/gradle.properties index a907ce2d34b..76d2dfe4de1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w45a +minecraftVersion=24w46a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java similarity index 87% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java index a3a80e54d1a..31b68034114 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingTransientAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java @@ -25,15 +25,13 @@ package org.spongepowered.common.accessor.world.entity.monster.creaking; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.monster.creaking.CreakingTransient; +import net.minecraft.world.entity.monster.creaking.Creaking; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(CreakingTransient.class) -public interface CreakingTransientAccessor { +@Mixin(Creaking.class) +public interface CreakingAccessor { @Accessor("homePos") BlockPos accessor$homePos(); - @Accessor("homePos") void accessor$setHomePos(BlockPos pos); - } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 2bd0ef591fc..25428b831b8 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -107,7 +107,7 @@ "world.entity.monster.VexAccessor", "world.entity.monster.VindicatorAccessor", "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.monster.creaking.CreakingTransientAccessor", + "world.entity.monster.creaking.CreakingAccessor", "world.entity.npc.AbstractVillagerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java index 7bec37c48c6..953b3716fbc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java @@ -25,9 +25,8 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.world.entity.monster.creaking.Creaking; -import net.minecraft.world.entity.monster.creaking.CreakingTransient; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.creaking.CreakingTransientAccessor; +import org.spongepowered.common.accessor.world.entity.monster.creaking.CreakingAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.VecHelper; @@ -38,12 +37,12 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(Creaking.class) .create(Keys.CREAKING_IS_LINKED) - .get(e -> e instanceof CreakingTransient); + .get(Creaking::isTransient); registrator - .asMutable(CreakingTransient.class) + .asMutable(Creaking.class) .create(Keys.CREAKING_HOME_POSITION) - .get(h -> VecHelper.toVector3i(((CreakingTransientAccessor) h).accessor$homePos())) - .set((h, v) -> ((CreakingTransientAccessor) h).accessor$setHomePos(VecHelper.toBlockPos(v))); + .get(h -> VecHelper.toVector3i(((CreakingAccessor) h).accessor$homePos())) + .set((h, v) -> h.setTransient(VecHelper.toBlockPos(v))); ; } // @formatter:on From 9b83c9328f0f13be96cd49772a04c8f01737093e Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 10 Nov 2024 14:21:28 +0200 Subject: [PATCH 125/586] Fix registries that rely on order Vanilla no longer allows to register items to arbitrary ids but some of our registries rely on this due to the way vanilla stores this data and has no natural registries for them. Fixing this by registering the items in the order we want them to be present in and then verying their ids match the ones we expected afterwards. While this is very brittle, it is the most straight forward way to ensure we stay in sync with vanilla elements without more complex changes. --- .../common/registry/RegistryHolderLogic.java | 23 ++++++++----------- .../common/registry/RegistryLoader.java | 3 ++- .../loader/VanillaRegistryLoader.java | 6 ++--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 5fa7a4589bd..6aa0912b050 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -178,19 +178,16 @@ public Registry createRegistry(final RegistryType type, final @Nullabl if (defaultValues != null) { final MappedRegistry mr = (MappedRegistry) registry; defaultValues.forEach((vk, vi, vv) -> { - if (vi.isPresent()) { - mr.register( - net.minecraft.resources.ResourceKey.create(key, (ResourceLocation) (Object) vk), - vv, - RegistrationInfo.BUILT_IN - ); - } else { - mr.register( - net.minecraft.resources.ResourceKey.create(key, (ResourceLocation) (Object) vk), - vv, - RegistrationInfo.BUILT_IN - ); - } + mr.register( + net.minecraft.resources.ResourceKey.create(key, (ResourceLocation) (Object) vk), + vv, + RegistrationInfo.BUILT_IN + ); + vi.ifPresent(id -> { + if (mr.getId(vv) != id) { + throw new IllegalStateException("Registry entry " + vk + " was expected to have id of " + id + " but was instead " + mr.getId(vv)); + } + }); }); } diff --git a/src/main/java/org/spongepowered/common/registry/RegistryLoader.java b/src/main/java/org/spongepowered/common/registry/RegistryLoader.java index b16aaa5d37b..8521b091e51 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryLoader.java @@ -30,6 +30,7 @@ import org.spongepowered.api.registry.RegistryKey; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; @@ -37,7 +38,7 @@ public final class RegistryLoader extends InitialRegistryData { - private final Map values = new HashMap<>(); + private final Map values = new LinkedHashMap<>(); private @MonotonicNonNull Map ids; private RegistryLoader() { diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 6a04310d6d7..ab2279e8cb9 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -251,11 +251,11 @@ private static RegistryLoader criterion() { private static RegistryLoader fireworkShape() { return RegistryLoader.of(l -> { - l.addWithId(FireworkExplosion.Shape.BURST.getId(), FireworkShapes.BURST, () -> (FireworkShape) (Object) FireworkExplosion.Shape.BURST); - l.addWithId(FireworkExplosion.Shape.CREEPER.getId(), FireworkShapes.CREEPER, () -> (FireworkShape) (Object) FireworkExplosion.Shape.CREEPER); - l.addWithId(FireworkExplosion.Shape.LARGE_BALL.getId(), FireworkShapes.LARGE_BALL, () -> (FireworkShape) (Object) FireworkExplosion.Shape.LARGE_BALL); l.addWithId(FireworkExplosion.Shape.SMALL_BALL.getId(), FireworkShapes.SMALL_BALL, () -> (FireworkShape) (Object) FireworkExplosion.Shape.SMALL_BALL); + l.addWithId(FireworkExplosion.Shape.LARGE_BALL.getId(), FireworkShapes.LARGE_BALL, () -> (FireworkShape) (Object) FireworkExplosion.Shape.LARGE_BALL); l.addWithId(FireworkExplosion.Shape.STAR.getId(), FireworkShapes.STAR, () -> (FireworkShape) (Object) FireworkExplosion.Shape.STAR); + l.addWithId(FireworkExplosion.Shape.CREEPER.getId(), FireworkShapes.CREEPER, () -> (FireworkShape) (Object) FireworkExplosion.Shape.CREEPER); + l.addWithId(FireworkExplosion.Shape.BURST.getId(), FireworkShapes.BURST, () -> (FireworkShape) (Object) FireworkExplosion.Shape.BURST); }); } From 89310cdb22156c335b90a1823410c1e29c89fc81 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 11 Nov 2024 21:34:34 +0200 Subject: [PATCH 126/586] Fix Chunk#entities returning all entities of the world --- .../common/world/volume/VolumeStreamUtils.java | 4 ++-- .../world/level/chunk/LevelChunkMixin_API.java | 14 +++++++++----- .../entityactivation/EntityActivationRange.java | 3 +-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index b6f2f0b20dd..acd61727b3a 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -219,14 +219,14 @@ public static void validateStreamArgs(final Vector3i min, final Vector3i max, fi ) { if (chunk.getLevel() instanceof ServerLevel) { return ((PersistentEntitySectionManagerAccessor) ((ServerLevelAccessor) chunk.getLevel()).accessor$getEntityManager()).accessor$sectionStorage() - .getExistingSectionsInChunk(SectionPos.of(chunk.getPos(), 0).asLong()) + .getExistingSectionsInChunk(chunk.getPos().toLong()) .flatMap(EntitySection::getEntities) .filter(entity -> VecHelper.inBounds(entity.blockPosition(), min, max)) .map(entity -> new AbstractMap.SimpleEntry<>(entity.blockPosition(), entity)); } else if (Sponge.isClientAvailable() && chunk.getLevel() instanceof ClientLevel) { return ((TransientEntitySectionManagerAccessor) ((ClientLevelAccessor) chunk.getLevel()).accessor$getEntityStorage()) .accessor$sectionStorage() - .getExistingSectionsInChunk(SectionPos.of(chunk.getPos(), 0).asLong()) + .getExistingSectionsInChunk(chunk.getPos().toLong()) .flatMap(EntitySection::getEntities) .filter(entity -> VecHelper.inBounds(entity.blockPosition(), min, max)) .map(entity -> new AbstractMap.SimpleEntry<>(entity.blockPosition(), entity)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index 29080211aac..e8bb8cbfce8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -39,6 +39,9 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.UpgradeData; +import net.minecraft.world.level.entity.EntitySection; +import net.minecraft.world.level.entity.EntitySectionStorage; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.blending.BlendingData; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -71,7 +74,9 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.server.level.ServerLevelAccessor; import org.spongepowered.common.accessor.world.level.LevelAccessor; +import org.spongepowered.common.accessor.world.level.entity.PersistentEntitySectionManagerAccessor; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.data.holder.SpongeServerLocationBaseDataHolder; @@ -100,7 +105,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.stream.StreamSupport; @Mixin(net.minecraft.world.level.chunk.LevelChunk.class) @Implements(@Interface(iface = WorldChunk.class, prefix = "worldChunk$", remap = Interface.Remap.NONE)) @@ -418,12 +422,12 @@ public Optional entity(final UUID uuid) { .filter(x -> x.chunkPosition().equals(this.chunkPos)); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Collection entities() { - return (Collection) (Object) StreamSupport.stream( - ((LevelAccessor) this.level).invoker$getEntities().getAll().spliterator(), false) - .collect(Collectors.toList()); + final PersistentEntitySectionManager entityManager = ((ServerLevelAccessor) this.level).accessor$getEntityManager(); + final EntitySectionStorage entitySectionStorage = ((PersistentEntitySectionManagerAccessor) entityManager).accessor$sectionStorage(); + return (Collection) entitySectionStorage.getExistingSectionsInChunk(this.chunkPos.toLong()).flatMap(EntitySection::getEntities).toList(); } @SuppressWarnings({"rawtypes", "unchecked"}) diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index 0e1337201d6..6f123326cde 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -25,7 +25,6 @@ package org.spongepowered.common.mixin.plugin.entityactivation; import com.google.common.collect.ImmutableMap; -import net.minecraft.core.SectionPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -262,7 +261,7 @@ public static void activateEntities(final ServerLevel world) { private static void activateChunkEntities(final ServerPlayer player, final LevelChunk chunk) { final PersistentEntitySectionManager entityManager = ((ServerLevelAccessor) chunk.getLevel()).accessor$getEntityManager(); final EntitySectionStorage entitySectionStorage = ((PersistentEntitySectionManagerAccessor) entityManager).accessor$sectionStorage(); - entitySectionStorage.getExistingSectionsInChunk(SectionPos.of(chunk.getPos(), 0).asLong()).flatMap(EntitySection::getEntities).forEach(entity -> { + entitySectionStorage.getExistingSectionsInChunk(chunk.getPos().toLong()).flatMap(EntitySection::getEntities).forEach(entity -> { if (!entity.chunkPosition().equals(chunk.getPos())) { return; } From 43f6ac3a8e4e4c0e21f2c1f24edde678f6dbfdb5 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 11 Nov 2024 21:35:37 +0200 Subject: [PATCH 127/586] Fix ChunkEvent#Unload fired too late --- .../core/server/level/ChunkHolderMixin.java | 34 ++++++++++++++++--- .../core/server/level/ChunkMapMixin.java | 14 -------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java index a58cb5b70d4..6b3535cd498 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java @@ -53,18 +53,44 @@ abstract class ChunkHolderMixin extends GenerationChunkHolderMixin { @Shadow public abstract CompletableFuture> shadow$getEntityTickingChunkFuture(); // @formatter:on + private LevelChunk impl$loadedChunk; + /** * After onFullChunkStatusChange */ @Inject(method = "lambda$scheduleFullChunkPromotion$4", at = @At("TAIL")) private void impl$onScheduleFullChunkPromotion(final ChunkMap $$0x, final FullChunkStatus $$1x, final CallbackInfo ci) { - if ($$1x == FullChunkStatus.ENTITY_TICKING && ShouldFire.CHUNK_EVENT_LOAD) { + if ($$1x == FullChunkStatus.ENTITY_TICKING) { this.shadow$getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).ifSuccess(chunk -> { - final Vector3i chunkPos = VecHelper.toVector3i(chunk.getPos()); - final ChunkEvent.Load event = SpongeEventFactory.createChunkEventLoad(PhaseTracker.getInstance().currentCause(), + this.impl$loadedChunk = chunk; + if (ShouldFire.CHUNK_EVENT_LOAD) { + final Vector3i chunkPos = VecHelper.toVector3i(chunk.getPos()); + final ChunkEvent.Load event = SpongeEventFactory.createChunkEventLoad(PhaseTracker.getInstance().currentCause(), (WorldChunk) chunk, chunkPos, (ResourceKey) (Object) chunk.getLevel().dimension().location()); - SpongeCommon.post(event); + SpongeCommon.post(event); + } }); } } + + @Inject(method = "demoteFullChunk", at = @At("HEAD")) + private void impl$onDemoteFullChunkPre(final ChunkMap $$0x, final FullChunkStatus $$1x, final CallbackInfo ci) { + if (this.impl$loadedChunk != null && ShouldFire.CHUNK_EVENT_UNLOAD_PRE) { + final Vector3i chunkPos = VecHelper.toVector3i(this.impl$loadedChunk.getPos()); + final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPre(PhaseTracker.getInstance().currentCause(), + (WorldChunk) this.impl$loadedChunk, chunkPos, (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().location()); + SpongeCommon.post(event); + } + } + + @Inject(method = "demoteFullChunk", at = @At("TAIL")) + private void impl$onDemoteFullChunkPost(final ChunkMap $$0x, final FullChunkStatus $$1x, final CallbackInfo ci) { + if (this.impl$loadedChunk != null && ShouldFire.CHUNK_EVENT_UNLOAD_POST) { + final Vector3i chunkPos = VecHelper.toVector3i(this.impl$loadedChunk.getPos()); + final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPost(PhaseTracker.getInstance().currentCause(), chunkPos, + (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().location()); + SpongeCommon.post(event); + } + this.impl$loadedChunk = null; + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java index 4780c5edbcd..2a19edb8b3e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java @@ -117,14 +117,6 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { ) ) private void impl$onSetUnloaded(final ServerLevel level, final LevelChunk chunk) { - final Vector3i chunkPos = VecHelper.toVector3i(chunk.getPos()); - - if (ShouldFire.CHUNK_EVENT_UNLOAD_PRE) { - final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPre(PhaseTracker.getInstance().currentCause(), - (WorldChunk) chunk, chunkPos, (ResourceKey) (Object) this.level.dimension().location()); - SpongeCommon.post(event); - } - level.unload(chunk); for (final Direction dir : Constants.Chunk.CARDINAL_DIRECTIONS) { @@ -136,12 +128,6 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { ((LevelChunkBridge) neighbor).bridge$setNeighborChunk(oppositeIndex, null); } } - - if (ShouldFire.CHUNK_EVENT_UNLOAD_POST) { - final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPost(PhaseTracker.getInstance().currentCause(), chunkPos, - (ResourceKey) (Object) this.level.dimension().location()); - SpongeCommon.post(event); - } } @Inject(method = "save", at = @At(value = "HEAD"), cancellable = true) From dbdc282bf8f291ce84c71927493846a186b27a23 Mon Sep 17 00:00:00 2001 From: Nel <57587152+nelind3@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:29:23 +0100 Subject: [PATCH 128/586] Update ServerLevelMixin::save to match the vanilla impl again (#4148) --- .../common/mixin/core/server/level/ServerLevelMixin.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 3f7af4b2ea8..ce4e2f2b124 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -46,6 +46,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.util.ProgressListener; import net.minecraft.world.RandomSequences; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.entity.player.Player; @@ -60,6 +61,7 @@ import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.storage.LevelStorageSource; @@ -136,6 +138,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel // @formatter:off @Shadow @Final private ServerLevelData serverLevelData; + @Shadow @Final private PersistentEntitySectionManager entityManager; @Shadow @Final private LevelTicks blockTicks; @Shadow @Final private LevelTicks fluidTicks; @Shadow private int emptyTime; @@ -398,6 +401,12 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, chunkProvider.save(flush); } + if (flush) { + this.entityManager.saveAll(); + } else { + this.entityManager.autoSave(); + } + Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPost(currentCause, ((ServerWorld) this))); } } From 8c20e204ba011a7453ba6f7c3c183ce94063de02 Mon Sep 17 00:00:00 2001 From: aromaa Date: Thu, 14 Nov 2024 19:06:47 +0200 Subject: [PATCH 129/586] Fix maps --- .../common/map/decoration/SpongeMapDecorationBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java b/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java index f66e259aeba..1b65b346685 100644 --- a/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java +++ b/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java @@ -125,7 +125,7 @@ public MapDecoration.Builder fromContainer(final DataView container) { final byte rot = this.getByteFromContainer(container, Constants.Map.DECORATION_ROTATION); - final var mcType = BuiltInRegistries.MAP_DECORATION_TYPE.get((ResourceLocation) (Object) type); + final var mcType = BuiltInRegistries.MAP_DECORATION_TYPE.getValue((ResourceLocation) (Object) type); if (mcType == null) { throw new IllegalStateException("Missing a MapDecorationType, could not find one for Minecraft's MapDecoration.Type: " + type); } From 7a43d1aaaae20857113dff5c881f3545d50c5d65 Mon Sep 17 00:00:00 2001 From: aromaa Date: Thu, 14 Nov 2024 19:08:07 +0200 Subject: [PATCH 130/586] Implement DataTranslatable TypeSerializer --- .../DataTranslatableTypeSerializer.java | 73 +++++++++++++++++++ .../common/config/PluginConfigManager.java | 3 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/spongepowered/common/config/DataTranslatableTypeSerializer.java diff --git a/src/main/java/org/spongepowered/common/config/DataTranslatableTypeSerializer.java b/src/main/java/org/spongepowered/common/config/DataTranslatableTypeSerializer.java new file mode 100644 index 00000000000..9ff9379395f --- /dev/null +++ b/src/main/java/org/spongepowered/common/config/DataTranslatableTypeSerializer.java @@ -0,0 +1,73 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.config; + +import io.leangen.geantyref.GenericTypeReflector; +import org.spongepowered.api.data.DataManager; +import org.spongepowered.api.data.persistence.DataTranslator; +import org.spongepowered.common.data.persistence.ConfigurateTranslator; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; + +import javax.inject.Inject; + +public final class DataTranslatableTypeSerializer implements TypeSerializer { + + private final DataManager dataManager; + + @Inject + DataTranslatableTypeSerializer(final DataManager dataManager) { + this.dataManager = dataManager; + } + + public boolean accepts(final Type x) { + return this.dataManager.translator(GenericTypeReflector.erase(x)).isPresent(); + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(final Type type, final ConfigurationNode value) throws SerializationException { + final Class clazz = (Class) GenericTypeReflector.erase(type); + final DataTranslator translator = this.dataManager.translator(clazz) + .orElseThrow(() -> new SerializationException("Could not translate of DataTranslatable type: " + clazz.getName())); + return translator.translate(ConfigurateTranslator.instance().translate(value)); + } + + @SuppressWarnings("unchecked") + @Override + public void serialize(final Type type, final Object obj, final ConfigurationNode value) throws SerializationException { + if (obj == null) { + value.raw(null); + } else { + final Class clazz = (Class) GenericTypeReflector.erase(type); + final DataTranslator translator = this.dataManager.translator(clazz) + .orElseThrow(() -> new SerializationException("Could not translate of DataTranslatable type: " + clazz.getName())); + ConfigurateTranslator.instance().translateDataToNode(value, translator.translate(obj)); + } + } +} diff --git a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java index 60389388981..3fb5af7a96c 100644 --- a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java +++ b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java @@ -49,7 +49,7 @@ public final class PluginConfigManager implements ConfigManager { private final WatchServiceListener listener; @Inject - PluginConfigManager(final DataSerializableTypeSerializer dataSerializableSerializer) throws IOException { + PluginConfigManager(final DataSerializableTypeSerializer dataSerializableSerializer, final DataTranslatableTypeSerializer dataTranslatableSerializer) throws IOException { // TODO: Move this onto the async scheduler, rather than shared FJ pool? this.listener = WatchServiceListener.builder() .threadFactory(new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Sponge-WatchService-%d").build()) @@ -60,6 +60,7 @@ public final class PluginConfigManager implements ConfigManager { // See https://github.com/SpongePowered/SpongeCommon/issues/1348 .register(DataSerializableTypeSerializer::accepts, dataSerializableSerializer) .registerAll(SpongeAdventure.CONFIGURATE.serializers()) + .register(dataTranslatableSerializer::accepts, dataTranslatableSerializer) .build(); } From 87d0ae6710257259e69555004d0af7977986acad Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 16 Nov 2024 12:15:15 -0800 Subject: [PATCH 131/586] chore: make the snapshot runnable - fix some imports - Ingredients use a stream of items now --- .../minecraft/world/item/crafting/IngredientMixin_API.java | 5 +++-- .../vanilla/server/packs/PluginPackResources.java | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java index 9e1b16db4be..096b1ee5784 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/IngredientMixin_API.java @@ -39,6 +39,7 @@ import org.spongepowered.common.item.util.ItemStackUtil; import java.util.List; +import java.util.stream.Stream; @Mixin(Ingredient.class) @Implements(@Interface(iface = org.spongepowered.api.item.recipe.crafting.Ingredient.class, prefix = "ingredient$", remap = Remap.NONE)) @@ -46,11 +47,11 @@ public abstract class IngredientMixin_API { // @formatter:off @Shadow public abstract boolean shadow$test(@Nullable ItemStack p_test_1_); - @Shadow public abstract List> shadow$items(); + @Shadow public abstract Stream> shadow$items(); // @formatter:on public List ingredient$displayedItems() { - return this.shadow$items().stream().map((holder) -> (ItemType) holder.value()).toList(); + return this.shadow$items().map((holder) -> (ItemType) holder.value()).toList(); } public boolean ingredient$test(final ItemStackLike itemStack) { diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java index 067a29faa37..8879fce54c7 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java @@ -30,7 +30,7 @@ import net.minecraft.server.packs.AbstractPackResources; import net.minecraft.server.packs.PackLocationInfo; import net.minecraft.server.packs.PackType; -import net.minecraft.server.packs.metadata.MetadataSectionSerializer; +import net.minecraft.server.packs.metadata.MetadataSectionType; import net.minecraft.server.packs.metadata.pack.PackMetadataSection; import net.minecraft.server.packs.resources.IoSupplier; import org.checkerframework.checker.nullness.qual.Nullable; @@ -109,8 +109,8 @@ private ResourceLocation convertResourcePath(final String namespace, final Path @Nullable @Override - public T getMetadataSection(final MetadataSectionSerializer deserializer) throws IOException { - if (deserializer.getMetadataSectionName().equals("pack")) { + public T getMetadataSection(final MetadataSectionType deserializer) throws IOException { + if (deserializer.name().equals("pack")) { return (T) this.metadata; } return null; From 0ee303e3550b549113be27f546703f759bcd72e4 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 18 Nov 2024 20:21:49 +0200 Subject: [PATCH 132/586] Re-enable riding player entities --- .../common/mixin/core/world/entity/EntityMixin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index fff2eb84924..ffdf5b5fb9b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -992,4 +992,10 @@ public void stopRiding() { }*/ + @Redirect(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;canSerialize()Z")) + private boolean impl$allowRidingAnything(final EntityType instance) { + //Vanilla has started to prevent riding non-serializable entities. + //This results in players being unable to ride other players. + return true; + } } From 3e80501780ae54e2e94e40f88da1585cf50a7a36 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 18 Nov 2024 20:22:09 +0200 Subject: [PATCH 133/586] Fix movement events --- .../ServerGamePacketListenerImplMixin.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 6af24aacca1..4dc4445da99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -265,9 +265,9 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack this.shadow$teleport(new PositionMoveRotation( VecHelper.toVanillaVector3d(fromPosition), Vec3.ZERO, - (float) toRotation.y(), (float) toRotation.x() + (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) ), - EnumSet.of(Relative.X_ROT, Relative.Y_ROT) + Relative.ROTATION ); ci.cancel(); return; @@ -283,10 +283,11 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); this.shadow$teleport(new PositionMoveRotation( - VecHelper.toVanillaVector3d(toPosition), + VecHelper.toVanillaVector3d(toPosition.sub(originalToPosition)), Vec3.ZERO, - (float) toRotation.y(), (float) toRotation.x()), - EnumSet.allOf(Relative.class)); + (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) + ), + Relative.ALL); ci.cancel(); } else if (!toRotation.equals(originalToRotation)) { // Notify the client about the new rotation. @@ -294,9 +295,12 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // The rotation values can be out of "valid" range so set them directly to the same value the client has. this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); - this.shadow$teleport(fromPosition.x(), fromPosition.y(), fromPosition.z(), - (float) toRotation.y(), (float) toRotation.x(), - EnumSet.allOf(RelativeMovement.class)); + this.shadow$teleport(new PositionMoveRotation( + Vec3.ZERO, + Vec3.ZERO, + (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) + ), + EnumSet.of(Relative.X, Relative.Y, Relative.Z, Relative.X_ROT, Relative.Y_ROT, Relative.DELTA_X, Relative.DELTA_Y, Relative.DELTA_Z)); // Let MC handle the movement but override the rotation. ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$yRot((float) toRotation.y()); From 1fff0942ef29a492f2baf0b148462dfbcda048a1 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 21 Nov 2024 21:27:05 +0100 Subject: [PATCH 134/586] Disable spotless on forge until ready --- .github/workflows/check-spotless.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-spotless.yaml b/.github/workflows/check-spotless.yaml index 5919a3117ef..acbdc2e8064 100644 --- a/.github/workflows/check-spotless.yaml +++ b/.github/workflows/check-spotless.yaml @@ -11,5 +11,5 @@ jobs: uses: SpongePowered/.github/.github/workflows/shared-check-spotless.yaml@master with: runtime_version: 21 - extra_gradle_params: "-Pprojects=vanilla,forge,neoforge,testplugins" + extra_gradle_params: "-Pprojects=vanilla,neoforge,testplugins" secrets: inherit From 837b428d1a653cda9803dbdedfb1ee5aad829cb3 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 21 Nov 2024 22:07:37 -0800 Subject: [PATCH 135/586] chore: update to 1.21.4-pre1 - fixes CreakingData - fixes unleashing injection point for the event --- gradle.properties | 2 +- gradle/verification-metadata.xml | 389 ++++++++++++++++++ .../monster/creaking/CreakingAccessor.java | 37 -- .../resources/mixins.sponge.accessors.json | 1 - .../data/provider/entity/CreakingData.java | 5 +- .../data/provider/entity/LeashableData.java | 6 +- .../item/stack/SpawnEggItemStackData.java | 5 +- .../core/world/entity/LeashableMixin.java | 31 ++ .../mixin/core/world/entity/MobMixin.java | 28 -- 9 files changed, 428 insertions(+), 76 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java diff --git a/gradle.properties b/gradle.properties index 76d2dfe4de1..a672366bc6c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=24w46a +minecraftVersion=1.21.4-pre1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index fb9c7fed25e..f75d2916e53 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -245,6 +245,11 @@ + + + + + @@ -290,6 +295,11 @@ + + + + + @@ -315,6 +325,11 @@ + + + + + @@ -489,6 +504,14 @@ + + + + + + + + @@ -499,6 +522,11 @@ + + + + + @@ -971,6 +999,14 @@ + + + + + + + + @@ -1011,6 +1047,11 @@ + + + + + @@ -1072,6 +1113,14 @@ + + + + + + + + @@ -1159,6 +1208,14 @@ + + + + + + + + @@ -1199,6 +1256,14 @@ + + + + + + + + @@ -1358,6 +1423,14 @@ + + + + + + + + @@ -1401,6 +1474,22 @@ + + + + + + + + + + + + + + + + @@ -1547,6 +1636,14 @@ + + + + + + + + @@ -1587,6 +1684,14 @@ + + + + + + + + @@ -1603,6 +1708,14 @@ + + + + + + + + @@ -1949,6 +2062,14 @@ + + + + + + + + @@ -1957,6 +2078,14 @@ + + + + + + + + @@ -1965,6 +2094,14 @@ + + + + + + + + @@ -1973,6 +2110,14 @@ + + + + + + + + @@ -1981,11 +2126,24 @@ + + + + + + + + + + + + + @@ -1994,6 +2152,14 @@ + + + + + + + + @@ -2002,6 +2168,14 @@ + + + + + + + + @@ -2010,6 +2184,17 @@ + + + + + + + + + + + @@ -2024,6 +2209,14 @@ + + + + + + + + @@ -2058,6 +2251,14 @@ + + + + + + + + @@ -2338,6 +2539,14 @@ + + + + + + + + @@ -2362,6 +2571,14 @@ + + + + + + + + @@ -3556,6 +3773,14 @@ + + + + + + + + @@ -3564,6 +3789,14 @@ + + + + + + + + @@ -3932,6 +4165,16 @@ + + + + + + + + + + @@ -4003,6 +4246,14 @@ + + + + + + + + @@ -4032,6 +4283,14 @@ + + + + + + + + @@ -4115,6 +4374,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -4154,6 +4433,14 @@ + + + + + + + + @@ -4162,11 +4449,24 @@ + + + + + + + + + + + + + @@ -4359,6 +4659,11 @@ + + + + + @@ -4404,6 +4709,11 @@ + + + + + @@ -4462,6 +4772,14 @@ + + + + + + + + @@ -4495,6 +4813,11 @@ + + + + + @@ -4537,6 +4860,14 @@ + + + + + + + + @@ -4587,6 +4918,14 @@ + + + + + + + + @@ -5400,6 +5739,14 @@ + + + + + + + + @@ -5432,6 +5779,14 @@ + + + + + + + + @@ -5440,6 +5795,14 @@ + + + + + + + + @@ -6447,6 +6810,14 @@ + + + + + + + + @@ -6468,6 +6839,11 @@ + + + + + @@ -6503,6 +6879,11 @@ + + + + + @@ -6770,6 +7151,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java deleted file mode 100644 index 31b68034114..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/creaking/CreakingAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.entity.monster.creaking; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.monster.creaking.Creaking; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Creaking.class) -public interface CreakingAccessor { - - @Accessor("homePos") BlockPos accessor$homePos(); - -} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 25428b831b8..9f2fce5e00d 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -107,7 +107,6 @@ "world.entity.monster.VexAccessor", "world.entity.monster.VindicatorAccessor", "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.monster.creaking.CreakingAccessor", "world.entity.npc.AbstractVillagerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java index 953b3716fbc..e1717027b15 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CreakingData.java @@ -26,7 +26,6 @@ import net.minecraft.world.entity.monster.creaking.Creaking; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.creaking.CreakingAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.VecHelper; @@ -37,11 +36,11 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(Creaking.class) .create(Keys.CREAKING_IS_LINKED) - .get(Creaking::isTransient); + .get(Creaking::isHeartBound); registrator .asMutable(Creaking.class) .create(Keys.CREAKING_HOME_POSITION) - .get(h -> VecHelper.toVector3i(((CreakingAccessor) h).accessor$homePos())) + .get(h -> VecHelper.toVector3i(h.getHomePos())) .set((h, v) -> h.setTransient(VecHelper.toBlockPos(v))); ; } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java b/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java index 1948a9b0db0..c910e629552 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java @@ -42,13 +42,11 @@ public static void register(final DataProviderRegistrator registrator) { final var ld = h.getLeashData(); return ld == null ? null : (Entity) ld.leashHolder; }) - .delete(h -> { - h.dropLeash(true, false); - }) + .delete(Leashable::dropLeash) .set((h, v) -> { if (v == null) { // TODO remove - h.dropLeash(true, false); + h.dropLeash(); } else { h.setLeashedTo((net.minecraft.world.entity.Entity) v, true); } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java index 622f02e98f2..56429297ddf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java @@ -32,6 +32,7 @@ import net.minecraft.world.item.component.CustomData; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.EntityArchetype; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.entity.SpongeEntityArchetypeBuilder; @@ -46,7 +47,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(stack -> { final Item item = stack.getItem(); final SpawnEggItem eggItem = (SpawnEggItem) item; - final EntityType type = eggItem.getType(stack); + final EntityType type = eggItem.getType(SpongeCommon.vanillaRegistryAccess(), stack); final var tag = stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY).getUnsafe(); final EntityArchetype.Builder builder = EntityArchetype.builder().type((org.spongepowered.api.entity.EntityType) type); @@ -60,7 +61,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(stack -> { final Item item = stack.getItem(); final SpawnEggItem eggItem = (SpawnEggItem) item; - return (org.spongepowered.api.entity.EntityType) eggItem.getType(stack); + return (org.spongepowered.api.entity.EntityType) eggItem.getType(SpongeCommon.vanillaRegistryAccess(), stack); }) ; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java index b0d13ae0a35..0a1b7f7ed8e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java @@ -25,14 +25,22 @@ package org.spongepowered.common.mixin.core.world.entity; import net.minecraft.world.entity.Leashable; +import org.checkerframework.checker.units.qual.A; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.entity.UnleashEntityEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.tracking.PhaseTracker; + +import java.util.Objects; @Mixin(Leashable.class) public interface LeashableMixin { @@ -47,4 +55,27 @@ public interface LeashableMixin { } } + @Inject(method = "dropLeash(Lnet/minecraft/world/entity/Entity;ZZ)V", at = @At("HEAD"), cancellable = true) + private static void impl$onDropLeash(final net.minecraft.world.entity.Entity entity, final boolean $$1, final boolean $$2, final CallbackInfo ci) { + if (entity == null || entity.level().isClientSide) { + return; + } + + Leashable.LeashData leashData = ((Leashable) (Object) entity).getLeashData(); + if (leashData == null) { + return; + } + + final net.minecraft.world.entity.Entity holder = leashData.leashHolder; + + final CauseStackManager csm = PhaseTracker.getCauseStackManager(); + csm.pushCause(Objects.requireNonNullElse(holder, entity)); + final UnleashEntityEvent event = SpongeEventFactory.createUnleashEntityEvent(csm.currentCause(), (Entity) entity); + SpongeCommon.post(event); + csm.popCause(); + if (event.isCancelled()) { + ci.cancel(); + } + } + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 530c2f8de59..24dc347e796 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -86,34 +86,6 @@ public abstract class MobMixin extends LivingEntityMixin { } } - @Inject(method = "dropLeash", cancellable = true, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;dropLeash(ZZ)V")) - private void impl$ThrowUnleashEvent(final boolean sendPacket, final boolean dropLead, final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { - return; - } - - var leashData = this.shadow$getLeashData(); - if (leashData == null) { - return; - } - - final net.minecraft.world.entity.Entity entity = leashData.leashHolder; - - final CauseStackManager csm = PhaseTracker.getCauseStackManager(); - if (entity == null) { - csm.pushCause(this); - } else { - csm.pushCause(entity); - } - final UnleashEntityEvent event = SpongeEventFactory.createUnleashEntityEvent(csm.currentCause(), (Living) this); - SpongeCommon.post(event); - csm.popCause(); - if (event.isCancelled()) { - ci.cancel(); - } - } - /** * @author gabizou - January 4th, 2016 * From c0c06c801d96e9b3b4e4b03fe43db208c67aa8b8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 21 Nov 2024 22:10:38 -0800 Subject: [PATCH 136/586] chore: update from api-13 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 15e9b4d0827..4220ac0021e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 15e9b4d0827896bf6639baa23647c63d7001ca98 +Subproject commit 4220ac0021e0d0fb2cbb12e1e38748423a590a85 From d878472ab4313e6e2ff78639585716d1806ea415 Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 22 Nov 2024 22:34:54 +0200 Subject: [PATCH 137/586] Update slot packets --- .../event/tracking/phase/packet/PacketPhaseUtil.java | 8 +++++--- src/main/java/org/spongepowered/common/util/BookUtil.java | 8 +++----- .../impl/server/level/ServerPlayer_Mixin_Inventory.java | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 4b398bf6b44..dbef0b36d06 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -30,6 +30,8 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.common.ServerboundClientInformationPacket; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.network.protocol.game.ClientboundSetCursorItemPacket; +import net.minecraft.network.protocol.game.ClientboundSetPlayerInventoryPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.server.level.ServerLevel; @@ -103,7 +105,7 @@ public static void handleSlotRestore(@Nullable final Player player, final @Nulla final org.spongepowered.api.item.inventory.ItemStack stack = snapshot.asMutable(); slot.set(stack); ((net.minecraft.server.level.ServerPlayer) player).connection.send( - new ClientboundContainerSetSlotPacket(-2, player.inventoryMenu.getStateId(), ((SlotAdapter) slot).getOrdinal(), ItemStackUtil.toNative(stack))); + new ClientboundSetPlayerInventoryPacket(((SlotAdapter) slot).getOrdinal(), ItemStackUtil.toNative(stack))); } else { final int slotNumber = ((SlotAdapter) slot).getOrdinal(); final Slot nmsSlot = containerMenu.getSlot(slotNumber); @@ -138,7 +140,7 @@ public static void handleCursorRestore(final Player player, final Transaction Date: Mon, 25 Nov 2024 19:19:06 -0800 Subject: [PATCH 138/586] chore: update to 1.21.4-pre2 - Furnaces changed field names for burn times and cooking times - I assume these fields are correctly renamed for their accessors, they appear to function the same way for their Data API Keys --- gradle.properties | 2 +- .../entity/AbstractFurnaceBlockEntityAccessor.java | 12 ++++++------ .../entity/AbstractFurnaceBlockEntityMixin_API.java | 12 ++++++------ .../entity/AbstractFurnaceBlockEntityMixin.java | 6 +++--- .../AbstractFurnaceBlockEntityMixin_Vanilla.java | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/gradle.properties b/gradle.properties index a672366bc6c..ce9cfb79194 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.4-pre1 +minecraftVersion=1.21.4-pre2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor.java index 2ec3b5a53e5..784fb5e1a0c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor.java @@ -34,17 +34,17 @@ @Mixin(AbstractFurnaceBlockEntity.class) public interface AbstractFurnaceBlockEntityAccessor { - @Accessor("litTime") int accessor$litTime(); + @Accessor("litTotalTime") int accessor$litTime(); - @Accessor("litTime") void accessor$litTime(final int litTime); + @Accessor("litTotalTime") void accessor$litTime(final int litTime); - @Accessor("litDuration") int accessor$litDuration(); + @Accessor("litTimeRemaining") int accessor$litDuration(); - @Accessor("litDuration") void accessor$litDuration(final int litDuration); + @Accessor("litTimeRemaining") void accessor$litDuration(final int litDuration); - @Accessor("cookingProgress") int accessor$cookingProgress(); + @Accessor("cookingTimer") int accessor$cookingProgress(); - @Accessor("cookingProgress") void accessor$cookingProgress(final int cookingProgress); + @Accessor("cookingTimer") void accessor$cookingProgress(final int cookingProgress); @Accessor("cookingTotalTime") int accessor$cookingTotalTime(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java index d2f65b5e945..6daaeeea2f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java @@ -42,9 +42,9 @@ public abstract class AbstractFurnaceBlockEntityMixin_API extends BaseContainerBlockEntityMixin_API implements FurnaceBlockEntity { // @formatter:off - @Shadow int litTime; - @Shadow int litDuration; - @Shadow int cookingProgress; + @Shadow int litTimeRemaining; + @Shadow int litTotalTime; + @Shadow int cookingTimer; @Shadow int cookingTotalTime; @Shadow protected NonNullList items; // @formatter:on @@ -64,9 +64,9 @@ public abstract class AbstractFurnaceBlockEntityMixin_API extends BaseContainerB @Override public DataContainer toContainer() { return super.toContainer() - .set(Constants.TileEntity.Furnace.BURN_TIME, this.litTime) - .set(Constants.TileEntity.Furnace.BURN_TIME_TOTAL, this.litDuration) - .set(Constants.TileEntity.Furnace.COOK_TIME, this.cookingProgress) + .set(Constants.TileEntity.Furnace.BURN_TIME, this.litTimeRemaining) + .set(Constants.TileEntity.Furnace.BURN_TIME_TOTAL, this.litTotalTime) + .set(Constants.TileEntity.Furnace.COOK_TIME, this.cookingTimer) .set(Constants.TileEntity.Furnace.COOK_TIME_TOTAL, this.cookingTotalTime); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 37dbda079b0..b3cd4278e08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -65,7 +65,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock // @Formatter:off @Shadow protected NonNullList items; - @Shadow int cookingProgress; + @Shadow int cookingTimer; @Shadow int cookingTotalTime; // @Formatter:on @@ -130,7 +130,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock shift = At.Shift.BEFORE, value = "FIELD", opcode = Opcodes.PUTFIELD, - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingProgress:I" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingTimer:I" ), slice = @Slice( from = @At( @@ -149,7 +149,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock } private void impl$callInteruptSmeltEvent() { - if (this.cookingProgress > 0) { + if (this.cookingTimer > 0) { final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(this.items.get(1)); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); final var recipe = this.bridge$getCurrentRecipe(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 24ac7f4ffd7..d836ecb8c41 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -70,7 +70,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // @formatter:off @Shadow protected NonNullList items; - @Shadow int cookingProgress; + @Shadow int cookingTimer; // @formatter:on private boolean vanilla$filledWaterBucket; @@ -92,7 +92,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(slots.get(1)); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); - if (entity.cookingProgress == 0) { // Start + if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); @@ -122,7 +122,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); if (event.isCancelled()) { - return entity.cookingProgress; // dont tick down + return entity.cookingTimer; // dont tick down } return clampedCookTime; From c6bf924dd324f9d8371cde6397cfd00f2a6f3dd1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 28 Nov 2024 21:34:44 -0800 Subject: [PATCH 139/586] chore: update to 1.21.4-rc1 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ce9cfb79194..645c39445e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.4-pre2 +minecraftVersion=1.21.4-rc1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 592268eb3fcacfbc4067edb8a6cd9a5861f95c76 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 28 Nov 2024 21:46:20 -0800 Subject: [PATCH 140/586] chore: fix nits --- .../vanilla/generator/BlockStatePropertiesGenerator.java | 3 ++- .../vanilla/generator/BlockStatePropertyKeysGenerator.java | 3 ++- .../org/spongepowered/vanilla/generator/GeneratorMain.java | 1 - .../vanilla/generator/RegistryEntriesGenerator.java | 3 --- .../common/accessor/network/chat/StyleAccessor.java | 1 - .../common/data/provider/item/stack/ItemStackData.java | 1 - .../world/level/levelgen/structure/StructureMixin_API.java | 1 - .../common/mixin/core/world/entity/LeashableMixin.java | 2 -- .../common/mixin/core/world/entity/MobMixin.java | 6 ------ 9 files changed, 4 insertions(+), 17 deletions(-) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index b20d1a0c357..202e77ae676 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -62,7 +62,6 @@ import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; -import javax.lang.model.element.Modifier; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; @@ -70,6 +69,8 @@ import java.util.Map; import java.util.TreeMap; +import javax.lang.model.element.Modifier; + /** * Generates catalog classes for {@link BlockState} properties. */ diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index 80a2d6685b6..d00816a08ce 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -63,7 +63,6 @@ import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; -import javax.lang.model.element.Modifier; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; @@ -71,6 +70,8 @@ import java.util.TreeMap; import java.util.function.Function; +import javax.lang.model.element.Modifier; + /** * Generates catalog classes for {@link BlockState} properties. */ diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 01d1c00cd60..0ec23cbeff2 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -69,7 +69,6 @@ import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.WorldDataConfiguration; -import net.minecraft.world.level.block.CreakingHeartBlock; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; import net.minecraft.world.level.block.state.properties.DripstoneThickness; diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index 73ea1f9a0ee..507be679495 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -24,8 +24,6 @@ */ package org.spongepowered.vanilla.generator; -import com.squareup.javapoet.AnnotationSpec; -import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; @@ -38,7 +36,6 @@ import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; -import org.jetbrains.annotations.ApiStatus; import java.io.IOException; import java.util.Comparator; diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java index d45e749941e..d7d933d9354 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java @@ -35,7 +35,6 @@ import org.spongepowered.common.UntransformedInvokerError; import javax.annotation.Nullable; -import java.util.Optional; @Mixin(Style.class) public interface StyleAccessor { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 29c378c600e..49581493d78 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -42,7 +42,6 @@ import net.minecraft.world.item.Rarity; import net.minecraft.world.item.component.ChargedProjectiles; import net.minecraft.world.item.component.Consumable; -import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.DamageResistant; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java index 6d790982a78..8a3c6acabed 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java @@ -32,7 +32,6 @@ import net.minecraft.core.SectionPos; import net.minecraft.core.registries.Registries; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.MobCategory; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java index 0a1b7f7ed8e..7167accef44 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java @@ -25,10 +25,8 @@ package org.spongepowered.common.mixin.core.world.entity; import net.minecraft.world.entity.Leashable; -import org.checkerframework.checker.units.qual.A; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.SpongeEventFactory; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 24dc347e796..8062adfa50f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -34,10 +34,6 @@ import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.ai.goal.GoalExecutorTypes; import org.spongepowered.api.entity.living.Agent; -import org.spongepowered.api.entity.living.Living; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.entity.UnleashEntityEvent; import org.spongepowered.api.event.entity.ai.SetAITargetEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -47,14 +43,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.bridge.world.entity.ai.goal.GoalSelectorBridge; import org.spongepowered.common.bridge.world.entity.player.PlayerBridge; import org.spongepowered.common.entity.EntityUtil; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; -import org.spongepowered.common.event.tracking.PhaseTracker; @Mixin(Mob.class) public abstract class MobMixin extends LivingEntityMixin { From f2470b6a7b4ea6f15c81af545fb5bd26dadedde9 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 30 Nov 2024 13:37:41 -0800 Subject: [PATCH 141/586] chore: update to 1.21.4-rc3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 645c39445e6..f0a2b891bfd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.4-rc1 +minecraftVersion=1.21.4-rc3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 07fb930c2bb31f121864c1d0fec2e609aee06e52 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 16 Dec 2024 12:35:44 -0800 Subject: [PATCH 142/586] chore: update to 1.21.4 release --- forge/gradle.properties | 2 +- .../forge/hook/ForgeItemHooks.java | 3 +- gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 133 ++++++++++++++++++ neoforge/gradle.properties | 2 +- 6 files changed, 139 insertions(+), 5 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index acc83580cf4..d59013cf19b 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=52.0.3 +forgeVersion=54.0.6 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/forge/src/main/java/org/spongepowered/forge/hook/ForgeItemHooks.java b/forge/src/main/java/org/spongepowered/forge/hook/ForgeItemHooks.java index 296d642e82a..03c25141938 100644 --- a/forge/src/main/java/org/spongepowered/forge/hook/ForgeItemHooks.java +++ b/forge/src/main/java/org/spongepowered/forge/hook/ForgeItemHooks.java @@ -24,6 +24,7 @@ */ package org.spongepowered.forge.hook; +import net.minecraft.core.Holder; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.Enchantment; import org.spongepowered.common.hooks.ItemHooks; @@ -32,6 +33,6 @@ public class ForgeItemHooks implements ItemHooks { @Override public boolean canEnchantmentBeAppliedToItem(Enchantment enchantment, ItemStack stack) { - return stack.canApplyAtEnchantingTable(enchantment); + return stack.canApplyAtEnchantingTable(Holder.direct(enchantment)); } } diff --git a/gradle.properties b/gradle.properties index f0a2b891bfd..80242caa6da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.4-rc3 +minecraftVersion=1.21.4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 37be89a71b0..d602cd2b52c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ format = { version = "1.1" } # See SpongeAPI's gradle/libs.versions.toml for many dependency declarations that Sponge also uses [versions] asm = "9.7" -log4j = "2.22.1" +log4j = "2.24.1" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" bootstrap = "2.1.1" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f75d2916e53..857523b9616 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1006,6 +1006,9 @@ + + + @@ -1304,6 +1307,9 @@ + + + @@ -1430,6 +1436,9 @@ + + + @@ -1820,6 +1829,14 @@ + + + + + + + + @@ -3111,6 +3128,14 @@ + + + + + + + + @@ -3146,6 +3171,14 @@ + + + + + + + + @@ -3189,6 +3222,14 @@ + + + + + + + + @@ -3261,6 +3302,14 @@ + + + + + + + + @@ -3309,6 +3358,14 @@ + + + + + + + + @@ -3357,6 +3414,14 @@ + + + + + + + + @@ -3441,6 +3506,20 @@ + + + + + + + + + + + + + + @@ -3457,6 +3536,14 @@ + + + + + + + + @@ -3513,6 +3600,14 @@ + + + + + + + + @@ -3561,6 +3656,14 @@ + + + + + + + + @@ -3609,6 +3712,14 @@ + + + + + + + + @@ -3655,6 +3766,14 @@ + + + + + + + + @@ -3686,6 +3805,9 @@ + + + @@ -4897,6 +5019,14 @@ + + + + + + + + @@ -5746,6 +5876,9 @@ + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 42d6f02f9fc..ebc2e73e9d3 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.3.0-beta +neoForgeVersion=21.4.30-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file From efb1b64fc162e3cf9b29bfe6f9b2e50fdb903964 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 11 Nov 2024 16:48:47 -0800 Subject: [PATCH 143/586] fix: work on re-enabling spongeforge for 1.21.3 --- forge/gradle.properties | 2 +- .../spongepowered/forge/SpongeForgeMod.java | 8 +- .../server/level/ServerPlayerMixin_Forge.java | 7 +- ...rverGamePacketListenerImplMixin_Forge.java | 25 ++- .../world/entity/LivingEntityMixin_Forge.java | 12 +- .../world/entity/vehicle/BoatMixin_Forge.java | 12 +- ...rverPlayerGameModeMixin_Forge_Tracker.java | 2 +- .../BlockBehaviorMixin_Forge_Tracker.java | 2 +- gradle/verification-metadata.xml | 159 ++++++++++++++++++ 9 files changed, 202 insertions(+), 27 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index acc83580cf4..f3f921aae37 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=52.0.3 +forgeVersion=53.0.25 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index 200740664e5..3cccd1d9797 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -25,6 +25,8 @@ package org.spongepowered.forge; import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.minecraftforge.common.MinecraftForge; @@ -64,10 +66,10 @@ public final class SpongeForgeMod { private final Logger logger = LogManager.getLogger("spongeforge"); - public SpongeForgeMod() { + public SpongeForgeMod(FMLJavaModLoadingContext ctx) { // WorldPersistenceHooks.addHook(SpongeLevelDataPersistence.INSTANCE); // TODO SF 1.19.4 - final IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + final IEventBus modBus = ctx.getModEventBus(); // modBus: add all FML events with it modBus.addListener(this::onCommonSetup); @@ -144,7 +146,7 @@ public void onRegister(RegisterEvent event) { .sized(0.6F, 1.8F) .clientTrackingRange(org.spongepowered.common.util.Constants.Entity.Player.TRACKING_RANGE) .updateInterval(2) - .build("sponge:human") + .build(ResourceKey.create(ForgeRegistries.Keys.ENTITY_TYPES, ResourceLocation.parse("sponge:human"))) ; event.register(ForgeRegistries.Keys.ENTITY_TYPES, helper -> helper.register(HumanEntity.KEY, SpongeEntityTypes.HUMAN)); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java index b06f9cb2cce..25f11215d82 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java @@ -24,8 +24,10 @@ */ package org.spongepowered.forge.mixin.core.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -37,10 +39,13 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Forge extends LivingEntityMixin_Forge { + @Shadow public abstract ServerLevel shadow$serverLevel(); + // override from LivingEntityMixin_Forge @Override protected void forge$onElytraUse(final CallbackInfo ci) { - final PhaseContext context = PhaseTracker.SERVER.getPhaseContext(); + final ServerLevel level = this.shadow$serverLevel(); + final PhaseContext context = PhaseTracker.getWorldInstance(level).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java index f8e9a9a30af..f3c363bcbec 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java @@ -25,6 +25,8 @@ package org.spongepowered.forge.mixin.core.server.network; import net.minecraft.network.protocol.game.ServerGamePacketListener; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.RecipeHolder; @@ -33,6 +35,7 @@ import org.spongepowered.api.item.inventory.crafting.CraftingInventory; import org.spongepowered.api.item.inventory.query.QueryTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; @@ -44,23 +47,29 @@ @Mixin(ServerGamePacketListenerImpl.class) public abstract class ServerGamePacketListenerImplMixin_Forge implements ServerGamePacketListener { - @SuppressWarnings({"unchecked", "rawtypes"}) - @Redirect(method = "lambda$handlePlaceRecipe$10", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerPlayer;)V")) - private void forge$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final RecipeHolder recipe, final net.minecraft.server.level.ServerPlayer player) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + @Shadow public ServerPlayer player; + + @Redirect(method = "handlePlaceRecipe", + at = @At(value = "INVOKE", target = "net/minecraft/world/inventory/RecipeBookMenu.handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) + private RecipeBookMenu.PostPlaceAction forge$onPlaceRecipe( + final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, + final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); + final var player = this.player; final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); + final RecipeBookMenu.PostPlaceAction result; if (!(craftInv instanceof CraftingInventory)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); SpongeCommon.logger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire."); - return; + return result; } try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, recipe, player, (CraftingInventory) craftInv)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); player.containerMenu.broadcastChanges(); } + return result; } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java index 050c899e5cc..a91a34fa01e 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java @@ -34,12 +34,12 @@ public abstract class LivingEntityMixin_Forge { @Inject( - method = "updateFallFlying", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;elytraFlightTick(Lnet/minecraft/world/entity/LivingEntity;I)Z", - shift = At.Shift.AFTER - ) + method = "updateFallFlying", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", + shift = At.Shift.AFTER + ) ) protected void forge$onElytraUse(final CallbackInfo ci) { } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java index f00eb8a1c45..e52b4a69c3c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java @@ -26,21 +26,21 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; -@Mixin(Boat.class) -public abstract class BoatMixin_Forge implements BoatBridge { +@Mixin(AbstractBoat.class) +public abstract class BoatMixin_Forge implements AbstractBoatBridge { @Redirect(method = "getGroundFriction", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;getFriction(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)F") + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/state/BlockState;getFriction(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)F") ) private float forge$getBlockFrictionIfBoatIsNotOverridingMovingOnLand(BlockState caller, LevelReader level, BlockPos pos, Entity entity) { final boolean movesOnLand = this.bridge$getMoveOnLand(); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java index b3f8c60f891..0b0b2dd3e13 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java @@ -63,7 +63,7 @@ public abstract class ServerPlayerGameModeMixin_Forge_Tracker { final ItemStack itemStack, final Level level, final BlockState state, final BlockPos pos, final Player player ) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); // Log the prepare drops here because Forge rewrites // this method to call mine block before calling destroy block diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java index 8784263a379..973df0af53f 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java @@ -42,7 +42,7 @@ public abstract class BlockBehaviorMixin_Forge_Tracker { method = "getLootTable", at = @At( value = "FIELD", - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;lootTableSupplier:Ljava/util/function/Supplier;", + target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;drops:Ljava/util/Optional;", remap = false ) ) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4046353e1be..7f3a0944ff0 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1699,6 +1699,14 @@ + + + + + + + + @@ -2964,6 +2972,14 @@ + + + + + + + + @@ -3036,6 +3052,22 @@ + + + + + + + + + + + + + + + + @@ -3084,6 +3116,22 @@ + + + + + + + + + + + + + + + + @@ -3132,6 +3180,22 @@ + + + + + + + + + + + + + + + + @@ -3216,6 +3280,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3232,6 +3324,14 @@ + + + + + + + + @@ -3288,6 +3388,22 @@ + + + + + + + + + + + + + + + + @@ -3336,6 +3452,22 @@ + + + + + + + + + + + + + + + + @@ -3384,6 +3516,22 @@ + + + + + + + + + + + + + + + + @@ -3430,6 +3578,14 @@ + + + + + + + + @@ -3461,6 +3617,9 @@ + + + From 6ad95591066b60bab3ba9de709c5198e48eed7da Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 13:18:06 +0100 Subject: [PATCH 144/586] WIP Replace arch-loom with ForgeGradle --- bootstrap-dev/build.gradle.kts | 3 + bootstrap-dev/src/main/java/module-info.java | 6 + .../spongepowered/bootstrap/dev/Multimap.java | 36 ++++ .../bootstrap/dev}/SourceSet.java | 2 +- .../dev}/SpongeDevClasspathFixer.java | 47 ++--- ...e.bootstrap.api.BootstrapClasspathModifier | 1 + .../impl/SpongeImplementationExtension.java | 104 ++++++++-- forge/build.gradle.kts | 160 +++++++-------- gradle/libs.versions.toml | 4 +- gradle/verification-metadata.xml | 186 ++++++++++++++++++ neoforge/build.gradle.kts | 2 +- settings.gradle.kts | 1 + vanilla/build.gradle.kts | 43 ++-- vanilla/src/devlaunch/java/module-info.java | 6 - ...e.bootstrap.api.BootstrapClasspathModifier | 1 - 15 files changed, 426 insertions(+), 176 deletions(-) create mode 100644 bootstrap-dev/build.gradle.kts create mode 100644 bootstrap-dev/src/main/java/module-info.java create mode 100644 bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java rename {vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch => bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev}/SourceSet.java (98%) rename {vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch => bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev}/SpongeDevClasspathFixer.java (84%) create mode 100644 bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier delete mode 100644 vanilla/src/devlaunch/java/module-info.java delete mode 100644 vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier diff --git a/bootstrap-dev/build.gradle.kts b/bootstrap-dev/build.gradle.kts new file mode 100644 index 00000000000..408470bf53e --- /dev/null +++ b/bootstrap-dev/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + api(libs.bootstrap.api) +} diff --git a/bootstrap-dev/src/main/java/module-info.java b/bootstrap-dev/src/main/java/module-info.java new file mode 100644 index 00000000000..c46b80848e7 --- /dev/null +++ b/bootstrap-dev/src/main/java/module-info.java @@ -0,0 +1,6 @@ +module org.spongepowered.boostrap.dev { + requires net.minecraftforge.bootstrap.api; + exports org.spongepowered.bootstrap.dev; + + provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer; +} diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java new file mode 100644 index 00000000000..e56fa029fdd --- /dev/null +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.dev; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +public class Multimap extends HashMap> { + + public void add(K key, V value) { + this.computeIfAbsent(key, k -> new LinkedList<>()).add(value); + } +} diff --git a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java similarity index 98% rename from vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java rename to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java index a4fa3b1b537..540c752afcc 100644 --- a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.devlaunch; +package org.spongepowered.bootstrap.dev; import java.nio.file.Files; import java.nio.file.Path; diff --git a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java similarity index 84% rename from vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java rename to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 47c8f979594..7e4e7b8ec5a 100644 --- a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -22,17 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.devlaunch; +package org.spongepowered.bootstrap.dev; import net.minecraftforge.bootstrap.api.BootstrapClasspathModifier; +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,11 +49,12 @@ public String name() { */ @Override public boolean process(final List classpath) { - final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(";")); - final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(";")); + final Set ignoredLibs = Set.of("bootstrap-dev.jar"); + final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); + final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); - final Map> bootSourceSets = new HashMap<>(); - final Map> unknownProjects = new HashMap<>(); + final Multimap bootSourceSets = new Multimap<>(); + final Multimap unknownProjects = new Multimap<>(); final List spongeImplUnion = new ArrayList<>(); final List gameLibs = new ArrayList<>(); @@ -75,8 +74,11 @@ public boolean process(final List classpath) { } switch (sourceSet.project()) { - case "modlauncher-transformers": - bootSourceSets.computeIfAbsent("transformers", k -> new LinkedList<>()).add(path); + case "bootstrap-dev": + // ignore + break; + case "modlauncher-transformers", "library-manager": + bootSourceSets.add(sourceSet.project(), path); break; case "SpongeAPI": switch (sourceSet.name()) { @@ -91,21 +93,15 @@ public boolean process(final List classpath) { break; } break; - case "Sponge", "vanilla": - switch (sourceSet.name()) { - case "devlaunch": - // ignore - break; - case "applaunch": - bootSourceSets.computeIfAbsent("applaunch", k -> new LinkedList<>()).add(path); - break; - default: - spongeImplUnion.add(path); - break; + case "Sponge", "vanilla", "forge": + if (sourceSet.name().equals("applaunch")) { + bootSourceSets.add("applaunch", path); + } else { + spongeImplUnion.add(path); } break; default: - unknownProjects.computeIfAbsent(sourceSet.project(), k -> new LinkedList<>()).add(path); + unknownProjects.add(sourceSet.project(), path); break; } return true; @@ -113,6 +109,13 @@ public boolean process(final List classpath) { final String fileName = path.getFileName().toString(); + if (ignoredLibs.contains(fileName)) { + if (DEBUG) { + System.out.println("Ignored: " + path); + } + return true; + } + if (bootLibs.contains(fileName)) { if (DEBUG) { System.out.println("Boot: " + path); diff --git a/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier b/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier new file mode 100644 index 00000000000..32a491ef8a6 --- /dev/null +++ b/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier @@ -0,0 +1 @@ +org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java index 09dc131237a..7881f2a2d2b 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java @@ -37,6 +37,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; +import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -44,6 +45,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.StringJoiner; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -60,33 +63,100 @@ public SpongeImplementationExtension(final Project project, final Logger logger) this.logger = logger; } - public void copyModulesExcludingProvided(final Configuration source, final Configuration provided, final Configuration target) { - final DependencyHandler deps = this.project.getDependencies(); + private record Module(ModuleIdentifier id, String classifier) {} + + public String buildRuntimeFileNames(final Configuration config) { + final Configuration runtimeConfig = this.project.getConfigurations().getByName("runtimeClasspath"); + + final Map runtimeFileNames = new HashMap<>(); + for (final ResolvedArtifact artifact : runtimeConfig.getResolvedConfiguration().getResolvedArtifacts()) { + final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); + if (id instanceof ModuleComponentIdentifier moduleId) { + runtimeFileNames.put(new Module(moduleId.getModuleIdentifier(), artifact.getClassifier()), artifact.getFile().getName()); + } + } + + final StringJoiner joiner = new StringJoiner(File.pathSeparator); + + for (final ResolvedArtifact artifact : config.getResolvedConfiguration().getResolvedArtifacts()) { + final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); + + String fileName = null; + if (id instanceof ModuleComponentIdentifier moduleId) { + fileName = runtimeFileNames.get(new Module(moduleId.getModuleIdentifier(), artifact.getClassifier())); + } + + if (fileName == null) { + fileName = artifact.getFile().getName(); + } + + joiner.add(fileName); + } + + return joiner.toString(); + } + private String buildDependencyNotation(final ModuleComponentIdentifier moduleId, final String classifier) { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + String notation = module.getGroup() + ":" + module.getName() + ":" + moduleId.getVersion(); + if (classifier != null) { + notation += ":" + classifier; + } + return notation; + } + + public void copyModulesExcludingProvided(final Configuration source, final Configuration provided, final Configuration target) { final Map providedModuleVersions = new HashMap<>(); - for (ResolvedArtifact artifact : provided.getResolvedConfiguration().getResolvedArtifacts()) { + for (final ResolvedArtifact artifact : provided.getResolvedConfiguration().getResolvedArtifacts()) { final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); - if (id instanceof ModuleComponentIdentifier) { - final ModuleComponentIdentifier moduleId = (ModuleComponentIdentifier) id; + if (id instanceof ModuleComponentIdentifier moduleId) { providedModuleVersions.put(moduleId.getModuleIdentifier(), moduleId.getVersion()); } } + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + final String version = moduleId.getVersion(); + + final String providedVersion = providedModuleVersions.get(module); + if (providedVersion == null) { + return false; + } + + if (!providedVersion.equals(version)) { + this.logger.warn("Version mismatch for module {}. {} expects {} but {} has {}.", module, source.getName(), version, provided.getName(), providedVersion); + } + return true; + }, target); + } + + public void copyModulesExcludingPrefix(final Configuration source, final String group, final String namePrefix, final Configuration target) { + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + return module.getGroup().equals(group) && module.getName().startsWith(namePrefix); + }, target); + } + + public void copyModulesExcludingExact(final Configuration source, final String group, final String name, final Configuration target) { + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + return module.getGroup().equals(group) && module.getName().equals(name); + }, target); + } + + private void copyModulesExcludingPredicate(final Configuration source, final Predicate predicate, final Configuration target) { + final DependencyHandler deps = this.project.getDependencies(); + for (ResolvedArtifact artifact : source.getResolvedConfiguration().getResolvedArtifacts()) { final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); - if (id instanceof ModuleComponentIdentifier) { - final ModuleComponentIdentifier moduleId = (ModuleComponentIdentifier) id; - final ModuleIdentifier module = moduleId.getModuleIdentifier(); - final String version = moduleId.getVersion(); - - final String providedVersion = providedModuleVersions.get(module); - if (providedVersion == null) { - ModuleDependency dep = (ModuleDependency) deps.create(module.getGroup() + ":" + module.getName() + ":" + version); - dep.setTransitive(false); - target.getDependencies().add(dep); - } else if (!providedVersion.equals(version)) { - this.logger.warn("Version mismatch for module {}. {} expects {} but {} has {}.", module, source.getName(), version, provided.getName(), providedVersion); + if (id instanceof ModuleComponentIdentifier moduleId) { + if (predicate.test(moduleId)) { + continue; } + + final ModuleDependency dep = (ModuleDependency) deps.create(this.buildDependencyNotation(moduleId, artifact.getClassifier())); + dep.setTransitive(false); + target.getDependencies().add(dep); } // projects are not copied because we cannot always recreate properly a project dependency from the resolved artefact diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 7aeb4a2e696..1a4feb36864 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,12 +1,12 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.minecraftforge.gradle.userdev.UserDevExtension buildscript { repositories { maven("https://repo.spongepowered.org/repository/maven-public") { name = "sponge" } - maven("https://maven.architectury.dev/") + maven("https://maven.minecraftforge.net/") } } @@ -14,10 +14,11 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("dev.architectury.loom") version "1.6.411" + id("net.minecraftforge.gradle") version "[6.0.24,6.2)" } val commonProject = parent!! +val bootstrapDevProject = commonProject.project(":bootstrap-dev") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -38,6 +39,11 @@ repositories { } // SpongeForge libraries +val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") { + // Ideally we would filter minecraft itself and only keep its dependencies for this layer, + // but I couldn't find a way to do it without breaking ForgeGradle. + extendsFrom(configurations.minecraft.get()) +} val serviceLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceLibraries") val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") @@ -46,28 +52,21 @@ val gameManagedLibrariesConfig: NamedDomainObjectProvider = confi val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") -val runTaskOnlyConfig: NamedDomainObjectProvider = configurations.register("runTaskOnly") - -configurations.named("forgeRuntimeLibrary") { - extendsFrom(serviceLibrariesConfig.get()) -} - // ModLauncher layers +val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { + extendsFrom(bootLibrariesConfig.get()) +} val serviceLayerConfig: NamedDomainObjectProvider = configurations.register("serviceLayer") { + extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) - extendsFrom(configurations.getByName("forgeDependencies")) } val langLayerConfig: NamedDomainObjectProvider = configurations.register("langLayer") { - extendsFrom(configurations.getByName("forgeDependencies")) + extendsFrom(bootLayerConfig.get()) } val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) - - afterEvaluate { - extendsFrom(configurations.getByName("minecraftNamedCompile")) - } } // SpongeCommon source sets @@ -141,6 +140,10 @@ val forgeMain by sourceSets.named("main") { configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } + + // The rest of the project because we want everything in the initial classpath + spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) + spongeImpl.addDependencyToRuntimeOnly(forgeMixins, this) } configurations.configureEach { @@ -155,48 +158,8 @@ configurations.configureEach { } } -extensions.configure(LoomGradleExtensionAPI::class) { - silentMojangMappingsLicense() - accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) - - mixin { - useLegacyMixinAp.set(false) - } - - forge { - useCustomMixin.set(false) - } - - mods { - named("main") { - sourceSet(forgeMixins) - sourceSet(forgeAccessors) - sourceSet(forgeLaunch) - - sourceSet(main.get(), commonProject) - sourceSet(mixins.get(), commonProject) - sourceSet(accessors.get(), commonProject) - sourceSet(launch.get(), commonProject) - - configuration(gameManagedLibrariesConfig.get()) - configuration(gameShadedLibrariesConfig.get()) - } - } - - // Arch-loom bug, skip broken union-relauncher - runs.forEach { - it.mainClass.set("net.minecraftforge.bootstrap.ForgeBootstrap") - } -} - dependencies { - "minecraft"("com.mojang:minecraft:${minecraftVersion}") - "forge"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") - "mappings"(loom.layered { - officialMojangMappings { - nameSyntheticMembers = true - } - }) + "minecraft"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) @@ -231,13 +194,56 @@ dependencies { gameShadedLibraries("org.spongepowered:spongeapi:$apiVersion") { isTransitive = false } afterEvaluate { - spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), configurations.getByName("forgeDependencies"), serviceShadedLibrariesConfig.get()) + spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), bootLayerConfig.get(), serviceShadedLibrariesConfig.get()) spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) } - val runTaskOnly = runTaskOnlyConfig.name - // Arch-loom bug, fix support of MOD_CLASSES - runTaskOnly("net.minecraftforge:bootstrap-dev:2.1.3") + runtimeOnly(project(bootstrapDevProject.path)) +} + +val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations + +extensions.configure(UserDevExtension::class) { + mappings("official", "1.21.3") + // accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) TODO + + reobf = false + + runs { + configureEach { + ideaModule("Sponge.SpongeForge.main") + + property("forge.logging.markers", "REGISTRIES") + property("forge.logging.console.level", "debug") + + // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + + args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) + + environment("MOD_CLASSES", "nop") + } + + create("client") { + workingDirectory(file("run/client")) + } + + create("server") { + workingDirectory(file("run/client")) + args("--nogui") + } + } +} + +afterEvaluate { + extensions.configure(UserDevExtension::class) { + // Configure bootstrap-dev + val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev + val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) + runs.configureEach { + jvmArgs("-Dsponge.dev.boot=$bootFileNames") + jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") + } + } } val forgeManifest = java.manifest { @@ -254,8 +260,6 @@ val forgeManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } -val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations - tasks { jar { manifest.from(forgeManifest) @@ -306,38 +310,6 @@ tasks { duplicatesStrategy = DuplicatesStrategy.WARN } - afterEvaluate { - withType(net.fabricmc.loom.task.AbstractRunTask::class) { - // Default classpath is a mess, we better start a new one from scratch - classpath = files( - configurations.getByName("forgeRuntimeLibrary"), - forgeServicesJar, forgeLangJar, runTaskOnlyConfig - ) - - testPluginsProject?.also { - val testPluginsOutput = it.sourceSets.getByName("main").output - val dirs: MutableList = mutableListOf() - dirs.add(testPluginsOutput.resourcesDir!!) - dirs.addAll(testPluginsOutput.classesDirs) - environment["SPONGE_PLUGINS"] = dirs.joinToString("&") - - dependsOn(it.tasks.classes) - } - - argumentProviders += CommandLineArgumentProvider { - mixinConfigs.asSequence() - .flatMap { sequenceOf("--mixin.config", it) } - .toList() - } - - // jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath - - sourceSets.forEach { - dependsOn(it.classesTaskName) - } - } - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") forgeAppLaunch.resources.srcDir(installerResources) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 867ada7f2fe..cbc47e0b08d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,8 +8,8 @@ asm = "9.7" log4j = "2.22.1" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" -bootstrap = "2.1.1" -modlauncher = "10.2.1" +bootstrap = "2.1.3" +modlauncher = "10.2.2" neo-modlauncher = "11.0.3" securemodules = "2.2.20" jarjar = "0.3.26" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7f3a0944ff0..328daf4d49e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -168,6 +168,9 @@ + + + @@ -208,6 +211,9 @@ + + + @@ -1523,6 +1529,14 @@ + + + + + + + + @@ -1715,6 +1729,14 @@ + + + + + + + + @@ -2046,6 +2068,9 @@ + + + @@ -2773,6 +2798,14 @@ + + + + + + + + @@ -2811,18 +2844,40 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -2847,10 +2902,21 @@ + + + + + + + + + + + @@ -2890,6 +2956,9 @@ + + + @@ -2925,6 +2994,9 @@ + + + @@ -2976,6 +3048,9 @@ + + + @@ -3000,6 +3075,9 @@ + + + @@ -3064,6 +3142,9 @@ + + + @@ -3128,6 +3209,9 @@ + + + @@ -3192,6 +3276,9 @@ + + + @@ -3308,6 +3395,14 @@ + + + + + + + + @@ -3328,6 +3423,9 @@ + + + @@ -3400,6 +3498,9 @@ + + + @@ -3464,6 +3565,9 @@ + + + @@ -3528,6 +3632,9 @@ + + + @@ -3582,6 +3689,9 @@ + + + @@ -3669,6 +3779,14 @@ + + + + + + + + @@ -3680,6 +3798,19 @@ + + + + + + + + + + + + + @@ -4191,6 +4322,14 @@ + + + + + + + + @@ -4206,6 +4345,11 @@ + + + + + @@ -4313,11 +4457,24 @@ + + + + + + + + + + + + + @@ -4763,6 +4920,11 @@ + + + + + @@ -4787,6 +4949,14 @@ + + + + + + + + @@ -4810,6 +4980,11 @@ + + + + + @@ -4972,6 +5147,9 @@ + + + @@ -5337,6 +5515,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index a7b86632259..9cd699e0d03 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -312,7 +312,7 @@ tasks { .toList() } - jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + // jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath sourceSets.forEach { dependsOn(it.classesTaskName) diff --git a/settings.gradle.kts b/settings.gradle.kts index 00d638da944..6202443c650 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -70,6 +70,7 @@ includeBuild("SpongeAPI") { } include("modlauncher-transformers") include("library-manager") +include("bootstrap-dev") include("generator") // Optional projects diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index b936a70281c..00ac01e6f6c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -9,6 +9,7 @@ plugins { } val commonProject = parent!! +val bootstrapDevProject = commonProject.project(":bootstrap-dev") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -23,7 +24,6 @@ description = "The SpongeAPI implementation for Vanilla Minecraft" version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion) // SpongeVanilla libraries -val devlaunchLibrariesConfig: NamedDomainObjectProvider = configurations.register("devlaunchLibraries") val installerLibrariesConfig: NamedDomainObjectProvider = configurations.register("installerLibraries") val initLibrariesConfig: NamedDomainObjectProvider = configurations.register("initLibraries") // JVM initial classpath val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") @@ -54,13 +54,6 @@ val mixins: NamedDomainObjectProvider = commonProject.sourceSets.name val main: NamedDomainObjectProvider = commonProject.sourceSets.named("main") // SpongeVanilla source sets -// Dev launch -val vanillaDevLaunch by sourceSets.register("devlaunch") { - configurations.named(implementationConfigurationName) { - extendsFrom(devlaunchLibrariesConfig.get()) - } -} - // Prod launch val vanillaInstaller by sourceSets.register("installer") { configurations.named(implementationConfigurationName) { @@ -126,12 +119,7 @@ val vanillaMain by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) - spongeImpl.addDependencyToRuntimeOnly(vanillaDevLaunch, this) spongeImpl.addDependencyToRuntimeOnly(vanillaMixins, this) - - configurations.named(runtimeOnlyConfigurationName) { - extendsFrom(devlaunchLibrariesConfig.get()) - } } val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") @@ -157,9 +145,6 @@ configurations.configureEach { } dependencies { - val devlaunch = devlaunchLibrariesConfig.name - devlaunch(libs.bootstrap.api) - val installer = installerLibrariesConfig.name installer(apiLibs.gson) installer(platform(apiLibs.configurate.bom)) @@ -233,17 +218,8 @@ dependencies { exclude(group = "org.checkerframework", module = "checker-qual") } - // All minecraft deps except itself - configurations.minecraft.get().resolvedConfiguration.resolvedArtifacts - .map { - var id = it.id.componentIdentifier.toString() - if (it.classifier != null) { - id += ":" + it.classifier - } - id - } - .filter { !it.startsWith("net.minecraft:joined") } - .forEach { boot(it) { isTransitive = false } } + // All minecraft dependencies except itself + spongeImpl.copyModulesExcludingPrefix(configurations.minecraft.get(), "net.minecraft", "joined", bootLibrariesConfig.get()) boot(project(transformersProject.path)) { exclude(group = "cpw.mods", module = "modlauncher") @@ -271,9 +247,9 @@ dependencies { spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), bootLayerConfig.get(), gameManagedLibrariesConfig.get()) - val runOnly = vanillaMain.runtimeOnlyConfigurationName + runtimeOnly(project(bootstrapDevProject.path)) testPluginsProject?.also { - runOnly(project(it.path)) + runtimeOnly(project(it.path)) } } @@ -295,6 +271,10 @@ minecraft { args("--launchTarget", "sponge_client_it") } + // Configure bootstrap-dev + val bootFileNames = spongeImpl.buildRuntimeFileNames(bootLayerConfig.get()) + val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) + configureEach { targetVersion(apiJavaTarget.toInt()) workingDirectory(project.file("run/")) @@ -328,9 +308,8 @@ minecraft { // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath mainClass("net.minecraftforge.bootstrap.ForgeBootstrap") - // Configure resources - jvmArgs("-Dsponge.dev.boot=" + bootLayerConfig.get().resolvedConfiguration.resolvedArtifacts.joinToString(";") { it.file.name }) - jvmArgs("-Dsponge.dev.gameShaded=" + gameShadedLibrariesConfig.get().resolvedConfiguration.resolvedArtifacts.joinToString(";") { it.file.name }) + jvmArgs("-Dsponge.dev.boot=$bootFileNames") + jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } } } diff --git a/vanilla/src/devlaunch/java/module-info.java b/vanilla/src/devlaunch/java/module-info.java deleted file mode 100644 index 3328ffb314e..00000000000 --- a/vanilla/src/devlaunch/java/module-info.java +++ /dev/null @@ -1,6 +0,0 @@ -module org.spongepowered.vanilla.devlaunch { - requires net.minecraftforge.bootstrap.api; - exports org.spongepowered.vanilla.devlaunch; - - provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.vanilla.devlaunch.SpongeDevClasspathFixer; -} diff --git a/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier b/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier deleted file mode 100644 index 8351cd09f4e..00000000000 --- a/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.vanilla.devlaunch.SpongeDevClasspathFixer From a35bb81e20591d87d199defbc4a09da5be8d619b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 16:43:27 +0100 Subject: [PATCH 145/586] Rework SpongeForge mod locators and load resources in dev --- .../dev/SpongeDevClasspathFixer.java | 18 ++--- forge/build.gradle.kts | 5 +- .../moddiscovery/AbstractModProvider.java | 80 +++++++++++++++++++ .../moddiscovery/PluginFileParser.java | 75 ++++++++++++++--- .../SpongeForgeDependencyLocator.java | 17 +--- .../moddiscovery/SpongeForgeModLocator.java | 21 ++++- .../locator/EnvironmentPluginLocator.java | 14 +--- .../locator/PluginsDirectoryLocator.java | 10 +-- ...java => SpongePropertyLocatorService.java} | 9 ++- ...owered.plugin.PluginResourceLocatorService | 2 +- .../vanilla/installer/InstallerMain.java | 9 ++- 11 files changed, 192 insertions(+), 68 deletions(-) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/{GameResourceLocatorService.java => SpongePropertyLocatorService.java} (93%) diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 7e4e7b8ec5a..e1630913203 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -161,26 +161,26 @@ public boolean process(final List classpath) { }); } - final StringBuilder gameResourcesEnvBuilder = new StringBuilder(); + final StringBuilder resourcesEnvBuilder = new StringBuilder(); for (final Path resource : gameLibs) { - gameResourcesEnvBuilder.append(resource).append(';'); + resourcesEnvBuilder.append(resource).append(File.pathSeparator); } for (final List project : unknownProjects.values()) { for (final Path resource : project) { - gameResourcesEnvBuilder.append(resource).append('&'); + resourcesEnvBuilder.append(resource).append('&'); } - gameResourcesEnvBuilder.setCharAt(gameResourcesEnvBuilder.length() - 1, ';'); + resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar); } for (final Path resource : spongeImplUnion) { - gameResourcesEnvBuilder.append(resource).append('&'); + resourcesEnvBuilder.append(resource).append('&'); } - gameResourcesEnvBuilder.setLength(gameResourcesEnvBuilder.length() - 1); - final String gameResourcesEnv = gameResourcesEnvBuilder.toString(); + resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); + final String resourcesEnv = resourcesEnvBuilder.toString(); if (DEBUG) { - System.out.println("Game resources env: " + gameResourcesEnv); + System.out.println("Resources env: " + resourcesEnv); } - System.setProperty("sponge.gameResources", gameResourcesEnv); + System.setProperty("sponge.resources", resourcesEnv); return true; } } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 1a4feb36864..99f42629fcd 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -223,12 +223,9 @@ extensions.configure(UserDevExtension::class) { environment("MOD_CLASSES", "nop") } - create("client") { - workingDirectory(file("run/client")) - } + create("client") create("server") { - workingDirectory(file("run/client")) args("--nogui") } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java new file mode 100644 index 00000000000..5b71dde2099 --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.loading.moddiscovery; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.forgespi.locating.IModFile; +import net.minecraftforge.forgespi.locating.IModProvider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public abstract class AbstractModProvider implements IModProvider { + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public boolean isValid(final IModFile modFile) { + return true; + } + + @Override + public void initArguments(final Map arguments) { + } + + @Override + public void scanFile(final IModFile file, final Consumer pathConsumer) { + LOGGER.debug("Scan started: {}", file); + final SecureJar jar = file.getSecureJar(); + + Consumer consumer = pathConsumer; + final AtomicReference minStatus = new AtomicReference<>(SecureJar.Status.NONE); + if (jar.hasSecurityData()) { + minStatus.set(SecureJar.Status.VERIFIED); + consumer = path -> { + pathConsumer.accept(path); + SecureJar.Status status = jar.verifyPath(path); + if (status.ordinal() < minStatus.get().ordinal()) + minStatus.set(status); + }; + } + + try (final Stream files = Files.walk(jar.getRootPath())) { + files.filter(p -> p.toString().endsWith(".class")).forEach(consumer); + } catch (IOException e) { + LOGGER.debug("Scan failed: {}", file); + minStatus.set(SecureJar.Status.NONE); + } + + file.setSecurityStatus(minStatus.get()); + LOGGER.debug("Scan finished: {}", file); + } +} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java index 9102910689f..f63dfb7c498 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java @@ -24,14 +24,16 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery; +import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; +import net.minecraftforge.fml.loading.moddiscovery.ModFileParser; import net.minecraftforge.fml.loading.moddiscovery.ModJarMetadata; import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.locating.IModFile; -import net.minecraftforge.forgespi.locating.IModLocator; -import net.minecraftforge.forgespi.locating.ModFileFactory; +import net.minecraftforge.forgespi.locating.IModProvider; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.metadata.PluginMetadataFixer; import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; @@ -46,7 +48,11 @@ import java.nio.file.Path; import java.util.List; +@SuppressWarnings("UnstableApiUsage") public final class PluginFileParser { + private static final String MODS_TOML = "META-INF/mods.toml"; + private static final String MODULE_INFO = "module-info.class"; + private static Constructor modJarMetadataConstructor; static { @@ -58,7 +64,7 @@ public final class PluginFileParser { } } - private static IModFileInfo parsePluginMetadata(final IModFile iModFile) { + private static IModFileInfo parsePluginFileInfo(final IModFile iModFile) { final ModFile modFile = (ModFile) iModFile; AppLaunch.logger().debug("Considering plugin file candidate {}", modFile.getFilePath()); @@ -82,6 +88,14 @@ private static IModFileInfo parsePluginMetadata(final IModFile iModFile) { } } + private static IModFileInfo parseModFileInfo(final IModFile iModFile) { + return ModFileParser.modsTomlParser(iModFile); + } + + private static IModFileInfo parseLibraryFileInfo(final IModFile iModFile) { + return DummyModProvider.INSTANCE.manifestParser(iModFile); + } + private static ModJarMetadata newModJarMetadata() { try { return modJarMetadataConstructor.newInstance(); @@ -90,13 +104,56 @@ private static ModJarMetadata newModJarMetadata() { } } - public static ModFile newPluginInstance(final IModLocator locator, final Path... path) { - ModJarMetadata mjm = newModJarMetadata(); - ModFile modFile = (ModFile) ModFileFactory.FACTORY.build(SecureJar.from(jar -> mjm, path), locator, PluginFileParser::parsePluginMetadata); - mjm.setModFile(modFile); - return modFile; + private static boolean useModJarMetadata(final SecureJar jar) { + final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); + if (data.findFile(PluginFileParser.MODULE_INFO).isPresent()) { + return false; + } + return data.findFile(PluginFileParser.MODS_TOML).isPresent() || data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent(); + } + + public static ModFile newModFile(final IModProvider provider, boolean allowUnknown, final Path... paths) { + final ModJarMetadata mjm = newModJarMetadata(); + final SecureJar jar = SecureJar.from(j -> useModJarMetadata(j) ? mjm : JarMetadata.from(j, paths), paths); + + final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); + final String type = data.getManifest().getMainAttributes().getValue("FMLModType"); + + if (data.findFile(PluginFileParser.MODS_TOML).isPresent()) { + ModFile modFile = new ModFile(jar, provider, PluginFileParser::parseModFileInfo, type == null ? "MOD" : type); + mjm.setModFile(modFile); + return modFile; + } + + if (data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent()) { + ModFile modFile = new ModFile(jar, provider, PluginFileParser::parsePluginFileInfo, type == null ? "MOD" : type); + mjm.setModFile(modFile); + return modFile; + } + + if (!allowUnknown && type == null) { + throw new IllegalArgumentException("Unknown mod file type"); + } + + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, type == null ? "GAMELIBRARY" : type); + } + + public static ModFile newLibraryFile(final IModProvider provider, final Path... paths) { + final SecureJar jar = SecureJar.from(paths); + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, "GAMELIBRARY"); } - private PluginFileParser() { + private static class DummyModProvider extends AbstractModProvider { + private static final DummyModProvider INSTANCE = new DummyModProvider(); + + @Override + public String name() { + return "dummy"; + } + + @Override + public IModFileInfo manifestParser(IModFile mod) { + return super.manifestParser(mod); + } } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java index b73e593f3c6..4fa07561fdd 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java @@ -27,10 +27,8 @@ import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.Launcher; import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IDependencyLocator; import net.minecraftforge.forgespi.locating.IModFile; -import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.forge.applaunch.loading.moddiscovery.library.Log4JLogger; @@ -42,14 +40,13 @@ import java.util.List; import java.util.Map; -// works with ForgeProductionBootstrap to make this whole thing go public class SpongeForgeDependencyLocator extends AbstractModProvider implements IDependencyLocator { private static final Logger LOGGER = LogManager.getLogger(); private LibraryManager libraryManager; @Override - public List scanMods(Iterable loadedMods) { + public List scanMods(final Iterable loadedMods) { final List modFiles = new ArrayList<>(); // Add Sponge-specific libraries @@ -64,23 +61,13 @@ public List scanMods(Iterable loadedMods) { for (final LibraryManager.Library library : this.libraryManager.getAll("main")) { final Path path = library.file(); SpongeForgeDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - - final IModLocator.ModFileOrException fileOrException = createMod(path); - if (fileOrException.ex() != null) { - throw fileOrException.ex(); - } - modFiles.add(fileOrException.file()); + modFiles.add(PluginFileParser.newLibraryFile(this, path)); } } return modFiles; } - @Override - protected String getDefaultJarModType() { - return IModFile.Type.GAMELIBRARY.name(); - } - @Override public String name() { return "spongeforge"; diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java index e7c704b506b..841f97069a7 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java @@ -28,20 +28,23 @@ import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.Launcher; import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.forge.applaunch.plugin.ForgePluginPlatform; +import java.io.File; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Stream; public final class SpongeForgeModLocator extends AbstractModProvider implements IModLocator { private static final Logger LOGGER = LogManager.getLogger(); @@ -49,7 +52,19 @@ public final class SpongeForgeModLocator extends AbstractModProvider implements @Override public List scanMods() { if (!FMLEnvironment.production) { - return List.of(); + final List resources = new ArrayList<>(); + final String resourcesProp = System.getProperty("sponge.resources"); + if (resourcesProp != null) { + for (final String entry : resourcesProp.split(File.pathSeparator)) { + if (entry.isBlank()) { + continue; + } + + final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); + resources.add(new ModFileOrException(PluginFileParser.newModFile(this, true, paths), null)); + } + } + return resources; } try { @@ -66,7 +81,7 @@ public List scanMods() { } catch (Exception e) { throw new RuntimeException(e); } - }).map(this::createMod).toList(); + }).map((path -> new ModFileOrException(PluginFileParser.newModFile(this, false, path), null))).toList(); } catch (Exception e) { LOGGER.error("Failed to scan mod candidates", e); } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java index e2903123f0d..a76911d39dd 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java @@ -24,15 +24,14 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IModLocator; +import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.stream.Stream; public final class EnvironmentPluginLocator extends AbstractModProvider implements IModLocator { @@ -41,25 +40,16 @@ public final class EnvironmentPluginLocator extends AbstractModProvider implemen public List scanMods() { final List modFiles = new ArrayList<>(); for (final Path[] paths : EnvironmentPluginLocator.getPluginsPaths()) { - modFiles.add(new ModFileOrException(PluginFileParser.newPluginInstance(this, paths), null)); + modFiles.add(new ModFileOrException(PluginFileParser.newModFile(this, false, paths), null)); } return modFiles; } - @Override - protected ModFileOrException createMod(Path path) { - return new ModFileOrException(PluginFileParser.newPluginInstance(this, path), null); - } - @Override public String name() { return "environment plugin"; } - @Override - public void initArguments(final Map arguments) { - } - private static List getPluginsPaths() { final String env = System.getenv("SPONGE_PLUGINS"); if (env == null) { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java index 4202f337b93..e0ed9845745 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java @@ -27,12 +27,12 @@ import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; import net.minecraftforge.fml.loading.StringUtils; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; import java.nio.file.Files; @@ -40,7 +40,6 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.stream.Stream; public final class PluginsDirectoryLocator extends AbstractModProvider implements IModLocator { @@ -60,12 +59,13 @@ public List scanMods() { return modFiles; } + @SuppressWarnings("UnstableApiUsage") private Stream scanForPluginsIn(final Path pluginsDirectory) { final List excluded = ModDirTransformerDiscoverer.allExcluded(); return LamdbaExceptionUtils.uncheck(() -> Files.list(pluginsDirectory)) .filter((p) -> !excluded.contains(p) && StringUtils.toLowerCase(p.getFileName().toString()).endsWith(".jar")) .sorted(Comparator.comparing((path) -> StringUtils.toLowerCase(path.getFileName().toString()))) - .map((p) -> PluginFileParser.newPluginInstance(this, p)) + .map((p) -> PluginFileParser.newModFile(this, false, p)) .filter(ModFile::identifyMods); } @@ -73,8 +73,4 @@ private Stream scanForPluginsIn(final Path pluginsDirectory) { public String name() { return "plugins directory"; } - - @Override - public void initArguments(final Map arguments) { - } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java similarity index 93% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java rename to vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java index 0a1791fb459..19e5d2e8b4e 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java @@ -28,6 +28,7 @@ import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; import org.spongepowered.plugin.builtin.jvm.locator.JVMPluginResourceLocatorService; +import java.io.File; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -37,11 +38,11 @@ import java.util.Set; import java.util.stream.Stream; -public final class GameResourceLocatorService implements JVMPluginResourceLocatorService { +public final class SpongePropertyLocatorService implements JVMPluginResourceLocatorService { @Override public String name() { - return "game"; + return "sponge_resources"; } @Override @@ -49,9 +50,9 @@ public Set locatePluginResources(final Environment environmen environment.logger().info("Locating '{}' resources...", this.name()); final Set resources = new HashSet<>(); - final String resourcesProp = System.getProperty("sponge.gameResources"); + final String resourcesProp = System.getProperty("sponge.resources"); if (resourcesProp != null) { - for (final String entry : resourcesProp.split(";")) { + for (final String entry : resourcesProp.split(File.pathSeparator)) { if (entry.isBlank()) { continue; } diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService index 330fcb92be8..cf8cd29b6e7 100644 --- a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService +++ b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService @@ -1 +1 @@ -org.spongepowered.vanilla.applaunch.plugin.locator.GameResourceLocatorService \ No newline at end of file +org.spongepowered.vanilla.applaunch.plugin.locator.SpongePropertyLocatorService \ No newline at end of file diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index 9c36b84dd5e..370e4c18036 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -42,6 +42,7 @@ import org.spongepowered.vanilla.installer.model.mojang.VersionManifest; import org.tinylog.Logger; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -68,6 +69,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.StringJoiner; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.jar.JarFile; @@ -177,12 +179,11 @@ public void downloadAndRun() throws Exception { } } - final StringBuilder gameLibsEnv = new StringBuilder(); + final StringJoiner resourcesEnv = new StringJoiner(File.pathSeparator); for (final Path lib : gameLibs) { - gameLibsEnv.append(lib.toAbsolutePath()).append(';'); + resourcesEnv.add(lib.toAbsolutePath().toString()); } - gameLibsEnv.setLength(gameLibsEnv.length() - 1); - System.setProperty("sponge.gameResources", gameLibsEnv.toString()); + System.setProperty("sponge.resources", resourcesEnv.toString()); final List gameArgs = new ArrayList<>(LauncherCommandLine.remainingArgs); gameArgs.add("--launchTarget"); From 061dfd0e19f85cddb1b237e662c448696cdd4a87 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 21:24:52 +0100 Subject: [PATCH 146/586] Fix SpongeForge attack and furnace mixins --- ...AbstractFurnaceBlockEntityMixin_Forge.java | 24 ++++++++++--------- .../entity/LivingEntityMixin_Attack_Impl.java | 11 +++------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 34cab814694..5a8394cd809 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -27,10 +27,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.Level; +import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.objectweb.asm.Opcodes; @@ -69,7 +70,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // @formatter:off @Shadow protected NonNullList items; @Shadow int cookingProgress; - @Shadow private boolean shadow$canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, NonNullList slots, int maxStackSize) { + @Shadow private boolean shadow$canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, SingleRecipeInput input, NonNullList slots, int maxStackSize) { throw new UnsupportedOperationException("Shadowed canBurn"); } // @formatter:on @@ -79,15 +80,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // Tick up and Start @Redirect(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;I)Z", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", ordinal = 1)) private static boolean forge$checkIfCanSmelt(final AbstractFurnaceBlockEntity entityIn, - final RegistryAccess registryAccess, - final RecipeHolder recipe, - final NonNullList slots, - final int maxStackSize) { + final RegistryAccess registryAccess, + final RecipeHolder recipe, + final SingleRecipeInput input, + final NonNullList slots, + final int maxStackSize) { final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) (entityIn); - if (!entity.shadow$canBurn(registryAccess, recipe, slots, maxStackSize)) { + if (!entity.shadow$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { return false; } @@ -111,7 +113,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) private static int forge$resetCookTimeIfCancelled(final int newCookTime, final int zero, final int totalCookTime, - final Level level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { + final ServerLevel level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) entityIn; final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); @@ -133,7 +135,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF slice = @Slice( from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) )) - private void forge$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir) { + private void forge$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir) { this.forge$filledWaterBucket = true; } @@ -142,7 +144,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) private void forge$afterSmeltItem( - final RegistryAccess registryAccess, final RecipeHolder recipe, + final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir, final ItemStack itemIn, final ItemStack recipeResult, final ItemStack itemOut diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 8bce4b1a806..0835f4869de 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -43,7 +43,6 @@ import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -170,14 +169,10 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * After calling #actuallyHurt (even when invulnerable), if cancelled return early or is still invulnerable * and reset {@link #lastHurt} and {@link #invulnerableTime} */ - @Inject(method = "hurtServer", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt1( - final ServerLevel level, final DamageSource source, final float damageTaken, - final CallbackInfoReturnable cir, final float dealtDamage, final boolean isBlocked, - float $$5, boolean wasHurt - ) { + private void attackImpl$afterActuallyHurt1(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { if (this.attackImpl$actuallyHurtCancelled || damageTaken <= this.lastHurt) { this.invulnerableTime = this.attackImpl$InvulnerableTime; this.lastHurt = this.attackImpl$lastHurt; @@ -189,7 +184,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * After calling #actuallyHurt, if cancelled return early * Also reset values */ - @Inject(method = "hurtServer",cancellable = true, + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 1, target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) private void attackImpl$afterActuallyHurt2(ServerLevel $$0, DamageSource $$1, float $$2, CallbackInfoReturnable cir) { From c644444f3b55c5cb1785060f3b9cead39d03c90f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 17:28:39 +0100 Subject: [PATCH 147/586] Convert AW to AT for ForgeGradle --- build-logic/build.gradle | 5 + build-logic/settings.gradle | 9 +- .../gradle/impl/ConvertAWToAT.java | 109 ++++++++++++++++++ build.gradle.kts | 11 +- forge/build.gradle.kts | 12 +- generator/build.gradle.kts | 7 +- gradle/libs.versions.toml | 1 + neoforge/build.gradle.kts | 2 +- vanilla/build.gradle.kts | 11 +- 9 files changed, 140 insertions(+), 27 deletions(-) create mode 100644 build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java diff --git a/build-logic/build.gradle b/build-logic/build.gradle index 5cabd817724..1539cbfb1a6 100644 --- a/build-logic/build.gradle +++ b/build-logic/build.gradle @@ -13,6 +13,11 @@ indra { dependencies { api(apiLibs.gson) implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:${apiLibs.versions.ideaExt.get()}") + implementation(libs.at) + implementation(libs.accessWidener) + + // arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies + api("dev.architectury:architectury-loom:1.6.411") } indraSpotlessLicenser { diff --git a/build-logic/settings.gradle b/build-logic/settings.gradle index 9e7a64e236c..3e53ae9cde4 100644 --- a/build-logic/settings.gradle +++ b/build-logic/settings.gradle @@ -9,7 +9,14 @@ pluginManagement { dependencyResolutionManagement { repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS - repositories { pluginManagement.repositories.each { add(it) } } + repositories { + pluginManagement.repositories.each { add(it) } + maven { + url = "https://maven.architectury.dev/" + name = "architectury" + } + } + versionCatalogs { libs { from files("../gradle/libs.versions.toml") diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java new file mode 100644 index 00000000000..d3f1e05193d --- /dev/null +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java @@ -0,0 +1,109 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.gradle.impl; + +import dev.architectury.at.AccessChange; +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.ModifierChange; +import dev.architectury.at.io.AccessTransformFormats; +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import org.cadixdev.bombe.type.signature.MethodSignature; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.TaskAction; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Set; + +public abstract class ConvertAWToAT extends DefaultTask { + + @InputFiles + public abstract ConfigurableFileCollection getAccessWideners(); + + public void accessWideners(Object... paths) { + this.getAccessWideners().from(paths); + } + + @OutputFile + public abstract RegularFileProperty getAccessTransformer(); + + @TaskAction + public void convert() { + final Set awFiles = this.getAccessWideners().getFiles(); + final File atFile = this.getAccessTransformer().get().getAsFile(); + + final AccessTransformSet at = AccessTransformSet.create(); + + for (final File awFile : awFiles) { + try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) { + ConvertAWToAT.convert(reader, at); + } catch (final IOException e) { + throw new GradleException("Failed to read access widener: " + awFile, e); + } + } + + try (final BufferedWriter writer = Files.newBufferedWriter(atFile.toPath())) { + AccessTransformFormats.FML.write(writer, at); + } catch (IOException e) { + throw new GradleException("Failed to write access transformer: " + atFile, e); + } + } + + public static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { + new AccessWidenerReader(new AccessWidenerVisitor() { + @Override + public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(name).merge(ConvertAWToAT.convertEntry(access)); + } + + @Override + public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), ConvertAWToAT.convertEntry(access)); + } + + @Override + public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(owner).mergeField(name, ConvertAWToAT.convertEntry(access)); + } + }).read(reader); + } + + public static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { + return switch (access) { + case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC); + case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE); + }; + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 936320ff20b..85ce26ad312 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -176,6 +176,10 @@ dependencies { } } +minecraft { + accessWideners(main.resources.filter { it.name.endsWith(".accesswidener") }) +} + allprojects { configurations.configureEach { resolutionStrategy.dependencySubstitution { @@ -199,13 +203,6 @@ allprojects { minecraft { version(minecraftVersion) injectRepositories(false) - project.sourceSets["main"].resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { - accessWideners(it) - parent?.minecraft?.accessWideners(it) - } } dependencies { diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 99f42629fcd..3394d182ff7 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,5 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.userdev.UserDevExtension +import org.spongepowered.gradle.impl.ConvertAWToAT buildscript { repositories { @@ -201,11 +202,17 @@ dependencies { runtimeOnly(project(bootstrapDevProject.path)) } +val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { + accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(forgeMain.resources.filter { it.name.endsWith(".accesswidener") }) + accessTransformer.set(project.layout.buildDirectory.file("generated/resources/at.cfg")) +} + val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { mappings("official", "1.21.3") - // accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) TODO + accessTransformers.from(convertAWToAT.flatMap { it.accessTransformer }) reobf = false @@ -213,8 +220,7 @@ extensions.configure(UserDevExtension::class) { configureEach { ideaModule("Sponge.SpongeForge.main") - property("forge.logging.markers", "REGISTRIES") - property("forge.logging.console.level", "debug") + // property("forge.logging.console.level", "debug") // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath diff --git a/generator/build.gradle.kts b/generator/build.gradle.kts index 6481b69c15c..da7ca6bedc2 100644 --- a/generator/build.gradle.kts +++ b/generator/build.gradle.kts @@ -5,12 +5,7 @@ plugins { description = "Code generator for automatically producing API catalog classes based off of Vanilla MC data" minecraft { - rootProject.sourceSets["main"].resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { - accessWideners(it) - } + accessWideners(rootProject.sourceSets["main"].resources.filter { it.name.endsWith(".accesswidener") }) } configurations.configureEach { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cbc47e0b08d..d2eca4aaf9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,6 +68,7 @@ terminalConsoleAppender = { module = "net.minecrell:terminalconsoleappender", ve # buildtime-only vineflower = { module = "org.vineflower:vineflower", version.ref = "vineflower" } +at = { module = "dev.architectury:at", version = "1.0.1" } [plugins] blossom = { id = "net.kyori.blossom", version = "2.1.0" } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 9cd699e0d03..96e95d67d69 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -14,7 +14,7 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("dev.architectury.loom") version "1.6.411" + id("dev.architectury.loom") } val commonProject = parent!! diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 00ac01e6f6c..90595bb3a29 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -126,15 +126,8 @@ val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations minecraft { - main.get().resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { accessWideners(it) } - - vanillaMain.resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { accessWideners(it) } + accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(vanillaMain.resources.filter { it.name.endsWith(".accesswidener") }) } configurations.configureEach { From cd0ea4ab3ec705e9629887e8130a5e8b421472a7 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:10:34 +0100 Subject: [PATCH 148/586] Load test plugins on SpongeForge --- .../dev/SpongeDevClasspathFixer.java | 44 ++++++++++--------- forge/build.gradle.kts | 18 ++------ .../applaunch/resources/META-INF/MANIFEST.MF | 1 + forge/src/lang/resources/META-INF/MANIFEST.MF | 2 + library-manager/build.gradle.kts | 8 ++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + modlauncher-transformers/build.gradle.kts | 2 +- .../src/main/resources/META-INF/MANIFEST.MF | 2 +- 8 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 forge/src/applaunch/resources/META-INF/MANIFEST.MF create mode 100644 forge/src/lang/resources/META-INF/MANIFEST.MF create mode 100644 library-manager/src/main/resources/META-INF/MANIFEST.MF diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index e1630913203..1fc983100b0 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -53,11 +53,12 @@ public boolean process(final List classpath) { final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); - final Multimap bootSourceSets = new Multimap<>(); - final Multimap unknownProjects = new Multimap<>(); + // boot layer + final Multimap bootUnions = new Multimap<>(); - final List spongeImplUnion = new ArrayList<>(); - final List gameLibs = new ArrayList<>(); + // game or plugin layer + final Multimap unions = new Multimap<>(); + final List libs = new ArrayList<>(); final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false); @@ -78,7 +79,7 @@ public boolean process(final List classpath) { // ignore break; case "modlauncher-transformers", "library-manager": - bootSourceSets.add(sourceSet.project(), path); + bootUnions.add(sourceSet.project(), path); break; case "SpongeAPI": switch (sourceSet.name()) { @@ -89,19 +90,25 @@ public boolean process(final List classpath) { hasAPISourceSet.set(true); // no break default: - spongeImplUnion.add(path); + unions.add("sponge", path); break; } break; case "Sponge", "vanilla", "forge": - if (sourceSet.name().equals("applaunch")) { - bootSourceSets.add("applaunch", path); - } else { - spongeImplUnion.add(path); + switch (sourceSet.name()) { + case "applaunch": + bootUnions.add("applaunch", path); + break; + case "lang": + unions.add("lang", path); + break; + default: + unions.add("sponge", path); + break; } break; default: - unknownProjects.add(sourceSet.project(), path); + unions.add(sourceSet.project(), path); break; } return true; @@ -127,14 +134,14 @@ public boolean process(final List classpath) { if (DEBUG) { System.out.println("Sponge: " + path); } - spongeImplUnion.add(path); + unions.add("sponge", path); return true; } if (DEBUG) { System.out.println("Game: " + path); } - gameLibs.add(path); + libs.add(path); return true; }); @@ -142,12 +149,12 @@ public boolean process(final List classpath) { return false; } - for (final List sourceSets : bootSourceSets.values()) { + for (final List sourceSets : bootUnions.values()) { classpath.add(sourceSets.toArray(Path[]::new)); } if (hasAPISourceSet.get()) { - spongeImplUnion.removeIf((path) -> { + unions.get("sponge").removeIf((path) -> { if (Files.isRegularFile(path)) { final String fileName = path.getFileName().toString(); if (fileName.startsWith("spongeapi") && fileName.endsWith(".jar")) { @@ -162,18 +169,15 @@ public boolean process(final List classpath) { } final StringBuilder resourcesEnvBuilder = new StringBuilder(); - for (final Path resource : gameLibs) { + for (final Path resource : libs) { resourcesEnvBuilder.append(resource).append(File.pathSeparator); } - for (final List project : unknownProjects.values()) { + for (final List project : unions.values()) { for (final Path resource : project) { resourcesEnvBuilder.append(resource).append('&'); } resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar); } - for (final Path resource : spongeImplUnion) { - resourcesEnvBuilder.append(resource).append('&'); - } resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); final String resourcesEnv = resourcesEnvBuilder.toString(); diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 3394d182ff7..b3a90619a7b 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -145,6 +145,7 @@ val forgeMain by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) spongeImpl.addDependencyToRuntimeOnly(forgeMixins, this) + spongeImpl.addDependencyToRuntimeOnly(forgeLang, this) } configurations.configureEach { @@ -200,6 +201,9 @@ dependencies { } runtimeOnly(project(bootstrapDevProject.path)) + testPluginsProject?.also { + runtimeOnly(project(it.path)) + } } val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { @@ -299,20 +303,6 @@ tasks { from(forgeLang.output) } - val forgeServicesJar by registering(Jar::class) { - archiveClassifier.set("services") - - manifest { - from(forgeManifest) - attributes("Automatic-Module-Name" to "spongeforge.services") - } - - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(forgeAppLaunch.output) - - duplicatesStrategy = DuplicatesStrategy.WARN - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") forgeAppLaunch.resources.srcDir(installerResources) diff --git a/forge/src/applaunch/resources/META-INF/MANIFEST.MF b/forge/src/applaunch/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..c54a634b615 --- /dev/null +++ b/forge/src/applaunch/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Automatic-Module-Name: spongeforge.services diff --git a/forge/src/lang/resources/META-INF/MANIFEST.MF b/forge/src/lang/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..8e85d7c5e2a --- /dev/null +++ b/forge/src/lang/resources/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Automatic-Module-Name: spongeforge.lang +FMLModType: LANGPROVIDER diff --git a/library-manager/build.gradle.kts b/library-manager/build.gradle.kts index e2a23945059..11fc683e50f 100644 --- a/library-manager/build.gradle.kts +++ b/library-manager/build.gradle.kts @@ -1,3 +1,11 @@ dependencies { implementation(apiLibs.gson) } + +tasks { + jar { + manifest { + attributes("Automatic-Module-Name" to "sponge.library_manager") + } + } +} diff --git a/library-manager/src/main/resources/META-INF/MANIFEST.MF b/library-manager/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..68336aaf212 --- /dev/null +++ b/library-manager/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Automatic-Module-Name: sponge.library_manager diff --git a/modlauncher-transformers/build.gradle.kts b/modlauncher-transformers/build.gradle.kts index 390fab762bd..ab8303b3673 100644 --- a/modlauncher-transformers/build.gradle.kts +++ b/modlauncher-transformers/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { tasks { jar { manifest { - attributes("Automatic-Module-Name" to "sponge.modlauncher.transformers") + attributes("Automatic-Module-Name" to "sponge.modlauncher_transformers") } } } diff --git a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF b/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF index 0a1e1f7343d..8e5fb5b07e5 100644 --- a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF +++ b/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF @@ -1 +1 @@ -Automatic-Module-Name: sponge.modlauncher.transformers +Automatic-Module-Name: sponge.modlauncher_transformers From fe195a7911ce2a22bc9a65e0d051039898c850ba Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:11:41 +0100 Subject: [PATCH 149/586] Fix branding mixin on Forge --- .../internal/BrandingControlMixin_Forge.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java index 841f6ba78ea..c92ec5c3b54 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java @@ -36,16 +36,7 @@ public abstract class BrandingControlMixin_Forge { * @reason This is also not Kansas anymore */ @Overwrite - public static String getClientBranding() { - return "forge/spongeforge"; - } - - /** - * @author Zidane - * @reason What that said above - */ - @Overwrite - public static String getServerBranding() { + public static String getBranding() { return "forge/spongeforge"; } } From 2321a693d786747780c78a6289c5f2b1c84e1aeb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:30:09 +0100 Subject: [PATCH 150/586] Update verification metadata --- gradle/verification-metadata.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 328daf4d49e..2cf4b8bf80a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6,6 +6,7 @@ + @@ -2286,6 +2287,14 @@ + + + + + + + + From e5e0121efd81dd8d9921262a9e53800d91a7ca1a Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 23 Dec 2024 00:45:33 +0200 Subject: [PATCH 151/586] Fix ExplosionEvent.Pre cancelling --- .../tracker/server/level/ServerLevelMixin_Tracker.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index e1766cb999a..990a2389412 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -373,6 +373,14 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem this.tracker$apiExplosion = apiExplosion; } + @Inject(method = "explode", cancellable = true, at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;explode()V", shift = At.Shift.AFTER)) + private void tracker$onCancelled(final CallbackInfo ci) { + if (this.tracker$apiExplosion == null) { + ci.cancel(); + } + } + /** * See {@link net.minecraft.client.multiplayer.ClientPacketListener#handleExplosion} for client side handling */ From 707b3f1ac6fd309338d6affd9b60bd4a4938b45d Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 23 Dec 2024 00:46:14 +0200 Subject: [PATCH 152/586] Implement tab list entry order --- SpongeAPI | 2 +- .../common/entity/player/tab/SpongeTabList.java | 4 ++-- .../entity/player/tab/SpongeTabListEntry.java | 16 +++++++++++++++- .../entity/player/tab/TabListEntryBuilder.java | 11 ++++++++++- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index c0f65a12e41..f4245597d6d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c0f65a12e41afb4a6891efd0c6c00a7b0f2ddea4 +Subproject commit f4245597d6dc09becafbcff46a1afbc365ee2eca diff --git a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java index 8d49e1212f2..072decba587 100644 --- a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java +++ b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabList.java @@ -151,6 +151,7 @@ private void addEntry(final ClientboundPlayerInfoUpdatePacket.Entry entry) { entry.latency(), (GameMode) (Object) entry.gameMode(), entry.listed(), + entry.listOrder(), entry.chatSession() == null ? null : entry.chatSession().profilePublicKey() ), false); } @@ -190,11 +191,10 @@ public Optional removeEntry(final UUID uniqueId) { @SuppressWarnings("ConstantConditions") void sendUpdate(final TabListEntry entry, final EnumSet actions) { final ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, List.of()); - int listOrder = 0; // TODO expose to API final RemoteChatSession.Data chatSessionData = ((SpongeTabListEntry) entry).profilePublicKey() == null ? null : new RemoteChatSession.Data(entry.profile().uuid(), ((SpongeTabListEntry) entry).profilePublicKey()); final net.minecraft.network.chat.Component displayName = entry.displayName().isPresent() ? SpongeAdventure.asVanilla(entry.displayName().get()) : null; final ClientboundPlayerInfoUpdatePacket.Entry data = new ClientboundPlayerInfoUpdatePacket.Entry(entry.profile().uniqueId(), SpongeGameProfile.toMcProfile(entry.profile()), - entry.listed(), entry.latency(), (GameType) (Object) entry.gameMode(), displayName, listOrder, chatSessionData); + entry.listed(), entry.latency(), (GameType) (Object) entry.gameMode(), displayName, entry.weight(), chatSessionData); ((ClientboundPlayerInfoUpdatePacketAccessor) packet).accessor$entries(List.of(data)); this.player.connection.send(packet); } diff --git a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabListEntry.java b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabListEntry.java index 355ada3d91b..566f25f008e 100644 --- a/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabListEntry.java +++ b/src/main/java/org/spongepowered/common/entity/player/tab/SpongeTabListEntry.java @@ -52,12 +52,13 @@ public final class SpongeTabListEntry implements TabListEntry { private int latency; private GameMode gameMode; private boolean listed; + private int weight; private boolean updateWithoutSend; private final ProfilePublicKey.Data profilePublicKey; public SpongeTabListEntry( final TabList list, final GameProfile profile, @Nullable final Component displayName, final int latency, final GameMode gameMode, - final boolean listed, final ProfilePublicKey.Data profilePublicKey) { + final boolean listed, final int weight, final ProfilePublicKey.Data profilePublicKey) { Preconditions.checkState(list instanceof SpongeTabList, "list is not a SpongeTabList"); this.list = (SpongeTabList) list; this.profile = Objects.requireNonNull(profile, "profile"); @@ -65,6 +66,7 @@ public SpongeTabListEntry( this.latency = latency; this.gameMode = Objects.requireNonNull(gameMode, "game mode"); this.listed = listed; + this.weight = weight; this.profilePublicKey = profilePublicKey; } @@ -126,6 +128,18 @@ public SpongeTabListEntry setListed(boolean listed) { return this; } + @Override + public int weight() { + return this.weight; + } + + @Override + public SpongeTabListEntry setWeight(int weight) { + this.weight = weight; + this.sendUpdate(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER); + return this; + } + public ProfilePublicKey.Data profilePublicKey() { return this.profilePublicKey; } diff --git a/src/main/java/org/spongepowered/common/entity/player/tab/TabListEntryBuilder.java b/src/main/java/org/spongepowered/common/entity/player/tab/TabListEntryBuilder.java index cb974eb6caf..3c1e136d1cd 100644 --- a/src/main/java/org/spongepowered/common/entity/player/tab/TabListEntryBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/player/tab/TabListEntryBuilder.java @@ -44,6 +44,7 @@ public final class TabListEntryBuilder implements TabListEntry.Builder { private int latency; private boolean listed = true; private @Nullable GameMode gameMode; + private int weight; @Override public TabListEntry.Builder list(TabList list) { @@ -81,13 +82,19 @@ public TabListEntry.Builder listed(boolean listed) { return this; } + @Override + public TabListEntry.Builder weight(int weight) { + this.weight = weight; + return this; + } + @Override public TabListEntry build() { Preconditions.checkState(this.list != null, "list must be set"); Preconditions.checkState(this.profile != null, "profile must be set"); Preconditions.checkState(this.gameMode != null, "game mode must be set"); - return new SpongeTabListEntry(this.list, this.profile, this.displayName, this.latency, this.gameMode, this.listed, null); + return new SpongeTabListEntry(this.list, this.profile, this.displayName, this.latency, this.gameMode, this.listed, this.weight, null); } @Override @@ -97,6 +104,7 @@ public TabListEntry.Builder from(TabListEntry value) { this.displayName = value.displayName().orElse(null); this.latency = value.latency(); this.gameMode = Objects.requireNonNull(value.gameMode(), "game mode"); + this.weight = value.weight(); return this; } @@ -107,6 +115,7 @@ public TabListEntry.Builder reset() { this.displayName = null; this.latency = 0; this.gameMode = null; + this.weight = 0; return this; } From 52c4d263c6063fcbdcae78e6948df97cb1c343d6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 23 Dec 2024 22:24:11 +0100 Subject: [PATCH 153/586] Fix dev classpath when root directory is not "Sponge" --- .../bootstrap/dev/SourceSet.java | 30 ++++--- .../dev/SpongeDevClasspathFixer.java | 89 +++++++++++-------- forge/build.gradle.kts | 1 + vanilla/build.gradle.kts | 1 + 4 files changed, 68 insertions(+), 53 deletions(-) diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java index 540c752afcc..badeb5407dc 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java @@ -29,7 +29,7 @@ import java.util.ArrayList; import java.util.List; -public record SourceSet(String project, String name, String format) { +public record SourceSet(Path project, String name, String format) { @Override public String toString() { @@ -57,32 +57,34 @@ public static SourceSet identify(Path path) { } // from right to left - final List parts = new ArrayList<>(); + final List names = new ArrayList<>(); + final List paths = new ArrayList<>(); while (path != null) { - parts.add(path.getFileName().toString()); - if (parts.size() >= 5) { + names.add(path.getFileName().toString()); + paths.add(path); + if (names.size() >= 5) { break; } path = path.getParent(); } - if (parts.size() >= 4 && (parts.get(0).equals("classes") || parts.get(0).equals("resources"))) { - final String name = parts.get(1); - return new SourceSet(parts.get(3), name.equals("production") ? "main" : name, "IntelliJ"); + if (names.size() >= 4 && (names.get(0).equals("classes") || names.get(0).equals("resources"))) { + final String name = names.get(1); + return new SourceSet(paths.get(3), name.equals("production") ? "main" : name, "IntelliJ"); } - if (parts.size() >= 4 && (parts.get(1).equals("resources") || parts.get(1).equals("generated"))) { - return new SourceSet(parts.get(3), parts.get(0), "Gradle"); + if (names.size() >= 4 && (names.get(1).equals("resources") || names.get(1).equals("generated"))) { + return new SourceSet(paths.get(3), names.get(0), "Gradle"); } - if (parts.size() >= 5 && parts.get(2).equals("classes")) { - return new SourceSet(parts.get(4), parts.get(0), "Gradle"); + if (names.size() >= 5 && names.get(2).equals("classes")) { + return new SourceSet(paths.get(4), names.get(0), "Gradle"); } - if (parts.size() >= 3 && parts.get(1).equals("bin")) { - return new SourceSet(parts.get(2), parts.get(0), "Eclipse"); + if (names.size() >= 3 && names.get(1).equals("bin")) { + return new SourceSet(paths.get(2), names.get(0), "Eclipse"); } - return new SourceSet("", parts.get(0), "Unknown"); + return new SourceSet(paths.get(0), "?", "Unknown"); } } diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 1fc983100b0..ab566c5f915 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -29,6 +29,7 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -49,6 +50,7 @@ public String name() { */ @Override public boolean process(final List classpath) { + final Path spongeRoot = Paths.get(System.getProperty("sponge.dev.root")).toAbsolutePath(); final Set ignoredLibs = Set.of("bootstrap-dev.jar"); final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); @@ -70,46 +72,55 @@ public boolean process(final List classpath) { final Path path = paths[0]; final SourceSet sourceSet = SourceSet.identify(path); if (sourceSet != null) { - if (DEBUG) { - System.out.println("SourceSet (" + sourceSet + "): " + path); - } + if (sourceSet.project().startsWith(spongeRoot)) { + if (DEBUG) { + System.out.println("Sponge SourceSet (" + sourceSet + "): " + path); + } - switch (sourceSet.project()) { - case "bootstrap-dev": - // ignore - break; - case "modlauncher-transformers", "library-manager": - bootUnions.add(sourceSet.project(), path); - break; - case "SpongeAPI": - switch (sourceSet.name()) { - case "ap": - // ignore - break; - case "main": - hasAPISourceSet.set(true); - // no break - default: - unions.add("sponge", path); - break; - } - break; - case "Sponge", "vanilla", "forge": - switch (sourceSet.name()) { - case "applaunch": - bootUnions.add("applaunch", path); - break; - case "lang": - unions.add("lang", path); - break; - default: - unions.add("sponge", path); - break; - } - break; - default: - unions.add(sourceSet.project(), path); - break; + final String projectName = spongeRoot.relativize(sourceSet.project()).toString(); + switch (projectName) { + case "bootstrap-dev": + // ignore + break; + case "modlauncher-transformers", "library-manager": + bootUnions.add(projectName, path); + break; + case "SpongeAPI": + switch (sourceSet.name()) { + case "ap": + // ignore + break; + case "main": + hasAPISourceSet.set(true); + // no break + default: + unions.add("sponge", path); + break; + } + break; + case "", "vanilla", "forge": + switch (sourceSet.name()) { + case "applaunch": + bootUnions.add("applaunch", path); + break; + case "lang": + unions.add("lang", path); + break; + default: + unions.add("sponge", path); + break; + } + break; + default: + unions.add(projectName, path); + break; + } + } else { + if (DEBUG) { + System.out.println("External SourceSet (" + sourceSet + "): " + path); + } + + unions.add(sourceSet.project().toString(), path); } return true; } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index b3a90619a7b..c973f13168e 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -247,6 +247,7 @@ afterEvaluate { val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) runs.configureEach { + jvmArgs("-Dsponge.dev.root=" + project.rootDir) jvmArgs("-Dsponge.dev.boot=$bootFileNames") jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 90595bb3a29..27fc697f86c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -301,6 +301,7 @@ minecraft { // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath mainClass("net.minecraftforge.bootstrap.ForgeBootstrap") + jvmArgs("-Dsponge.dev.root=" + project.rootDir) jvmArgs("-Dsponge.dev.boot=$bootFileNames") jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } From cd1052a11acbd12097c8c28fcc6b16ee53ffc565 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 24 Dec 2024 22:24:22 +0100 Subject: [PATCH 154/586] Generate access transformer during Gradle configuration phase --- .../impl/{ConvertAWToAT.java => AWToAT.java} | 42 +++++++------------ forge/build.gradle.kts | 15 +++---- 2 files changed, 19 insertions(+), 38 deletions(-) rename build-logic/src/main/java/org/spongepowered/gradle/impl/{ConvertAWToAT.java => AWToAT.java} (72%) diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java similarity index 72% rename from build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java rename to build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java index d3f1e05193d..da782c13dc6 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java @@ -32,43 +32,27 @@ import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerVisitor; import org.cadixdev.bombe.type.signature.MethodSignature; -import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.Set; -public abstract class ConvertAWToAT extends DefaultTask { +public class AWToAT { + private static final Logger logger = Logging.getLogger(AWToAT.class); - @InputFiles - public abstract ConfigurableFileCollection getAccessWideners(); - - public void accessWideners(Object... paths) { - this.getAccessWideners().from(paths); - } - - @OutputFile - public abstract RegularFileProperty getAccessTransformer(); - - @TaskAction - public void convert() { - final Set awFiles = this.getAccessWideners().getFiles(); - final File atFile = this.getAccessTransformer().get().getAsFile(); + public static void convert(final Iterable awFiles, final File atFile) { + AWToAT.logger.lifecycle("Converting AWs {} to AT {} ...", awFiles, atFile); final AccessTransformSet at = AccessTransformSet.create(); for (final File awFile : awFiles) { try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) { - ConvertAWToAT.convert(reader, at); + AWToAT.convert(reader, at); } catch (final IOException e) { throw new GradleException("Failed to read access widener: " + awFile, e); } @@ -79,28 +63,30 @@ public void convert() { } catch (IOException e) { throw new GradleException("Failed to write access transformer: " + atFile, e); } + + AWToAT.logger.lifecycle("Converted AWs to AT."); } - public static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { + private static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { new AccessWidenerReader(new AccessWidenerVisitor() { @Override public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(name).merge(ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(name).merge(AWToAT.convertEntry(access)); } @Override public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), AWToAT.convertEntry(access)); } @Override public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(owner).mergeField(name, ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(owner).mergeField(name, AWToAT.convertEntry(access)); } }).read(reader); } - public static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { + private static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { return switch (access) { case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC); case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE); diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index c973f13168e..34ba73d2a51 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,6 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.userdev.UserDevExtension -import org.spongepowered.gradle.impl.ConvertAWToAT +import org.spongepowered.gradle.impl.AWToAT buildscript { repositories { @@ -206,18 +206,15 @@ dependencies { } } -val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { - accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) - accessWideners(forgeMain.resources.filter { it.name.endsWith(".accesswidener") }) - accessTransformer.set(project.layout.buildDirectory.file("generated/resources/at.cfg")) -} +val awFiles: Set = files(main.get().resources, forgeMain.resources).filter { it.name.endsWith(".accesswidener") }.files +val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile +AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { mappings("official", "1.21.3") - accessTransformers.from(convertAWToAT.flatMap { it.accessTransformer }) - + accessTransformers.from(atFile) reobf = false runs { @@ -225,11 +222,9 @@ extensions.configure(UserDevExtension::class) { ideaModule("Sponge.SpongeForge.main") // property("forge.logging.console.level", "debug") - // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) - environment("MOD_CLASSES", "nop") } From 88778c3405ec9e8f902f96dfc5bbe27a55e74d28 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 25 Dec 2024 22:31:30 -0800 Subject: [PATCH 155/586] feat: enable forge 1.21.3 --- .github/workflows/deploy.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 5b6b154fd91..dc10e45473e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -29,13 +29,13 @@ jobs: matrix: project: - vanilla -# - forge + - forge - neoforge include: - project: vanilla gradleProject: SpongeVanilla -# - project: forge -# gradleProject: SpongeForge + - project: forge + gradleProject: SpongeForge - project: neoforge gradleProject: SpongeNeo steps: From 2934e15eb4ac8453a5d6d2f05f573312fae17111 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 26 Dec 2024 00:22:55 -0800 Subject: [PATCH 156/586] fix: omit jackson-core from neoforge jar Also fixes a newer NeoForge compatibility with ServerExplosionMixin. Fixes #4153 --- .../level/ServerExplosionMixin_Forge.java | 114 +++++++++++++++++ .../resources/mixins.spongeforge.core.json | 83 ++++++------- gradle/verification-metadata.xml | 54 ++++++++ neoforge/build.gradle.kts | 3 + neoforge/gradle.properties | 2 +- .../level/ServerExplosionMixin_NeoForge.java | 115 ++++++++++++++++++ .../resources/mixins.spongeneo.core.json | 83 ++++++------- .../world/level/ServerExplosionMixin.java | 56 +-------- .../level/ServerExplosionMixin_Vanilla.java | 115 ++++++++++++++++++ .../resources/mixins.spongevanilla.core.json | 1 + 10 files changed, 488 insertions(+), 138 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java new file mode 100644 index 00000000000..b2b2936d6ca --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java @@ -0,0 +1,114 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.world.level; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.world.ExplosionEvent; +import org.spongepowered.api.world.explosion.Explosion; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.util.VecHelper; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Mixin(ServerExplosion.class) +public abstract class ServerExplosionMixin_Forge { + + // @formatter:off + @Shadow @Final private ServerLevel level; + + @Shadow protected abstract boolean shadow$interactsWithBlocks(); + // @formatter:on + + /** + * These two fields are used in the mixin below, but require a redirect specific for SpongeVanilla + * and SpongeForge as NeoForge makes a change to the method being used here. + * + * @see org.spongepowered.common.mixin.core.world.level.ServerExplosionMixin + */ + private boolean impl$shouldDamageEntities; + private double impl$knockbackMultiplier; + private List impl$affectedBlocks; + + @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List forge$throwEventToFilterEntitiesOnHurt(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + final List entities; + if (this.impl$shouldDamageEntities) { + // filter out invulnerable entities before event + entities = instance.getEntities(sourceEntity, aabb).stream() + .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) + .toList(); + } else { + entities = Collections.emptyList(); + } + + if (ShouldFire.EXPLOSION_EVENT_DETONATE) { + final var apiWorld = (ServerWorld) this.level; + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); + final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); + final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); + if (SpongeCommon.post(event)) { + this.impl$affectedBlocks.clear(); // no blocks affected + return Collections.emptyList(); // no entities affected + } + if (this.shadow$interactsWithBlocks()) { + this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); + } + if (this.impl$shouldDamageEntities) { + return event.entities().stream().map(Entity.class::cast).toList(); + } + } + return entities; + } + + + @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 forge$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { + // Honor our knockback value from event + return new Vec3($$0 * this.impl$knockbackMultiplier, + $$1 * this.impl$knockbackMultiplier, + $$2 * this.impl$knockbackMultiplier); + } + +} diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index ae82ddbcc44..82aa52ae4c8 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -1,43 +1,44 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.forge.mixin.core", - "priority": 1301, - "mixins": [ - "api.event.EventMixin_Forge", - "api.event.block.ChangeBlockEvent_AllMixin_Forge", - "api.event.entity.ChangeEntityWorldEvent_PreMixin_Forge", - "api.event.entity.ChangeEventWorldEvent_PostMixin_Forge", - "commands.CommandsMixin_Forge", - "minecraftforge.MinecraftForgeMixin_Forge", - "minecraftforge.event.entity.EntityTravelToDimensionEventMixin_Forge", - "minecraftforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Forge", - "minecraftforge.event.world.BlockEvent_BreakEventMixin_Forge", - "minecraftforge.event.world.BlockEventMixin_Forge", - "minecraftforge.internal.BrandingControlMixin_Forge", - "minecraftforge.registries.ForgeRegistryMixin_Forge", - "minecraftforge.registries.RegistryManagerMixin_Forge", - "network.ConnectionMixin_Forge", - "network.protocol.common.ClientboundCustomPayloadPacketMixin_Forge", - "network.protocol.common.ServerboundCustomPayloadPacketMixin_Forge", - "server.BootstrapMixin_Forge", - "server.MinecraftServerMixin_Forge", - "server.commands.SpreadPlayersCommandMixin_Forge", - "server.level.ServerPlayerMixin_Forge", - "server.network.ServerGamePacketListenerImplMixin_Forge", - "world.entity.LivingEntityMixin_Forge", - "world.entity.LivingEntityMixin_Forge_Attack_Impl", - "world.entity.item.ItemEntityMixin_Forge", - "world.entity.player.PlayerMixin_Forge_Attack_Impl", - "world.entity.vehicle.BoatMixin_Forge", - "world.level.block.FireBlockMixin_Forge", - "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Forge" - ], - "client": [ - "client.MinecraftMixin_Forge", - "client.main.MainMixin_Forge" - ], - "server": [ - "server.MainMixin_Forge" - ] + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.forge.mixin.core", + "priority": 1301, + "mixins": [ + "api.event.EventMixin_Forge", + "api.event.block.ChangeBlockEvent_AllMixin_Forge", + "api.event.entity.ChangeEntityWorldEvent_PreMixin_Forge", + "api.event.entity.ChangeEventWorldEvent_PostMixin_Forge", + "commands.CommandsMixin_Forge", + "minecraftforge.MinecraftForgeMixin_Forge", + "minecraftforge.event.entity.EntityTravelToDimensionEventMixin_Forge", + "minecraftforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Forge", + "minecraftforge.event.world.BlockEvent_BreakEventMixin_Forge", + "minecraftforge.event.world.BlockEventMixin_Forge", + "minecraftforge.internal.BrandingControlMixin_Forge", + "minecraftforge.registries.ForgeRegistryMixin_Forge", + "minecraftforge.registries.RegistryManagerMixin_Forge", + "network.ConnectionMixin_Forge", + "network.protocol.common.ClientboundCustomPayloadPacketMixin_Forge", + "network.protocol.common.ServerboundCustomPayloadPacketMixin_Forge", + "server.BootstrapMixin_Forge", + "server.MinecraftServerMixin_Forge", + "server.commands.SpreadPlayersCommandMixin_Forge", + "server.level.ServerPlayerMixin_Forge", + "server.network.ServerGamePacketListenerImplMixin_Forge", + "world.entity.LivingEntityMixin_Forge", + "world.entity.LivingEntityMixin_Forge_Attack_Impl", + "world.entity.item.ItemEntityMixin_Forge", + "world.entity.player.PlayerMixin_Forge_Attack_Impl", + "world.entity.vehicle.BoatMixin_Forge", + "world.level.ServerExplosionMixin_Forge", + "world.level.block.FireBlockMixin_Forge", + "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Forge" + ], + "client": [ + "client.MinecraftMixin_Forge", + "client.main.MainMixin_Forge" + ], + "server": [ + "server.MainMixin_Forge" + ] } \ No newline at end of file diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2cf4b8bf80a..e174819790a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3911,6 +3911,14 @@ + + + + + + + + @@ -3988,6 +3996,20 @@ + + + + + + + + + + + + + + @@ -4028,6 +4050,22 @@ + + + + + + + + + + + + + + + + @@ -4044,6 +4082,14 @@ + + + + + + + + @@ -4060,6 +4106,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 96e95d67d69..73d56f909dc 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -352,6 +352,9 @@ tasks { from(commonProject.sourceSets.named("applaunch").map { it.output }) from(forgeAppLaunch.output) + // We need to exclude this as NeoForge ships jackson-core as a library + // and we would be violating the packages + dependencyFilter.exclude(dependencyFilter.dependency("com.fasterxml.jackson.core:jackson-core")) // Make sure to relocate access widener so that we don't conflict with other coremods relocate("net.fabricmc.accesswidener", "org.spongepowered.neoforge.libs.accesswidener") diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 42d6f02f9fc..834881bed03 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.3.0-beta +neoForgeVersion=21.3.35-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java new file mode 100644 index 00000000000..43e3768598b --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java @@ -0,0 +1,115 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.world.level; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.world.ExplosionEvent; +import org.spongepowered.api.world.explosion.Explosion; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.util.VecHelper; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Mixin(ServerExplosion.class) +public abstract class ServerExplosionMixin_NeoForge { + + + // @formatter:off + @Shadow @Final private ServerLevel level; + + @Shadow protected abstract boolean shadow$interactsWithBlocks(); + // @formatter:on + + /** + * These two fields are used in the mixin below, but require a redirect specific for SpongeVanilla + * and SpongeForge as NeoForge makes a change to the method being used here. + * + * @see org.spongepowered.common.mixin.core.world.level.ServerExplosionMixin + */ + private boolean impl$shouldDamageEntities; + private double impl$knockbackMultiplier; + private List impl$affectedBlocks; + + @Redirect(method = "hurtEntities(Ljava/util/List;)V", at = @At(value = "INVOKE", + target = "net/minecraft/server/level/ServerLevel.getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List neo$throwEventForHurtEntities(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + final List entities; + if (this.impl$shouldDamageEntities) { + // filter out invulnerable entities before event + entities = instance.getEntities(sourceEntity, aabb).stream() + .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) + .toList(); + } else { + entities = Collections.emptyList(); + } + + if (ShouldFire.EXPLOSION_EVENT_DETONATE) { + final var apiWorld = (ServerWorld) this.level; + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); + final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); + final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); + if (SpongeCommon.post(event)) { + this.impl$affectedBlocks.clear(); // no blocks affected + return Collections.emptyList(); // no entities affected + } + if (this.shadow$interactsWithBlocks()) { + this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); + } + if (this.impl$shouldDamageEntities) { + return event.entities().stream().map(Entity.class::cast).toList(); + } + } + return entities; + } + + + @Redirect(method = "hurtEntities(Ljava/util/List;)V", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 neo$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { + // Honor our knockback value from event + return new Vec3($$0 * this.impl$knockbackMultiplier, + $$1 * this.impl$knockbackMultiplier, + $$2 * this.impl$knockbackMultiplier); + } + +} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index 40f3495d5e5..82d10e7dbf2 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -1,44 +1,45 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.neoforge.mixin.core", - "priority": 1301, - "mixins": [ - "api.event.EventMixin_Neo", - "api.event.block.ChangeBlockEvent_AllMixin_Neo", - "api.event.entity.ChangeEntityWorldEvent_PreMixin_Neo", - "api.event.entity.ChangeEventWorldEvent_PostMixin_Neo", - "commands.CommandsMixin_Neo", - "neoforge.NeoForgeMixin_Neo", - "neoforge.event.entity.EntityTravelToDimensionEventMixin_Neo", - "neoforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Neo", - "neoforge.event.world.BlockEvent_BreakEventMixin_Neo", - "neoforge.event.world.BlockEventMixin_Neo", - "neoforge.internal.BrandingControlMixin_Neo", - "neoforge.registries.RegistryManagerMixin_Neo", - "network.ConnectionMixin_Neo", - "server.BootstrapMixin_Neo", - "server.MinecraftServerMixin_Neo", - "server.commands.SpreadPlayersCommandMixin_Neo", - "server.level.ServerEntityMixin_Neo", - "server.level.ServerPlayerMixin_Neo", - "server.network.ServerGamePacketListenerImplMixin_Neo", - "world.entity.EntityMixin_Neo", - "world.entity.LivingEntityMixin_Neo", - "world.entity.LivingEntityMixin_Neo_Attack_Impl", - "world.entity.animal.SnowGolemMixin_Neo", - "world.entity.item.ItemEntityMixin_Neo", - "world.entity.player.PlayerMixin_Neo_Attack_Impl", - "world.entity.projectile.FishingHookMixin_Neo", - "world.entity.vehicle.AbstractBoatMixin_Neo", - "world.level.block.FireBlockMixin_Neo", - "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" - ], - "client": [ - "client.MinecraftMixin_Neo", - "client.main.MainMixin_Neo" - ], - "server": [ - "server.MainMixin_Neo" + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.neoforge.mixin.core", + "priority": 1301, + "mixins": [ + "api.event.EventMixin_Neo", + "api.event.block.ChangeBlockEvent_AllMixin_Neo", + "api.event.entity.ChangeEntityWorldEvent_PreMixin_Neo", + "api.event.entity.ChangeEventWorldEvent_PostMixin_Neo", + "commands.CommandsMixin_Neo", + "neoforge.NeoForgeMixin_Neo", + "neoforge.event.entity.EntityTravelToDimensionEventMixin_Neo", + "neoforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Neo", + "neoforge.event.world.BlockEvent_BreakEventMixin_Neo", + "neoforge.event.world.BlockEventMixin_Neo", + "neoforge.internal.BrandingControlMixin_Neo", + "neoforge.registries.RegistryManagerMixin_Neo", + "network.ConnectionMixin_Neo", + "server.BootstrapMixin_Neo", + "server.MinecraftServerMixin_Neo", + "server.commands.SpreadPlayersCommandMixin_Neo", + "server.level.ServerEntityMixin_Neo", + "server.level.ServerPlayerMixin_Neo", + "server.network.ServerGamePacketListenerImplMixin_Neo", + "world.entity.EntityMixin_Neo", + "world.entity.LivingEntityMixin_Neo", + "world.entity.LivingEntityMixin_Neo_Attack_Impl", + "world.entity.animal.SnowGolemMixin_Neo", + "world.entity.item.ItemEntityMixin_Neo", + "world.entity.player.PlayerMixin_Neo_Attack_Impl", + "world.entity.projectile.FishingHookMixin_Neo", + "world.entity.vehicle.AbstractBoatMixin_Neo", + "world.level.ServerExplosionMixin_NeoForge", + "world.level.block.FireBlockMixin_Neo", + "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" + ], + "client": [ + "client.MinecraftMixin_Neo", + "client.main.MainMixin_Neo" + ], + "server": [ + "server.MainMixin_Neo" ] } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java index 87cc5812fae..9572b7d8276 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/ServerExplosionMixin.java @@ -31,14 +31,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.ServerExplosion; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.world.ExplosionEvent; -import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -46,17 +39,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.level.ExplosionBridge; import org.spongepowered.common.event.ShouldFire; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.util.VecHelper; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.StringJoiner; -import java.util.stream.Collectors; @Mixin(net.minecraft.world.level.ServerExplosion.class) public abstract class ServerExplosionMixin implements ExplosionBridge { @@ -84,6 +72,7 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { private int impl$resolution; private float impl$randomness; private double impl$knockbackMultiplier; + private List impl$affectedBlocks; @Inject(method = "", at = @At("RETURN")) private void impl$onConstructed(final ServerLevel $$0, final Entity $$1, final DamageSource $$2, @@ -95,7 +84,6 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { this.impl$knockbackMultiplier = 1.0; } - private List impl$affectedBlocks; @Redirect(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;calculateExplodedPositions()Ljava/util/List;")) @@ -109,48 +97,6 @@ public abstract class ServerExplosionMixin implements ExplosionBridge { return this.impl$affectedBlocks; } - - @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) - private List impl$onGetHurtEntities(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { - final List entities; - if (this.impl$shouldDamageEntities) { - // filter out invulnerable entities before event - entities = instance.getEntities(sourceEntity, aabb).stream() - .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) - .toList(); - } else { - entities = Collections.emptyList(); - } - - if (ShouldFire.EXPLOSION_EVENT_DETONATE) { - final var apiWorld = (ServerWorld) this.level; - final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); - final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); - final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); - final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); - if (SpongeCommon.post(event)) { - this.impl$affectedBlocks.clear(); // no blocks affected - return Collections.emptyList(); // no entities affected - } - if (this.shadow$interactsWithBlocks()) { - this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); - } - if (this.impl$shouldDamageEntities) { - return event.entities().stream().map(Entity.class::cast).toList(); - } - } - return entities; - } - - @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 impl$onAddKnockback(final double $$0, final double $$1, final double $$2) { - // Honor our knockback value from event - return new Vec3($$0 * this.impl$knockbackMultiplier, - $$1 * this.impl$knockbackMultiplier, - $$2 * this.impl$knockbackMultiplier); - } - @Redirect(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerExplosion;interactWithBlocks(Ljava/util/List;)V")) private void impl$onInteractWithBlocks(final ServerExplosion instance, final List $$0) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java new file mode 100644 index 00000000000..a7118055ba4 --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java @@ -0,0 +1,115 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.world.level; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.world.ExplosionEvent; +import org.spongepowered.api.world.explosion.Explosion; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.util.VecHelper; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Mixin(ServerExplosion.class) +public abstract class ServerExplosionMixin_Vanilla { + + + // @formatter:off + @Shadow @Final private ServerLevel level; + + @Shadow protected abstract boolean shadow$interactsWithBlocks(); + // @formatter:on + + /** + * These two fields are used in the mixin below, but require a redirect specific for SpongeVanilla + * and SpongeForge as NeoForge makes a change to the method being used here. + * + * @see org.spongepowered.common.mixin.core.world.level.ServerExplosionMixin + */ + private boolean impl$shouldDamageEntities; + private double impl$knockbackMultiplier; + + private List impl$affectedBlocks; + + @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List vanilla$throwEventToFilterEntitiesOnHurt(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + final List entities; + if (this.impl$shouldDamageEntities) { + // filter out invulnerable entities before event + entities = instance.getEntities(sourceEntity, aabb).stream() + .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) + .toList(); + } else { + entities = Collections.emptyList(); + } + + if (ShouldFire.EXPLOSION_EVENT_DETONATE) { + final var apiWorld = (ServerWorld) this.level; + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); + final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); + final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); + if (SpongeCommon.post(event)) { + this.impl$affectedBlocks.clear(); // no blocks affected + return Collections.emptyList(); // no entities affected + } + if (this.shadow$interactsWithBlocks()) { + this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); + } + if (this.impl$shouldDamageEntities) { + return event.entities().stream().map(Entity.class::cast).toList(); + } + } + return entities; + } + + @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 vanilla$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { + // Honor our knockback value from event + return new Vec3($$0 * this.impl$knockbackMultiplier, + $$1 * this.impl$knockbackMultiplier, + $$2 * this.impl$knockbackMultiplier); + } + +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index dd3af254426..f5a6e04c79b 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -36,6 +36,7 @@ "world.entity.item.ItemEntityMixin_Vanilla", "world.entity.player.PlayerMixin_Vanilla_Attack_Impl", "world.entity.vehicle.AbstractBoatMixin_Vanilla", + "world.level.ServerExplosionMixin_Vanilla", "world.level.block.FireBlockMixin_Vanilla", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", "world.level.storage.LevelStorageSourceMixin_Vanilla" From d1f83fdeb1b919de3bbd634ec7ddfd93a6922ee1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 26 Dec 2024 00:26:46 -0800 Subject: [PATCH 157/586] fix: actually build SpongeForge for 1.21.3 --- .github/workflows/common-run-build.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 52f9e692f81..d1cffe4ff01 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -16,13 +16,13 @@ jobs: matrix: project: - vanilla -# - forge + - forge - neoforge include: - project: vanilla gradleProject: SpongeVanilla -# - project: forge -# gradleProject: SpongeForge + - project: forge + gradleProject: SpongeForge - project: neoforge gradleProject: SpongeNeo steps: From a70cf80bad3dea3c3ebc2a3453a43029d027b07e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 26 Dec 2024 21:48:38 +0100 Subject: [PATCH 158/586] Fix access transformer error when directory doesn't exist --- .../java/org/spongepowered/gradle/impl/AWToAT.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java index da782c13dc6..65d457b3a20 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; public class AWToAT { private static final Logger logger = Logging.getLogger(AWToAT.class); @@ -58,8 +59,13 @@ public static void convert(final Iterable awFiles, final File atFile) { } } - try (final BufferedWriter writer = Files.newBufferedWriter(atFile.toPath())) { - AccessTransformFormats.FML.write(writer, at); + try { + final Path atPath = atFile.toPath(); + Files.createDirectories(atPath.getParent()); + + try (final BufferedWriter writer = Files.newBufferedWriter(atPath)) { + AccessTransformFormats.FML.write(writer, at); + } } catch (IOException e) { throw new GradleException("Failed to write access transformer: " + atFile, e); } From fd7af7483204fa51319df2db3ba87b5a888517a6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 27 Dec 2024 16:45:28 +0100 Subject: [PATCH 159/586] Properly specify versions in manifest templates --- forge/build.gradle.kts | 8 +-- .../resource-templates/META-INF/mods.toml | 8 +-- neoforge/build.gradle.kts | 7 +-- .../META-INF/neoforge.mods.toml | 4 +- testplugins/build.gradle.kts | 13 +++++ .../META-INF/sponge_plugins.json | 11 ++-- vanilla/build.gradle.kts | 4 +- .../META-INF/sponge_plugins.json | 52 ++++++------------- 8 files changed, 50 insertions(+), 57 deletions(-) rename testplugins/src/main/{resources => resource-templates}/META-INF/sponge_plugins.json (98%) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 34ba73d2a51..9ef47aca230 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -255,7 +255,7 @@ val forgeManifest = java.manifest { "Specification-Vendor" to "SpongePowered", "Specification-Version" to apiVersion, "Implementation-Title" to project.name, - "Implementation-Version" to spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion, forgeVersion), + "Implementation-Version" to version, "Implementation-Vendor" to "SpongePowered" ) // These two are included by most CI's @@ -387,8 +387,10 @@ tasks { sourceSets { main { blossom.resources { - property("version", project.provider { project.version.toString() }) - property("description", project.description.toString()) + property("apiVersion", apiVersion) + property("version", version.toString()) + property("description", description.toString()) + property("forgeVersion", forgeVersion) } } } diff --git a/forge/src/main/resource-templates/META-INF/mods.toml b/forge/src/main/resource-templates/META-INF/mods.toml index b6a82ce527b..dd478d7f7fa 100644 --- a/forge/src/main/resource-templates/META-INF/mods.toml +++ b/forge/src/main/resource-templates/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" -loaderVersion="[52,)" +loaderVersion="[53,)" license="MIT License" issueTrackerURL="https://github.com/SpongePowered/Sponge/issues" @@ -17,7 +17,7 @@ description = "{{ description }}" [[dependencies.spongeforge]] modId="forge" mandatory=true -versionRange="[52,)" +versionRange="[{{ forgeVersion }},)" ordering="AFTER" side="BOTH" @@ -41,14 +41,14 @@ description="The SpongeAPI implementation targeting vanilla Minecraft and 3rd pa [[dependencies.sponge]] modId="spongeapi" mandatory=true -versionRange="[12.0.0,)" +versionRange="[{{ apiVersion }},)" ordering="AFTER" side="BOTH" [[mods]] modId="spongeapi" -version="12.0.0" +version="{{ apiVersion }}" displayName="SpongeAPI" displayTest="IGNORE_SERVER_VERSION" credits="SpongePowered and Contributors" diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 73d56f909dc..335b47b036c 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -231,7 +231,7 @@ val forgeManifest = java.manifest { "Specification-Vendor" to "SpongePowered", "Specification-Version" to apiVersion, "Implementation-Title" to project.name, - "Implementation-Version" to spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion, neoForgeVersion), + "Implementation-Version" to version, "Implementation-Vendor" to "SpongePowered" ) // These two are included by most CI's @@ -412,8 +412,9 @@ tasks { sourceSets { main { blossom.resources { - property("version", project.provider { project.version.toString() }) - property("description", project.description.toString()) + property("apiVersion", apiVersion) + property("version", version.toString()) + property("description", description.toString()) property("neoForgeVersion", neoForgeVersion) } } diff --git a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml b/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml index c380ea9b18d..9fcfe577a05 100644 --- a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml +++ b/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml @@ -41,14 +41,14 @@ description="The SpongeAPI implementation targeting vanilla Minecraft and 3rd pa [[dependencies.sponge]] modId="spongeapi" mandatory=true -versionRange="[12.0.0,)" +versionRange="[{{ apiVersion }},)" ordering="AFTER" side="BOTH" [[mods]] modId="spongeapi" -version="12.0.0" +version="{{ apiVersion }}" displayName="SpongeAPI" displayTest="IGNORE_SERVER_VERSION" credits="SpongePowered and Contributors" diff --git a/testplugins/build.gradle.kts b/testplugins/build.gradle.kts index 293ff49b8e4..befaab02414 100644 --- a/testplugins/build.gradle.kts +++ b/testplugins/build.gradle.kts @@ -1,5 +1,18 @@ +plugins { + alias(libs.plugins.blossom) +} + val apiVersion: String by project dependencies { annotationProcessor(implementation("org.spongepowered:spongeapi:$apiVersion")!!) } + +sourceSets { + main { + blossom.resources { + property("apiVersion", apiVersion.replace("-SNAPSHOT", "")) + property("description", description.toString()) + } + } +} diff --git a/testplugins/src/main/resources/META-INF/sponge_plugins.json b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json similarity index 98% rename from testplugins/src/main/resources/META-INF/sponge_plugins.json rename to testplugins/src/main/resource-templates/META-INF/sponge_plugins.json index 28da6901e80..8af3eb43009 100644 --- a/testplugins/src/main/resources/META-INF/sponge_plugins.json +++ b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json @@ -5,7 +5,7 @@ }, "license": "MIT", "global": { - "version": "11.0.0", + "version": "{{ apiVersion }}", "links": { "homepage": "https://www.spongepowered.org", "source": "https://www.spongepowered.org/source", @@ -20,7 +20,7 @@ "dependencies": [ { "id": "spongeapi", - "version": "11.0.0" + "version": "{{ apiVersion }}" } ] }, @@ -202,14 +202,12 @@ { "id": "maptest", "name": "MapTest", - "version": "1.0.0", "entrypoint": "org.spongepowered.test.map.MapTest", "description": "Tests map api" }, { "id": "collidetest", "name": "CollideTest", - "version": "1.0.0", "entrypoint": "org.spongepowered.test.collide.CollideTest", "description": "Tests collide events" }, @@ -222,7 +220,6 @@ { "id": "chunkmanagertest", "name": "Chunk Manager Test", - "version": "1.0.0", "entrypoint": "org.spongepowered.test.chunkmanager.ChunkManagerTest", "description": "Tests the Chunk Manager" }, @@ -354,7 +351,7 @@ "dependencies": [ { "id": "parentmoduletestplugin", - "version": "12.0.0", + "version": "{{ apiVersion }}", "load-order": "BEFORE" } ] @@ -370,7 +367,7 @@ "dependencies": [ { "id": "childmoduletestplugin", - "version": "12.0.0", + "version": "{{ apiVersion }}", "load-order": "AFTER" } ] diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 28dd846d589..3d3d5ad6383 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -315,7 +315,7 @@ val vanillaManifest = java.manifest { "Specification-Vendor" to "SpongePowered", "Specification-Version" to apiVersion, "Implementation-Title" to project.name, - "Implementation-Version" to spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion), + "Implementation-Version" to version, "Implementation-Vendor" to "SpongePowered" ) // These two are included by most CI's @@ -332,7 +332,7 @@ vanillaLaunch.apply { blossom.resources { property("apiVersion", apiVersion) property("minecraftVersion", minecraftVersion) - property("version", provider { project.version.toString() }) + property("version", version.toString()) } } vanillaInstaller.apply { diff --git a/vanilla/src/launch/resource-templates/META-INF/sponge_plugins.json b/vanilla/src/launch/resource-templates/META-INF/sponge_plugins.json index 5a9c035285f..45938219309 100644 --- a/vanilla/src/launch/resource-templates/META-INF/sponge_plugins.json +++ b/vanilla/src/launch/resource-templates/META-INF/sponge_plugins.json @@ -4,6 +4,19 @@ "version": "1.0" }, "license": "MIT", + "global": { + "links": { + "homepage": "https://www.spongepowered.org", + "source": "https://www.spongepowered.org/source", + "issues": "https://www.spongepowered.org/issues" + }, + "contributors": [ + { + "name": "SpongePowered", + "description": "Lead Developer" + } + ] + }, "plugins": [ { "id": "spongevanilla", @@ -11,41 +24,19 @@ "version": "{{ version }}", "entrypoint": "org.spongepowered.vanilla.SpongeVanilla", "description": "Vanilla Minecraft with Sponge", - "links": { - "homepage": "https://www.spongepowered.org", - "source": "https://www.spongepowered.org/source", - "issues": "https://www.spongepowered.org/issues" - }, - "contributors": [ - { - "name": "SpongePowered", - "description": "Lead Developer" - } - ], "dependencies": [ { "id": "sponge", - "version": "{{ minecraftVersion }}-{{ apiVersion }}" + "version": "{{ version }}" } ] }, { "id": "sponge", "name": "Sponge", - "version": "{{ minecraftVersion }}-{{ apiVersion }}", + "version": "{{ version }}", "entrypoint": "org.spongepowered.common.SpongeCommon", "description": "The common Sponge implementation", - "links": { - "homepage": "https://www.spongepowered.org", - "source": "https://www.spongepowered.org/source", - "issues": "https://www.spongepowered.org/issues" - }, - "contributors": [ - { - "name": "SpongePowered", - "description": "Lead Developer" - } - ], "dependencies": [ { "id": "minecraft", @@ -62,18 +53,7 @@ "name": "SpongeAPI", "version": "{{ apiVersion }}", "entrypoint": "org.spongepowered.api.Sponge", - "description": "The Minecraft API specification", - "links": { - "homepage": "https://www.spongepowered.org", - "source": "https://www.spongepowered.org/source", - "issues": "https://www.spongepowered.org/issues" - }, - "contributors": [ - { - "name": "SpongePowered", - "description": "Lead Developer" - } - ] + "description": "The Minecraft API specification" } ] } \ No newline at end of file From 8fa0e2c79e33ef71bbee72bb2099f455425a283c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 27 Dec 2024 22:53:36 +0100 Subject: [PATCH 160/586] Fix furnace ticking errors on modded platforms --- .../block/entity/AbstractFurnaceBlockEntityMixin_Forge.java | 6 +++--- .../block/entity/AbstractFurnaceBlockEntityMixin_Neo.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 5a8394cd809..34fe7d2c2e7 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -98,13 +98,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); if (entity.cookingProgress == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -173,7 +173,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(PhaseTracker.getCauseStackManager().currentCause(), entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index 13e9b1fcd28..d3c6d8b31e1 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -95,13 +95,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); if (entity.cookingProgress == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -181,7 +181,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { From 4854c57da7efe6de7d2eeb371624de344bac327c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 28 Dec 2024 13:55:19 +0100 Subject: [PATCH 161/586] Generate IntelliJ run configurations on sync --- .../org/spongepowered/gradle/impl/IdeHelper.java | 12 ++++++++++++ build.gradle.kts | 6 +++--- forge/build.gradle.kts | 8 ++++++++ vanilla/build.gradle.kts | 3 ++- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 build-logic/src/main/java/org/spongepowered/gradle/impl/IdeHelper.java diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/IdeHelper.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/IdeHelper.java new file mode 100644 index 00000000000..3ca6ee2b837 --- /dev/null +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/IdeHelper.java @@ -0,0 +1,12 @@ +package org.spongepowered.gradle.impl; + +public class IdeHelper { + + public static boolean isIdeaActive() { + return Boolean.getBoolean("idea.active"); + } + + public static boolean isIdeaSync() { + return Boolean.getBoolean("idea.sync.active"); + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 85ce26ad312..3f68034fdaa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,13 +22,15 @@ val recommendedVersion: String by project val organization: String by project val projectUrl: String by project +version = spongeImpl.generateImplementationVersionString(apiVersion, minecraftVersion, recommendedVersion) + val commonManifest = java.manifest { attributes( "Specification-Title" to "Sponge", "Specification-Vendor" to "SpongePowered", "Specification-Version" to apiVersion, "Implementation-Title" to project.name, - "Implementation-Version" to spongeImpl.generateImplementationVersionString(apiVersion, minecraftVersion, recommendedVersion), + "Implementation-Version" to version, "Implementation-Vendor" to "SpongePowered" ) // These two are included by most CI's @@ -36,8 +38,6 @@ val commonManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } -version = spongeImpl.generateImplementationVersionString(apiVersion, minecraftVersion, recommendedVersion) - // SpongeCommon configurations val applaunchConfig by configurations.register("applaunch") diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 9ef47aca230..7cb76eb963b 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,6 +1,8 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.userdev.UserDevExtension +import org.gradle.internal.DefaultTaskExecutionRequest import org.spongepowered.gradle.impl.AWToAT +import org.spongepowered.gradle.impl.IdeHelper buildscript { repositories { @@ -384,6 +386,12 @@ tasks { } } +if (IdeHelper.isIdeaSync()) { + afterEvaluate { + gradle.startParameter.taskRequests.add(DefaultTaskExecutionRequest(listOf(":SpongeForge:genIntellijRuns"))) + } +} + sourceSets { main { blossom.resources { diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 3d3d5ad6383..947e63efb0f 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -1,4 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.spongepowered.gradle.impl.IdeHelper plugins { id("org.spongepowered.gradle.vanilla") @@ -272,7 +273,7 @@ minecraft { targetVersion(apiJavaTarget.toInt()) workingDirectory(project.file("run/")) - if (org.spongepowered.gradle.vanilla.internal.util.IdeConfigurer.isIdeaImport()) { // todo(zml): promote to API... eventually + if (IdeHelper.isIdeaActive()) { // IntelliJ does not properly report its compatibility jvmArgs("-Dterminal.ansi=true", "-Djansi.mode=force") } From 85730115cb99c5883ef70756c320f30875dea31b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 29 Dec 2024 13:26:26 +0100 Subject: [PATCH 162/586] Update Gradle to 8.8 and Arch-loom to 1.7.423 --- SpongeAPI | 2 +- build-logic/build.gradle | 2 +- gradle/verification-metadata.xml | 44 ++++++++++++++++++++++++ gradle/wrapper/gradle-wrapper.properties | 4 +-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index f4245597d6d..33e16ee41f7 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit f4245597d6dc09becafbcff46a1afbc365ee2eca +Subproject commit 33e16ee41f73944322efca814c44bdb1a9794027 diff --git a/build-logic/build.gradle b/build-logic/build.gradle index 1539cbfb1a6..00d4c56f993 100644 --- a/build-logic/build.gradle +++ b/build-logic/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation(libs.accessWidener) // arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies - api("dev.architectury:architectury-loom:1.6.411") + api("dev.architectury:architectury-loom:1.7.423") } indraSpotlessLicenser { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e174819790a..3e81f7dd6de 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -180,6 +180,9 @@ + + + @@ -223,6 +226,9 @@ + + + @@ -1746,6 +1752,14 @@ + + + + + + + + @@ -1937,6 +1951,9 @@ + + + @@ -2303,6 +2320,14 @@ + + + + + + + + @@ -3815,11 +3840,24 @@ + + + + + + + + + + + + + @@ -3867,6 +3905,9 @@ + + + @@ -3931,6 +3972,9 @@ + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 381baa9cef1..8a1f6b97f47 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 7f150a03ba009efb16aff1ef368d450b84bedb01 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 29 Dec 2024 14:33:23 +0100 Subject: [PATCH 163/586] Update verification metadata --- gradle/verification-metadata.xml | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d1cd3e58d31..c84a8ad3482 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2535,6 +2535,14 @@ + + + + + + + + @@ -4405,6 +4413,14 @@ + + + + + + + + @@ -4480,6 +4496,14 @@ + + + + + + + + @@ -4547,6 +4571,20 @@ + + + + + + + + + + + + + + @@ -4571,6 +4609,22 @@ + + + + + + + + + + + + + + + + @@ -4627,6 +4681,14 @@ + + + + + + + + @@ -4651,6 +4713,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5908,6 +5994,9 @@ + + + @@ -6709,6 +6798,14 @@ + + + + + + + + @@ -6790,6 +6887,14 @@ + + + + + + + + @@ -6946,6 +7051,14 @@ + + + + + + + + @@ -6998,6 +7111,14 @@ + + + + + + + + @@ -7050,6 +7171,14 @@ + + + + + + + + From 8a6fe452b58e768a512010d59f85958f7ef0cc48 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 29 Dec 2024 15:57:02 +0100 Subject: [PATCH 164/586] Fix SpongeNeo furnace mixin --- .../block/entity/AbstractFurnaceBlockEntityMixin_Neo.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index d3c6d8b31e1..1b0cb717b55 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -70,7 +70,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // @formatter:off @Shadow protected NonNullList items; - @Shadow int cookingProgress; + @Shadow int cookingTimer; // @formatter:on private boolean neo$filledWaterBucket; @@ -93,13 +93,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(slots.get(1)); final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); - if (entity.cookingProgress == 0) { // Start + if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up - final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); + final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.getFirst()); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); SpongeCommon.post(event); @@ -124,7 +124,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id())); SpongeCommon.post(event); if (event.isCancelled()) { - return entity.cookingProgress; // dont tick down + return entity.cookingTimer; // dont tick down } return clampedCookTime; From a786569f92c5c2b3652c2f49d11556959b4396ad Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 29 Dec 2024 15:43:09 -0800 Subject: [PATCH 165/586] feat: API 13 release Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 33e16ee41f7..0f857e9e90a 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 33e16ee41f73944322efca814c44bdb1a9794027 +Subproject commit 0f857e9e90ace1d9d06aa75d12b59079855432e7 From e7a39bd77298611f8200b327cfc1f07bbcaadbf1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 21 Apr 2024 15:29:53 -0700 Subject: [PATCH 166/586] !feat: Refactor Interactions to use Transactions --- SpongeAPI | 2 +- .../bridge/world/TrackedWorldBridge.java | 13 +++ .../event/SpongeCommonEventFactory.java | 4 +- .../context/transaction/EffectTransactor.java | 10 +- .../context/transaction/GameTransaction.java | 31 +++--- .../ResultingTransactionBySideEffect.java | 6 +- .../context/transaction/TransactionSink.java | 38 ++++--- .../TransactionalCaptureSupplier.java | 5 +- .../effect/AddBlockLootDropsEffect.java | 12 ++- .../transaction/effect/BlockAddedEffect.java | 12 ++- .../transaction/effect/BlockChangeArgs.java | 36 +++++++ .../BroadcastInventoryChangesEffect.java | 12 +-- .../CheckBlockPostPlacementIsSameEffect.java | 13 +-- .../effect/ChunkChangeCompleteEffect.java | 12 +-- .../transaction/effect/EffectResult.java | 19 ++-- .../effect/EntityPerformingDropsEffect.java | 10 +- .../effect/ExplodeBlockEffect.java | 16 ++- .../transaction/effect/InteractionArgs.java | 42 ++++++++ .../effect/InteractionItemEffect.java | 58 ++++++++++ .../InteractionUseItemOnBlockEffect.java | 59 ++++++++++ .../transaction/effect/InventoryEffect.java | 10 +- .../effect/NotifyClientEffect.java | 11 +- .../effect/NotifyNeighborSideEffect.java | 12 ++- .../effect/OldBlockOnReplaceEffect.java | 13 +-- .../PerformBlockDropsFromDestruction.java | 10 +- .../effect/PlayerContainerRefreshEffect.java | 52 +++++++++ .../transaction/effect/PrepareBlockDrops.java | 10 +- .../effect/ProcessingSideEffect.java | 13 +-- .../RemoveTileEntityFromChunkEffect.java | 12 +-- ...SetAndRegisterBlockEntityToLevelChunk.java | 12 +-- .../effect/SetBlockToChunkSectionEffect.java | 12 +-- .../effect/SpawnDestructBlocksEffect.java | 12 +-- .../effect/UpdateChunkLightManagerEffect.java | 11 +- .../effect/UpdateConnectingBlocksEffect.java | 13 ++- .../effect/UpdateHeightMapEffect.java | 11 +- .../effect/UpdateLightSideEffect.java | 13 +-- ...reateNewTileEntityPostPlacementEffect.java | 10 +- .../effect/UpdateWorldRendererEffect.java | 11 +- .../transaction/effect/UseItemArgs.java | 41 +++++++ .../transaction/effect/UseItemEffect.java | 64 +++++++++++ .../WorldBlockChangeCompleteEffect.java | 10 +- .../effect/WorldDestroyBlockLevelEffect.java | 10 +- .../inventory/InteractItemTransaction.java | 101 ++++++++++++++++++ .../inventory/InventoryBasedTransaction.java | 5 + .../transaction/pipeline/ChunkPipeline.java | 8 +- .../pipeline/TileEntityPipeline.java | 21 ++-- .../pipeline/UseBlockPipeline.java | 101 ++++++++++++++++++ .../pipeline/UseItemOnBlockPipeline.java | 100 +++++++++++++++++ .../transaction/pipeline/UseItemPipeline.java | 100 +++++++++++++++++ .../transaction/pipeline/WorldPipeline.java | 20 ++-- .../transaction/type/TransactionTypes.java | 3 +- .../level/ServerLevelMixin_Tracker.java | 85 ++++++++++++++- .../ServerPlayerGameModeMixin_Tracker.java | 101 ++++++++---------- .../VolumeTransformationTest.java | 3 +- 54 files changed, 1153 insertions(+), 278 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockChangeArgs.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java diff --git a/SpongeAPI b/SpongeAPI index 05573747a54..1645168a747 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 05573747a54dc967d4592e1244e6bde88651afe4 +Subproject commit 1645168a747b4316aa298331a1d35965301ca79f diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index 740a8eed68c..c5c48c5c380 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -26,11 +26,16 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.phys.BlockHitResult; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.world.BlockChangeFlag; @@ -39,6 +44,9 @@ import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import java.util.Optional; @@ -105,4 +113,9 @@ public interface TrackedWorldBridge { */ SpongeBlockSnapshot bridge$createSnapshotWithEntity(BlockState state, BlockPos pos, BlockChangeFlag updateFlag, @Nullable BlockEntity tileEntity); + UseItemOnBlockPipeline bridge$startInteractionUseOnChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + + UseBlockPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + + UseItemPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 6ec6a447ce9..5a769dface4 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -339,10 +339,10 @@ public static InteractBlockEvent.Primary callInteractBlockEventPrimary(final Ser } } - public static InteractBlockEvent.Secondary callInteractBlockEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack heldItem, final Vector3d hitVec, final BlockSnapshot targetBlock, final Direction targetSide, final InteractionHand hand) { + public static InteractBlockEvent.Secondary.Pre callInteractBlockEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack heldItem, final Vector3d hitVec, final BlockSnapshot targetBlock, final Direction targetSide, final InteractionHand hand) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { SpongeCommonEventFactory.applyCommonInteractContext(player, heldItem, hand, targetBlock, null, frame); - final InteractBlockEvent.Secondary event = SpongeEventFactory.createInteractBlockEventSecondary(frame.currentCause(), + final InteractBlockEvent.Secondary.Pre event = SpongeEventFactory.createInteractBlockEventSecondaryPre(frame.currentCause(), Tristate.UNDEFINED, Tristate.UNDEFINED, Tristate.UNDEFINED, Tristate.UNDEFINED, targetBlock, hitVec, targetSide); SpongeCommon.post(event); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EffectTransactor.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EffectTransactor.java index cabf97ef8ca..b1e025c7e73 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EffectTransactor.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EffectTransactor.java @@ -30,13 +30,13 @@ import java.util.Deque; public class EffectTransactor implements AutoCloseable { - final @Nullable ResultingTransactionBySideEffect previousEffect; + final @Nullable ResultingTransactionBySideEffect previousEffect; public final @Nullable GameTransaction<@NonNull ?> parent; private final TransactionalCaptureSupplier supplier; - private final ResultingTransactionBySideEffect effect; + private final ResultingTransactionBySideEffect effect; - EffectTransactor(final ResultingTransactionBySideEffect effect, final @Nullable GameTransaction<@NonNull ?> parent, - final @Nullable ResultingTransactionBySideEffect previousEffect, final TransactionalCaptureSupplier transactor) { + EffectTransactor(final ResultingTransactionBySideEffect effect, final @Nullable GameTransaction<@NonNull ?> parent, + final @Nullable ResultingTransactionBySideEffect previousEffect, final TransactionalCaptureSupplier transactor) { /* | ChangeBlock(1) <- head will be RemoveTileEntity(1), tail is still RemoveTileentity(1) | |- RemoveTileEntity <- Head will be ChangeBlock(2) tail is still ChangeBlock(2) @@ -55,7 +55,7 @@ public void close() { && this.parent.sideEffects != null && this.parent.getEffects().peekLast() == this.effect ) { - final Deque effects = this.parent.getEffects(); + final Deque> effects = this.parent.getEffects(); effects.removeLast(); if (effects.isEmpty()) { this.parent.sideEffects = null; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java index cb50e5af272..391443f3f19 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java @@ -54,7 +54,7 @@ public abstract class GameTransaction implements protected boolean cancelled = false; // Children Definitions - @Nullable LinkedList sideEffects; + @Nullable LinkedList> sideEffects; // LinkedList node definitions @Nullable GameTransaction<@NonNull ?> previous; @@ -75,14 +75,14 @@ public final TransactionType getTransactionType() { return this.transactionType; } - final Deque getEffects() { + final Deque> getEffects() { if (this.sideEffects == null) { this.sideEffects = new LinkedList<>(); } return this.sideEffects; } - public final void addLast(final ResultingTransactionBySideEffect effect) { + public final void addLast(final ResultingTransactionBySideEffect effect) { if (this.sideEffects == null) { this.sideEffects = new LinkedList<>(); } @@ -97,7 +97,7 @@ public final boolean hasAnyPrimaryChildrenTransactions() { if (this.sideEffects == null) { return false; } - for (final ResultingTransactionBySideEffect sideEffect : this.sideEffects) { + for (final ResultingTransactionBySideEffect sideEffect : this.sideEffects) { @Nullable GameTransaction<@NonNull ?> transaction = sideEffect.head; while (transaction != null) { if (transaction.transactionType.isPrimary() || transaction.hasChildTransactions()) { @@ -131,10 +131,17 @@ public abstract Optional generateEvent( public final void markCancelled() { this.cancelled = true; this.childIterator().forEachRemaining(GameTransaction::markCancelled); + if (this.next != null && this.next.hasUnknownChainRequiringCancellation()) { + this.next.markCancelled(); + } } public abstract boolean markCancelledTransactions(E event, ImmutableList> transactions); + protected boolean hasUnknownChainRequiringCancellation() { + return false; + } + public void postProcessEvent(final PhaseContext<@NonNull ?> context, final E event) { } @@ -183,16 +190,16 @@ protected void captureState() { } private static class ChildIterator implements Iterator> { - private final Iterator effectIterator; + private final Iterator> effectIterator; private @Nullable GameTransaction<@NonNull ?> cachedNext; private @MonotonicNonNull GameTransaction<@NonNull ?> pointer; private boolean hasNoRemainingElements = false; - ChildIterator(final Iterator iterator) { + ChildIterator(final Iterator> iterator) { // We're going to search the iterator's effects until we find the first at least this.effectIterator = iterator; while (this.effectIterator.hasNext()) { - final ResultingTransactionBySideEffect next = this.effectIterator.next(); + final ResultingTransactionBySideEffect next = this.effectIterator.next(); if (next.head != null) { this.cachedNext = next.head; this.pointer = next.head; @@ -219,7 +226,7 @@ public boolean hasNext() { // start search for the next, sadly because effects don't make a clean chain, // there can be many effects with no transactions recorded while (this.effectIterator.hasNext()) { - final ResultingTransactionBySideEffect next = this.effectIterator.next(); + final ResultingTransactionBySideEffect next = this.effectIterator.next(); if (next.head != null) { this.cachedNext = next.head; return true; @@ -250,16 +257,16 @@ public boolean hasNext() { private static class ReverseChildIterator implements Iterator> { - private final Iterator effectIterator; + private final Iterator> effectIterator; private @Nullable GameTransaction<@NonNull ?> cachedPrevious; private @MonotonicNonNull GameTransaction<@NonNull ?> pointer; private boolean hasNoRemainingElements = false; - ReverseChildIterator(final Iterator iterator) { + ReverseChildIterator(final Iterator> iterator) { // We're going to search the iterator's effects until we find the first at least this.effectIterator = iterator; while (this.effectIterator.hasNext()) { - final ResultingTransactionBySideEffect next = this.effectIterator.next(); + final ResultingTransactionBySideEffect next = this.effectIterator.next(); if (next.tail != null) { this.pointer = next.tail; this.cachedPrevious = next.tail; @@ -287,7 +294,7 @@ public boolean hasNext() { // start search for the next, sadly because effects don't make a clean chain, // there can be many effects with no transactions recorded while (this.effectIterator.hasNext()) { - final ResultingTransactionBySideEffect next = this.effectIterator.next(); + final ResultingTransactionBySideEffect next = this.effectIterator.next(); if (next.tail != null) { this.cachedPrevious = next.tail; return true; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/ResultingTransactionBySideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/ResultingTransactionBySideEffect.java index c224628dbbc..3cae058b582 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/ResultingTransactionBySideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/ResultingTransactionBySideEffect.java @@ -33,12 +33,12 @@ import java.util.Iterator; import java.util.Optional; -public class ResultingTransactionBySideEffect { - public final ProcessingSideEffect effect; +public class ResultingTransactionBySideEffect { + public final ProcessingSideEffect effect; @Nullable GameTransaction<@NonNull ?> head; @Nullable GameTransaction<@NonNull ?> tail; - public ResultingTransactionBySideEffect(final ProcessingSideEffect effect) { + public ResultingTransactionBySideEffect(final ProcessingSideEffect effect) { this.effect = effect; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index 0e62dddece7..73655b3996b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -44,6 +45,7 @@ import net.minecraft.world.ticks.ScheduledTick; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.ItemStackSnapshot; @@ -51,6 +53,7 @@ import org.spongepowered.api.item.inventory.crafting.CraftingInventory; import org.spongepowered.api.item.inventory.transaction.SlotTransaction; import org.spongepowered.api.scheduler.ScheduledUpdate; +import org.spongepowered.api.util.Direction; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.BlockChangeFlags; import org.spongepowered.common.SpongeCommon; @@ -73,6 +76,7 @@ import org.spongepowered.common.event.tracking.context.transaction.effect.EntityPerformingDropsEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.InventoryEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.PrepareBlockDrops; +import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; import org.spongepowered.common.event.tracking.context.transaction.inventory.ClickCreativeMenuTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.ClickMenuTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.CloseMenuTransaction; @@ -81,6 +85,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.CraftingTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.DropFromPlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.ExplicitInventoryOmittedTransaction; +import org.spongepowered.common.event.tracking.context.transaction.inventory.InteractItemTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.InventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.OpenMenuTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlaceRecipeTransaction; @@ -98,6 +103,7 @@ import org.spongepowered.common.world.BlockChange; import org.spongepowered.common.world.SpongeBlockChangeFlag; import org.spongepowered.common.world.volume.VolumeStreamUtils; +import org.spongepowered.math.vector.Vector3d; import java.lang.ref.WeakReference; import java.util.Objects; @@ -122,7 +128,7 @@ interface TransactionSink { @Deprecated void logTransaction(StatefulTransaction transaction); - EffectTransactor pushEffect(final ResultingTransactionBySideEffect effect); + EffectTransactor pushEffect(final ResultingTransactionBySideEffect effect); default ChangeBlock logBlockChange(final SpongeBlockSnapshot originalBlockSnapshot, final BlockState newState, final BlockChangeFlag flags @@ -175,7 +181,7 @@ default EffectTransactor logBlockDrops( original.blockChange = BlockChange.MODIFY; final PrepareBlockDropsTransaction transaction = new PrepareBlockDropsTransaction(pos, state, original); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(PrepareBlockDrops.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(PrepareBlockDrops.getInstance())); } @SuppressWarnings({"ConstantConditions", "unchecked"}) @@ -260,7 +266,7 @@ default boolean logTileRemoval(final @Nullable BlockEntity tileentity, final Sup final EntityPerformingDropsTransaction transaction = new EntityPerformingDropsTransaction(entity); this.logTransaction(transaction); if (transaction.recorded()) { - return this.pushEffect(new ResultingTransactionBySideEffect(EntityPerformingDropsEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(EntityPerformingDropsEffect.getInstance())); } return null; } @@ -336,44 +342,44 @@ default EffectTransactor logClickContainer( final ClickMenuTransaction transaction = new ClickMenuTransaction( player, menu, slotNum, buttonNum, clickType, slot, ItemStackUtil.snapshotOf(player.containerMenu.getCarried())); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logPlayerInventoryChangeWithEffect(final Player player, final PlayerInventoryTransaction.EventCreator eventCreator) { final PlayerInventoryTransaction transaction = new PlayerInventoryTransaction(player, eventCreator); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logCreativeClickContainer(final int slotNum, final ItemStackSnapshot creativeStack, final Player player) { final ClickCreativeMenuTransaction transaction = new ClickCreativeMenuTransaction(player, slotNum, creativeStack); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logDropFromPlayerInventory(final ServerPlayer player, final boolean dropAll) { final DropFromPlayerInventoryTransaction transaction = new DropFromPlayerInventoryTransaction(player, dropAll); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logOpenInventory(final Player player) { final OpenMenuTransaction transaction = new OpenMenuTransaction(player); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logCloseInventory(final Player player, final boolean clientSource) { final CloseMenuTransaction transaction = new CloseMenuTransaction(player, clientSource); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logPlaceRecipe(final boolean shift, final RecipeHolder recipe, final ServerPlayer player, final CraftingInventory craftInv) { final PlaceRecipeTransaction transaction = new PlaceRecipeTransaction(player, shift, recipe, craftInv); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default void logSelectTrade(final ServerPlayer player, final int item) { @@ -405,12 +411,20 @@ default void logCrafting(final Player player, @Nullable final ItemStack craftedS default EffectTransactor logIgnoredInventory(AbstractContainerMenu containerMenu) { final ExplicitInventoryOmittedTransaction transaction = new ExplicitInventoryOmittedTransaction(containerMenu); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } default EffectTransactor logInventoryTransaction(final AbstractContainerMenu containerMenu) { final InventoryTransaction transaction = new InventoryTransaction((Inventory) containerMenu); this.logTransaction(transaction); - return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance())); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } + + default void logSecondaryInteractionTransaction( + final ServerPlayer playerIn, final ItemStack stackIn, final Vector3d hitVec, + final BlockSnapshot snapshot, final Direction direction, final InteractionHand handIn) { + final InteractItemTransaction transaction = new InteractItemTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); + this.logTransaction(transaction); + } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java index 2eaea7e33b9..36edd7e27c6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java @@ -38,6 +38,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.ICaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.effect.PrepareBlockDrops; +import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; import org.spongepowered.common.event.tracking.context.transaction.type.TransactionType; import java.util.Collections; @@ -94,9 +95,9 @@ public boolean isEmpty() { */ @Override - public EffectTransactor pushEffect(final ResultingTransactionBySideEffect effect) { + public EffectTransactor pushEffect(final ResultingTransactionBySideEffect effect) { final GameTransaction<@NonNull ?> parentTransaction = Optional.ofNullable(this.effect) - .map(child -> (GameTransaction) child.tail) + .map(child -> child.tail) .orElse(Objects.requireNonNull(this.tail, "Somehow pushing a new effect without an owning Transaction")); final EffectTransactor effectTransactor = new EffectTransactor(effect, parentTransaction, this.effect, this); this.effect = effect; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java index 05d963c3f60..5b431acffe9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/AddBlockLootDropsEffect.java @@ -40,7 +40,7 @@ import org.spongepowered.common.util.VecHelper; import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class AddBlockLootDropsEffect implements ProcessingSideEffect { +public final class AddBlockLootDropsEffect implements ProcessingSideEffect { private static final class Holder { static final AddBlockLootDropsEffect INSTANCE = new AddBlockLootDropsEffect(); @@ -53,10 +53,12 @@ public static AddBlockLootDropsEffect getInstance() { AddBlockLootDropsEffect() {} @Override - public EffectResult processSideEffect( - final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, - final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final BlockState newState = args.newState(); + final SpongeBlockChangeFlag flag = args.flag(); + final int limit = args.limit(); final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); final ServerLevel world = pipeline.getServerWorld(); @@ -70,6 +72,6 @@ public EffectResult processSideEffect( phaseContext.populateLootContext(lootBuilder); - return new EffectResult(newState, oldState.state().getDrops(lootBuilder), false); + return new EffectResult<>(newState, oldState.state().getDrops(lootBuilder), false); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java index 50b2977f8b2..9c7daa20f57 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockAddedEffect.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class BlockAddedEffect implements ProcessingSideEffect { +public final class BlockAddedEffect implements ProcessingSideEffect { private static final class Holder { static final BlockAddedEffect INSTANCE = new BlockAddedEffect(); @@ -42,9 +42,11 @@ public static BlockAddedEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final var flag = args.flag(); + final var newState = args.newState(); // Vanilla will check if this is the server // if (!this.level.isClientSide) { // var2.onPlace(this.level, var1, var11, var3); @@ -55,6 +57,6 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli if (flag.performBlockPhysics()) { newState.onPlace(pipeline.getServerWorld(), oldState.pos(), oldState.state(), flag.movingBlocks()); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockChangeArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockChangeArgs.java new file mode 100644 index 00000000000..2a572a21dc3 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BlockChangeArgs.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.common.world.SpongeBlockChangeFlag; + +public record BlockChangeArgs( + BlockState newState, + SpongeBlockChangeFlag flag, + int limit +) implements ProcessingSideEffect.Args { + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BroadcastInventoryChangesEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BroadcastInventoryChangesEffect.java index 8664482ce9b..5d4300c3fb2 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BroadcastInventoryChangesEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/BroadcastInventoryChangesEffect.java @@ -25,14 +25,14 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class BroadcastInventoryChangesEffect implements ProcessingSideEffect { +public final class BroadcastInventoryChangesEffect implements ProcessingSideEffect { private static final class Holder { static final BroadcastInventoryChangesEffect INSTANCE = new BroadcastInventoryChangesEffect(); @@ -41,16 +41,16 @@ public static BroadcastInventoryChangesEffect getInstance() { return Holder.INSTANCE; } public static EffectTransactor transact(final TransactionalCaptureSupplier transactor) { - return transactor.pushEffect(new ResultingTransactionBySideEffect(BroadcastInventoryChangesEffect.getInstance())); + return transactor.pushEffect(new ResultingTransactionBySideEffect<>(BroadcastInventoryChangesEffect.getInstance())); } BroadcastInventoryChangesEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java index 951ba947beb..378827bf319 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/CheckBlockPostPlacementIsSameEffect.java @@ -26,11 +26,11 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class CheckBlockPostPlacementIsSameEffect implements ProcessingSideEffect { +public final class CheckBlockPostPlacementIsSameEffect implements ProcessingSideEffect { private static final class Holder { static final CheckBlockPostPlacementIsSameEffect INSTANCE = new CheckBlockPostPlacementIsSameEffect(); } @@ -40,17 +40,18 @@ public static CheckBlockPostPlacementIsSameEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final var newState = args.newState(); final LevelChunkSection chunkSection = pipeline.getAffectedSection(); final int x = oldState.pos().getX() & 15; final int y = oldState.pos().getY() & 15; final int z = oldState.pos().getZ() & 15; final BlockState currentState = chunkSection.getBlockState(x, y, z); if (!currentState.is(newState.getBlock())) { - return new EffectResult(newState, true); + return new EffectResult<>(newState, true); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java index 426a2637da3..4d705e43610 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ChunkChangeCompleteEffect.java @@ -26,15 +26,16 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class ChunkChangeCompleteEffect implements ProcessingSideEffect { +public final class ChunkChangeCompleteEffect implements ProcessingSideEffect { private static final class Holder { static final ChunkChangeCompleteEffect INSTANCE = new ChunkChangeCompleteEffect(); } + ChunkChangeCompleteEffect() { } @@ -43,13 +44,12 @@ public static ChunkChangeCompleteEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { - final LevelChunk chunk = pipeline.getAffectedChunk(); // this.unsaved = true; // Vanilla, we'll just call the accessor available chunk.markUnsaved(); - return new EffectResult(oldState.state(), true); + return new EffectResult<>(oldState.state(), true); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EffectResult.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EffectResult.java index 3ceacfb2e23..e6076ae2b0b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EffectResult.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EffectResult.java @@ -25,30 +25,35 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collections; import java.util.List; -public final class EffectResult { +public final class EffectResult<@Nullable R> { - public static final EffectResult NULL_RETURN = new EffectResult(null, true); - public static final EffectResult NULL_PASS = new EffectResult(null, false); + public static <@Nullable T> EffectResult nullReturn() { + return new EffectResult<>(null, true); + } + + public static <@Nullable T> EffectResult nullPass() { + return new EffectResult<>(null, false); + } - public final @Nullable BlockState resultingState; + public final @Nullable R resultingState; public final List drops; public final boolean hasResult; - public EffectResult(final @Nullable BlockState resultingState, final boolean hasResult) { + public EffectResult(final @Nullable R resultingState, final boolean hasResult) { this.resultingState = resultingState; this.hasResult = hasResult; this.drops = Collections.emptyList(); } - public EffectResult(final @Nullable BlockState resultingState, final List drops, final boolean hasResult) { + public EffectResult(final @Nullable R resultingState, final List drops, final boolean hasResult) { this.resultingState = resultingState; this.drops = drops; this.hasResult = hasResult; } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EntityPerformingDropsEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EntityPerformingDropsEffect.java index eeb7ee4e4e5..4d9d4065a3d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EntityPerformingDropsEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/EntityPerformingDropsEffect.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class EntityPerformingDropsEffect implements ProcessingSideEffect { +public final class EntityPerformingDropsEffect implements ProcessingSideEffect { private static final class Holder { static final EntityPerformingDropsEffect INSTANCE = new EntityPerformingDropsEffect(); @@ -40,10 +40,10 @@ public static EntityPerformingDropsEffect getInstance() { EntityPerformingDropsEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java index f47669e56ea..af08550e265 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ExplodeBlockEffect.java @@ -28,14 +28,14 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.phase.general.ExplosionContext; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class ExplodeBlockEffect implements ProcessingSideEffect { +public final class ExplodeBlockEffect implements ProcessingSideEffect { private static final class Holder { static final ExplodeBlockEffect INSTANCE = new ExplodeBlockEffect(); @@ -47,20 +47,18 @@ public static ExplodeBlockEffect getInstance() { ExplodeBlockEffect() {} - @SuppressWarnings({"unchecked", "rawtypes"}) @Override - public EffectResult processSideEffect( - final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, - final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); final ServerLevel world = pipeline.getServerWorld(); final BlockPos pos = oldState.pos(); - if (phaseContext instanceof ExplosionContext) { - oldState.state().getBlock().wasExploded(world, pos, ((ExplosionContext) phaseContext).getExplosion()); + if (phaseContext instanceof ExplosionContext ec) { + oldState.state().getBlock().wasExploded(world, pos, ec.getExplosion()); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java new file mode 100644 index 00000000000..fac849e78d2 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public record InteractionArgs( + Level world, + ServerPlayer player, + InteractionHand hand, + BlockHitResult blockRaytraceResult, + BlockState blockstate, + ItemStack copiedStack +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java new file mode 100644 index 00000000000..8ccfc3a0b4e --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java @@ -0,0 +1,58 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.world.InteractionResult; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; + +public final class InteractionItemEffect implements ProcessingSideEffect { + + private static final class Holder { + static final InteractionItemEffect INSTANCE = new InteractionItemEffect(); + } + + public static InteractionItemEffect getInstance() { + return Holder.INSTANCE; + } + + @Override + public EffectResult processSideEffect( + UseBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + ) { + final var player = args.player(); + final var world = args.world(); + final var blockstate = args.blockstate(); + final var blockHitResult = args.blockRaytraceResult(); + final InteractionResult result = blockstate.useWithoutItem(world, player, blockHitResult); + pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); + try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { + args.player().containerMenu.broadcastChanges(); + } + return new EffectResult<>(result, true); + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java new file mode 100644 index 00000000000..71d393a62fe --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java @@ -0,0 +1,59 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.world.ItemInteractionResult; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; + +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { + + private static final class Holder { + static final InteractionUseItemOnBlockEffect INSTANCE = new InteractionUseItemOnBlockEffect(); + } + + public static InteractionUseItemOnBlockEffect getInstance() { + return Holder.INSTANCE; + } + + @Override + public EffectResult processSideEffect( + UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionArgs args + ) { + final var player = args.player(); + final var hand = args.hand(); + final var world = args.world(); + final var blockRaytraceResult = args.blockRaytraceResult(); + final var blockstate = args.blockstate(); + final ItemInteractionResult result = blockstate.useItemOn(args.copiedStack(), world, player, hand, blockRaytraceResult); + pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); + try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { + args.player().containerMenu.broadcastChanges(); + } + return new EffectResult<>(result, true); + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InventoryEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InventoryEffect.java index 459b9c9c038..e58f1cb2849 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InventoryEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InventoryEffect.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class InventoryEffect implements ProcessingSideEffect { +public final class InventoryEffect implements ProcessingSideEffect { private static final class Holder { static final InventoryEffect INSTANCE = new InventoryEffect(); @@ -40,10 +40,10 @@ public static InventoryEffect getInstance() { InventoryEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java index db70695e346..5ce7d8ec413 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyClientEffect.java @@ -28,11 +28,12 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class NotifyClientEffect implements ProcessingSideEffect { +public final class NotifyClientEffect implements ProcessingSideEffect { private static final class Holder { static final NotifyClientEffect INSTANCE = new NotifyClientEffect(); @@ -45,9 +46,11 @@ public static NotifyClientEffect getInstance() { NotifyClientEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final BlockState newState = args.newState(); + final SpongeBlockChangeFlag flag = args.flag(); final LevelChunk chunk = pipeline.getAffectedChunk(); final ServerLevel world = pipeline.getServerWorld(); @@ -58,7 +61,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli // this.notifyBlockUpdate(pos, blockstate, newWorldState, flags); world.sendBlockUpdated(oldState.pos(), oldState.state(), newState, flag.getRawFlag()); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java index f69722fdf70..94ff114d231 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java @@ -26,11 +26,11 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class NotifyNeighborSideEffect implements ProcessingSideEffect { +public final class NotifyNeighborSideEffect implements ProcessingSideEffect { private static final class Holder { static final NotifyNeighborSideEffect INSTANCE = new NotifyNeighborSideEffect(); @@ -44,9 +44,11 @@ public static NotifyNeighborSideEffect getInstance() { @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final var flag = args.flag(); + final var newState = args.newState(); final ServerLevel world = pipeline.getServerWorld(); // Vanilla isClientSide is redundant @@ -59,7 +61,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli world.updateNeighbourForOutputSignal(oldState.pos(), newState.getBlock()); } } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java index e635d85aa93..4050f8325c3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class OldBlockOnReplaceEffect implements ProcessingSideEffect { +public final class OldBlockOnReplaceEffect implements ProcessingSideEffect { private static final class Holder { static final OldBlockOnReplaceEffect INSTANCE = new OldBlockOnReplaceEffect(); } @@ -42,9 +42,8 @@ public static OldBlockOnReplaceEffect getInstance() { } @Override - public EffectResult processSideEffect( - final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { // Normally, vanilla does this: // boolean var14 = var11.hasBlockEntity(); @@ -56,7 +55,9 @@ public EffectResult processSideEffect( // However, since we know we're not on the client (ChunkPipeline is not // used outside of server world context) // we can safely just do oldState.onRemove(this.level, var1, var2, var3). + final var flag = args.flag(); + final var newState = args.newState(); oldState.state().onRemove(pipeline.getServerWorld(), oldState.pos(), newState, flag.movingBlocks()); - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java index c2f898c2c4a..94896c4e5af 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PerformBlockDropsFromDestruction.java @@ -27,11 +27,11 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class PerformBlockDropsFromDestruction implements ProcessingSideEffect { +public final class PerformBlockDropsFromDestruction implements ProcessingSideEffect { private static final class Holder { static final PerformBlockDropsFromDestruction INSTANCE = new PerformBlockDropsFromDestruction(); @@ -43,11 +43,11 @@ public static PerformBlockDropsFromDestruction getInstance() { PerformBlockDropsFromDestruction() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { Block.dropResources(oldState.state(), pipeline.getServerWorld(), oldState.pos(), oldState.tileEntity(), oldState.destroyer(), ItemStack.EMPTY); - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java new file mode 100644 index 00000000000..a0f81ef9ad0 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java @@ -0,0 +1,52 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.world.InteractionResult; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; + +public final class PlayerContainerRefreshEffect implements ProcessingSideEffect { + + private static final class Holder { + static final PlayerContainerRefreshEffect INSTANCE = new PlayerContainerRefreshEffect(); + } + + public static PlayerContainerRefreshEffect getInstance() { + return Holder.INSTANCE; + } + + @Override + public EffectResult processSideEffect( + UseItemOnBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + ) { + pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); + try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { + args.player().containerMenu.broadcastChanges(); + } + return EffectResult.nullPass(); + } +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PrepareBlockDrops.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PrepareBlockDrops.java index 9c3c772729e..4ea2225adf3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PrepareBlockDrops.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PrepareBlockDrops.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class PrepareBlockDrops implements ProcessingSideEffect { +public final class PrepareBlockDrops implements ProcessingSideEffect { private static final class Holder { static final PrepareBlockDrops INSTANCE = new PrepareBlockDrops(); @@ -41,10 +41,10 @@ public static PrepareBlockDrops getInstance() { PrepareBlockDrops() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java index 2d62b184f61..6c4a7d1ff09 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java @@ -24,16 +24,13 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; +import org.checkerframework.checker.nullness.qual.Nullable; @FunctionalInterface -public interface ProcessingSideEffect { +public interface ProcessingSideEffect { - EffectResult processSideEffect(BlockPipeline pipeline, PipelineCursor oldState, BlockState newState, SpongeBlockChangeFlag flag, - int limit - ); + EffectResult processSideEffect(T pipeline, C oldState, A args); + + sealed interface Args permits BlockChangeArgs, InteractionArgs, UseItemArgs {} } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java index ff4588db8da..77cf679a028 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/RemoveTileEntityFromChunkEffect.java @@ -26,11 +26,11 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class RemoveTileEntityFromChunkEffect implements ProcessingSideEffect { +public final class RemoveTileEntityFromChunkEffect implements ProcessingSideEffect { private static final class Holder { static final RemoveTileEntityFromChunkEffect INSTANCE = new RemoveTileEntityFromChunkEffect(); @@ -43,14 +43,14 @@ public static RemoveTileEntityFromChunkEffect getInstance() { RemoveTileEntityFromChunkEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final BlockEntity tileEntity = oldState.tileEntity(); if (tileEntity == null) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } pipeline.getAffectedChunk().removeBlockEntity(oldState.pos()); - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java index 196a7c20bf2..4333e3e40d0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetAndRegisterBlockEntityToLevelChunk.java @@ -31,9 +31,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class SetAndRegisterBlockEntityToLevelChunk implements ProcessingSideEffect { +public final class SetAndRegisterBlockEntityToLevelChunk implements ProcessingSideEffect { private static final class Holder { static final SetAndRegisterBlockEntityToLevelChunk INSTANCE = new SetAndRegisterBlockEntityToLevelChunk(); @@ -46,17 +45,16 @@ public static SetAndRegisterBlockEntityToLevelChunk getInstance() { SetAndRegisterBlockEntityToLevelChunk() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, - final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final ServerLevel serverWorld = pipeline.getServerWorld(); final @Nullable BlockEntity blockEntity = oldState.tileEntity(); final BlockPos pos = oldState.pos(); if (serverWorld.isOutsideBuildHeight(pos)) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } pipeline.getAffectedChunk().addAndRegisterBlockEntity(blockEntity); - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java index 678aa48cff2..a680290bb94 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SetBlockToChunkSectionEffect.java @@ -26,11 +26,11 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class SetBlockToChunkSectionEffect implements ProcessingSideEffect { +public final class SetBlockToChunkSectionEffect implements ProcessingSideEffect { private static final class Holder { private static final SetBlockToChunkSectionEffect INSTANCE = new SetBlockToChunkSectionEffect(); @@ -42,17 +42,17 @@ public static SetBlockToChunkSectionEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final BlockState newState = args.newState(); final LevelChunkSection chunkSection = pipeline.getAffectedSection(); final int x = oldState.pos().getX() & 15; final int y = oldState.pos().getY() & 15; final int z = oldState.pos().getZ() & 15; final BlockState oldStateReturned = chunkSection.setBlockState(x, y, z, newState); if (oldStateReturned == newState) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java index 3e144a2249d..ac4eeacd846 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/SpawnDestructBlocksEffect.java @@ -29,13 +29,13 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; import java.util.List; -public final class SpawnDestructBlocksEffect implements ProcessingSideEffect { +public final class SpawnDestructBlocksEffect implements ProcessingSideEffect { private static final class Holder { static final SpawnDestructBlocksEffect INSTANCE = new SpawnDestructBlocksEffect(); @@ -47,11 +47,9 @@ public static SpawnDestructBlocksEffect getInstance() { SpawnDestructBlocksEffect() {} - @SuppressWarnings({"unchecked", "rawtypes"}) @Override - public EffectResult processSideEffect( - final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, - final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final ServerLevel world = pipeline.getServerWorld(); final BlockPos pos = oldState.pos(); @@ -60,6 +58,6 @@ public EffectResult processSideEffect( drops.forEach(drop -> Block.popResource(world, pos, drop)); - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java index 4cedc0c5810..32535c79b54 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java @@ -26,11 +26,11 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class UpdateChunkLightManagerEffect implements ProcessingSideEffect { +public final class UpdateChunkLightManagerEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateChunkLightManagerEffect INSTANCE = new UpdateChunkLightManagerEffect(); @@ -43,9 +43,8 @@ public static UpdateChunkLightManagerEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, - final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final LevelChunkSection chunkSection = pipeline.getAffectedSection(); final boolean wasEmpty = pipeline.wasEmpty(); @@ -53,6 +52,6 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli if (wasEmpty != isStillEmpty) { pipeline.getServerWorld().getChunkSource().getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java index 28049195867..127b1ef7444 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateConnectingBlocksEffect.java @@ -27,11 +27,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class UpdateConnectingBlocksEffect implements ProcessingSideEffect { +public final class UpdateConnectingBlocksEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateConnectingBlocksEffect INSTANCE = new UpdateConnectingBlocksEffect(); @@ -44,11 +44,14 @@ public static UpdateConnectingBlocksEffect getInstance() { UpdateConnectingBlocksEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { final ServerLevel world = pipeline.getServerWorld(); final BlockPos pos = oldState.pos(); + final var flag = args.flag(); + final var newState = args.newState(); + final var limit = args.limit(); if (flag.updateNeighboringShapes() && limit > 0) { // int i = p_241211_3_ & -34; // Vanilla negates 34 to flip neighbor notification and and "state drops" final int withoutNeighborDropsAndNestedNeighborUpdates = flag.asNestedNeighborUpdates().getRawFlag(); @@ -60,7 +63,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli newState.updateIndirectNeighbourShapes(world, pos, withoutNeighborDropsAndNestedNeighborUpdates, limit - 1); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java index de2b04b4949..a9ffa8d929a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateHeightMapEffect.java @@ -26,14 +26,14 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.Heightmap; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.accessor.world.level.chunk.ChunkAccessAccessor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; import java.util.Map; -public final class UpdateHeightMapEffect implements ProcessingSideEffect { +public final class UpdateHeightMapEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateHeightMapEffect INSTANCE = new UpdateHeightMapEffect(); @@ -46,9 +46,10 @@ public static UpdateHeightMapEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final var newState = args.newState(); final Map heightMap = ((ChunkAccessAccessor) pipeline.getAffectedChunk()).accessor$heightmaps(); if (heightMap == null) { throw new IllegalStateException("Heightmap dereferenced!"); @@ -60,6 +61,6 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli heightMap.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(x, y, z, newState); heightMap.get(Heightmap.Types.OCEAN_FLOOR).update(x, y, z, newState); heightMap.get(Heightmap.Types.WORLD_SURFACE).update(x, y, z, newState); - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index b8962419f59..d3d168df41f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -29,11 +29,11 @@ import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.lighting.LightEngine; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class UpdateLightSideEffect implements ProcessingSideEffect { +public final class UpdateLightSideEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateLightSideEffect INSTANCE = new UpdateLightSideEffect(); @@ -47,12 +47,13 @@ public static UpdateLightSideEffect getInstance() { } @Override - public EffectResult processSideEffect( + public EffectResult<@Nullable BlockState> processSideEffect( final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + final BlockChangeArgs args ) { + final var flag = args.flag(); if (!flag.updateLighting()) { - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } final ServerLevel serverWorld = pipeline.getServerWorld(); final BlockState currentState = pipeline.getAffectedChunk().getBlockState(oldState.pos()); @@ -90,7 +91,7 @@ public EffectResult processSideEffect( // this.profiler.endSection(); filler.pop(); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java index aec887a346a..b6aa7aa1741 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java @@ -33,9 +33,8 @@ import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class UpdateOrCreateNewTileEntityPostPlacementEffect implements ProcessingSideEffect { +public final class UpdateOrCreateNewTileEntityPostPlacementEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateOrCreateNewTileEntityPostPlacementEffect INSTANCE = new UpdateOrCreateNewTileEntityPostPlacementEffect(); @@ -49,9 +48,10 @@ public static UpdateOrCreateNewTileEntityPostPlacementEffect getInstance() { @SuppressWarnings("deprecation") @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final var newState = args.newState(); final ServerLevel serverWorld = pipeline.getServerWorld(); final LevelChunk chunk = pipeline.getAffectedChunk(); if (((BlockStateBridge) newState).bridge$hasTileEntity()) { @@ -69,6 +69,6 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli ((LevelChunkAccessor) chunk).accessor$updateBlockEntityTicker(maybeNewTileEntity); } } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java index 41a44be0d32..6c91e24d4d6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateWorldRendererEffect.java @@ -25,11 +25,11 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class UpdateWorldRendererEffect implements ProcessingSideEffect { +public final class UpdateWorldRendererEffect implements ProcessingSideEffect { private static final class Holder { static final UpdateWorldRendererEffect INSTANCE = new UpdateWorldRendererEffect(); @@ -42,12 +42,13 @@ public static UpdateWorldRendererEffect getInstance() { UpdateWorldRendererEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, - final BlockState newState, final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, + final BlockChangeArgs args ) { + final var newState = args.newState(); if (oldState.state() != newState) { pipeline.getServerWorld().setBlocksDirty(oldState.pos(), oldState.state(), newState); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java new file mode 100644 index 00000000000..aebd7497bb2 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java @@ -0,0 +1,41 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; + +public record UseItemArgs( + Level world, + ServerPlayer player, + InteractionHand hand, + BlockHitResult result, + ItemStack copiedStack, + boolean creative +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java new file mode 100644 index 00000000000..130e414c734 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java @@ -0,0 +1,64 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.UseOnContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; + +public class UseItemEffect implements ProcessingSideEffect { + + private static final class Holder { + static final UseItemEffect INSTANCE = new UseItemEffect(); + } + + public static UseItemEffect getInstance() { + return UseItemEffect.Holder.INSTANCE; + } + + @Override + public EffectResult processSideEffect( + UseItemPipeline pipeline, InteractionResult oldState, UseItemArgs args + ) { + final var stack = args.copiedStack(); + final InteractionResult result; + final var context = new UseOnContext(args.player(), args.hand(), args.result()); + if (args.creative()) { + int $$14 = stack.getCount(); + result = stack.useOn(context); + stack.setCount($$14); + } else { + result = stack.useOn(context); + } + pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); + try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { + args.player().containerMenu.broadcastChanges(); + } + return new EffectResult<>(result, true); + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java index 58491086353..648300d5aac 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java @@ -25,11 +25,12 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class WorldBlockChangeCompleteEffect implements ProcessingSideEffect{ +public final class WorldBlockChangeCompleteEffect implements ProcessingSideEffect { private static final class Holder { static final WorldBlockChangeCompleteEffect INSTANCE = new WorldBlockChangeCompleteEffect(); @@ -42,12 +43,13 @@ public static WorldBlockChangeCompleteEffect getInstance() { WorldBlockChangeCompleteEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { + final BlockState newState = args.newState(); + final SpongeBlockChangeFlag flag = args.flag(); if (flag.notifyPathfinding()) { pipeline.getServerWorld().onBlockStateChange(oldState.pos(), oldState.state(), newState); } - return new EffectResult(oldState.state(), true); + return new EffectResult<>(oldState.state(), true); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java index 86e5e16119c..05a171680cd 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldDestroyBlockLevelEffect.java @@ -27,11 +27,11 @@ import net.minecraft.world.level.block.BaseFireBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; -import org.spongepowered.common.world.SpongeBlockChangeFlag; -public final class WorldDestroyBlockLevelEffect implements ProcessingSideEffect { +public final class WorldDestroyBlockLevelEffect implements ProcessingSideEffect { private static final class Holder { static final WorldDestroyBlockLevelEffect INSTANCE = new WorldDestroyBlockLevelEffect(); @@ -44,12 +44,12 @@ public static WorldDestroyBlockLevelEffect getInstance() { WorldDestroyBlockLevelEffect() {} @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, final int limit + public EffectResult<@Nullable BlockState> processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockChangeArgs args ) { if (!(oldState.state().getBlock() instanceof BaseFireBlock)) { pipeline.getServerWorld().levelEvent(2001, oldState.pos(), Block.getId(oldState.state())); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java new file mode 100644 index 00000000000..3302e01d076 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java @@ -0,0 +1,101 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.inventory; + +import com.google.common.collect.ImmutableList; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; +import org.spongepowered.api.util.Direction; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; +import org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes; +import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.util.PrettyPrinter; +import org.spongepowered.math.vector.Vector3d; + +import java.util.Optional; +import java.util.function.BiConsumer; + +public class InteractItemTransaction extends GameTransaction { + + + private final Vector3d hitVec; + private final BlockSnapshot snapshot; + private final Direction direction; + private final InteractionHand hand; + private final ItemStackSnapshot stack; + + public InteractItemTransaction(ServerPlayer playerIn, ItemStack stackIn, Vector3d hitVec, BlockSnapshot snapshot, Direction direction, InteractionHand handIn) { + super(TransactionTypes.INTERACT_BLOCK_SECONDARY.get()); + this.stack = ItemStackUtil.snapshotOf(stackIn); + this.hitVec = hitVec; + this.snapshot = snapshot; + this.direction = direction; + this.hand = handIn; + } + + + @Override + public Optional, CauseStackManager.StackFrame>> getFrameMutator( + @Nullable GameTransaction<@NonNull ?> parent + ) { + return Optional.empty(); + } + + @Override + public void addToPrinter(PrettyPrinter printer) { + + } + + @Override + public Optional generateEvent( + final PhaseContext<@NonNull ?> context, + final @Nullable GameTransaction<@NonNull ?> parent, + final ImmutableList> gameTransactions, + final Cause currentCause + ) { + return Optional.empty(); + } + + @Override + public void restore(PhaseContext<@NonNull ?> context, InteractBlockEvent.Secondary.Composite event) { + + } + + @Override + public boolean markCancelledTransactions( + final InteractBlockEvent.Secondary.Composite event, + final ImmutableList> gameTransactions) { + return false; + } +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InventoryBasedTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InventoryBasedTransaction.java index 45672accf3a..be736521434 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InventoryBasedTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InventoryBasedTransaction.java @@ -67,6 +67,11 @@ protected InventoryBasedTransaction(final Inventory inventory) { this.inventory = inventory; } + @Override + protected boolean hasUnknownChainRequiringCancellation() { + return true; + } + @Override public Optional, CauseStackManager.StackFrame>> getFrameMutator( @Nullable final GameTransaction<@NonNull ?> parent diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java index accd704f681..2c4d8c5ad9c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java @@ -37,6 +37,7 @@ import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.block.ChangeBlock; +import org.spongepowered.common.event.tracking.context.transaction.effect.BlockChangeArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; import org.spongepowered.common.world.SpongeBlockChangeFlag; @@ -118,12 +119,11 @@ public LevelChunkSection getAffectedSection() { for (final ResultingTransactionBySideEffect effect : this.chunkEffects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final EffectResult result = effect.effect.processSideEffect( + final var args = new BlockChangeArgs(proposedState, flag, limit); + final EffectResult<@Nullable BlockState> result = effect.effect.processSideEffect( this, formerState, - proposedState, - flag, - limit + args ); if (result.hasResult) { return result.resultingState; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java index 2a5dc819629..8f684044a29 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/TileEntityPipeline.java @@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import org.checkerframework.checker.nullness.qual.Nullable; @@ -33,6 +34,7 @@ import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.BlockChangeArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; import org.spongepowered.common.world.SpongeBlockChangeFlag; @@ -49,7 +51,7 @@ public final class TileEntityPipeline implements BlockPipeline { private final @Nullable Supplier chunkSupplier; private final @Nullable Supplier serverWorld; private final @Nullable Supplier sectionSupplier; - private final List effects; + private final List> effects; private TileEntityPipeline(final Builder builder) { this.chunkSupplier = builder.chunkSupplier; @@ -98,15 +100,18 @@ public boolean wasEmpty() { public boolean processEffects(final PhaseContext context, final PipelineCursor initialCursor) { PipelineCursor currentCursor = initialCursor; - for (final ResultingTransactionBySideEffect effect : this.effects) { + for (final ResultingTransactionBySideEffect effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final EffectResult result = effect.effect.processSideEffect( - this, - currentCursor, + final BlockChangeArgs args = new BlockChangeArgs( currentCursor.state(), (SpongeBlockChangeFlag) BlockChangeFlags.NONE, currentCursor.limit() ); + final EffectResult<@Nullable BlockState> result = effect.effect.processSideEffect( + this, + currentCursor, + args + ); if (result.resultingState != currentCursor.state()) { currentCursor = new PipelineCursor( result.resultingState, @@ -129,13 +134,13 @@ public static final class Builder { @Nullable Supplier serverWorld; @Nullable Supplier chunkSupplier; @Nullable Supplier sectionSupplier; - List effects; + List> effects; - public Builder addEffect(final ProcessingSideEffect effect) { + public Builder addEffect(final ProcessingSideEffect effect) { if (this.effects == null) { this.effects = new LinkedList<>(); } - this.effects.add(new ResultingTransactionBySideEffect(Objects.requireNonNull(effect, "Effect is null"))); + this.effects.add(new ResultingTransactionBySideEffect<>(Objects.requireNonNull(effect, "Effect is null"))); return this; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java new file mode 100644 index 00000000000..4203d6474ad --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java @@ -0,0 +1,101 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; + +import java.util.List; +import java.util.Objects; + +public class UseBlockPipeline { + + private final ServerLevel worldIn; + private final ServerPlayer player; + private final InteractionHand hand; + private final BlockHitResult blockRaytraceResult; + private final BlockState blockstate; + private final ItemStack copiedStack; + private final List> effects; + private final TransactionalCaptureSupplier transactor; + + + public UseBlockPipeline(ServerLevel worldIn, + ServerPlayer playerIn, + InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, + BlockState blockstate, + ItemStack copiedStack, + final TransactionalCaptureSupplier transactor) { + + this.worldIn = worldIn; + this.player = playerIn; + this.hand = handIn; + this.blockRaytraceResult = blockRaytraceResultIn; + this.blockstate = blockstate; + this.copiedStack = copiedStack; + this.effects = List.of( + new ResultingTransactionBySideEffect<>(InteractionItemEffect.getInstance()) + ); + this.transactor = transactor; + } + + public InteractionResult processInteraction(PhaseContext context) { + var interaction = InteractionResult.PASS; + for (final var effect : this.effects) { + try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { + final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final EffectResult result = effect.effect.processSideEffect( + this, + interaction, + args + ); + if (result.hasResult) { + final @Nullable InteractionResult resultingState = result.resultingState; + interaction = Objects.requireNonNullElse(resultingState, interaction); + } + } + } + return interaction; + } + + public TransactionalCaptureSupplier transactor() { + return this.transactor; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java new file mode 100644 index 00000000000..82ba980892b --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; + +import java.util.List; +import java.util.Objects; + +public final class UseItemOnBlockPipeline { + + private final ServerLevel worldIn; + private final ServerPlayer player; + private final InteractionHand hand; + private final BlockHitResult blockRaytraceResult; + private final BlockState blockstate; + private final ItemStack copiedStack; + private final List> effects; + private final TransactionalCaptureSupplier transactor; + + + public UseItemOnBlockPipeline(ServerLevel worldIn, + ServerPlayer playerIn, + InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, + BlockState blockstate, + ItemStack copiedStack, + final TransactionalCaptureSupplier transactor) { + + this.worldIn = worldIn; + this.player = playerIn; + this.hand = handIn; + this.blockRaytraceResult = blockRaytraceResultIn; + this.blockstate = blockstate; + this.copiedStack = copiedStack; + this.effects = List.of( + new ResultingTransactionBySideEffect<>(InteractionUseItemOnBlockEffect.getInstance()) + ); + this.transactor = transactor; + } + + public ItemInteractionResult processInteraction(PhaseContext context) { + var interaction = ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + for (final var effect : this.effects) { + try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { + final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final EffectResult result = effect.effect.processSideEffect( + this, + interaction, + args + ); + if (result.hasResult) { + final @Nullable ItemInteractionResult resultingState = result.resultingState; + interaction = Objects.requireNonNullElse(resultingState, interaction); + } + } + } + return interaction; + } + + public TransactionalCaptureSupplier transactor() { + return this.transactor; + } +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java new file mode 100644 index 00000000000..ce4fbd53238 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemEffect; + +import java.util.List; +import java.util.Objects; + +public class UseItemPipeline { + + private final ServerLevel worldIn; + private final ServerPlayer player; + private final InteractionHand hand; + private final ItemStack copiedStack; + private final BlockHitResult blockRaytraceResult; + private final boolean creative; + private final List> effects; + private final TransactionalCaptureSupplier transactor; + + + public UseItemPipeline(ServerLevel worldIn, + ServerPlayer playerIn, + InteractionHand handIn, + ItemStack copiedStack, + BlockHitResult blockRaytraceResult, + boolean creative, + final TransactionalCaptureSupplier transactor) { + + this.worldIn = worldIn; + this.player = playerIn; + this.hand = handIn; + this.copiedStack = copiedStack; + this.blockRaytraceResult = blockRaytraceResult; + this.creative = creative; + this.effects = List.of( + new ResultingTransactionBySideEffect<>(UseItemEffect.getInstance()) + ); + this.transactor = transactor; + } + + public InteractionResult processInteraction(PhaseContext context) { + var interaction = InteractionResult.PASS; + for (final var effect : this.effects) { + try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { + final var args = new UseItemArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); + final EffectResult result = effect.effect.processSideEffect( + this, + interaction, + args + ); + if (result.hasResult) { + final @Nullable InteractionResult resultingState = result.resultingState; + interaction = Objects.requireNonNullElse(resultingState, interaction); + } + } + } + return interaction; + } + + public TransactionalCaptureSupplier transactor() { + return this.transactor; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java index fe5a8e9b355..3b6f49db7a9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java @@ -36,6 +36,7 @@ import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.BlockChangeArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; import org.spongepowered.common.world.SpongeBlockChangeFlag; @@ -52,7 +53,7 @@ public final class WorldPipeline implements BlockPipeline { private final Supplier serverWorld; private final Supplier sectionSupplier; private final boolean wasEmpty; - private final List worldEffects; + private final List> worldEffects; private final ChunkPipeline chunkPipeline; WorldPipeline(final Builder builder) { @@ -101,14 +102,13 @@ public boolean processEffects(final PhaseContext context, final BlockState cu final int oldOpacity = oldState.getLightBlock(); PipelineCursor formerState = new PipelineCursor(oldState, pos, existing, destroyer, limit); - for (final ResultingTransactionBySideEffect effect : this.worldEffects) { + for (final ResultingTransactionBySideEffect effect : this.worldEffects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final EffectResult result = effect.effect.processSideEffect( + final var args = new BlockChangeArgs(newProposedState, flag, limit); + final EffectResult<@Nullable BlockState> result = effect.effect.processSideEffect( this, formerState, - newProposedState, - flag, - limit + args ); if (result.hasResult) { return result.resultingState != null; @@ -134,8 +134,8 @@ public static final class Builder { final Supplier serverWorld; final Supplier chunkSupplier; - final Supplier sectionSupplier; - @MonotonicNonNull List effects; + final Supplier<@Nullable LevelChunkSection> sectionSupplier; + @MonotonicNonNull List> effects; final ChunkPipeline chunkPipeline; Builder(final ChunkPipeline chunkPipeline) { @@ -145,11 +145,11 @@ public static final class Builder { this.chunkPipeline = chunkPipeline; } - public Builder addEffect(final ProcessingSideEffect effect) { + public Builder addEffect(final ProcessingSideEffect effect) { if (this.effects == null) { this.effects = new LinkedList<>(); } - this.effects.add(new ResultingTransactionBySideEffect(Objects.requireNonNull(effect, "Effect is null"))); + this.effects.add(new ResultingTransactionBySideEffect<>(Objects.requireNonNull(effect, "Effect is null"))); return this; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java index 2301cc5bfb0..188b314c4a3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java @@ -29,6 +29,7 @@ import org.spongepowered.api.event.Cancellable; import org.spongepowered.api.event.Event; import org.spongepowered.api.event.block.ChangeBlockEvent; +import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.block.NotifyNeighborBlockEvent; import org.spongepowered.api.event.block.ScheduleBlockUpdateEvent; import org.spongepowered.api.event.entity.HarvestEntityEvent; @@ -67,7 +68,7 @@ public final class TransactionTypes { public static final DefaultedRegistryReference> SLOT_CHANGE = TransactionTypes.key(ResourceKey.sponge("slot_change")); - public static final DefaultedRegistryReference> SPAWN_ENTITY = TransactionTypes.key(ResourceKey.sponge("spawn_entity")); + public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); // SORTFIELDS:OFF diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 990a2389412..31844e0afc9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -35,8 +35,10 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockEventData; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; @@ -48,6 +50,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -105,6 +108,9 @@ import org.spongepowered.common.event.tracking.context.transaction.pipeline.ChunkPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; import org.spongepowered.common.event.tracking.phase.tick.TickPhase; @@ -446,11 +452,11 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem // Then build and use the BlockPipeline final ChunkPipeline chunkPipeline = mixinChunk.bridge$createChunkPipeline(pos, newState, currentState, spongeFlag, limit); final WorldPipeline.Builder worldPipelineBuilder = WorldPipeline.builder(chunkPipeline); - worldPipelineBuilder.addEffect((pipeline, oldState, newState1, flag1, cursorLimit) -> { + worldPipelineBuilder.addEffect((pipeline, oldState, args) -> { if (oldState == null) { - return EffectResult.NULL_RETURN; + return EffectResult.nullReturn(); } - return EffectResult.NULL_PASS; + return EffectResult.nullPass(); }) .addEffect(UpdateLightSideEffect.getInstance()) .addEffect(CheckBlockPostPlacementIsSameEffect.getInstance()) @@ -576,6 +582,79 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable return builder.build(); } + @Override + public UseItemOnBlockPipeline bridge$startInteractionUseOnChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + return null; + } + if (this.bridge$isFake()) { + return null; + } + + final var instance = PhaseTracker.getInstance(); + if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); + } + final var pipeline = new UseItemOnBlockPipeline( + (ServerLevel) worldIn, + playerIn, + handIn, + blockRaytraceResultIn, + blockstate, + copiedStack, + instance.getPhaseContext().getTransactor() + ); + return pipeline; + } + + @Override + public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + return null; + } + if (this.bridge$isFake()) { + return null; + } + + final var instance = PhaseTracker.getInstance(); + if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); + } + final var pipeline = new UseBlockPipeline( + (ServerLevel) worldIn, + playerIn, + handIn, + blockRaytraceResultIn, + blockstate, + copiedStack, + instance.getPhaseContext().getTransactor() + ); + return pipeline; + } + @Override + public UseItemPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + return null; + } + if (this.bridge$isFake()) { + return null; + } + + final var instance = PhaseTracker.getInstance(); + if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); + } + return new UseItemPipeline( + (ServerLevel) worldIn, + playerIn, + handIn, + copiedStack, + blockRaytraceResult, + creative, + instance.getPhaseContext().getTransactor() + ); + } + /** * Technically an overwrite, but because this is simply an override, we can * effectively do as we need to, which is determine if we are performing diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 1a01fd029a5..b06c7ac4d21 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -34,12 +34,10 @@ import net.minecraft.world.MenuProvider; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -56,16 +54,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.server.level.ServerPlayerGameModeBridge; +import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.inventory.container.ContainerBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.inventory.InventoryEventFactory; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; -import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.effect.InventoryEffect; -import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.registry.provider.DirectionFacingProvider; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; @@ -78,7 +72,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { @Shadow protected net.minecraft.server.level.ServerLevel level; @Shadow private GameType gameModeForPlayer; - @Shadow public abstract boolean isCreative(); + @Shadow public abstract boolean shadow$isCreative(); @Inject(method = "useItem", cancellable = true, at = @At(value = "INVOKE", @@ -105,7 +99,9 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl final BlockSnapshot snapshot = ((ServerWorld) (worldIn)).createSnapshot(VecHelper.toVector3i(blockpos)); final Vector3d hitVec = Vector3d.from(blockRaytraceResultIn.getBlockPos().getX(), blockRaytraceResultIn.getBlockPos().getY(), blockRaytraceResultIn.getBlockPos().getZ()); final org.spongepowered.api.util.Direction direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get(); - final InteractBlockEvent.Secondary event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final PhaseContext phaseContext = PhaseTracker.getInstance().getPhaseContext(); + phaseContext.getTransactor().logSecondaryInteractionTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final InteractBlockEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); final Tristate useItem = event.useItemResult(); final Tristate useBlock = event.useBlockResult(); ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(event.isCancelled()); @@ -113,49 +109,53 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl player.inventoryMenu.sendAllDataToRemote(); return InteractionResult.FAIL; } - final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); - // Sponge end - if (this.gameModeForPlayer == GameType.SPECTATOR) { - final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); - if (inamedcontainerprovider != null) { - playerIn.openMenu(inamedcontainerprovider); - final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); - final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { - frame.pushCause(playerIn); - frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld)(worldIn)).createSnapshot(pos)); - ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); - if (!InventoryEventFactory.callInteractContainerOpenEvent(playerIn)) { - return InteractionResult.SUCCESS; + try (final var frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + frame.pushCause(event); + // Sponge end + if (this.gameModeForPlayer == GameType.SPECTATOR) { + final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); + if (inamedcontainerprovider != null) { + playerIn.openMenu(inamedcontainerprovider); + final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); + final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); + try (final CauseStackManager.StackFrame blockHit = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + blockHit.pushCause(playerIn); + blockHit.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos)); + ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); + if (!InventoryEventFactory.callInteractContainerOpenEvent(playerIn)) { + return InteractionResult.SUCCESS; + } } + return InteractionResult.SUCCESS; + } else { + return InteractionResult.PASS; } - return InteractionResult.SUCCESS; - } else { - return InteractionResult.PASS; } - } else { final boolean flag = !playerIn.getMainHandItem().isEmpty() || !playerIn.getOffhandItem().isEmpty(); final boolean flag1 = playerIn.isSecondaryUseActive() && flag; final ItemStack copiedStack = stackIn.copy(); if (useBlock != Tristate.FALSE && !flag1) { // Sponge check useBlock - final InteractionResult result = blockstate.useItemOn(playerIn.getItemInHand(handIn), worldIn, playerIn, handIn, blockRaytraceResultIn); - - if (result.consumesAction()) { + final var useInteraction = ((TrackedWorldBridge) level).bridge$startInteractionUseOnChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + if (useInteraction == null) { + return InteractionResult.FAIL; + } + final InteractionResult itemInteract = useInteraction.processInteraction(phaseContext); + if (itemInteract.consumesAction()) { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack); - return result; + return itemInteract; } - - if (result instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { + if (itemInteract instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge - final InteractionResult result2 = blockstate.useWithoutItem(worldIn, playerIn, blockRaytraceResultIn); + final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + final InteractionResult result2 = interaction.processInteraction(phaseContext); if (result2.consumesAction()) { // Sponge Start if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { - frame.pushCause(playerIn); - frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos)); + try (final CauseStackManager.StackFrame blockUse = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + blockUse.pushCause(playerIn); + blockUse.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos)); ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); if (!InventoryEventFactory.callInteractContainerOpenEvent(playerIn)) { return InteractionResult.FAIL; @@ -167,6 +167,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl CriteriaTriggers.DEFAULT_BLOCK_USE.trigger(playerIn, blockpos); return result2; } + } } @@ -176,26 +177,9 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(true); return InteractionResult.PASS; } - // Sponge end - final UseOnContext itemusecontext = new UseOnContext(playerIn, handIn, blockRaytraceResultIn); - final InteractionResult result; - if (this.isCreative()) { - final int i = stackIn.getCount(); - result = stackIn.useOn(itemusecontext); - stackIn.setCount(i); - } else { - result = stackIn.useOn(itemusecontext); - // Sponge start - log change in hand - final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); - final TransactionalCaptureSupplier transactor = context.getTransactor(); - if (!transactor.isEmpty()) { //TODO: Add effect to attach the transaction to be the child of the parents - try (final EffectTransactor ignored = context.getTransactor().pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()))) { - transactor.logPlayerInventoryChange(this.player, PlayerInventoryTransaction.EventCreator.STANDARD); - this.player.inventoryMenu.broadcastChanges(); - } - } - // Sponge end - } + final var interaction = ((TrackedWorldBridge) level).bridge$startItemInteractionChange(worldIn, playerIn, handIn, copiedStack, blockRaytraceResultIn, this.shadow$isCreative()); + final var result = interaction.processInteraction(phaseContext); + if (result.consumesAction()) { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack); @@ -204,7 +188,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return result; } else { // Sponge start - if(useBlock == Tristate.FALSE && !flag1) { + if (useBlock == Tristate.FALSE && !flag1) { ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(true); } // Sponge end @@ -214,5 +198,4 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl } } - } diff --git a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java index d0fec3da68f..b78ad302ca2 100644 --- a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java +++ b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java @@ -331,8 +331,7 @@ void testTransformationsOfPositions( .sub(VolumePositionTranslators.BLOCK_OFFSET); final Vector3i invertedBlockPos = invertedTransformedPos.toInt(); final Vector3i expectedPos; - Assertions.assertTrue( - type instanceof StubState, + Assertions.assertInstanceOf(StubState.class, type, () -> String.format("expected state to be a stub state for pos: [%f, %f, %f] but got %s", x, y, z, type ) From 96990e0bd281f3a7d520dfab6a3de75cb4c1a6b7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 6 May 2024 01:06:26 -0700 Subject: [PATCH 167/586] feat: Add other interactions as pipeline transactions --- .editorconfig | 2 + .../bridge/world/TrackedWorldBridge.java | 5 +- .../event/SpongeCommonEventFactory.java | 4 +- .../transaction/EventByTransaction.java | 2 +- .../context/transaction/GameTransaction.java | 13 ++ .../context/transaction/TransactionSink.java | 26 +++- .../TransactionalCaptureSupplier.java | 7 +- ...actionArgs.java => InteractionAtArgs.java} | 2 +- .../effect/InteractionItemEffect.java | 4 +- .../InteractionUseItemOnBlockEffect.java | 4 +- .../effect/ProcessingSideEffect.java | 6 +- .../transaction/effect/UseItemArgs.java | 5 +- .../transaction/effect/UseItemAtArgs.java | 41 +++++++ ...efreshEffect.java => UseItemAtEffect.java} | 29 +++-- .../transaction/effect/UseItemEffect.java | 18 +-- .../transaction/effect/UseItemOnArgs.java | 39 ++++++ .../inventory/CompositeTransaction.java | 68 +++++++++++ .../inventory/InteractItemTransaction.java | 53 ++++----- .../InteractItemWithBlockTransaction.java | 112 ++++++++++++++++++ .../pipeline/UseBlockPipeline.java | 6 +- .../pipeline/UseItemAtPipeline.java | 100 ++++++++++++++++ .../pipeline/UseItemOnBlockPipeline.java | 6 +- .../transaction/pipeline/UseItemPipeline.java | 18 +-- .../transaction/type/TransactionTypes.java | 4 +- .../loader/SpongeCommonRegistryLoader.java | 2 +- .../core/world/entity/ai/goal/GoalMixin.java | 3 + ...GamePacketListenerImplMixin_Inventory.java | 10 +- .../level/ServerLevelMixin_Tracker.java | 69 +++++++---- .../ServerPlayerGameModeMixin_Tracker.java | 13 +- .../test/projectile/ProjectileTest.java | 2 +- .../test/volumestream/VolumeStreamTest.java | 2 +- 31 files changed, 550 insertions(+), 125 deletions(-) rename src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/{InteractionArgs.java => InteractionAtArgs.java} (98%) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java rename src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/{PlayerContainerRefreshEffect.java => UseItemAtEffect.java} (68%) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java diff --git a/.editorconfig b/.editorconfig index ea24aef8a80..14179785cef 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,6 +12,8 @@ insert_final_newline = false max_line_length = 120 tab_width = 4 +[{*.json,*.jsonc,*.png.mcmeta,mcmod.info,pack.mcmeta}] +indent_size = 2 [*.yaml] indent_size = 2 \ No newline at end of file diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index c5c48c5c380..91d1e7d860a 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -45,6 +45,7 @@ import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; @@ -117,5 +118,7 @@ public interface TrackedWorldBridge { UseBlockPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseItemPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + UseItemAtPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + + UseItemPipeline bridge$startItemInteractionUseChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack); } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 5a769dface4..6a5eff8d157 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -297,10 +297,10 @@ public static InteractItemEvent.Primary callInteractItemEventPrimary(final net.m } } - public static InteractItemEvent.Secondary callInteractItemEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack stack, final InteractionHand hand) { + public static InteractItemEvent.Secondary.Pre callInteractItemEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack stack, final InteractionHand hand) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { SpongeCommonEventFactory.applyCommonInteractContext(player, stack, hand, null, null, frame); - final InteractItemEvent.Secondary event = SpongeEventFactory.createInteractItemEventSecondary(frame.currentCause(), ItemStackUtil.snapshotOf(stack)); + final var event = SpongeEventFactory.createInteractItemEventSecondaryPre(frame.currentCause(), ItemStackUtil.snapshotOf(stack)); SpongeCommon.post(event); return event; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java index eed31f53d27..a2dc78e740c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java @@ -32,7 +32,7 @@ import org.spongepowered.api.event.Event; @DefaultQualifier(NonNull.class) -record EventByTransaction( +public record EventByTransaction( T event, ImmutableList> transactions, @Nullable GameTransaction<@NonNull ?> parent, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java index 391443f3f19..9f524c74b75 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java @@ -46,6 +46,7 @@ import java.util.Optional; import java.util.StringJoiner; import java.util.function.BiConsumer; +import java.util.stream.Stream; @DefaultQualifier(NonNull.class) public abstract class GameTransaction implements TransactionFlow, StatefulTransaction { @@ -189,6 +190,18 @@ protected void captureState() { } + public void associateSideEffectEvents(E e, Stream elements) { + + } + + public void pushCause(CauseStackManager.StackFrame frame, E e) { + frame.pushCause(e); + } + + public void finalizeSideEffects(E e) { + + } + private static class ChildIterator implements Iterator> { private final Iterator> effectIterator; private @Nullable GameTransaction<@NonNull ?> cachedNext; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index 73655b3996b..303ebf915a6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -27,7 +27,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -46,6 +45,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.ItemStackSnapshot; @@ -74,6 +74,7 @@ import org.spongepowered.common.event.tracking.context.transaction.block.ScheduleUpdateTransaction; import org.spongepowered.common.event.tracking.context.transaction.effect.BlockAddedEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.EntityPerformingDropsEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.InventoryEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.PrepareBlockDrops; import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; @@ -86,6 +87,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.DropFromPlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.ExplicitInventoryOmittedTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.InteractItemTransaction; +import org.spongepowered.common.event.tracking.context.transaction.inventory.InteractItemWithBlockTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.InventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.OpenMenuTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlaceRecipeTransaction; @@ -421,10 +423,26 @@ default EffectTransactor logInventoryTransaction(final AbstractContainerMenu con } default void logSecondaryInteractionTransaction( - final ServerPlayer playerIn, final ItemStack stackIn, final Vector3d hitVec, - final BlockSnapshot snapshot, final Direction direction, final InteractionHand handIn) { - final InteractItemTransaction transaction = new InteractItemTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final ServerPlayer playerIn, final Vector3d hitVec, + final BlockSnapshot snapshot, final Direction direction, InteractBlockEvent.Secondary.Pre event) { + final InteractItemWithBlockTransaction transaction = new InteractItemWithBlockTransaction(playerIn, + hitVec, + snapshot, + direction, + event.originalUseBlockResult(), + event.useBlockResult(), + event.originalUseItemResult(), + event.useItemResult() + ); this.logTransaction(transaction); } + default EffectTransactor logSecondaryInteractItemTransaction( + final ServerPlayer playerIn, final ItemStack stackIn + ) { + final InteractItemTransaction transaction = new InteractItemTransaction(playerIn, stackIn); + this.logTransaction(transaction); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InteractionItemEffect.getInstance())); + } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java index 36edd7e27c6..d5bb7c3cb0b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java @@ -311,13 +311,16 @@ private static void generateEventForTransaction( if (transaction.sideEffects == null || transaction.sideEffects.isEmpty()) { continue; } - generatedEvent.ifPresent(frame::pushCause); + generatedEvent.ifPresent(e -> transaction.pushCause(frame, e)); for (final ResultingTransactionBySideEffect sideEffect : transaction.sideEffects) { if (sideEffect.head == null) { continue; } - builder.addAll(TransactionalCaptureSupplier.batchTransactions(sideEffect.head, pointer, context, transactionPostEventBuilder)); + final var elements = TransactionalCaptureSupplier.batchTransactions(sideEffect.head, pointer, context, transactionPostEventBuilder); + generatedEvent.ifPresent(e -> transaction.associateSideEffectEvents(e, elements.stream().map(EventByTransaction::event))); + builder.addAll(elements); } + generatedEvent.ifPresent(transaction::finalizeSideEffects); } } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java similarity index 98% rename from src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java rename to src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java index fac849e78d2..5cd9000fdc3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java @@ -31,7 +31,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -public record InteractionArgs( +public record InteractionAtArgs( Level world, ServerPlayer player, InteractionHand hand, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java index 8ccfc3a0b4e..57af8e795a9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java @@ -29,7 +29,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; -public final class InteractionItemEffect implements ProcessingSideEffect { +public final class InteractionItemEffect implements ProcessingSideEffect.Simple { private static final class Holder { static final InteractionItemEffect INSTANCE = new InteractionItemEffect(); @@ -41,7 +41,7 @@ public static InteractionItemEffect getInstance() { @Override public EffectResult processSideEffect( - UseBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + UseBlockPipeline pipeline, InteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var world = args.world(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java index 71d393a62fe..e0bcef3e8e8 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java @@ -29,7 +29,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; -public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { private static final class Holder { static final InteractionUseItemOnBlockEffect INSTANCE = new InteractionUseItemOnBlockEffect(); @@ -41,7 +41,7 @@ public static InteractionUseItemOnBlockEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionArgs args + UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var hand = args.hand(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java index 6c4a7d1ff09..be0e3f21018 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java @@ -29,8 +29,12 @@ @FunctionalInterface public interface ProcessingSideEffect { + interface Simple extends ProcessingSideEffect { + + } + EffectResult processSideEffect(T pipeline, C oldState, A args); - sealed interface Args permits BlockChangeArgs, InteractionArgs, UseItemArgs {} + sealed interface Args permits BlockChangeArgs, InteractionAtArgs, UseItemOnArgs, UseItemAtArgs, UseItemArgs {} } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java index aebd7497bb2..eeb1c6c3f2f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java @@ -25,17 +25,16 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.BlockHitResult; public record UseItemArgs( Level world, ServerPlayer player, InteractionHand hand, - BlockHitResult result, ItemStack copiedStack, - boolean creative + ServerPlayerGameMode gameMode ) implements ProcessingSideEffect.Args { } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java new file mode 100644 index 00000000000..ab8616303c3 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java @@ -0,0 +1,41 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; + +public record UseItemAtArgs( + Level world, + ServerPlayer player, + InteractionHand hand, + BlockHitResult result, + ItemStack copiedStack, + boolean creative +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java similarity index 68% rename from src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java rename to src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java index a0f81ef9ad0..2f7dc7ea299 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java @@ -25,28 +25,43 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.UseOnContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; -public final class PlayerContainerRefreshEffect implements ProcessingSideEffect { +public class UseItemAtEffect implements ProcessingSideEffect.Simple { private static final class Holder { - static final PlayerContainerRefreshEffect INSTANCE = new PlayerContainerRefreshEffect(); + static final UseItemAtEffect INSTANCE = new UseItemAtEffect(); } - public static PlayerContainerRefreshEffect getInstance() { - return Holder.INSTANCE; + private UseItemAtEffect() { + } + + public static UseItemAtEffect getInstance() { + return UseItemAtEffect.Holder.INSTANCE; } @Override public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + UseItemAtPipeline pipeline, InteractionResult oldState, UseItemAtArgs args ) { + final var stack = args.copiedStack(); + final InteractionResult result; + final var context = new UseOnContext(args.player(), args.hand(), args.result()); + if (args.creative()) { + int count = stack.getCount(); + result = stack.useOn(context); + stack.setCount(count); + } else { + result = stack.useOn(context); + } pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { args.player().containerMenu.broadcastChanges(); } - return EffectResult.nullPass(); + return new EffectResult<>(result, true); } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java index 130e414c734..9a102746cc4 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java @@ -25,17 +25,19 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.context.UseOnContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; -public class UseItemEffect implements ProcessingSideEffect { +public class UseItemEffect implements ProcessingSideEffect.Simple { private static final class Holder { static final UseItemEffect INSTANCE = new UseItemEffect(); } + private UseItemEffect() { + } + public static UseItemEffect getInstance() { return UseItemEffect.Holder.INSTANCE; } @@ -44,16 +46,8 @@ public static UseItemEffect getInstance() { public EffectResult processSideEffect( UseItemPipeline pipeline, InteractionResult oldState, UseItemArgs args ) { - final var stack = args.copiedStack(); - final InteractionResult result; - final var context = new UseOnContext(args.player(), args.hand(), args.result()); - if (args.creative()) { - int $$14 = stack.getCount(); - result = stack.useOn(context); - stack.setCount($$14); - } else { - result = stack.useOn(context); - } + final var gameMode = args.gameMode(); + final InteractionResult result = gameMode.useItem(args.player(), args.world(), args.copiedStack(), args.hand()); pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { args.player().containerMenu.broadcastChanges(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java new file mode 100644 index 00000000000..72029fd5deb --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; + +public record UseItemOnArgs( + UseOnContext context, + ItemStack itemStack, + ItemStackSnapshot itemStackSnapshot, + ServerPlayer player, + boolean isCreative +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java new file mode 100644 index 00000000000..ab730bdad7c --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.inventory; + +import com.google.common.collect.ImmutableList; +import org.spongepowered.api.event.Cancellable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.CompositeEvent; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.impl.AbstractCompositeEvent; +import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; +import org.spongepowered.common.event.tracking.context.transaction.type.TransactionType; + +import java.util.stream.Stream; + +public abstract class CompositeTransaction extends GameTransaction { + protected CompositeTransaction(TransactionType transactionType) { + super(transactionType); + } + + @Override + public void associateSideEffectEvents(E event, Stream elements) { + elements.forEach(event.children()::add); + } + + @Override + public void finalizeSideEffects(E post) { + // This finalizes the list to be immutable + ((AbstractCompositeEvent) post).postInit(); + } + + public void pushCause(CauseStackManager.StackFrame frame, E e) { + frame.pushCause(e.baseEvent()); + } + + @Override + public boolean markCancelledTransactions( + final E event, + final ImmutableList> gameTransactions) { + event.children().stream().filter(e -> e instanceof Cancellable) + .map(e -> (Cancellable) e) + .forEach(e -> e.setCancelled(event.isCancelled())); + return false; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java index 3302e01d076..c2a8fc0399c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java @@ -26,50 +26,46 @@ import com.google.common.collect.ImmutableList; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.item.inventory.ItemStackSnapshot; -import org.spongepowered.api.util.Direction; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; import org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.PrettyPrinter; -import org.spongepowered.math.vector.Vector3d; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.function.BiConsumer; -public class InteractItemTransaction extends GameTransaction { +public class InteractItemTransaction extends CompositeTransaction { - - private final Vector3d hitVec; - private final BlockSnapshot snapshot; - private final Direction direction; - private final InteractionHand hand; + private final ServerPlayer player; private final ItemStackSnapshot stack; - public InteractItemTransaction(ServerPlayer playerIn, ItemStack stackIn, Vector3d hitVec, BlockSnapshot snapshot, Direction direction, InteractionHand handIn) { - super(TransactionTypes.INTERACT_BLOCK_SECONDARY.get()); + public InteractItemTransaction( + final ServerPlayer playerIn, final ItemStack stackIn) { + super(TransactionTypes.INTERACT_ITEM_SECONDARY.get()); + this.player = playerIn; this.stack = ItemStackUtil.snapshotOf(stackIn); - this.hitVec = hitVec; - this.snapshot = snapshot; - this.direction = direction; - this.hand = handIn; - } + } @Override public Optional, CauseStackManager.StackFrame>> getFrameMutator( @Nullable GameTransaction<@NonNull ?> parent ) { - return Optional.empty(); + return Optional.of((context, frame) -> { + frame.pushCause(this.player); + }); } @Override @@ -78,24 +74,23 @@ public void addToPrinter(PrettyPrinter printer) { } @Override - public Optional generateEvent( + public Optional generateEvent( final PhaseContext<@NonNull ?> context, final @Nullable GameTransaction<@NonNull ?> parent, - final ImmutableList> gameTransactions, + final ImmutableList> gameTransactions, final Cause currentCause ) { - return Optional.empty(); + final var root = SpongeEventFactory.createInteractItemEventSecondary(currentCause, this.stack); + final List list = new ArrayList<>(); + final var composite = SpongeEventFactory.createInteractItemEventSecondaryPost(currentCause, root, list); + return Optional.of(composite); } - @Override - public void restore(PhaseContext<@NonNull ?> context, InteractBlockEvent.Secondary.Composite event) { - } @Override - public boolean markCancelledTransactions( - final InteractBlockEvent.Secondary.Composite event, - final ImmutableList> gameTransactions) { - return false; + public void restore(PhaseContext<@NonNull ?> context, InteractItemEvent.Secondary.Post event) { + } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java new file mode 100644 index 00000000000..d49727d6adb --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java @@ -0,0 +1,112 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.inventory; + +import com.google.common.collect.ImmutableList; +import net.minecraft.server.level.ServerPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.util.Direction; +import org.spongepowered.api.util.Tristate; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; +import org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes; +import org.spongepowered.common.util.PrettyPrinter; +import org.spongepowered.math.vector.Vector3d; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.BiConsumer; + +public class InteractItemWithBlockTransaction extends CompositeTransaction { + + private final Vector3d hitVec; + private final BlockSnapshot snapshot; + private final Direction direction; + private final ServerPlayer player; + private final Tristate originalBlockResult, blockResult, originalItemResult, itemResult; + + public InteractItemWithBlockTransaction( + final ServerPlayer playerIn, final Vector3d hitVec, final BlockSnapshot snapshot, + final Direction direction, + final Tristate originalBlockResult, final Tristate useBlockResult, + final Tristate originalUseItemResult, final Tristate useItemResult) { + super(TransactionTypes.INTERACT_BLOCK_SECONDARY.get()); + this.player = playerIn; + this.hitVec = hitVec; + this.snapshot = snapshot; + this.direction = direction; + this.originalBlockResult = originalBlockResult; + this.blockResult = useBlockResult; + this.originalItemResult = originalUseItemResult; + this.itemResult = useItemResult; + } + + + @Override + public Optional, CauseStackManager.StackFrame>> getFrameMutator( + @Nullable GameTransaction<@NonNull ?> parent + ) { + return Optional.of((context, frame) -> { + frame.pushCause(this.player); + }); + } + + @Override + public void addToPrinter(PrettyPrinter printer) { + + } + + @Override + public Optional generateEvent( + final PhaseContext<@NonNull ?> context, + final @Nullable GameTransaction<@NonNull ?> parent, + final ImmutableList> gameTransactions, + final Cause currentCause + ) { + final var root = SpongeEventFactory.createInteractBlockEventSecondary(currentCause, + this.originalBlockResult, this.blockResult, + this.originalItemResult, this.itemResult, + this.snapshot, this.hitVec, + this.direction + ); + final List list = new ArrayList<>(); + final InteractBlockEvent.Secondary.Post composite = SpongeEventFactory.createInteractBlockEventSecondaryPost(currentCause, root, list); + return Optional.of(composite); + } + + @Override + public void restore(PhaseContext<@NonNull ?> context, InteractBlockEvent.Secondary.Post event) { + + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java index 4203d6474ad..f543af72bd6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java @@ -37,7 +37,7 @@ import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; import java.util.List; @@ -51,7 +51,7 @@ public class UseBlockPipeline { private final BlockHitResult blockRaytraceResult; private final BlockState blockstate; private final ItemStack copiedStack; - private final List> effects; + private final List> effects; private final TransactionalCaptureSupplier transactor; @@ -79,7 +79,7 @@ public InteractionResult processInteraction(PhaseContext context) { var interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java new file mode 100644 index 00000000000..2f2c5f16b17 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtEffect; + +import java.util.List; +import java.util.Objects; + +public class UseItemAtPipeline { + + private final ServerLevel worldIn; + private final ServerPlayer player; + private final InteractionHand hand; + private final ItemStack copiedStack; + private final BlockHitResult blockRaytraceResult; + private final boolean creative; + private final List> effects; + private final TransactionalCaptureSupplier transactor; + + + public UseItemAtPipeline(ServerLevel worldIn, + ServerPlayer playerIn, + InteractionHand handIn, + ItemStack copiedStack, + BlockHitResult blockRaytraceResult, + boolean creative, + final TransactionalCaptureSupplier transactor) { + + this.worldIn = worldIn; + this.player = playerIn; + this.hand = handIn; + this.copiedStack = copiedStack; + this.blockRaytraceResult = blockRaytraceResult; + this.creative = creative; + this.effects = List.of( + new ResultingTransactionBySideEffect<>(UseItemAtEffect.getInstance()) + ); + this.transactor = transactor; + } + + public InteractionResult processInteraction(PhaseContext context) { + var interaction = InteractionResult.PASS; + for (final var effect : this.effects) { + try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { + final var args = new UseItemAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); + final EffectResult result = effect.effect.processSideEffect( + this, + interaction, + args + ); + if (result.hasResult) { + final @Nullable InteractionResult resultingState = result.resultingState; + interaction = Objects.requireNonNullElse(resultingState, interaction); + } + } + } + return interaction; + } + + public TransactionalCaptureSupplier transactor() { + return this.transactor; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java index 82ba980892b..c24001d5719 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java @@ -37,7 +37,7 @@ import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; import java.util.List; @@ -51,7 +51,7 @@ public final class UseItemOnBlockPipeline { private final BlockHitResult blockRaytraceResult; private final BlockState blockstate; private final ItemStack copiedStack; - private final List> effects; + private final List> effects; private final TransactionalCaptureSupplier transactor; @@ -79,7 +79,7 @@ public ItemInteractionResult processInteraction(PhaseContext context) { var interaction = ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java index ce4fbd53238..f2f315e91a7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java @@ -29,7 +29,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.BlockHitResult; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; @@ -48,26 +47,19 @@ public class UseItemPipeline { private final ServerPlayer player; private final InteractionHand hand; private final ItemStack copiedStack; - private final BlockHitResult blockRaytraceResult; - private final boolean creative; private final List> effects; private final TransactionalCaptureSupplier transactor; - public UseItemPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - ItemStack copiedStack, - BlockHitResult blockRaytraceResult, - boolean creative, - final TransactionalCaptureSupplier transactor) { + ServerPlayer playerIn, + InteractionHand handIn, + ItemStack copiedStack, + final TransactionalCaptureSupplier transactor) { this.worldIn = worldIn; this.player = playerIn; this.hand = handIn; this.copiedStack = copiedStack; - this.blockRaytraceResult = blockRaytraceResult; - this.creative = creative; this.effects = List.of( new ResultingTransactionBySideEffect<>(UseItemEffect.getInstance()) ); @@ -78,7 +70,7 @@ public InteractionResult processInteraction(PhaseContext context) { var interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final var args = new UseItemArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); + final var args = new UseItemArgs(this.worldIn, this.player, this.hand,this.copiedStack, this.player.gameMode); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java index 188b314c4a3..fcab599e3d6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java @@ -36,6 +36,7 @@ import org.spongepowered.api.event.entity.SpawnEntityEvent; import org.spongepowered.api.event.item.inventory.AffectSlotEvent; import org.spongepowered.api.event.item.inventory.ChangeInventoryEvent; +import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.event.item.inventory.container.ClickContainerEvent; import org.spongepowered.api.event.item.inventory.container.InteractContainerEvent; import org.spongepowered.api.registry.DefaultedRegistryReference; @@ -68,7 +69,8 @@ public final class TransactionTypes { public static final DefaultedRegistryReference> SLOT_CHANGE = TransactionTypes.key(ResourceKey.sponge("slot_change")); - public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); + public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); + public static final DefaultedRegistryReference> INTERACT_ITEM_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); // SORTFIELDS:OFF diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java index eb6b5a2ff83..7d7570ff6b5 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java @@ -48,7 +48,7 @@ public class SpongeCommonRegistryLoader { l.add(TransactionTypes.NEIGHBOR_NOTIFICATION, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.SCHEDULE_BLOCK_UPDATE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.SLOT_CHANGE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); - l.add(TransactionTypes.SPAWN_ENTITY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); + l.add(TransactionTypes.INTERACT_BLOCK_SECONDARY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); }); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java index ab09ccf8e03..48052fae4f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java @@ -29,6 +29,7 @@ import org.spongepowered.api.entity.ai.goal.GoalExecutor; import org.spongepowered.api.entity.ai.goal.GoalType; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -42,6 +43,8 @@ @Mixin(Goal.class) public abstract class GoalMixin implements GoalBridge { + @Shadow protected abstract int shadow$adjustedTickDelay(int $$0); + private Supplier impl$type; private GoalExecutor impl$owner; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index 6866a22f93b..fa0e5eab5b3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -49,12 +49,12 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.inventory.container.MenuBridge; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.inventory.custom.SpongeInventoryMenu; import org.spongepowered.common.item.util.ItemStackUtil; @@ -122,12 +122,10 @@ public class ServerGamePacketListenerImplMixin_Inventory { final Level param1, final ItemStack param2, final InteractionHand param3) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(this.player, PlayerInventoryTransaction.EventCreator.STANDARD)) { - final InteractionResult result = serverPlayerGameMode.useItem(param0, param1, param2, param3); - this.player.inventoryMenu.broadcastChanges(); // capture - return result; + try (final EffectTransactor ignored = transactor.logSecondaryInteractItemTransaction(param0, param2)) { + final var pipeline = ((TrackedWorldBridge) param1).bridge$startItemInteractionUseChange(param1, param0, param3, param2); + return pipeline.processInteraction(context); } - // TrackingUtil.processBlockCaptures called by UseItemPacketState } @Redirect(method = "handleContainerClose", diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 31844e0afc9..ece610b5871 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -109,6 +109,7 @@ import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; @@ -131,15 +132,15 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @Redirect( - // This normally would target this.entityTickList.forEach((var2x) -> - // but we don't have lambda syntax support yet. - method = "lambda$tick$2", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;guardEntityTick(Ljava/util/function/Consumer;Lnet/minecraft/world/entity/Entity;)V") + // This normally would target this.entityTickList.forEach((var2x) -> + // but we don't have lambda syntax support yet. + method = "lambda$tick$2", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;guardEntityTick(Ljava/util/function/Consumer;Lnet/minecraft/world/entity/Entity;)V") ) private void tracker$wrapNormalEntityTick(final ServerLevel level, final Consumer entityUpdateConsumer, - final Entity entity + final Entity entity ) { final PhaseContext<@NonNull ?> currentState = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); TrackingUtil.tickEntity(entityUpdateConsumer, entity); @@ -158,9 +159,9 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem * or we wrap in this method here. * * @param blockState The block state being ticked - * @param worldIn The world (this world) - * @param posIn The position of the block - * @param randomIn The world random + * @param worldIn The world (this world) + * @param posIn The position of the block + * @param randomIn The world random * @author gabizou - January 11th, 2020 - Minecraft 1.14.3 */ @Redirect(method = "tickBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V", @@ -453,11 +454,11 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final ChunkPipeline chunkPipeline = mixinChunk.bridge$createChunkPipeline(pos, newState, currentState, spongeFlag, limit); final WorldPipeline.Builder worldPipelineBuilder = WorldPipeline.builder(chunkPipeline); worldPipelineBuilder.addEffect((pipeline, oldState, args) -> { - if (oldState == null) { - return EffectResult.nullReturn(); - } - return EffectResult.nullPass(); - }) + if (oldState == null) { + return EffectResult.nullReturn(); + } + return EffectResult.nullPass(); + }) .addEffect(UpdateLightSideEffect.getInstance()) .addEffect(CheckBlockPostPlacementIsSameEffect.getInstance()) .addEffect(UpdateWorldRendererEffect.getInstance()) @@ -547,7 +548,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public SpongeBlockSnapshot bridge$createSnapshot(final net.minecraft.world.level.block.state.BlockState state, final BlockPos pos, - final BlockChangeFlag updateFlag + final BlockChangeFlag updateFlag ) { final SpongeBlockSnapshot.BuilderImpl builder = SpongeBlockSnapshot.BuilderImpl.pooled(); builder.reset(); @@ -595,7 +596,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - final var pipeline = new UseItemOnBlockPipeline( + return new UseItemOnBlockPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -604,9 +605,9 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable copiedStack, instance.getPhaseContext().getTransactor() ); - return pipeline; } + @Override public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer @@ -620,7 +621,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - final var pipeline = new UseBlockPipeline( + return new UseBlockPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -629,10 +630,9 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable copiedStack, instance.getPhaseContext().getTransactor() ); - return pipeline; } @Override - public UseItemPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer return null; } @@ -644,7 +644,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - return new UseItemPipeline( + return new UseItemAtPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -655,6 +655,27 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable ); } + public UseItemPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { + if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + return null; + } + if (this.bridge$isFake()) { + return null; + } + + final var instance = PhaseTracker.getInstance(); + if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); + } + return new UseItemPipeline( + (ServerLevel) worldIn, + playerIn, + handIn, + copiedStack, + instance.getPhaseContext().getTransactor() + ); + } + /** * Technically an overwrite, but because this is simply an override, we can * effectively do as we need to, which is determine if we are performing @@ -699,7 +720,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(RemoveTileEntityFromChunkEffect.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } super.shadow$removeBlockEntity(immutable); @@ -731,7 +752,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(SetAndRegisterBlockEntityToLevelChunk.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index b06c7ac4d21..15b021aee54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -41,7 +41,6 @@ import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.util.Tristate; import org.spongepowered.api.world.server.ServerLocation; @@ -80,7 +79,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { public void impl$callInteractItemSecondary(final ServerPlayer player, final Level level, final ItemStack stack, final InteractionHand hand, final CallbackInfoReturnable cir ) { - final InteractItemEvent.Secondary event = SpongeCommonEventFactory.callInteractItemEventSecondary(player, stack, hand); + final InteractItemEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractItemEventSecondary(player, stack, hand); if (event.isCancelled()) { player.inventoryMenu.sendAllDataToRemote(); cir.setReturnValue(InteractionResult.FAIL); @@ -98,12 +97,16 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl // Sponge start final BlockSnapshot snapshot = ((ServerWorld) (worldIn)).createSnapshot(VecHelper.toVector3i(blockpos)); final Vector3d hitVec = Vector3d.from(blockRaytraceResultIn.getBlockPos().getX(), blockRaytraceResultIn.getBlockPos().getY(), blockRaytraceResultIn.getBlockPos().getZ()); - final org.spongepowered.api.util.Direction direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get(); + final var direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get(); final PhaseContext phaseContext = PhaseTracker.getInstance().getPhaseContext(); - phaseContext.getTransactor().logSecondaryInteractionTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); - final InteractBlockEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final var event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); final Tristate useItem = event.useItemResult(); final Tristate useBlock = event.useBlockResult(); + phaseContext.getTransactor().logSecondaryInteractionTransaction(playerIn, + hitVec, + snapshot, + direction, + event); ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(event.isCancelled()); if (event.isCancelled()) { player.inventoryMenu.sendAllDataToRemote(); diff --git a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java index 9d9743c1ce3..1f70e0e6626 100644 --- a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java @@ -208,7 +208,7 @@ public ProjectileTestListener() { } @Listener - private void onClickBlock(final InteractBlockEvent.Secondary event, @First final ServerPlayer player) { + private void onClickBlock(final InteractBlockEvent.Secondary.Pre event, @First final ServerPlayer player) { final Vector3d interactionPoint = event.interactionPoint(); final ServerWorld world = player.world(); final EntityType nextType = this.projectileTypes.poll(); diff --git a/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java b/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java index 1de067274ed..67e0a85ccb0 100644 --- a/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java @@ -407,7 +407,7 @@ private void onInteract(final InteractBlockEvent.Primary event, @Root final Play } @Listener - public void onInteract(final InteractBlockEvent.Secondary event, @Root final Player player) { + public void onInteract(final InteractBlockEvent.Secondary.Pre event, @Root final Player player) { event.context().get(EventContextKeys.USED_ITEM).ifPresent(snapshot -> { final BlockSnapshot block = event.block(); if (snapshot.type().equals(ItemTypes.WOODEN_AXE.get()) && block != BlockSnapshot.empty()) { From d83145f496b2c860a4ba247ed1f8ed1aaff20a4d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 29 Sep 2024 20:46:39 -0700 Subject: [PATCH 168/586] wip: update to the new event generator --- gradle/verification-metadata.xml | 15 +++++++++++++++ .../inventory/CompositeTransaction.java | 5 ++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c84a8ad3482..234e29b5b32 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -20,6 +20,8 @@ + + @@ -702,6 +704,11 @@ + + + + + @@ -722,6 +729,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java index ab730bdad7c..c72a64f677d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java @@ -59,9 +59,8 @@ public void pushCause(CauseStackManager.StackFrame frame, E e) { public boolean markCancelledTransactions( final E event, final ImmutableList> gameTransactions) { - event.children().stream().filter(e -> e instanceof Cancellable) - .map(e -> (Cancellable) e) - .forEach(e -> e.setCancelled(event.isCancelled())); + event.setCancelled(true); + gameTransactions.forEach(GameTransaction::markCancelled); return false; } From 5e670a96cb035a979049494a7cf0a7805bf3e77e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 5 Jan 2025 00:43:30 -0800 Subject: [PATCH 169/586] feat: update to event-impl-gen 8 release --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 61 ++++++++++++++++-- .../data/provider/block/state/BlockData.java | 2 +- .../InteractionUseItemOnBlockEffect.java | 10 +-- .../inventory/CompositeTransaction.java | 4 +- .../pipeline/UseBlockPipeline.java | 2 +- .../pipeline/UseItemAtPipeline.java | 2 +- .../pipeline/UseItemOnBlockPipeline.java | 12 ++-- .../transaction/pipeline/UseItemPipeline.java | 2 +- .../transaction/type/TransactionTypes.java | 1 + .../loader/SpongeCommonRegistryLoader.java | 1 + .../level/ServerLevelMixin_Tracker.java | 64 ++++++++----------- .../ServerPlayerGameModeMixin_Tracker.java | 6 +- 13 files changed, 104 insertions(+), 65 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 1645168a747..a9b2770ff0a 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 1645168a747b4316aa298331a1d35965301ca79f +Subproject commit a9b2770ff0a2a7e023334a3ca271c1771c1d1357 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 234e29b5b32..68e8994380f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -20,8 +20,6 @@ - - @@ -704,11 +702,6 @@ - - - - - @@ -737,6 +730,14 @@ + + + + + + + + @@ -1564,6 +1565,14 @@ + + + + + + + + @@ -2363,6 +2372,14 @@ + + + + + + + + @@ -5875,6 +5892,9 @@ + + + @@ -5944,6 +5964,9 @@ + + + @@ -6601,6 +6624,14 @@ + + + + + + + + @@ -7913,6 +7944,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java index 9d7066fdf5a..d173833d882 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java @@ -54,7 +54,7 @@ private BlockData() { } // @formatter:off - public static void register(final DataProviderRegistrator registrator) { + @SuppressWarnings("deprecation") public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(Block.class) .create(Keys.BLAST_RESISTANCE) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java index e0bcef3e8e8..0400b726f92 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java @@ -24,12 +24,12 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; -public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { private static final class Holder { static final InteractionUseItemOnBlockEffect INSTANCE = new InteractionUseItemOnBlockEffect(); @@ -40,15 +40,15 @@ public static InteractionUseItemOnBlockEffect getInstance() { } @Override - public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionAtArgs args + public EffectResult processSideEffect( + UseItemOnBlockPipeline pipeline, InteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var hand = args.hand(); final var world = args.world(); final var blockRaytraceResult = args.blockRaytraceResult(); final var blockstate = args.blockstate(); - final ItemInteractionResult result = blockstate.useItemOn(args.copiedStack(), world, player, hand, blockRaytraceResult); + final InteractionResult result = blockstate.useItemOn(args.copiedStack(), world, player, hand, blockRaytraceResult); pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { args.player().containerMenu.broadcastChanges(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java index c72a64f677d..6bb8c06583c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java @@ -35,8 +35,8 @@ import java.util.stream.Stream; -public abstract class CompositeTransaction extends GameTransaction { - protected CompositeTransaction(TransactionType transactionType) { +public abstract class CompositeTransaction> extends GameTransaction { + protected CompositeTransaction(TransactionType transactionType) { super(transactionType); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java index f543af72bd6..ac84e89cf0b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java @@ -76,7 +76,7 @@ public UseBlockPipeline(ServerLevel worldIn, } public InteractionResult processInteraction(PhaseContext context) { - var interaction = InteractionResult.PASS; + InteractionResult interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java index 2f2c5f16b17..a9606f31c03 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java @@ -75,7 +75,7 @@ public UseItemAtPipeline(ServerLevel worldIn, } public InteractionResult processInteraction(PhaseContext context) { - var interaction = InteractionResult.PASS; + InteractionResult interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { final var args = new UseItemAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java index c24001d5719..c48d9e1865e 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java @@ -27,7 +27,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -51,7 +51,7 @@ public final class UseItemOnBlockPipeline { private final BlockHitResult blockRaytraceResult; private final BlockState blockstate; private final ItemStack copiedStack; - private final List> effects; + private final List> effects; private final TransactionalCaptureSupplier transactor; @@ -75,18 +75,18 @@ public UseItemOnBlockPipeline(ServerLevel worldIn, this.transactor = transactor; } - public ItemInteractionResult processInteraction(PhaseContext context) { - var interaction = ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + public InteractionResult processInteraction(PhaseContext context) { + InteractionResult interaction = InteractionResult.TRY_WITH_EMPTY_HAND; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); - final EffectResult result = effect.effect.processSideEffect( + final EffectResult result = effect.effect.processSideEffect( this, interaction, args ); if (result.hasResult) { - final @Nullable ItemInteractionResult resultingState = result.resultingState; + final @Nullable InteractionResult resultingState = result.resultingState; interaction = Objects.requireNonNullElse(resultingState, interaction); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java index f2f315e91a7..67e57baa368 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java @@ -67,7 +67,7 @@ public UseItemPipeline(ServerLevel worldIn, } public InteractionResult processInteraction(PhaseContext context) { - var interaction = InteractionResult.PASS; + InteractionResult interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { final var args = new UseItemArgs(this.worldIn, this.player, this.hand,this.copiedStack, this.player.gameMode); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java index fcab599e3d6..8569612f2dc 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java @@ -71,6 +71,7 @@ public final class TransactionTypes { public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); public static final DefaultedRegistryReference> INTERACT_ITEM_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); + public static final DefaultedRegistryReference> SPAWN_ENTITY = TransactionTypes.key(ResourceKey.sponge("spawn_entity")); // SORTFIELDS:OFF diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java index 7d7570ff6b5..475053f0f5a 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java @@ -49,6 +49,7 @@ public class SpongeCommonRegistryLoader { l.add(TransactionTypes.SCHEDULE_BLOCK_UPDATE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.SLOT_CHANGE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.INTERACT_BLOCK_SECONDARY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); + l.add(TransactionTypes.SPAWN_ENTITY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); }); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index ece610b5871..5abcff4bb6e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -32,6 +32,7 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; @@ -66,6 +67,7 @@ import org.spongepowered.api.world.LocatableBlock; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -406,6 +408,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem this.tracker$apiExplosion = null; } + @Unique private void tracker$cancelExplosionEffects(final Entity entity) { // TODO cancel effects if (entity instanceof ExplosiveBridge explosiveBridge) { @@ -440,6 +443,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem return Optional.of(this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); } + @Unique private WorldPipeline.Builder bridge$makePipeline( final BlockPos pos, final BlockState currentState, @@ -516,13 +520,10 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable return false; } else { // Sponge Start - Sanity check against the PhaseTracker for instances - if (this.bridge$isFake()) { + final var instance = this.tracker$validateServerThread(); + if (instance == null) { return super.destroyBlock(pos, doDrops, p_241212_3_, limit); } - final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); - if (!instance.onSidedThread()) { - throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); - } final FluidState fluidstate = this.shadow$getFluidState(pos); final BlockState emptyBlock = fluidstate.createLegacyBlock(); final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(3); @@ -585,17 +586,10 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public UseItemOnBlockPipeline bridge$startInteractionUseOnChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { - if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer - return null; - } - if (this.bridge$isFake()) { + final var instance = this.tracker$validateServerThread(); + if (instance == null) { return null; } - - final var instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { - throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); - } return new UseItemOnBlockPipeline( (ServerLevel) worldIn, playerIn, @@ -610,17 +604,10 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { - if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + final var instance = this.tracker$validateServerThread(); + if (instance == null) { return null; } - if (this.bridge$isFake()) { - return null; - } - - final var instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { - throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); - } return new UseBlockPipeline( (ServerLevel) worldIn, playerIn, @@ -631,19 +618,28 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable instance.getPhaseContext().getTransactor() ); } - @Override - public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + + @Unique + private PhaseTracker tracker$validateServerThread() { if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer return null; } if (this.bridge$isFake()) { return null; } - final var instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + if (instance.getSidedThread() != PhaseTracker.getServerInstanceExplicitly().getSidedThread() && instance != PhaseTracker.getServerInstanceExplicitly()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } + return instance; + } + + @Override + public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + final var instance = this.tracker$validateServerThread(); + if (instance == null) { + return null; + } return new UseItemAtPipeline( (ServerLevel) worldIn, playerIn, @@ -655,18 +651,12 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable ); } + @Override public UseItemPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { - if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer - return null; - } - if (this.bridge$isFake()) { + final var instance = this.tracker$validateServerThread(); + if (instance == null) { return null; } - - final var instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { - throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); - } return new UseItemPipeline( (ServerLevel) worldIn, playerIn, @@ -685,7 +675,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable *
    *
  • This world instance is managed and verified by Sponge
  • *
  • This world must {@link LevelBridge#bridge$isFake()} return {@code false}
  • - *
  • The {@link PhaseTracker#SERVER}'s {@link PhaseTracker#getSidedThread()} must be {@code ==} {@link Thread#currentThread()}
  • The {@link PhaseTracker#getServerInstanceExplicitly}'s {@link PhaseTracker#getSidedThread()} must be {@code ==} {@link Thread#currentThread()}The current {@link IPhaseState} must be allowing to record transactions with an applicable {@link org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier} *
* After which, we may be able to appropriately associate the {@link net.minecraft.world.level.block.entity.BlockEntity} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 15b021aee54..523170ece67 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -150,8 +150,8 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl if (itemInteract instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); - final InteractionResult result2 = interaction.processInteraction(phaseContext); - if (result2.consumesAction()) { + final var result = interaction.processInteraction(phaseContext); + if (result.consumesAction()) { // Sponge Start if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); @@ -168,7 +168,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl // Sponge End CriteriaTriggers.DEFAULT_BLOCK_USE.trigger(playerIn, blockpos); - return result2; + return result; } } From 6fd4332158b05960518808c2f5e462bf50b0c989 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Jan 2025 10:08:04 -0800 Subject: [PATCH 170/586] chore: when updating chunk section status, use callback This was added somewhere between 1.21.2 and 1.21.3, a missed update during snapshots. Being that this callback is only used for Clients, this has no real effect on the server code where transactions are being executed. --- .../effect/UpdateChunkLightManagerEffect.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java index 4cedc0c5810..29b1c9a2a6d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; +import net.minecraft.core.SectionPos; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; @@ -35,6 +36,7 @@ public final class UpdateChunkLightManagerEffect implements ProcessingSideEffect private static final class Holder { static final UpdateChunkLightManagerEffect INSTANCE = new UpdateChunkLightManagerEffect(); } + private UpdateChunkLightManagerEffect() { } @@ -43,15 +45,32 @@ public static UpdateChunkLightManagerEffect getInstance() { } @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, - final SpongeBlockChangeFlag flag, - final int limit + public EffectResult processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, + final SpongeBlockChangeFlag flag, final int limit ) { + /* + Continuing from LevelChunk.setBlockState + + boolean $$11 = $$4.hasOnlyAir(); + if ($$5 != $$11) { + this.level.getChunkSource().getLightEngine().updateSectionStatus($$0, $$11); + this.level.getChunkSource().onSectionEmptinessChanged(this.chunkPos.x, SectionPos.blockToSectionCoord($$3), this.chunkPos.z, $$11); + } + + */ + final var chunk = pipeline.getAffectedChunk(); + final var blockY = oldState.pos().getY(); final LevelChunkSection chunkSection = pipeline.getAffectedSection(); final boolean wasEmpty = pipeline.wasEmpty(); final boolean isStillEmpty = chunkSection.hasOnlyAir(); if (wasEmpty != isStillEmpty) { - pipeline.getServerWorld().getChunkSource().getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); + final var source = pipeline.getServerWorld().getChunkSource(); + source.getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); + final var sectionPos = SectionPos.blockToSectionCoord(blockY); + final var chunkX = chunk.getPos().x; + final var chunkZ = chunk.getPos().z; + source.onSectionEmptinessChanged(chunkX, sectionPos, chunkZ, isStillEmpty); } return EffectResult.NULL_PASS; } From 9f3fa2ae3cd7aff804e9b9214ee3ce0a1ea9925b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Jan 2025 10:40:21 -0800 Subject: [PATCH 171/586] fix: composite transactions respect event cancellation --- .../bridge/world/TrackedWorldBridge.java | 45 +++----- .../effect/InteractionItemEffect.java | 6 +- .../InteractionUseItemOnBlockEffect.java | 6 +- .../transaction/effect/UseItemAtEffect.java | 6 +- .../transaction/effect/UseItemEffect.java | 6 +- .../inventory/CompositeTransaction.java | 8 +- .../pipeline/InteractionPipeline.java | 32 ++++++ .../pipeline/UseBlockPipeline.java | 101 ------------------ .../pipeline/UseItemAtPipeline.java | 100 ----------------- .../pipeline/UseItemOnBlockPipeline.java | 100 ----------------- .../transaction/pipeline/UseItemPipeline.java | 92 ---------------- .../level/ServerLevelMixin_Tracker.java | 79 +++++++------- .../ServerPlayerGameModeMixin_Tracker.java | 15 ++- 13 files changed, 112 insertions(+), 484 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index 91d1e7d860a..049e851f266 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -28,15 +28,13 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.common.block.SpongeBlockSnapshot; @@ -44,10 +42,10 @@ import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import java.util.Optional; @@ -59,16 +57,14 @@ */ public interface TrackedWorldBridge { - boolean bridge$forceSpawnEntity(Entity entity); - Optional bridge$startBlockChange(BlockPos pos, BlockState state, int rawFlags); /** * Delegates to the {@link ServerLevel} to perform the lookup for a {@link LevelChunk} * such that if the target {@link BlockPos} results in a {@code false} for - * {@link ServerLevel#isBlockLoaded(BlockPos)}, {@link BlockSnapshot#empty()} + * {@link ServerLevel#isLoaded(BlockPos)}, {@link BlockSnapshot#empty()} * will be returned. Likewise, optimizes the creation of the snapshot by performing - * the {@link LevelChunk#getBlockState(BlockPos)} and {@link LevelChunk#getTileEntity(BlockPos, Chunk.CreateEntityType)} + * the {@link LevelChunk#getBlockState(BlockPos)} and {@link LevelChunk#getBlockEntity(BlockPos, LevelChunk.EntityCreationType)} * lookup on the same chunk, avoiding an additional chunk lookup. * *

This should be used when the "known" {@link BlockState} for the target @@ -83,17 +79,13 @@ public interface TrackedWorldBridge { } /** - * Creates a {@link BlockSnapshot} but performs an additional {@link LevelChunk#getTileEntity(BlockPos, Chunk.CreateEntityType)} + * Creates a {@link BlockSnapshot} but performs an additional {@link LevelChunk#getBlockEntity(BlockPos, LevelChunk.EntityCreationType)} * lookup if the providing {@link BlockState#getBlock()} {@code instanceof} is * {@code true} for being an {@link EntityBlock} or * {@link BlockStateBridge#bridge$hasTileEntity()}, and associates * the resulting snapshot of said Tile with the snapshot. This is useful for in-progress * snapshot creation during transaction building for {@link TransactionalCaptureSupplier}. * - *

If the {@link BlockEntity} is already known, and no lookups are needed, use - * {@link #bridge$createSnapshotWithEntity(BlockState, BlockPos, BlockChangeFlag, BlockEntity)} as it avoids - * any further chunk lookups.

- * * @param state The block state * @param pos The target position * @param updateFlag The update flag @@ -101,24 +93,11 @@ public interface TrackedWorldBridge { */ SpongeBlockSnapshot bridge$createSnapshot(BlockState state, BlockPos pos, BlockChangeFlag updateFlag); - /** - * Similar to {@link #bridge$createSnapshot(BlockState, BlockPos, BlockChangeFlag)}, - * but with the added avoidance of a {@link BlockEntity} lookup during the creation of the resulting - * {@link SpongeBlockSnapshot}. - * - * @param state The state - * @param pos The position - * @param updateFlag The update flag - * @param tileEntity The tile entity to serialize, if available - * @return The snapshot, never NONE - */ - SpongeBlockSnapshot bridge$createSnapshotWithEntity(BlockState state, BlockPos pos, BlockChangeFlag updateFlag, @Nullable BlockEntity tileEntity); - - UseItemOnBlockPipeline bridge$startInteractionUseOnChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionUseOnChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseBlockPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseItemAtPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + InteractionPipeline<@NonNull UseItemAtArgs> bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); - UseItemPipeline bridge$startItemInteractionUseChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack); + InteractionPipeline<@NonNull UseItemArgs> bridge$startItemInteractionUseChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java index 57af8e795a9..59a90650401 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public final class InteractionItemEffect implements ProcessingSideEffect.Simple { +public final class InteractionItemEffect implements ProcessingSideEffect.Simple, InteractionAtArgs, InteractionResult> { private static final class Holder { static final InteractionItemEffect INSTANCE = new InteractionItemEffect(); @@ -41,7 +41,7 @@ public static InteractionItemEffect getInstance() { @Override public EffectResult processSideEffect( - UseBlockPipeline pipeline, InteractionResult oldState, InteractionAtArgs args + InteractionPipeline pipeline, InteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var world = args.world(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java index 0400b726f92..c6180c95510 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect, InteractionResult, InteractionAtArgs, InteractionResult> { private static final class Holder { static final InteractionUseItemOnBlockEffect INSTANCE = new InteractionUseItemOnBlockEffect(); @@ -41,7 +41,7 @@ public static InteractionUseItemOnBlockEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, InteractionResult oldState, InteractionAtArgs args + InteractionPipeline pipeline, InteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var hand = args.hand(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java index 2f7dc7ea299..5f1f031232f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java @@ -28,9 +28,9 @@ import net.minecraft.world.item.context.UseOnContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public class UseItemAtEffect implements ProcessingSideEffect.Simple { +public class UseItemAtEffect implements ProcessingSideEffect.Simple, UseItemAtArgs, InteractionResult> { private static final class Holder { static final UseItemAtEffect INSTANCE = new UseItemAtEffect(); @@ -45,7 +45,7 @@ public static UseItemAtEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemAtPipeline pipeline, InteractionResult oldState, UseItemAtArgs args + InteractionPipeline pipeline, InteractionResult oldState, UseItemAtArgs args ) { final var stack = args.copiedStack(); final InteractionResult result; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java index 9a102746cc4..05062274d74 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public class UseItemEffect implements ProcessingSideEffect.Simple { +public class UseItemEffect implements ProcessingSideEffect.Simple, UseItemArgs, InteractionResult> { private static final class Holder { static final UseItemEffect INSTANCE = new UseItemEffect(); @@ -44,7 +44,7 @@ public static UseItemEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemPipeline pipeline, InteractionResult oldState, UseItemArgs args + InteractionPipeline pipeline, InteractionResult oldState, UseItemArgs args ) { final var gameMode = args.gameMode(); final InteractionResult result = gameMode.useItem(args.player(), args.world(), args.copiedStack(), args.hand()); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java index 6bb8c06583c..6b7fe2aa6d0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java @@ -25,7 +25,6 @@ package org.spongepowered.common.event.tracking.context.transaction.inventory; import com.google.common.collect.ImmutableList; -import org.spongepowered.api.event.Cancellable; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.CompositeEvent; import org.spongepowered.api.event.Event; @@ -48,7 +47,7 @@ public void associateSideEffectEvents(E event, Stream elements) { @Override public void finalizeSideEffects(E post) { // This finalizes the list to be immutable - ((AbstractCompositeEvent) post).postInit(); + ((AbstractCompositeEvent) post).postInit(); } public void pushCause(CauseStackManager.StackFrame frame, E e) { @@ -59,9 +58,12 @@ public void pushCause(CauseStackManager.StackFrame frame, E e) { public boolean markCancelledTransactions( final E event, final ImmutableList> gameTransactions) { + if (!event.isCancelled()) { + return false; + } event.setCancelled(true); gameTransactions.forEach(GameTransaction::markCancelled); - return false; + return true; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java new file mode 100644 index 00000000000..cf25fc06e20 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java @@ -0,0 +1,32 @@ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.world.InteractionResult; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; + +import java.util.Objects; + +public record InteractionPipeline<@NonNull A extends ProcessingSideEffect.Args>( + A args, + InteractionResult defaultResult, + ProcessingSideEffect, InteractionResult, A, InteractionResult> effect, + TransactionalCaptureSupplier transactor +) { + + public InteractionResult processInteraction(final PhaseContext context) { + var result = this.defaultResult; + final ResultingTransactionBySideEffect, InteractionResult, A, InteractionResult> resultingEffect = new ResultingTransactionBySideEffect<>(this.effect); + try (final var ignored = context.getTransactor().pushEffect(resultingEffect)) { + final var effectResult = this.effect.processSideEffect(this, result, this.args); + if (effectResult.hasResult) { + final @Nullable InteractionResult resultingState = effectResult.resultingState; + result = Objects.requireNonNullElse(resultingState, result); + } + } + return result; + } +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java deleted file mode 100644 index ac84e89cf0b..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.context.transaction.pipeline; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; -import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; - -import java.util.List; -import java.util.Objects; - -public class UseBlockPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final BlockHitResult blockRaytraceResult; - private final BlockState blockstate; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - - public UseBlockPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - BlockHitResult blockRaytraceResultIn, - BlockState blockstate, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.blockRaytraceResult = blockRaytraceResultIn; - this.blockstate = blockstate; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(InteractionItemEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.PASS; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); - final EffectResult result = effect.effect.processSideEffect( - this, - interaction, - args - ); - if (result.hasResult) { - final @Nullable InteractionResult resultingState = result.resultingState; - interaction = Objects.requireNonNullElse(resultingState, interaction); - } - } - } - return interaction; - } - - public TransactionalCaptureSupplier transactor() { - return this.transactor; - } - -} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java deleted file mode 100644 index a9606f31c03..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.context.transaction.pipeline; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; -import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtEffect; - -import java.util.List; -import java.util.Objects; - -public class UseItemAtPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final ItemStack copiedStack; - private final BlockHitResult blockRaytraceResult; - private final boolean creative; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - - public UseItemAtPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - ItemStack copiedStack, - BlockHitResult blockRaytraceResult, - boolean creative, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.copiedStack = copiedStack; - this.blockRaytraceResult = blockRaytraceResult; - this.creative = creative; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(UseItemAtEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.PASS; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final var args = new UseItemAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); - final EffectResult result = effect.effect.processSideEffect( - this, - interaction, - args - ); - if (result.hasResult) { - final @Nullable InteractionResult resultingState = result.resultingState; - interaction = Objects.requireNonNullElse(resultingState, interaction); - } - } - } - return interaction; - } - - public TransactionalCaptureSupplier transactor() { - return this.transactor; - } - -} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java deleted file mode 100644 index c48d9e1865e..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.context.transaction.pipeline; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; -import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; - -import java.util.List; -import java.util.Objects; - -public final class UseItemOnBlockPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final BlockHitResult blockRaytraceResult; - private final BlockState blockstate; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - - public UseItemOnBlockPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - BlockHitResult blockRaytraceResultIn, - BlockState blockstate, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.blockRaytraceResult = blockRaytraceResultIn; - this.blockstate = blockstate; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(InteractionUseItemOnBlockEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.TRY_WITH_EMPTY_HAND; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); - final EffectResult result = effect.effect.processSideEffect( - this, - interaction, - args - ); - if (result.hasResult) { - final @Nullable InteractionResult resultingState = result.resultingState; - interaction = Objects.requireNonNullElse(resultingState, interaction); - } - } - } - return interaction; - } - - public TransactionalCaptureSupplier transactor() { - return this.transactor; - } -} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java deleted file mode 100644 index 67e57baa368..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.context.transaction.pipeline; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ItemStack; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; -import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemEffect; - -import java.util.List; -import java.util.Objects; - -public class UseItemPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - public UseItemPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(UseItemEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.PASS; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final var args = new UseItemArgs(this.worldIn, this.player, this.hand,this.copiedStack, this.player.gameMode); - final EffectResult result = effect.effect.processSideEffect( - this, - interaction, - args - ); - if (result.hasResult) { - final @Nullable InteractionResult resultingState = result.resultingState; - interaction = Objects.requireNonNullElse(resultingState, interaction); - } - } - } - return interaction; - } - - public TransactionalCaptureSupplier transactor() { - return this.transactor; - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 5abcff4bb6e..37ffb643799 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -37,6 +37,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; @@ -97,6 +98,9 @@ import org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity; import org.spongepowered.common.event.tracking.context.transaction.effect.CheckBlockPostPlacementIsSameEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.NotifyClientEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.NotifyNeighborSideEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.PerformBlockDropsFromDestruction; @@ -105,15 +109,16 @@ import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateConnectingBlocksEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateLightSideEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateWorldRendererEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.WorldBlockChangeCompleteEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.WorldDestroyBlockLevelEffect; import org.spongepowered.common.event.tracking.context.transaction.pipeline.ChunkPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; import org.spongepowered.common.event.tracking.phase.tick.TickPhase; @@ -585,36 +590,38 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public UseItemOnBlockPipeline bridge$startInteractionUseOnChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + public InteractionPipeline bridge$startInteractionUseOnChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemOnBlockPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - blockRaytraceResultIn, - blockstate, - copiedStack, + final var args = new InteractionAtArgs(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + return new InteractionPipeline<>( + args, + InteractionResult.TRY_WITH_EMPTY_HAND, + InteractionUseItemOnBlockEffect.getInstance(), instance.getPhaseContext().getTransactor() - ); + ); } @Override - public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + public InteractionPipeline bridge$startInteractionChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseBlockPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - blockRaytraceResultIn, - blockstate, - copiedStack, + final var args = new InteractionAtArgs(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + return new InteractionPipeline( + args, + InteractionResult.PASS, + InteractionItemEffect.getInstance(), instance.getPhaseContext().getTransactor() ); } @@ -627,7 +634,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return null; } - final var instance = PhaseTracker.getInstance(); + final var instance = PhaseTracker.getWorldInstance(this); if (instance.getSidedThread() != PhaseTracker.getServerInstanceExplicitly().getSidedThread() && instance != PhaseTracker.getServerInstanceExplicitly()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } @@ -635,35 +642,31 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + public InteractionPipeline bridge$startItemInteractionChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemAtPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - copiedStack, - blockRaytraceResult, - creative, + final var args = new UseItemAtArgs(worldIn, playerIn,handIn, blockRaytraceResult, copiedStack, creative); + return new InteractionPipeline<>( + args, + InteractionResult.PASS, + UseItemAtEffect.getInstance(), instance.getPhaseContext().getTransactor() ); } @Override - public UseItemPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { + public InteractionPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - copiedStack, - instance.getPhaseContext().getTransactor() - ); + final var args = new UseItemArgs(worldIn, playerIn, handIn, copiedStack, playerIn.gameMode); + return new InteractionPipeline<>(args, InteractionResult.PASS, UseItemEffect.getInstance(), instance.getPhaseContext().getTransactor()); } /** diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 523170ece67..831a595eb4f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -68,7 +68,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { @Shadow @Final protected ServerPlayer player; - @Shadow protected net.minecraft.server.level.ServerLevel level; + @Shadow protected ServerLevel level; @Shadow private GameType gameModeForPlayer; @Shadow public abstract boolean shadow$isCreative(); @@ -119,6 +119,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); if (inamedcontainerprovider != null) { playerIn.openMenu(inamedcontainerprovider); + // Sponge start - throw open container event final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); try (final CauseStackManager.StackFrame blockHit = PhaseTracker.getCauseStackManager().pushCauseFrame()) { @@ -129,7 +130,8 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return InteractionResult.SUCCESS; } } - return InteractionResult.SUCCESS; + // Sponge end + return InteractionResult.CONSUME; } else { return InteractionResult.PASS; } @@ -148,11 +150,13 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return itemInteract; } if (itemInteract instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { + // Sponge Start - use interaction pipeline final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); final var result = interaction.processInteraction(phaseContext); + // Sponge end if (result.consumesAction()) { - // Sponge Start + // Sponge Start - verify opened container is not changed, otherwise throw an event if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); @@ -170,18 +174,19 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl CriteriaTriggers.DEFAULT_BLOCK_USE.trigger(playerIn, blockpos); return result; } - } } if (!stackIn.isEmpty() && !playerIn.getCooldowns().isOnCooldown(stackIn)) { - // Sponge start + // Sponge start - verify event derived tristate if (useItem == Tristate.FALSE) { ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(true); return InteractionResult.PASS; } + // Sponge - run interaction through final var interaction = ((TrackedWorldBridge) level).bridge$startItemInteractionChange(worldIn, playerIn, handIn, copiedStack, blockRaytraceResultIn, this.shadow$isCreative()); final var result = interaction.processInteraction(phaseContext); + // Sponge end if (result.consumesAction()) { From 42571788b790e02bd84b56be74596a1da9c50d1f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Jan 2025 11:56:44 -0800 Subject: [PATCH 172/586] fix: use passed in itemstack for creative mode In creative, the stack is modified directly and re-adjusted to the original. We used to try and have a copied ItemStack for events, but we no longer need to keep the copied stack as it is captured at the beginning of the transaction. --- .../server/level/ServerLevelMixin_Tracker.java | 8 ++++---- .../level/ServerPlayerGameModeMixin_Tracker.java | 11 +++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 37ffb643799..56e2858fe9e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -590,7 +590,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public InteractionPipeline bridge$startInteractionUseOnChange( + public InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionUseOnChange( net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack ) { @@ -609,7 +609,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override - public InteractionPipeline bridge$startInteractionChange( + public InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionChange( net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack ) { @@ -618,7 +618,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable return null; } final var args = new InteractionAtArgs(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); - return new InteractionPipeline( + return new InteractionPipeline<>( args, InteractionResult.PASS, InteractionItemEffect.getInstance(), @@ -642,7 +642,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public InteractionPipeline bridge$startItemInteractionChange( + public InteractionPipeline<@NonNull UseItemAtArgs> bridge$startItemInteractionChange( net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 831a595eb4f..81917515756 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -138,21 +138,20 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl } final boolean flag = !playerIn.getMainHandItem().isEmpty() || !playerIn.getOffhandItem().isEmpty(); final boolean flag1 = playerIn.isSecondaryUseActive() && flag; - final ItemStack copiedStack = stackIn.copy(); if (useBlock != Tristate.FALSE && !flag1) { // Sponge check useBlock - final var useInteraction = ((TrackedWorldBridge) level).bridge$startInteractionUseOnChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + final var useInteraction = ((TrackedWorldBridge) level).bridge$startInteractionUseOnChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, stackIn); if (useInteraction == null) { return InteractionResult.FAIL; } final InteractionResult itemInteract = useInteraction.processInteraction(phaseContext); if (itemInteract.consumesAction()) { - CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack); + CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, stackIn); return itemInteract; } if (itemInteract instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { // Sponge Start - use interaction pipeline final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge - final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, stackIn); final var result = interaction.processInteraction(phaseContext); // Sponge end if (result.consumesAction()) { @@ -184,13 +183,13 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return InteractionResult.PASS; } // Sponge - run interaction through - final var interaction = ((TrackedWorldBridge) level).bridge$startItemInteractionChange(worldIn, playerIn, handIn, copiedStack, blockRaytraceResultIn, this.shadow$isCreative()); + final var interaction = ((TrackedWorldBridge) level).bridge$startItemInteractionChange(worldIn, playerIn, handIn, stackIn, blockRaytraceResultIn, this.shadow$isCreative()); final var result = interaction.processInteraction(phaseContext); // Sponge end if (result.consumesAction()) { - CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack); + CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, stackIn); } return result; From 5f7b407808961fd3895b943cd56c0743c69d0071 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 12 Jan 2025 21:42:48 +0100 Subject: [PATCH 173/586] Ship mixinextras-forge in prod --- forge/build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 5771a696f73..66ca13d9f9b 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -55,6 +55,8 @@ val gameManagedLibrariesConfig: NamedDomainObjectProvider = confi val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") +val productionExcludedLibrariesConfig: NamedDomainObjectProvider = configurations.register("productionExcludedLibraries") + // ModLauncher layers val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { extendsFrom(bootLibrariesConfig.get()) @@ -198,6 +200,12 @@ dependencies { val gameShadedLibraries = gameShadedLibrariesConfig.name gameShadedLibraries("org.spongepowered:spongeapi:$apiVersion") { isTransitive = false } + val gameManaged = gameManagedLibrariesConfig.name + gameManaged(libs.mixinextras.forge) // prod only + + val productionExcluded = productionExcludedLibrariesConfig.name + productionExcluded(libs.mixinextras.common) // dev only + afterEvaluate { spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), bootLayerConfig.get(), serviceShadedLibrariesConfig.get()) spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) @@ -309,6 +317,7 @@ tasks { group = "sponge" this.dependencies("main", gameManagedLibrariesConfig) this.excludeDependencies(gameShadedLibrariesConfig) + this.excludeDependencies(productionExcludedLibrariesConfig) outputFile.set(installerResources.map { it.file("sponge-libraries.json") }) } From ac2bbe555715e5661d374cd83456c65b7e863c20 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Jan 2025 15:00:01 -0800 Subject: [PATCH 174/586] feat: update to snapshot 25w02a A lot of small changes to note: - TicketTypes are now registered - Tickets are just dummy holders of the pending timeout - Entities referencing an "Owner" now use EntityReference for the duality of UUID + live Entity references - I've got concerns that the reference may be problematic with entity instances being recreated for various reasons. - Chat events have become records - ArmorItem has completely disappeared, so no more referencable characteristic to determine an ItemStack is an armor piece or not, short of checking the DataComponents applied - Tools have an added ability to be "destructive" in creative mode - SpawnLists for spawns are now using a WeightedList - A new block change flag being applied to prevent BlockEntities "drops" during a block change. This appears to be specific to MC-117574 - Sounds are now being played by entities, not just players, this is a signature change. --- SpongeAPI | 2 +- .../BlockStatePropertiesGenerator.java | 2 + .../BlockStatePropertyKeysGenerator.java | 2 + .../vanilla/generator/GeneratorMain.java | 8 + gradle.properties | 2 +- gradle/verification-metadata.xml | 8 + .../accessor/server/level/TicketAccessor.java | 18 +- .../world/entity/LivingEntityAccessor.java | 3 - .../world/entity/animal/FoxAccessor.java | 7 +- .../animal/horse/AbstractHorseAccessor.java} | 19 +- .../projectile/AbstractArrowAccessor.java} | 20 +- .../world/level/BaseSpawnerAccessor.java | 6 +- .../world/level/TicketStorageAccessor.java} | 36 +- .../world/level/chunk/LevelChunkAccessor.java | 6 + .../resources/mixins.sponge.accessors.json | 5 +- .../adventure/NativeComponentRenderer.java | 35 +- .../common/adventure/SpongeAdventure.java | 118 ++-- .../bridge/world/server/TicketBridge.java | 2 +- .../data/provider/block/state/BlockData.java | 1 + .../data/provider/block/state/WallData.java | 24 +- .../provider/entity/AbstractArrowData.java | 3 +- .../provider/entity/AbstractHorseData.java | 16 +- .../common/data/provider/entity/FoxData.java | 9 +- .../data/provider/entity/TameableData.java | 10 +- .../item/stack/ArmorItemStackData.java | 27 +- .../item/stack/ToolItemStackData.java | 29 +- .../data/provider/world/biome/BiomeData.java | 28 +- .../common/entity/EntityUtil.java | 15 +- .../entity/living/human/HumanEntity.java | 10 +- .../effect/NotifyNeighborSideEffect.java | 9 +- .../effect/OldBlockOnReplaceEffect.java | 65 +- .../effect/UpdateChunkLightManagerEffect.java | 14 + ...reateNewTileEntityPostPlacementEffect.java | 15 +- .../WorldBlockChangeCompleteEffect.java | 2 +- .../SpongeRandomEnchantmentListBuilder.java | 6 +- .../recipe/smithing/SpongeSmithingRecipe.java | 3 +- .../SpongeSmithingRecipeRegistration.java | 7 +- .../spongepowered/common/util/Constants.java | 7 +- .../common/util/DamageEventUtil.java | 4 +- .../common/world/SpongeBlockChangeFlag.java | 27 + .../world/biome/SpongeBiomeTemplate.java | 4 +- .../spawner/SpongeNaturalSpawnerFactory.java | 4 +- .../world/server/SpongeTicketTypeBuilder.java | 10 +- .../world/server/SpongeWorldManager.java | 19 +- .../server/level/ChunkMapMixin_API.java | 2 +- .../server/level/ServerLevelMixin_API.java | 3 +- .../server/level/TicketTypeMixin_API.java | 4 +- .../world/entity/animal/FoxMixin_API.java | 8 +- .../TrialSpawnerBlockEntityMixin_API.java | 2 +- .../StructureSpawnOverrideMixin_API.java | 7 +- .../mixin/core/nbt/CompoundTagMixin.java | 59 +- .../server/commands/TeleportCommandMixin.java | 2 +- .../server/level/DistanceManagerMixin.java | 73 +- .../core/server/level/ServerEntityMixin.java | 8 +- .../core/server/level/ServerLevelMixin.java | 17 +- .../core/server/level/ServerPlayerMixin.java | 6 +- .../mixin/core/server/level/TicketMixin.java | 7 +- .../core/server/level/TicketStorageMixin.java | 66 ++ .../ServerGamePacketListenerImplMixin.java | 5 +- .../mixin/core/world/entity/EntityMixin.java | 2 +- .../entity/LivingEntityMixin_Attack_Impl.java | 4 +- .../core/world/entity/player/PlayerMixin.java | 4 +- .../player/PlayerMixin_Attack_Impl.java | 20 +- .../core/world/item/FishingRodItemMixin.java | 21 +- .../SmithingTransformRecipeMixin.java | 5 +- .../world/level/block/NoteBlockMixin.java | 7 +- .../core/world/level/block/TntBlockMixin.java | 2 +- ...TamableAnimalMixin_Optimization_Owner.java | 25 +- .../entity/LivingEntityMixin_Tracker.java | 6 +- .../level/chunk/LevelChunkMixin_Tracker.java | 2 +- src/mixins/resources/mixins.sponge.api.json | 1 - src/mixins/resources/mixins.sponge.core.json | 627 +++++++++--------- .../vanilla/chat/ChatFormatter.java | 4 +- .../client/gui/widget/MetadataPanel.java | 6 +- .../entity/LivingEntityMixin_Attack_Impl.java | 7 +- 75 files changed, 985 insertions(+), 694 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/{server/level/TicketTypeAccessor.java => world/entity/animal/horse/AbstractHorseAccessor.java} (71%) rename src/accessors/java/org/spongepowered/common/accessor/{network/chat/HoverEvent_ItemStackInfoAccessor.java => world/entity/projectile/AbstractArrowAccessor.java} (67%) rename src/{mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/MobSpawnSettings_SpawnerDataMixin_API.java => accessors/java/org/spongepowered/common/accessor/world/level/TicketStorageAccessor.java} (59%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketStorageMixin.java diff --git a/SpongeAPI b/SpongeAPI index 05573747a54..2807da58dfa 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 05573747a54dc967d4592e1244e6bde88651afe4 +Subproject commit 2807da58dfafb891c0372b1efedec6473ffb64c0 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 202e77ae676..1c33db93fca 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -43,6 +43,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.ChestType; import net.minecraft.world.level.block.state.properties.ComparatorMode; +import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.DripstoneThickness; @@ -148,6 +149,7 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(ComparatorMode.class, BlockStatePropertiesGenerator.inDataTypePkg("ComparatorMode")); vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertiesGenerator.inDataTypePkg("TrialSpawnerState")); vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertiesGenerator.inDataTypePkg("VaultState")); + vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeartState")); // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertiesGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index d00816a08ce..cfde2f85d61 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -44,6 +44,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.ChestType; import net.minecraft.world.level.block.state.properties.ComparatorMode; +import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.DripstoneThickness; @@ -146,6 +147,7 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(ComparatorMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("ComparatorMode")); vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("TrialSpawnerState")); vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("VaultState")); + vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CreakingHeartState")); // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertyKeysGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 0ec23cbeff2..477370e700c 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -71,6 +71,7 @@ import net.minecraft.world.level.WorldDataConfiguration; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; +import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DripstoneThickness; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; @@ -372,6 +373,13 @@ private static List generators(final Context context) { "name", "sponge" ), + new EnumEntriesValidator<>( + "data.type", + "CreakingHeartStates", + CreakingHeartState.class, + "getSerializedName", + "sponge" + ), new RegistryEntriesGenerator<>( "data.type", "ArtTypes", diff --git a/gradle.properties b/gradle.properties index 80242caa6da..afcbac45aa5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.4 +minecraftVersion=25w02a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c84a8ad3482..35039e990f4 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1485,6 +1485,14 @@
+ + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketAccessor.java index 02b8f67d302..e185ca3443a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketAccessor.java @@ -25,26 +25,12 @@ package org.spongepowered.common.accessor.server.level; import net.minecraft.server.level.Ticket; -import net.minecraft.server.level.TicketType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; @Mixin(Ticket.class) -public interface TicketAccessor { +public interface TicketAccessor { - @Invoker("") - static Ticket accessor$createInstance(final TicketType ticketType, final int ticketLevel, final T key) { - throw new UntransformedInvokerError(); - } - - @Accessor("createdTick") long accessor$createdTick(); - - @Accessor("key") T accessor$key(); - - @Invoker("timedOut") boolean invoker$timedOut(long currentTimestamp); - - @Invoker("setCreatedTick") void invoker$setCreatedTick(long timestamp); + @Accessor("ticksLeft") long accessor$ticksLeft(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java index 4c6ed062320..6299d45af17 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java @@ -30,7 +30,6 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; @@ -83,8 +82,6 @@ public interface LivingEntityAccessor { @Accessor("lastHurt") void accessor$lastHurt(final float lastHurt); - @Accessor("lastHurtByMob") @Nullable LivingEntity accessor$lastHurtByMob(); - @Accessor("autoSpinAttackTicks") int accessor$autoSpinAttackTicks(); @Accessor("autoSpinAttackTicks") void accessor$autoSpinAttackTicks(final int autoSpinAttackTicks); @Accessor("autoSpinAttackDmg") float accessor$autoSpinAttackDmg(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java index ed8de32ec73..5fdf5b9ede6 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java @@ -25,6 +25,8 @@ package org.spongepowered.common.accessor.world.entity.animal; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.animal.Fox; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -32,16 +34,15 @@ import org.spongepowered.common.UntransformedAccessorError; import java.util.Optional; -import java.util.UUID; @Mixin(Fox.class) public interface FoxAccessor { - @Accessor("DATA_TRUSTED_ID_0") static EntityDataAccessor> accessor$DATA_TRUSTED_ID_0() { + @Accessor("DATA_TRUSTED_ID_0") static EntityDataAccessor>> accessor$DATA_TRUSTED_ID_0() { throw new UntransformedAccessorError(); } - @Accessor("DATA_TRUSTED_ID_1") static EntityDataAccessor> accessor$DATA_TRUSTED_ID_1() { + @Accessor("DATA_TRUSTED_ID_1") static EntityDataAccessor>> accessor$DATA_TRUSTED_ID_1() { throw new UntransformedAccessorError(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketTypeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java similarity index 71% rename from src/accessors/java/org/spongepowered/common/accessor/server/level/TicketTypeAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java index bcbe0aa9f11..db34c538344 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/TicketTypeAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java @@ -22,20 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.server.level; +package org.spongepowered.common.accessor.world.entity.animal.horse; -import net.minecraft.server.level.TicketType; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.horse.AbstractHorse; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; +import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.Comparator; +@Mixin(AbstractHorse.class) +public interface AbstractHorseAccessor { -@Mixin(TicketType.class) -public interface TicketTypeAccessor { + @Accessor("owner") void accessor$setOwner(EntityReference owner); - @Invoker("") - static TicketType accessor$createInstance(final String name, final Comparator comparator, final long lifetime) { - throw new UntransformedInvokerError(); - } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/chat/HoverEvent_ItemStackInfoAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java similarity index 67% rename from src/accessors/java/org/spongepowered/common/accessor/network/chat/HoverEvent_ItemStackInfoAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java index 14c89652187..812c3a52ca9 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/chat/HoverEvent_ItemStackInfoAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java @@ -22,21 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.network.chat; +package org.spongepowered.common.accessor.world.entity.projectile; -import net.minecraft.core.Holder; -import net.minecraft.core.component.DataComponentPatch; -import net.minecraft.network.chat.HoverEvent; -import net.minecraft.world.item.Item; +import net.minecraft.world.entity.projectile.AbstractArrow; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; +import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(HoverEvent.ItemStackInfo.class) -public interface HoverEvent_ItemStackInfoAccessor { +@Mixin(AbstractArrow.class) +public interface AbstractArrowAccessor { + + @Accessor("baseDamage") double accessor$baseDamage(); - @Invoker("") - static HoverEvent.ItemStackInfo invoker$new(final Holder item, final int count, final DataComponentPatch patch) { - throw new UntransformedInvokerError(); - } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseSpawnerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseSpawnerAccessor.java index 594ce45ca9d..2ea7c95ad05 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseSpawnerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseSpawnerAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.world.level; -import net.minecraft.util.random.SimpleWeightedRandomList; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.level.BaseSpawner; import net.minecraft.world.level.SpawnData; import org.spongepowered.asm.mixin.Mixin; @@ -37,9 +37,9 @@ public interface BaseSpawnerAccessor { @Accessor("spawnDelay") void accessor$spawnDelay(final int spawnDelay); - @Accessor("spawnPotentials") SimpleWeightedRandomList accessor$spawnPotentials(); + @Accessor("spawnPotentials") WeightedList accessor$spawnPotentials(); - @Accessor("spawnPotentials") void accessor$spawnPotentials(SimpleWeightedRandomList newData); + @Accessor("spawnPotentials") void accessor$spawnPotentials(WeightedList newData); @Accessor("nextSpawnData") SpawnData accessor$nextSpawnData(); @Accessor("nextSpawnData") void accessor$nextSpawnData(SpawnData spawnData); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/MobSpawnSettings_SpawnerDataMixin_API.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/TicketStorageAccessor.java similarity index 59% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/MobSpawnSettings_SpawnerDataMixin_API.java rename to src/accessors/java/org/spongepowered/common/accessor/world/level/TicketStorageAccessor.java index 1e0b11b06b5..41b774f440e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/MobSpawnSettings_SpawnerDataMixin_API.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/TicketStorageAccessor.java @@ -22,36 +22,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.biome; +package org.spongepowered.common.accessor.world.level; -import net.minecraft.world.level.biome.MobSpawnSettings; -import org.spongepowered.api.entity.EntityType; -import org.spongepowered.api.world.biome.spawner.NaturalSpawner; -import org.spongepowered.asm.mixin.Final; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.Ticket; +import net.minecraft.world.level.TicketStorage; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(MobSpawnSettings.SpawnerData.class) -public abstract class MobSpawnSettings_SpawnerDataMixin_API implements NaturalSpawner { +import java.util.List; - // @formatter:off - @Shadow @Final public net.minecraft.world.entity.EntityType type; - @Shadow @Final public int minCount; - @Shadow @Final public int maxCount; - // @formatter:on +@Mixin(TicketStorage.class) +public interface TicketStorageAccessor { - @Override - public EntityType type() { - return (EntityType) this.type; - } - - @Override - public int min() { - return this.minCount; - } - - @Override - public int max() { - return this.maxCount; - } + @Accessor("tickets") Long2ObjectOpenHashMap> accessor$tickets(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/LevelChunkAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/LevelChunkAccessor.java index f957f9ed1bb..e25d3bbc67a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/LevelChunkAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/LevelChunkAccessor.java @@ -27,6 +27,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; @@ -42,4 +43,9 @@ public interface LevelChunkAccessor { throw new UntransformedAccessorError(); } + @Accessor("LOGGER") + static Logger accessor$LOGGER() { + throw new UntransformedAccessorError(); + } + } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index cb03b9b7391..6a7acd2180b 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -21,7 +21,6 @@ "core.MappedRegistryAccessor", "entity.passive.AbstractChestedHorseEntityAccessor", "network.ConnectionAccessor", - "network.chat.HoverEvent_ItemStackInfoAccessor", "network.chat.StyleAccessor", "network.protocol.game.ClientboundAddEntityPacketAccessor", "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", @@ -41,7 +40,6 @@ "server.level.ServerPlayerAccessor", "server.level.ServerPlayerGameModeAccessor", "server.level.TicketAccessor", - "server.level.TicketTypeAccessor", "server.network.ServerCommonPacketListenerImplAccessor", "server.network.ServerGamePacketListenerImplAccessor", "server.network.ServerLoginPacketListenerImplAccessor", @@ -83,6 +81,7 @@ "world.entity.animal.TropicalFishAccessor", "world.entity.animal.TurtleAccessor", "world.entity.animal.WolfAccessor", + "world.entity.animal.horse.AbstractHorseAccessor", "world.entity.animal.horse.HorseAccessor", "world.entity.animal.horse.LlamaAccessor", "world.entity.animal.horse.TraderLlamaAccessor", @@ -111,6 +110,7 @@ "world.entity.npc.AbstractVillagerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", + "world.entity.projectile.AbstractArrowAccessor", "world.entity.projectile.ArrowAccessor", "world.entity.projectile.EyeOfEnderAccessor", "world.entity.projectile.FireworkRocketEntityAccessor", @@ -152,6 +152,7 @@ "world.level.NaturalSpawner_SpawnStateAccessor", "world.level.NaturalSpawnerAccessor", "world.level.ServerExplosionAccessor", + "world.level.TicketStorageAccessor", "world.level.biome.Biome_ClimateSettingsAccessor", "world.level.biome.BiomeAccessor", "world.level.biome.MobSpawnSettingsAccessor", diff --git a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java index bb0d6e3abfa..b740f9cae50 100644 --- a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java +++ b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java @@ -78,7 +78,7 @@ public MessageFormat translate(final @NonNull String key, final @NonNull Locale /** * Gets a message format from a key and context. * - * @param key a translation key + * @param key a translation key * @param context a context * @return a message format or {@code null} to skip translation */ @@ -93,26 +93,29 @@ public Component render(@NonNull MutableComponent component, final @NonNull C co final net.minecraft.network.chat.HoverEvent hover = component.getStyle().getHoverEvent(); - if (hover != null) { + if (hover != null) { component.setStyle(component.getStyle().withHoverEvent(this.renderHoverEvent(hover, context))); } return component; } private HoverEvent renderHoverEvent(final HoverEvent input, final @NonNull C context) { - final HoverEvent.Action action = input.getAction(); - if (action == HoverEvent.Action.SHOW_TEXT) { - final Component original = input.getValue(HoverEvent.Action.SHOW_TEXT); - return new HoverEvent(HoverEvent.Action.SHOW_TEXT, this.render(original.copy(), context)); - } else if (action == HoverEvent.Action.SHOW_ENTITY) { - final HoverEvent.EntityTooltipInfo data = input.getValue(HoverEvent.Action.SHOW_ENTITY); - if (data.name.isPresent()) { - final Component rendered = this.render(data.name.get().copy(), context); - return new HoverEvent(HoverEvent.Action.SHOW_ENTITY, new HoverEvent.EntityTooltipInfo(data.type, data.id, rendered)); - } - } - - return input; + return switch (input) { + case HoverEvent.ShowText st -> { + final Component original = st.text(); + yield new HoverEvent.ShowText(this.render(original.copy(), context)); + } + case HoverEvent.ShowEntity se -> { + final HoverEvent.EntityTooltipInfo original = se.entity(); + if (original.name.isPresent()) { + final Component rendered = this.render(original.name.get().copy(), context); + final var info = new HoverEvent.EntityTooltipInfo(original.type, original.uuid, rendered); + yield new HoverEvent.ShowEntity(info); + } + yield input; + } + default -> input; + }; } protected @NonNull MutableComponent renderTranslatable(final MutableComponent component, final @NonNull TranslatableContents contents, final @NonNull C context) { @@ -135,7 +138,7 @@ private HoverEvent renderHoverEvent(final HoverEvent input, final @NonNull C con final Object[] args = contents.getArgs(); final MutableComponent result; // no arguments makes this render very simple - if(args.length == 0) { + if (args.length == 0) { result = Component.literal(format.format(null, new StringBuffer(), null).toString()); } else { result = Component.literal(""); diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index afd8a7a3f8c..cc81288b6e3 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -76,7 +76,6 @@ import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.HoverEvent.Action; -import net.minecraft.network.chat.HoverEvent.ItemStackInfo; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.contents.BlockDataSource; import net.minecraft.network.chat.contents.EntityDataSource; @@ -104,7 +103,6 @@ import org.spongepowered.api.registry.DefaultedRegistryReference; import org.spongepowered.api.util.Tristate; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.network.chat.HoverEvent_ItemStackInfoAccessor; import org.spongepowered.common.accessor.network.chat.StyleAccessor; import org.spongepowered.common.bridge.adventure.BossBarBridge; import org.spongepowered.common.bridge.adventure.ComponentBridge; @@ -113,6 +111,9 @@ import org.spongepowered.common.launch.Launch; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -352,7 +353,7 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c // no caching public static Style asAdventure(final net.minecraft.network.chat.Style mcStyle) { - final net.kyori.adventure.text.format.Style.Builder builder = net.kyori.adventure.text.format.Style.style(); + final Style.Builder builder = Style.style(); final StyleAccessor $access = (StyleAccessor) mcStyle; builder.font(SpongeAdventure.asAdventure($access.accessor$font())); // font @@ -370,7 +371,7 @@ public static Style asAdventure(final net.minecraft.network.chat.Style mcStyle) } final net.minecraft.network.chat.ClickEvent clickEvent = mcStyle.getClickEvent(); if (clickEvent != null) { - builder.clickEvent(ClickEvent.clickEvent(SpongeAdventure.asAdventure(clickEvent.getAction()), clickEvent.getValue())); + builder.clickEvent(SpongeAdventure.asAdventure(clickEvent)); } builder.insertion(mcStyle.getInsertion()); // insertion return builder.build(); @@ -500,36 +501,78 @@ public static ChatFormatting asVanilla(final NamedTextColor color) { @SuppressWarnings("ConstantConditions") public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEvent event) { - final Action action = event.getAction(); - if (action == Action.SHOW_TEXT) { - return HoverEvent.showText(SpongeAdventure.asAdventure(event.getValue(Action.SHOW_TEXT))); - } else if (action == Action.SHOW_ENTITY) { - final net.minecraft.network.chat.HoverEvent.EntityTooltipInfo value = event.getValue( - Action.SHOW_ENTITY); - final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - return HoverEvent.showEntity( - SpongeAdventure.asAdventure(entityTypeRegistry.getKey(value.type)), - value.id, - SpongeAdventure.asAdventure(value.name) - ); - } else if (action == Action.SHOW_ITEM) { - final ItemStackInfo value = event.getValue(Action.SHOW_ITEM); - final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); - final ItemStack itemStack = value.getItemStack(); - return HoverEvent.showItem( - SpongeAdventure.asAdventure(itemRegistry.getKey(itemStack.getItem())), - itemStack.getCount(), - SpongeAdventure.asAdventure(itemStack.getComponentsPatch()) - ); + return switch (event) { + case net.minecraft.network.chat.HoverEvent.ShowItem si: + final var stack = si.item(); + final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); + yield HoverEvent.showItem( + SpongeAdventure.asAdventure(stack.getItemHolder().unwrap().map(ResourceKey::location, itemRegistry::getKey)), + stack.getCount(), + SpongeAdventure.asAdventure(stack.getComponentsPatch()) + ); + case net.minecraft.network.chat.HoverEvent.ShowEntity se: + final net.minecraft.network.chat.HoverEvent.EntityTooltipInfo value = se.entity(); + final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); + yield HoverEvent.showEntity( + SpongeAdventure.asAdventure(entityTypeRegistry.getKey(value.type)), + value.uuid, + SpongeAdventure.asAdventure(value.name) + ); + case net.minecraft.network.chat.HoverEvent.ShowText st: + yield HoverEvent.showText(SpongeAdventure.asAdventure(st.text())); + default: + throw new IllegalStateException("Unexpected value: " + event); + }; + } + + public static @Nullable ClickEvent asAdventure(final net.minecraft.network.chat.@Nullable ClickEvent ce) { + if (ce == null) { + return null; } - throw new IllegalArgumentException(event.toString()); + return switch (ce) { + case net.minecraft.network.chat.ClickEvent.OpenUrl ou -> { + try { + yield ClickEvent.openUrl(ou.uri().toURL()); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Invalid URL: " + ou.uri(), e); + } + } + case net.minecraft.network.chat.ClickEvent.OpenFile of -> ClickEvent.openFile(of.file().getPath()); + case net.minecraft.network.chat.ClickEvent.RunCommand rc -> ClickEvent.runCommand(rc.command()); + case net.minecraft.network.chat.ClickEvent.SuggestCommand sc -> ClickEvent.suggestCommand(sc.command()); + case net.minecraft.network.chat.ClickEvent.ChangePage cp -> ClickEvent.changePage(cp.page()); + default -> throw new IllegalStateException("Unexpected value: " + ce); + }; } public static net.minecraft.network.chat.@Nullable ClickEvent asVanillaNullable(final @Nullable ClickEvent event) { if (event == null) { return null; } - return new net.minecraft.network.chat.ClickEvent(SpongeAdventure.asVanilla(event.action()), event.value()); + return switch (event.action()) { + case OPEN_URL ->{ + URI page; + try { + page = new URI(event.value()); + } catch (final URISyntaxException e) { + throw new IllegalArgumentException("Invalid url: " + event.value(), e); + } + yield new net.minecraft.network.chat.ClickEvent.OpenUrl(page); + } + case COPY_TO_CLIPBOARD -> new net.minecraft.network.chat.ClickEvent.CopyToClipboard(event.value()); + case RUN_COMMAND -> new net.minecraft.network.chat.ClickEvent.RunCommand(event.value()); + case SUGGEST_COMMAND -> new net.minecraft.network.chat.ClickEvent.SuggestCommand(event.value()); + case CHANGE_PAGE ->{ + int page; + try { + page = Integer.parseInt(event.value()); + } catch (final NumberFormatException e) { + throw new IllegalArgumentException("Invalid page number: " + event.value(), e); + } + yield new net.minecraft.network.chat.ClickEvent.ChangePage(page); + } + default -> throw new IllegalArgumentException("Unknown click action: " + event.action()); + }; } public static net.minecraft.network.chat.@Nullable HoverEvent asVanillaNullable(final @Nullable HoverEvent event) { @@ -538,15 +581,11 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv } final HoverEvent.Action action = event.action(); if (action == HoverEvent.Action.SHOW_TEXT) { - return new net.minecraft.network.chat.HoverEvent( - Action.SHOW_TEXT, - SpongeAdventure.asVanilla((Component) event.value()) - ); + return new net.minecraft.network.chat.HoverEvent.ShowText(SpongeAdventure.asVanilla((Component) event.value())); } else if (action == HoverEvent.Action.SHOW_ENTITY) { final HoverEvent.ShowEntity value = (HoverEvent.ShowEntity) event.value(); final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - return new net.minecraft.network.chat.HoverEvent( - Action.SHOW_ENTITY, + return new net.minecraft.network.chat.HoverEvent.ShowEntity( new net.minecraft.network.chat.HoverEvent.EntityTooltipInfo( entityTypeRegistry.getValue(SpongeAdventure.asVanilla(value.type())), value.id(), @@ -556,19 +595,14 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv } else if (action == HoverEvent.Action.SHOW_ITEM) { final HoverEvent.ShowItem value = (HoverEvent.ShowItem) event.value(); final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); - return new net.minecraft.network.chat.HoverEvent( - Action.SHOW_ITEM, - HoverEvent_ItemStackInfoAccessor.invoker$new( - Holder.direct(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))), - value.count(), - SpongeAdventure.asVanilla(value.dataComponents()) - ) - ); + final var item = Holder.direct(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))); + final var stack = new ItemStack(item, value.count(), SpongeAdventure.asVanilla(value.dataComponents())); + return new net.minecraft.network.chat.HoverEvent.ShowItem(stack); } throw new IllegalArgumentException(event.toString()); } - public static Action asVanilla(final HoverEvent.Action action) { + public static Action asVanilla(final HoverEvent.Action action) { if (action == HoverEvent.Action.SHOW_TEXT) { return Action.SHOW_TEXT; } else if (action == HoverEvent.Action.SHOW_ITEM) { diff --git a/src/main/java/org/spongepowered/common/bridge/world/server/TicketBridge.java b/src/main/java/org/spongepowered/common/bridge/world/server/TicketBridge.java index e3903905cfb..5feb31c4a64 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/server/TicketBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/server/TicketBridge.java @@ -34,6 +34,6 @@ public interface TicketBridge { org.spongepowered.api.world.server.Ticket bridge$retrieveAppropriateTicket(); - void bridge$setParentTicket(Ticket parentTicket); + void bridge$setParentTicket(Ticket parentTicket); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java index 9d7066fdf5a..691deaaecb4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockData.java @@ -54,6 +54,7 @@ private BlockData() { } // @formatter:off + @SuppressWarnings("deprecation") public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(Block.class) diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/WallData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/WallData.java index c6d8332d720..fee457b8f63 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/WallData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/WallData.java @@ -42,32 +42,32 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(BlockState.class) .create(Keys.CONNECTED_DIRECTIONS) - .get(h -> DirectionalUtil.getHorizontalUpFrom(h, WallBlock.EAST_WALL, WallBlock.WEST_WALL, WallBlock.NORTH_WALL, WallBlock.SOUTH_WALL, WallBlock.UP)) - .set((h, v) -> DirectionalUtil.setHorizontalUpFor(h, v, WallBlock.EAST_WALL, WallBlock.WEST_WALL, WallBlock.NORTH_WALL, WallBlock.SOUTH_WALL, WallBlock.UP)) + .get(h -> DirectionalUtil.getHorizontalUpFrom(h, WallBlock.EAST, WallBlock.WEST, WallBlock.NORTH, WallBlock.SOUTH, WallBlock.UP)) + .set((h, v) -> DirectionalUtil.setHorizontalUpFor(h, v, WallBlock.EAST, WallBlock.WEST, WallBlock.NORTH, WallBlock.SOUTH, WallBlock.UP)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.IS_CONNECTED_EAST) - .get(h -> h.getValue(WallBlock.EAST_WALL) != WallSide.NONE) - .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.EAST_WALL, v)) + .get(h -> h.getValue(WallBlock.EAST) != WallSide.NONE) + .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.EAST, v)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.IS_CONNECTED_NORTH) - .get(h -> h.getValue(WallBlock.NORTH_WALL) != WallSide.NONE) - .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.NORTH_WALL, v)) + .get(h -> h.getValue(WallBlock.NORTH) != WallSide.NONE) + .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.NORTH, v)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.IS_CONNECTED_SOUTH) - .get(h -> h.getValue(WallBlock.SOUTH_WALL) != WallSide.NONE) - .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.SOUTH_WALL, v)) + .get(h -> h.getValue(WallBlock.SOUTH) != WallSide.NONE) + .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.SOUTH, v)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.IS_CONNECTED_UP) .get(h -> h.getValue(WallBlock.UP)) .set((h, v) -> h.setValue(WallBlock.UP, v)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.IS_CONNECTED_WEST) - .get(h -> h.getValue(WallBlock.WEST_WALL) != WallSide.NONE) - .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.WEST_WALL, v)) + .get(h -> h.getValue(WallBlock.WEST) != WallSide.NONE) + .set((h, v) -> WallData.setWallSideProperty(h, WallBlock.WEST, v)) .supports(h -> h.getBlock() instanceof WallBlock) .create(Keys.WALL_CONNECTION_STATES) - .get(h -> DirectionalUtil.getHorizontalFrom(h, WallBlock.EAST_WALL, WallBlock.WEST_WALL, WallBlock.NORTH_WALL, WallBlock.SOUTH_WALL)) - .set((h, v) -> DirectionalUtil.setHorizontalFor(h, v, WallBlock.EAST_WALL, WallBlock.WEST_WALL, WallBlock.NORTH_WALL, WallBlock.SOUTH_WALL)) + .get(h -> DirectionalUtil.getHorizontalFrom(h, WallBlock.EAST, WallBlock.WEST, WallBlock.NORTH, WallBlock.SOUTH)) + .set((h, v) -> DirectionalUtil.setHorizontalFor(h, v, WallBlock.EAST, WallBlock.WEST, WallBlock.NORTH, WallBlock.SOUTH)) .supports(h -> h.getBlock() instanceof WallBlock) ; } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java index 2ee80e000ee..df9f20c0230 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.projectile.AbstractArrow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.PickupRule; +import org.spongepowered.common.accessor.world.entity.projectile.AbstractArrowAccessor; import org.spongepowered.common.bridge.world.entity.projectile.AbstractArrowBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -40,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(AbstractArrow.class) .create(Keys.ATTACK_DAMAGE) - .get(AbstractArrow::getBaseDamage) + .get(a -> ((AbstractArrowAccessor) a).accessor$baseDamage()) .set(AbstractArrow::setBaseDamage) .create(Keys.IS_CRITICAL_HIT) .get(AbstractArrow::isCritArrow) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java index 06ba09e4c28..7c172711475 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java @@ -24,8 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.animal.horse.AbstractHorse; import org.spongepowered.api.data.Keys; +import org.spongepowered.common.accessor.world.entity.animal.horse.AbstractHorseAccessor; import org.spongepowered.common.bridge.world.entity.animal.horse.AbstractHorseBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -42,10 +44,18 @@ public static void register(final DataProviderRegistrator registrator) { .get(AbstractHorse::isTamed) .set(AbstractHorse::setTamed) .create(Keys.OWNER) - .get(AbstractHorse::getOwnerUUID) + .get(h -> { + final var owner = h.getOwnerReference(); + if (owner == null) { + return null; + } + return owner.getUUID(); + }) .set((h, v) -> { - h.setOwnerUUID(v); - h.setTamed(v != null); + ((AbstractHorseAccessor) h).accessor$setOwner(new EntityReference<>(v)); + }) + .delete(h -> { + h.setOwner(null); }) .asMutable(AbstractHorseBridge.class) .create(Keys.IS_SADDLED) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java index 9ab53c3d8aa..7d53c7a814f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.animal.Fox; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.FoxType; @@ -42,8 +43,8 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(Fox.class) .create(Keys.FIRST_TRUSTED) - .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_0()).orElse(null)) - .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v))) + .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_0()).map(EntityReference::getUUID).orElse(null)) + .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v).map(EntityReference::new))) .create(Keys.FOX_TYPE) .get(h -> (FoxType) (Object) h.getVariant()) .set((h, v) -> h.setVariant((Fox.Variant) (Object) v)) @@ -66,8 +67,8 @@ public static void register(final DataProviderRegistrator registrator) { .get(Fox::isSleeping) .set((h, v) -> ((FoxAccessor) h).invoker$setSleeping(v)) .create(Keys.SECOND_TRUSTED) - .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_1()).orElse(null)) - .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_1(), Optional.ofNullable(v))); + .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_1()).map(EntityReference::getUUID).orElse(null)) + .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_1(), Optional.ofNullable(v).map(EntityReference::new))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java index c7f3ff898d0..3216f124da9 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.TamableAnimal; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -44,9 +45,14 @@ public static void register(final DataProviderRegistrator registrator) { .get(TamableAnimal::isTame) .set((h, v) -> h.setTame(v, true)) .create(Keys.OWNER) - .get(TamableAnimal::getOwnerUUID) + .get(t -> { + if (t.getOwnerReference() == null) { + return null; + } + return t.getOwnerReference().getUUID(); + }) .set((h, v) -> { - h.setOwnerUUID(v); + h.setOwnerReference(new EntityReference<>(v)); h.setTame(v != null, true); }); } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index 45679626783..9a42e7eb7d2 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -26,10 +26,10 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ItemAttributeModifiers; import net.minecraft.world.item.equipment.Equippable; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.Keys; @@ -39,6 +39,8 @@ import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.data.provider.DataProviderRegistrator; +import java.util.function.Function; + public final class ArmorItemStackData { private ArmorItemStackData() { @@ -60,7 +62,7 @@ public static void register(final DataProviderRegistrator registrator) { .map(RegistryEntry::value) .orElse(null); }) - .supports(h -> h.getItem() instanceof ArmorItem) + .supports(isArmorItem()) .create(Keys.ARMOR_TRIM) .get(h -> { final net.minecraft.world.item.equipment.trim.@Nullable ArmorTrim trim = h.get(DataComponents.TRIM); @@ -77,7 +79,7 @@ public static void register(final DataProviderRegistrator registrator) { h.set(DataComponents.TRIM, (net.minecraft.world.item.equipment.trim.ArmorTrim) (Object) v); }) .delete(h -> h.remove(DataComponents.TRIM)) - .supports(h -> h.getItem() instanceof ArmorItem) + .supports(isArmorItem()) .create(Keys.DAMAGE_ABSORPTION) .get(h -> { final @Nullable ItemAttributeModifiers modifiersContainer = h.get(DataComponents.ATTRIBUTE_MODIFIERS); @@ -90,7 +92,7 @@ public static void register(final DataProviderRegistrator registrator) { .map(e -> e.modifier().amount()) .orElse(null); }) - .supports(h -> h.getItem() instanceof ArmorItem) + .supports(isArmorItem()) .create(Keys.EQUIPMENT_TYPE) .get(h -> { final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); @@ -100,7 +102,22 @@ public static void register(final DataProviderRegistrator registrator) { return (EquipmentType) (Object) equippable.slot(); }) - .supports(h -> h.getItem() instanceof ArmorItem); + .supports(isArmorItem()); } // @formatter:on + + private static @NonNull Function isArmorItem() { + return h -> { + final var components = h.getItem().components(); + final @Nullable Integer stackSize = components.get(DataComponents.MAX_STACK_SIZE); + if (stackSize == null) { + return false; + } + return components.has(DataComponents.EQUIPPABLE) + && components.has(DataComponents.ENCHANTABLE) + && components.has(DataComponents.MAX_DAMAGE) + && components.has(DataComponents.MAX_STACK_SIZE) + && (1 == stackSize); + }; + } } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ToolItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ToolItemStackData.java index 9d07383215f..8fa927bb9d4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ToolItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ToolItemStackData.java @@ -32,6 +32,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.Tool; import net.minecraft.world.level.block.Block; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ToolRule; @@ -53,40 +54,40 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.EFFICIENCY) .get(h -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { return (double) tool.defaultMiningSpeed(); } return null; }) .set((h, v) -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { - h.set(DataComponents.TOOL, new Tool(tool.rules(), v.floatValue(), tool.damagePerBlock())); + h.set(DataComponents.TOOL, new Tool(tool.rules(), v.floatValue(), tool.damagePerBlock(), tool.canDestroyBlocksInCreative())); return; } - h.set(DataComponents.TOOL, new Tool(List.of(), v.floatValue(), 1)); + h.set(DataComponents.TOOL, new Tool(List.of(), v.floatValue(), 1, true)); }) .delete(h -> h.remove(DataComponents.TOOL)) .create(Keys.TOOL_DAMAGE_PER_BLOCK) .get(h -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { return tool.damagePerBlock(); } return null; }) .set((h, v) -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { - h.set(DataComponents.TOOL, new Tool(tool.rules(), tool.defaultMiningSpeed(), v)); + h.set(DataComponents.TOOL, new Tool(tool.rules(), tool.defaultMiningSpeed(), v, tool.canDestroyBlocksInCreative())); return; } - h.set(DataComponents.TOOL, new Tool(List.of(), 1f, v)); + h.set(DataComponents.TOOL, new Tool(List.of(), 1f, v, true)); }) .create(Keys.TOOL_RULES) .get(h -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool == null) { return null; } @@ -94,17 +95,17 @@ public static void register(final DataProviderRegistrator registrator) { }) .set((h, v) -> { var mcValue = v.stream().map(Tool.Rule.class::cast).toList(); - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { - h.set(DataComponents.TOOL, new Tool(mcValue, tool.defaultMiningSpeed(), tool.damagePerBlock())); + h.set(DataComponents.TOOL, new Tool(mcValue, tool.defaultMiningSpeed(), tool.damagePerBlock(), tool.canDestroyBlocksInCreative())); return; } - h.set(DataComponents.TOOL, new Tool(mcValue, 1f, 1)); + h.set(DataComponents.TOOL, new Tool(mcValue, 1f, 1, true)); }) .delete(h -> { - final Tool tool = h.get(DataComponents.TOOL); + final @Nullable Tool tool = h.get(DataComponents.TOOL); if (tool != null) { - h.set(DataComponents.TOOL, new Tool(List.of(), tool.defaultMiningSpeed(), tool.damagePerBlock())); + h.set(DataComponents.TOOL, new Tool(List.of(), tool.defaultMiningSpeed(), tool.damagePerBlock(), tool.canDestroyBlocksInCreative())); } }) .create(Keys.CAN_HARVEST) diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index e63a348dd9e..501daf4f0b2 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.world.biome; import net.minecraft.core.Holder; +import net.minecraft.util.random.Weighted; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeGenerationSettings; @@ -148,13 +149,36 @@ private static Map> naturalSpawners(Biome b return map; } + public record WeightedSpanwer(Weighted data) implements NaturalSpawner { + + @Override + public EntityType type() { + return (EntityType) this.data.value().type(); + } + + @Override + public int min() { + return this.data.value().minCount(); + } + + @Override + public int max() { + return this.data.value().maxCount(); + } + + @Override + public int weight() { + return this.data.weight(); + } + } + private static Optional> naturalSpawner(Biome biome, MobCategory cat) { - final List unwrap = biome.getMobSettings().getMobs(cat).unwrap(); + final List> unwrap = biome.getMobSettings().getMobs(cat).unwrap(); if (unwrap.isEmpty()) { return Optional.empty(); } final List result = new ArrayList<>(); - unwrap.forEach(data -> result.add((NaturalSpawner) data)); + unwrap.forEach(data -> result.add(new WeightedSpanwer(data))); return Optional.of(result); } diff --git a/src/main/java/org/spongepowered/common/entity/EntityUtil.java b/src/main/java/org/spongepowered/common/entity/EntityUtil.java index 88f37ace57f..3c085c628d2 100644 --- a/src/main/java/org/spongepowered/common/entity/EntityUtil.java +++ b/src/main/java/org/spongepowered/common/entity/EntityUtil.java @@ -28,8 +28,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -import net.minecraft.util.random.SimpleWeightedRandomList; -import net.minecraft.util.random.WeightedEntry; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; @@ -207,11 +206,11 @@ public static SpawnData toSpawnData(final EntityArchetype value) { return new SpawnData(tag, Optional.empty(), Optional.empty()); } - public static WeightedTable toWeightedArchetypes(final SimpleWeightedRandomList spawnData) { + public static WeightedTable toWeightedArchetypes(final WeightedList spawnData) { final WeightedTable possibleEntities = new WeightedTable<>(); - for (final WeightedEntry.Wrapper weightedEntity : spawnData.unwrap()) { - final CompoundTag nbt = weightedEntity.data().entityToSpawn(); + for (final var weightedEntity : spawnData.unwrap()) { + final CompoundTag nbt = weightedEntity.value().entityToSpawn(); final String resourceLocation = nbt.getString(Constants.Entity.ENTITY_TYPE_ID); final var mcType = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getOptional(ResourceLocation.parse(resourceLocation)); final var type = mcType.map(org.spongepowered.api.entity.EntityType.class::cast).orElse(EntityTypes.PIG.get()); @@ -221,13 +220,13 @@ public static WeightedTable toWeightedArchetypes(final SimpleWe .entityData(NBTTranslator.INSTANCE.translateFrom(nbt)) .build(); - possibleEntities.add(new WeightedSerializableObject<>(archetype, weightedEntity.getWeight().asInt())); + possibleEntities.add(new WeightedSerializableObject<>(archetype, weightedEntity.weight())); } return possibleEntities; } - public static SimpleWeightedRandomList toSpawnPotentials(final WeightedTable table) { - final SimpleWeightedRandomList.Builder builder = SimpleWeightedRandomList.builder(); + public static WeightedList toSpawnPotentials(final WeightedTable table) { + final WeightedList.Builder builder = WeightedList.builder(); for (final var entry : table) { if (entry instanceof final WeightedObject weightedObj) { final var tag = NBTTranslator.INSTANCE.translate(weightedObj.get().entityData()); diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 16c9013f582..7b6aebd6c0d 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -294,11 +294,9 @@ public void internalSetAbsorptionAmount(float amount) { } @Override - protected float tickHeadTurn(final float p_110146_1_, final float p_110146_2_) { - final float retValue = super.tickHeadTurn(p_110146_1_, p_110146_2_); + protected void tickHeadTurn(final float p_110146_1_) { // Make the body rotation follow head rotation this.setYRot(this.getYHeadRot()); - return retValue; } private void setProfileName(final net.minecraft.network.chat.@Nullable Component newName) { @@ -394,7 +392,11 @@ private boolean isAliveAndInWorld() { private void respawnOnClient() { this.pushPackets(new ClientboundRemoveEntitiesPacket(this.getId()), this.createPlayerListPacket(EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class))); - this.pushPackets(this.getAddEntityPacket(new ServerEntity((ServerLevel) this.level(), this, 1, true, packet -> {}))); + this.pushPackets(this.getAddEntityPacket(new ServerEntity( + (ServerLevel) this.level(), + this, 1, true, packet -> {}, + (packet, list) -> {} + ))); } /** diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java index f69722fdf70..191f3fceca6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/NotifyNeighborSideEffect.java @@ -50,10 +50,15 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final ServerLevel world = pipeline.getServerWorld(); // Vanilla isClientSide is redundant - // if (!this.isClientSide && (flags & 1) != 0) { + // if (($$2 & 1) != 0) { + // this.updateNeighborsAt($$0, $$6.getBlock()); + // if (!this.isClientSide && $$1.hasAnalogOutputSignal()) { + // this.updateNeighbourForOutputSignal($$0, $$5); + // } + //} if (flag.updateNeighbors()) { // this.notifyNeighbors(pos, originalState.getBlock()); - world.blockUpdated(oldState.pos(), oldState.state().getBlock()); + world.updateNeighborsAt(oldState.pos(), oldState.state().getBlock()); if (newState.hasAnalogOutputSignal()) { // this.updateComparatorOutputLevel(pos, block); world.updateNeighbourForOutputSignal(oldState.pos(), newState.getBlock()); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java index e635d85aa93..7f5cf00edf7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java @@ -46,17 +46,60 @@ public EffectResult processSideEffect( final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { - // Normally, vanilla does this: - // boolean var14 = var11.hasBlockEntity(); - // if (!this.level.isClientSide) { - // var11.onRemove(this.level, var1, var2, var3); - // } else if (!var11.is(var12) && var14) { - // this.removeBlockEntity(var1); - // } - // However, since we know we're not on the client (ChunkPipeline is not - // used outside of server world context) - // we can safely just do oldState.onRemove(this.level, var1, var2, var3). - oldState.state().onRemove(pipeline.getServerWorld(), oldState.pos(), newState, flag.movingBlocks()); + // This replaces LevelChunk#setBlockState block: + /* + + if ($$14) { + if (this.level instanceof ServerLevel $$17) { + // -- this block is this side effect + if (hasBlockEntity && $$16) { + BlockEntity $$18 = this.level.getBlockEntity($$0); + if ($$18 != null) { + $$18.preRemoveSideEffects($$0, $$9, $$15); + } + } + + if (hasBlockEntity) { + this.removeBlockEntity($$0); + } + + if (($$2 & 1) != 0) { + $$9.affectNeighborsAfterRemoval($$17, $$0, $$15); + } + // -- end of side effect + } else if (hasBlockEntity) { + this.removeBlockEntity($$0); + } + } + Notes: + Since we know we're on the server context, we eliminate + if (this.level instanceof ServerLevel $$17) { + And likewise the check if hasBlockEntity, so we just fast forward into + the checks for physics flags + */ + boolean hasBlockEntity = oldState.state().hasBlockEntity(); + + final var pos = oldState.pos(); + + if (!oldState.state().is(newState.getBlock())) { + return EffectResult.NULL_PASS; + } + // Spogne adds the block physics flag + if (hasBlockEntity && !flag.structurePlacement() && flag.performBlockPhysics()) { + final var blockEntity = oldState.tileEntity(); + if (blockEntity != null) { + blockEntity.preRemoveSideEffects(pos, newState, flag.movingBlocks()); + } + } + + if (hasBlockEntity) { + pipeline.getAffectedChunk().removeBlockEntity(pos); + } + + if (flag.updateNeighbors()) { + oldState.state().affectNeighborsAfterRemoval(pipeline.getServerWorld(), pos, flag.movingBlocks()); + } + return EffectResult.NULL_PASS; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java index 4cedc0c5810..73123b9396a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; +import net.minecraft.core.SectionPos; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; @@ -47,11 +48,24 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final SpongeBlockChangeFlag flag, final int limit ) { + /* + Continuing from LevelChunk.setBlockState + + boolean $$11 = $$4.hasOnlyAir(); + if ($$5 != $$11) { + this.level.getChunkSource().getLightEngine().updateSectionStatus($$0, $$11); + this.level.getChunkSource().onSectionEmptinessChanged(this.chunkPos.x, SectionPos.blockToSectionCoord($$3), this.chunkPos.z, $$11); + } + + */ + final var chunk = pipeline.getAffectedChunk(); + final var blockY = oldState.pos().getY(); final LevelChunkSection chunkSection = pipeline.getAffectedSection(); final boolean wasEmpty = pipeline.wasEmpty(); final boolean isStillEmpty = chunkSection.hasOnlyAir(); if (wasEmpty != isStillEmpty) { pipeline.getServerWorld().getChunkSource().getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); + pipeline.getServerWorld().getChunkSource().onSectionEmptinessChanged(chunk.getPos().x, SectionPos.blockToSectionCoord(blockY), chunk.getPos().z, isStillEmpty); } return EffectResult.NULL_PASS; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java index aec887a346a..a596df27ebb 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java @@ -40,6 +40,7 @@ public final class UpdateOrCreateNewTileEntityPostPlacementEffect implements Pro private static final class Holder { static final UpdateOrCreateNewTileEntityPostPlacementEffect INSTANCE = new UpdateOrCreateNewTileEntityPostPlacementEffect(); } + UpdateOrCreateNewTileEntityPostPlacementEffect() { } @@ -49,13 +50,23 @@ public static UpdateOrCreateNewTileEntityPostPlacementEffect getInstance() { @SuppressWarnings("deprecation") @Override - public EffectResult processSideEffect(final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, + public EffectResult processSideEffect( + final BlockPipeline pipeline, final PipelineCursor oldState, final BlockState newState, final SpongeBlockChangeFlag flag, final int limit ) { + final var pos = oldState.pos(); final ServerLevel serverWorld = pipeline.getServerWorld(); final LevelChunk chunk = pipeline.getAffectedChunk(); + final var block = newState.getBlock(); if (((BlockStateBridge) newState).bridge$hasTileEntity()) { - final @Nullable BlockEntity maybeNewTileEntity = chunk.getBlockEntity(oldState.pos(), LevelChunk.EntityCreationType.CHECK); + var maybeNewTileEntity = chunk.getBlockEntity(oldState.pos(), LevelChunk.EntityCreationType.CHECK); + if (maybeNewTileEntity != null && !maybeNewTileEntity.isValidBlockState(newState)) { + LevelChunkAccessor.accessor$LOGGER().warn( + "Found mismatched block entity @ {}: type = {}, state = {}", pos, maybeNewTileEntity.getType().builtInRegistryHolder().key().location(), newState + ); + chunk.removeBlockEntity(pos); + maybeNewTileEntity = null; + } if (maybeNewTileEntity == null) { // var15 = ((EntityBlock)var12).newBlockEntity(var1, var2); // Vanilla // tileentity1 = state.createTileEntity(this.world); // Forge diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java index 58491086353..de6327ad949 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/WorldBlockChangeCompleteEffect.java @@ -46,7 +46,7 @@ public EffectResult processSideEffect(final BlockPipeline pipeline, final Pipeli final SpongeBlockChangeFlag flag, final int limit ) { if (flag.notifyPathfinding()) { - pipeline.getServerWorld().onBlockStateChange(oldState.pos(), oldState.state(), newState); + pipeline.getServerWorld().updatePOIOnBlockStateChange(oldState.pos(), oldState.state(), newState); } return new EffectResult(oldState.state(), true); } diff --git a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java index 7c2699c0549..f4ef3fdb492 100644 --- a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java +++ b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java @@ -115,7 +115,7 @@ private List basedOfFixedPool(final RandomSource randomIn, // Same code as net.minecraft.enchantment.EnchantmentHelper#selectEnchantment if (!list1.isEmpty()) { - WeightedRandom.getRandomItem(randomIn, list1).ifPresent(list::add); + WeightedRandom.getRandomItem(randomIn, list1, EnchantmentInstance::weight).ifPresent(list::add); while (randomIn.nextInt(50) <= this.level) { @@ -126,7 +126,7 @@ private List basedOfFixedPool(final RandomSource randomIn, break; } - WeightedRandom.getRandomItem(randomIn, list1).ifPresent(list::add); + WeightedRandom.getRandomItem(randomIn, list1, EnchantmentInstance::weight).ifPresent(list::add); this.level /= 2; } } @@ -135,7 +135,7 @@ private List basedOfFixedPool(final RandomSource randomIn, } public static List fromNative(final List list) { - return list.stream().map(data -> Enchantment.of(((EnchantmentType) (Object) data.enchantment.value()), data.level)).collect(Collectors.toList()); + return list.stream().map(data -> Enchantment.of(((EnchantmentType) (Object) data.enchantment().value()), data.level())).collect(Collectors.toList()); } public static List toNative(final List list) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index 42e3cf263b2..ce46ab28c13 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -34,6 +34,7 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingRecipeInput; import net.minecraft.world.item.crafting.SmithingTransformRecipe; +import net.minecraft.world.item.crafting.TransmuteResult; import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; import org.spongepowered.common.bridge.world.item.crafting.SmithingRecipeBridge; import org.spongepowered.common.item.recipe.ResultFunctionRecipe; @@ -66,7 +67,7 @@ public static SpongeSmithingRecipe of(final String spongeType, final Optional template, final Optional base, final Optional addition, final ItemStack spongeResult, final String resultFunctionId) { - super(template, base, addition, spongeResult); + super(template, base, addition, new TransmuteResult(spongeResult.getItemHolder(), spongeResult.getCount(), spongeResult.getComponentsPatch())); this.resultFunctionId = resultFunctionId; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java index 26261ca7cc3..fcee7525f4a 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java @@ -31,6 +31,7 @@ import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SmithingRecipeInput; import net.minecraft.world.item.crafting.SmithingTransformRecipe; +import net.minecraft.world.item.crafting.TransmuteResult; import org.spongepowered.api.datapack.DataPack; import org.spongepowered.api.item.recipe.Recipe; import org.spongepowered.api.item.recipe.RecipeRegistration; @@ -69,7 +70,11 @@ public SpongeSmithingRecipeRegistration(ResourceLocation key, String group, fina public Recipe recipe() { this.ensureCached(); if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, List.of(this.template, this.base, this.addition))) { - return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), this.spongeResult); + return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), new TransmuteResult( + this.spongeResult.getItemHolder(), + this.spongeResult.getCount(), + this.spongeResult.getComponentsPatch() + )); } return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), Optional.ofNullable(this.base), Optional.ofNullable(this.addition), diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index ed5de8bbd49..b52545e2f7a 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -982,8 +982,10 @@ public static final class BlockChangeFlags { * check if lighting is queued for the block change. */ public static final int LIGHTING_UPDATES = 1 << 7; // 128 if set, blocks lighting updates - public static final int PHYSICS_MASK = 1 << 8; // Sponge Added mask, because vanilla doesn't support it yet - public static final int PATHFINDING_UPDATES = 1 << 9; // Sponge Added mask, because vanilla doesn't allow bypassing notifications to ai pathfinders + public static final int STRUCTURE_PLACEMENT = 1 << 8; // 256 if set, blocks structure placement + + public static final int PHYSICS_MASK = 1 << 16; // Sponge Added mask, because vanilla doesn't support it yet + public static final int PATHFINDING_UPDATES = 1 << 17; // Sponge Added mask, because vanilla doesn't allow bypassing notifications to ai pathfinders // All of these flags are what we "expose" to the API // The flags that are naturally inverted are already inverted here by being masked in // with the opposite OR. @@ -993,6 +995,7 @@ public static final class BlockChangeFlags { | Constants.BlockChangeFlags.FORCE_RE_RENDER | Constants.BlockChangeFlags.NEIGHBOR_DROPS | Constants.BlockChangeFlags.DENY_NEIGHBOR_SHAPE_UPDATE + | Constants.BlockChangeFlags.STRUCTURE_PLACEMENT ; public static final int DEFAULT = Constants.BlockChangeFlags.BLOCK_UPDATED | Constants.BlockChangeFlags.NOTIFY_CLIENTS; diff --git a/src/main/java/org/spongepowered/common/util/DamageEventUtil.java b/src/main/java/org/spongepowered/common/util/DamageEventUtil.java index e471f06d4d6..dcf75daf729 100644 --- a/src/main/java/org/spongepowered/common/util/DamageEventUtil.java +++ b/src/main/java/org/spongepowered/common/util/DamageEventUtil.java @@ -104,13 +104,13 @@ public static DamageFunction createArmorModifiers(final LivingEntity living, fin * LivingEntity#getDamageAfterMagicAbsorb */ public static DamageFunction createResistanceModifier(final LivingEntity living) { - final var effect = living.getEffect(MobEffects.DAMAGE_RESISTANCE); + final var effect = living.getEffect(MobEffects.RESISTANCE); var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.DEFENSIVE_POTION_EFFECT, effect); return new DamageFunction(modifier, DamageEventUtil.createResistanceFunction(living)); } public static DoubleUnaryOperator createResistanceFunction(final LivingEntity living) { - final var effect = living.getEffect(MobEffects.DAMAGE_RESISTANCE); + final var effect = living.getEffect(MobEffects.RESISTANCE); final int base = effect == null ? 0 : (effect.getAmplifier() + 1) * 5; final int modifier = 25 - base; return damage -> Math.max(((damage * modifier) / 25.0F), 0.0f); diff --git a/src/main/java/org/spongepowered/common/world/SpongeBlockChangeFlag.java b/src/main/java/org/spongepowered/common/world/SpongeBlockChangeFlag.java index 63058a2ef14..a3061dc2c7e 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeBlockChangeFlag.java +++ b/src/main/java/org/spongepowered/common/world/SpongeBlockChangeFlag.java @@ -47,6 +47,7 @@ public final class SpongeBlockChangeFlag implements BlockChangeFlag { private final boolean lighting; private final boolean pathfindingUpdates; private final boolean neighborDrops; + private final boolean structurePlacement; private final int rawFlag; public SpongeBlockChangeFlag(final int flag) { @@ -58,6 +59,7 @@ public SpongeBlockChangeFlag(final int flag) { this.neighborDrops = (flag & Constants.BlockChangeFlags.NEIGHBOR_DROPS) == 0; // 32 this.blockMoving = (flag & Constants.BlockChangeFlags.BLOCK_MOVING) != 0; // 64 this.lighting = (flag & Constants.BlockChangeFlags.LIGHTING_UPDATES) == 0; // 128 vanilla check + this.structurePlacement = (flag & Constants.BlockChangeFlags.STRUCTURE_PLACEMENT) == 0; // 256 vanilla check this.performBlockPhysics = (flag & Constants.BlockChangeFlags.PHYSICS_MASK) == 0; // sponge this.pathfindingUpdates = (flag & Constants.BlockChangeFlags.PATHFINDING_UPDATES) == 0; // sponge this.rawFlag = flag; @@ -98,6 +100,11 @@ public boolean ignoreRender() { return this.ignoreRender; } + @Override + public boolean structurePlacement() { + return this.structurePlacement; + } + @Override public boolean forceClientRerender() { return this.forceReRender; @@ -354,6 +361,26 @@ public BlockChangeFlag withForcedReRender(boolean forcedReRender) { return BlockChangeFlagManager.fromNativeInt(maskedFlag); } + @Override + public BlockChangeFlag withStructurePlacement(boolean structurePlacement) { + if (this.structurePlacement == structurePlacement) { + return this; + } + final int maskedFlag = + (this.updateNeighbors ? Constants.BlockChangeFlags.BLOCK_UPDATED : 0) + | (this.notifyClients ? Constants.BlockChangeFlags.NOTIFY_CLIENTS : 0) + | (this.ignoreRender ? Constants.BlockChangeFlags.IGNORE_RENDER : 0) + | (this.forceReRender ? Constants.BlockChangeFlags.FORCE_RE_RENDER : 0) + | (this.updateNeighborShapes ? 0 : Constants.BlockChangeFlags.DENY_NEIGHBOR_SHAPE_UPDATE) + | (this.neighborDrops ? 0 : Constants.BlockChangeFlags.NEIGHBOR_DROPS) + | (this.blockMoving ? Constants.BlockChangeFlags.BLOCK_MOVING : 0) + | (this.performBlockPhysics ? 0 : Constants.BlockChangeFlags.PHYSICS_MASK) + | (this.lighting ? 0 : Constants.BlockChangeFlags.LIGHTING_UPDATES) + | (this.pathfindingUpdates ? 0 : Constants.BlockChangeFlags.PATHFINDING_UPDATES) + | (structurePlacement ? Constants.BlockChangeFlags.STRUCTURE_PLACEMENT : 0); + return BlockChangeFlagManager.fromNativeInt(maskedFlag); + } + public int getRawFlag() { return this.rawFlag; } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java index 481ed65a69c..ec488b86111 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java @@ -68,6 +68,7 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; +import org.spongepowered.common.data.provider.world.biome.BiomeData; import org.spongepowered.common.util.AbstractDataPackEntryBuilder; import java.io.IOException; @@ -203,7 +204,8 @@ protected BiomeTemplate build0() { final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() .creatureGenerationProbability(spawnChance.floatValue()); spawners.forEach((cat, spawner) -> spawner.forEach(sp -> { - spawnerBuilder.addSpawn((MobCategory) (Object) cat, (MobSpawnSettings.SpawnerData) sp); + final var data = ((BiomeData.WeightedSpanwer) sp).data(); + spawnerBuilder.addSpawn((MobCategory) (Object) cat, data.weight(), data.value()); })); spawnerCosts.forEach((type, cost) -> spawnerBuilder.addMobCharge((net.minecraft.world.entity.EntityType) (Object) type, cost.budget(), cost.charge())); diff --git a/src/main/java/org/spongepowered/common/world/biome/spawner/SpongeNaturalSpawnerFactory.java b/src/main/java/org/spongepowered/common/world/biome/spawner/SpongeNaturalSpawnerFactory.java index 03b5f845d7b..577c7827ea5 100644 --- a/src/main/java/org/spongepowered/common/world/biome/spawner/SpongeNaturalSpawnerFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/spawner/SpongeNaturalSpawnerFactory.java @@ -24,14 +24,16 @@ */ package org.spongepowered.common.world.biome.spawner; +import net.minecraft.util.random.Weighted; import net.minecraft.world.level.biome.MobSpawnSettings; import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.world.biome.spawner.NaturalSpawner; +import org.spongepowered.common.data.provider.world.biome.BiomeData; public class SpongeNaturalSpawnerFactory implements NaturalSpawner.Factory { @Override public NaturalSpawner of(final EntityType type, final int weight, final int min, final int max) { - return (NaturalSpawner) new MobSpawnSettings.SpawnerData((net.minecraft.world.entity.EntityType) type, weight, min, max); + return new BiomeData.WeightedSpanwer(new Weighted<>(new MobSpawnSettings.SpawnerData((net.minecraft.world.entity.EntityType) type, min, max), weight)); } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java index 0fbce2768fd..9c281ee6f05 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java @@ -28,7 +28,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.util.Ticks; import org.spongepowered.api.world.server.TicketType; -import org.spongepowered.common.accessor.server.level.TicketTypeAccessor; import org.spongepowered.common.util.Constants; import java.util.Comparator; @@ -78,9 +77,10 @@ public TicketType build() { if (this.comparator == null) { this.comparator = (v1, v2) -> 0; } - - return (TicketType) TicketTypeAccessor.accessor$createInstance(this.name, this.comparator, this.lifetime.isInfinite() - ? Constants.ChunkTicket.INFINITE_TIMEOUT - : this.lifetime.ticks()); + final var timeout = this.lifetime.isInfinite() ? Constants.ChunkTicket.INFINITE_TIMEOUT : this.lifetime.ticks(); + return (TicketType) (Object) new net.minecraft.server.level.TicketType( + timeout, + false, // TODO - Do we determine if a ticket type should be stored? + net.minecraft.server.level.TicketType.TicketUse.LOADING_AND_SIMULATION); } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index fec2d7c92b7..c340dfbaa26 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -50,10 +50,10 @@ import net.minecraft.world.entity.npc.WanderingTraderSpawner; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.CustomSpawner; -import net.minecraft.world.level.ForcedChunksSavedData; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.TicketStorage; import net.minecraft.world.level.WorldDataConfiguration; import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -140,7 +140,8 @@ public abstract class SpongeWorldManager implements WorldManager { private final Path defaultWorldDirectory, customWorldsDirectory; private final Map, ServerLevel> worlds; - private static final TicketType SPAWN_CHUNKS = TicketType.create("spawn_chunks", ResourceLocation::compareTo); + // TODO - pending https://github.com/SpongePowered/SpongeAPI/issues/2574 - 25w02a + private static final TicketType SPAWN_CHUNKS = TicketType.FORCED; public SpongeWorldManager(final MinecraftServer server) { this.server = server; @@ -708,7 +709,7 @@ private void unloadWorld0(final ServerLevel world) throws IOException { SpongeCommon.post(unloadWorldEvent); final BlockPos spawnPoint = world.getSharedSpawnPos(); - world.getChunkSource().removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, new ChunkPos(spawnPoint), 11, registryKey.location()); + world.getChunkSource().removeTicketWithRadius(SpongeWorldManager.SPAWN_CHUNKS, new ChunkPos(spawnPoint), 11); ((PrimaryLevelDataBridge) world.getLevelData()).bridge$configAdapter().save(); @@ -974,7 +975,7 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel wo final int diameter = ((borderRadius - 1) * 2) + 1; final int spawnChunks = diameter * diameter; - serverChunkProvider.addRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, borderRadius, world.dimension().location()); + serverChunkProvider.addTicketWithRadius(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, borderRadius); final CompletableFuture generationFuture = new CompletableFuture<>(); Sponge.asyncScheduler().submit( Task.builder().plugin(Launch.instance().platformPlugin()) @@ -996,7 +997,7 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel wo // Sponge Start - Release the chunk ticket if spawn is not set to be kept loaded... if (!((PrimaryLevelDataBridge) world.getLevelData()).bridge$performsSpawnLogic()) { - serverChunkProvider.removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location()); + serverChunkProvider.removeTicketWithRadius(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11); } return world; }); @@ -1010,7 +1011,7 @@ private void loadSpawnChunks(final ServerLevel world) { final ServerChunkCache serverChunkProvider = world.getChunkSource(); // serverChunkProvider.getLightEngine().setTaskPerBatch(500); ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos()); - serverChunkProvider.addRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location()); + serverChunkProvider.addTicketWithRadius(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11); while (serverChunkProvider.getTickingGenerated() != 441) { ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos() + 10L * TimeUtil.NANOSECONDS_PER_MILLISECOND); @@ -1029,14 +1030,14 @@ private void loadSpawnChunks(final ServerLevel world) { // Sponge Start - Release the chunk ticket if spawn is not set to be kept loaded... if (!((PrimaryLevelDataBridge) world.getLevelData()).bridge$performsSpawnLogic()) { - serverChunkProvider.removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location()); + serverChunkProvider.removeTicketWithRadius(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11); } } private void updateForcedChunks(final ServerLevel world, final ServerChunkCache serverChunkProvider) { - final ForcedChunksSavedData forcedChunksSaveData = world.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + final @Nullable TicketStorage forcedChunksSaveData = world.getDataStorage().get(TicketStorage.factory(), "chunks"); if (forcedChunksSaveData != null) { - final LongIterator longIterator = forcedChunksSaveData.getChunks().iterator(); + final LongIterator longIterator = forcedChunksSaveData.getForceLoadedChunks().iterator(); while (longIterator.hasNext()) { final long i = longIterator.nextLong(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ChunkMapMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ChunkMapMixin_API.java index f009a2dac26..951292ef152 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ChunkMapMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ChunkMapMixin_API.java @@ -67,7 +67,7 @@ public boolean valid(final @NonNull Ticket ticket) { @Override public @NonNull Optional> requestTicket(final @NonNull TicketType type, final @NonNull Vector3i chunkPosition, final @NonNull T value, final int radius) { - if (!(type instanceof net.minecraft.server.level.TicketType)) { + if (!((Object) type instanceof net.minecraft.server.level.TicketType)) { throw new IllegalArgumentException("TicketType must be a Minecraft TicketType"); } if (radius < 1) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index b84aa8eede6..8626fc0cc8e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -122,7 +122,6 @@ public abstract class ServerLevelMixin_API extends LevelMixin_API shadow$players(); @Shadow public abstract Raids shadow$getRaids(); @Nullable @Shadow public abstract Raid shadow$getRaidAt(BlockPos p_217475_1_); @@ -284,7 +283,7 @@ public boolean contains(final int x, final int y, final int z) { @Override public Optional entity(final UUID uniqueId) { - return Optional.ofNullable((org.spongepowered.api.entity.Entity) this.shadow$getEntity(Objects.requireNonNull(uniqueId, "uniqueId"))); + return Optional.ofNullable((org.spongepowered.api.entity.Entity) ((ServerLevel) (Object) this).getEntity(Objects.requireNonNull(uniqueId, "uniqueId"))); } // MutableBlockEntityVolume diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/TicketTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/TicketTypeMixin_API.java index 19ce2393353..f4b55f7ad58 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/TicketTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/TicketTypeMixin_API.java @@ -36,14 +36,14 @@ public abstract class TicketTypeMixin_API implements TicketType { // @formatter:off - @Shadow @Final private String name; @Shadow @Final private long timeout; // @formatter:on @Override public String name() { - return this.name; + // TODO - change this out + return ""; } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java index 5fe142e3f62..8cff309148a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.LivingEntity; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Fox; @@ -36,18 +38,20 @@ import java.util.Set; import java.util.UUID; +import java.util.stream.Stream; @Mixin(net.minecraft.world.entity.animal.Fox.class) @Implements(@Interface(iface = Fox.class, prefix = "fox$", remap = Remap.NONE)) public abstract class FoxMixin_API extends AnimalMixin_API implements Fox { // @formatter:off - @Shadow protected abstract boolean shadow$trusts(UUID p_213468_1_); + @Shadow abstract Stream> shadow$getTrustedEntities(); // @formatter:on + @Intrinsic public boolean fox$trusts(UUID uniqueId) { - return this.shadow$trusts(uniqueId); + return this.shadow$getTrustedEntities().map(EntityReference::getUUID).anyMatch(uniqueId::equals); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java index 28f49bdd338..d7d08227976 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java @@ -58,7 +58,7 @@ public void spawnImmediately(final boolean force) { spawnerData.accessor$totalMobsSpawned(spawnerData.accessor$totalMobsSpawned() + 1); spawnerData.accessor$nextMobSpawnsAt(this.level.getGameTime() + (long) spawnerConfig.ticksBetweenSpawn()); spawnerConfig.spawnPotentialsDefinition().getRandom(this.level.getRandom()).ifPresent(next -> { - spawnerData.accessor$nextSpawnData(Optional.of(next.data())); + spawnerData.accessor$nextSpawnData(Optional.of(next)); spawner.markUpdated(); }); }); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSpawnOverrideMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSpawnOverrideMixin_API.java index 72ada58616a..26537c3715f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSpawnOverrideMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSpawnOverrideMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen.structure; -import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.level.biome.MobSpawnSettings; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; import org.spongepowered.api.world.biome.spawner.NaturalSpawner; @@ -32,6 +32,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.data.provider.world.biome.BiomeData; import java.util.List; @@ -40,7 +41,7 @@ public abstract class StructureSpawnOverrideMixin_API implements StructureNatura // @formatter:off @Shadow @Final private StructureSpawnOverride.BoundingBoxType boundingBox; - @Shadow @Final private WeightedRandomList spawns; + @Shadow @Final private WeightedList spawns; // @formatter:on @Override @@ -50,6 +51,6 @@ public boolean full() { @Override public List spawners() { - return (List) this.spawns.unwrap(); + return this.spawns.unwrap().stream().map(BiomeData.WeightedSpanwer::new).toList(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java index 0ef1e4de132..b6e81cd0e8d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.mixin.core.nbt; -import com.google.common.base.Function; import com.google.common.collect.Maps; +import net.minecraft.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import org.apache.logging.log4j.Level; @@ -39,6 +39,7 @@ import org.spongepowered.common.util.PrettyPrinter; import java.util.Map; +import java.util.function.Function; /** * @author Zidane - Minecraft 1.14.4 @@ -56,38 +57,42 @@ public abstract class CompoundTagMixin { @Shadow @Final private Map tags; // @formatter:on - @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;transformValues(Ljava/util/Map;Lcom/google/common/base/Function;)Ljava/util/Map;")) + @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", + at = @At(value = "INVOKE", + target ="Lnet/minecraft/Util;mapValues(Ljava/util/Map;Ljava/util/function/Function;)Ljava/util/Map;")) private Map impl$checkForOverflowOnCopy(Map fromMap, Function function) { - return Maps.transformValues(fromMap, (tag) -> {try { - return tag == null ? null : tag.copy(); - } catch (StackOverflowError e) { - final PrettyPrinter printer = new PrettyPrinter(60) - .add("StackOverflow from trying to copy this compound") - .centre() - .hr(); - printer.addWrapped(70, "Sponge caught a stack overflow error, printing out some special" - + " handling and printouts to assist in finding out where this" - + " recursion is coming from."); - printer.add(); + return Util.mapValues(fromMap, (tag) -> { try { - printer.addWrapped(80, "%s : %s", "This compound", this); - } catch (final Throwable error) { - printer.addWrapped(80, "Unable to get the string of this compound. Printing out some of the entries to better assist"); + return tag == null ? null : tag.copy(); + } catch (StackOverflowError e) { + final PrettyPrinter printer = new PrettyPrinter(60) + .add("StackOverflow from trying to copy this compound") + .centre() + .hr(); + printer.addWrapped(70, "Sponge caught a stack overflow error, printing out some special" + + " handling and printouts to assist in finding out where this" + + " recursion is coming from."); + printer.add(); + try { + printer.addWrapped(80, "%s : %s", "This compound", this); + } catch (final Throwable error) { + printer.addWrapped(80, "Unable to get the string of this compound. Printing out some of the entries to better assist"); - for (final Map.Entry entry : this.tags.entrySet()) { - try { - printer.addWrapped(80, "%s : %s", entry.getKey(), entry.getValue()); - } catch (final Throwable throwable) { - printer.add(); - printer.addWrapped(80, "The offending key entry is belonging to " + entry.getKey()); - break; + for (final Map.Entry entry : this.tags.entrySet()) { + try { + printer.addWrapped(80, "%s : %s", entry.getKey(), entry.getValue()); + } catch (final Throwable throwable) { + printer.add(); + printer.addWrapped(80, "The offending key entry is belonging to " + entry.getKey()); + break; + } } } + printer.add(); + printer.log(SpongeCommon.logger(), Level.ERROR); + return null; } - printer.add(); - printer.log(SpongeCommon.logger(), Level.ERROR); - return null; - }}); + }); } @ModifyArg(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;(Ljava/util/Map;)V")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index a08d031d170..5e814d0e7cc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -118,7 +118,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, if (entityIn instanceof ServerPlayer sp) { ChunkPos chunkpos = new ChunkPos(new BlockPos((int) actualX, (int) actualY, (int) actualZ)); - worldIn.getChunkSource().addRegionTicket(TicketType.FORCED, chunkpos, 1, chunkpos); + worldIn.getChunkSource().addTicketWithRadius(TicketType.FORCED, chunkpos, 1); entityIn.stopRiding(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java index 99184b1c0e5..ca4bf8767a8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java @@ -24,23 +24,18 @@ */ package org.spongepowered.common.mixin.core.server.level; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.TicketType; import net.minecraft.util.Mth; -import net.minecraft.util.SortedArraySet; -import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.TicketStorage; import org.spongepowered.api.util.Ticks; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.api.world.server.Ticket; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.accessor.server.level.TicketAccessor; +import org.spongepowered.common.accessor.world.level.TicketStorageAccessor; import org.spongepowered.common.bridge.world.DistanceManagerBridge; import org.spongepowered.common.bridge.world.server.TicketBridge; import org.spongepowered.common.util.Constants; @@ -56,20 +51,18 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { // @formatter:off - @Shadow private void shadow$addTicket(final long chunkpos, final net.minecraft.server.level.Ticket ticket) { } - @Shadow protected abstract void shadow$removeTicket(long chunkPosIn, net.minecraft.server.level.Ticket ticketIn); - @Shadow @Final private Long2ObjectOpenHashMap>> tickets; - @Shadow private long ticketTickCounter; + @Shadow @Final TicketStorage ticketStorage; // @formatter:on @Override @SuppressWarnings({"unchecked", "ConstantConditions"}) public boolean bridge$checkTicketValid(final Ticket ticket) { // Only report the ticket is valid if it's associated with this manager. - final net.minecraft.server.level.Ticket nativeTicket = ((net.minecraft.server.level.Ticket) (Object) ticket); - final SortedArraySet> ticketsForChunk = this.tickets.get(((TicketBridge) ticket).bridge$chunkPosition()); - if (ticketsForChunk != null && ticketsForChunk.contains(nativeTicket)) { - return !((TicketAccessor) ticket).invoker$timedOut(this.ticketTickCounter); + final var nativeTicket = ((net.minecraft.server.level.Ticket) (Object) ticket); + final var bridgeTicket = (TicketBridge) ticket; + final var tickets = this.ticketStorage.getTickets(bridgeTicket.bridge$chunkPosition()); + if (tickets != null && tickets.contains(nativeTicket)) { + return nativeTicket.isTimedOut(); } return false; } @@ -78,8 +71,12 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { @SuppressWarnings("ConstantConditions") public Ticks bridge$timeLeft(final Ticket ticket) { if (this.bridge$checkTicketValid(ticket)) { - final long ticksElapsed = this.ticketTickCounter - ((TicketAccessor) ticket).accessor$createdTick(); - return new SpongeTicks(Math.max(0, ((net.minecraft.server.level.Ticket) (Object) ticket).getType().timeout() - ticksElapsed)); + final var mcTicket = (net.minecraft.server.level.Ticket) ticket; + if (mcTicket.getType().timeout() == 0) { + return Ticks.zero(); + } + final long left = ((TicketAccessor) ticket).accessor$ticksLeft(); + return new SpongeTicks(Math.max(0, left)); } return Ticks.zero(); } @@ -88,8 +85,9 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { @SuppressWarnings({"unchecked", "ConstantConditions"}) public boolean bridge$renewTicket(final Ticket ticket) { if (this.bridge$checkTicketValid(ticket)) { - final net.minecraft.server.level.Ticket nativeTicket = (net.minecraft.server.level.Ticket) (Object) ticket; - ((TicketAccessor) ticket).invoker$setCreatedTick(this.ticketTickCounter + nativeTicket.getType().timeout()); + final var nativeTicket = (net.minecraft.server.level.Ticket) (Object) ticket; + nativeTicket.resetTicksLeft(); + this.ticketStorage.setDirty(); return true; } return false; @@ -101,9 +99,9 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { final ServerWorld world, final org.spongepowered.api.world.server.TicketType ticketType, final Vector3i pos, final T value, final int distanceLimit) { final int distance = Mth.clamp(Constants.ChunkTicket.MAX_FULL_CHUNK_DISTANCE - distanceLimit, 0, Constants.ChunkTicket.MAX_FULL_CHUNK_TICKET_LEVEL); - final TicketType type = (net.minecraft.server.level.TicketType) ticketType; - final net.minecraft.server.level.Ticket ticketToRequest = TicketAccessor.accessor$createInstance(type, distance, value); - this.shadow$addTicket(VecHelper.toChunkPos(pos).toLong(), ticketToRequest); + final TicketType type = (TicketType) (Object) ticketType; + final net.minecraft.server.level.Ticket ticketToRequest = new net.minecraft.server.level.Ticket(type, distance); + this.ticketStorage.addTicket(VecHelper.toChunkPos(pos).toLong(), ticketToRequest); return Optional.of(((TicketBridge) (Object) ticketToRequest).bridge$retrieveAppropriateTicket()); } @@ -111,9 +109,8 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { @SuppressWarnings({"ConstantConditions"}) public boolean bridge$releaseTicket(final Ticket ticket) { if (this.bridge$checkTicketValid(ticket)) { - this.shadow$removeTicket(((TicketBridge) ticket).bridge$chunkPosition(), - (net.minecraft.server.level.Ticket) (Object) ticket); - return true; + final var chunkPos = ((TicketBridge) ticket).bridge$chunkPosition(); + return this.ticketStorage.removeTicket(chunkPos, (net.minecraft.server.level.Ticket) ticket); } return false; } @@ -121,32 +118,10 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { @SuppressWarnings({"ConstantConditions", "unchecked"}) @Override public Collection> bridge$tickets(final org.spongepowered.api.world.server.TicketType ticketType) { - return this.tickets.values().stream() - .flatMap(x -> x.stream().filter(ticket -> ticket.getType() == ticketType)) + return ((TicketStorageAccessor) this.ticketStorage).accessor$tickets().values().stream() + .flatMap(x -> x.stream().filter(ticket -> ticket.getType() == (TicketType) (Object) ticketType)) .map(x -> (Ticket) (Object) x) .collect(Collectors.toList()); } - @SuppressWarnings("ConstantConditions") - @Inject(method = "addTicket(JLnet/minecraft/server/level/Ticket;)V", at = @At("HEAD")) - private void impl$addChunkPosToTicket(final long chunkPos, final net.minecraft.server.level.Ticket ticket, final CallbackInfo ci) { - ((TicketBridge) (Object) ticket).bridge$setChunkPosition(chunkPos); - } - - @SuppressWarnings("ConstantConditions") - @Redirect(method = "addTicket(JLnet/minecraft/server/level/Ticket;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/Ticket;setCreatedTick(J)V")) - private void impl$setParentTicketIfApplicable(final net.minecraft.server.level.Ticket storedTicket, - final long ticketTickCounter, - final long chunkPosAsLong, - final net.minecraft.server.level.Ticket originalTicket) { - // We do this because we want to return the original ticket that will actually be operated on, but avoid a - // potentially costly search on an array - because addTicket doesn't return the ticket that is actually - // in the manager. - if (storedTicket != originalTicket) { - ((TicketBridge) (Object) originalTicket).bridge$setParentTicket(storedTicket); - } - ((TicketAccessor) (Object) storedTicket).invoker$setCreatedTick(ticketTickCounter); - } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java index 60d8af295f0..e4ca827fde1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java @@ -47,6 +47,7 @@ import java.util.Collection; import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Stream; @@ -79,10 +80,11 @@ public abstract class ServerEntityMixin { */ @Inject(method = "", at = @At("TAIL")) private void impl$wrapConsumer(final ServerLevel serverLevel, final Entity entity, final int trackingRange, - final boolean trackMovementDeltas, final Consumer> broadcaster, final CallbackInfo ci) { + final boolean trackMovementDeltas, final Consumer> broadcaster, + final BiConsumer filter, final CallbackInfo ci) { this.broadcast = (packet) -> { - if (this.entity instanceof VanishableBridge) { - if (!((VanishableBridge) this.entity).bridge$vanishState().invisible()) { + if (this.entity instanceof VanishableBridge bridge) { + if (!bridge.bridge$vanishState().invisible()) { broadcaster.accept(packet); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index ce4e2f2b124..01e4bdd9f79 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -49,7 +49,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.ai.village.poi.PoiType; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; @@ -147,7 +146,6 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow protected abstract void shadow$saveLevelData(final boolean $$0); @Shadow @Final private MinecraftServer server; - @Shadow public abstract void levelEvent(@Nullable Player $$0, int $$1, BlockPos $$2, int $$3); @Shadow @Nullable private EndDragonFight dragonFight; @Shadow @Final private List players; @@ -339,11 +337,14 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel return (WorldData) this.shadow$getLevelData(); } - @Redirect(method = "setDefaultSpawnPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;addRegionTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V")) - private void impl$respectKeepSpawnLoaded(final ServerChunkCache serverChunkProvider, final TicketType p_217228_1_, final ChunkPos p_217228_2_, - final int p_217228_3_, final Object p_217228_4_) { + @Redirect(method = "setDefaultSpawnPos", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerChunkCache;addTicketWithRadius(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;I)V" + )) + private void impl$respectKeepSpawnLoaded(ServerChunkCache serverChunkProvider, TicketType type, ChunkPos pos, int radius) { if ((((ServerWorldProperties) this.shadow$getLevelData()).performsSpawnLogic())) { - serverChunkProvider.addRegionTicket(p_217228_1_, p_217228_2_, p_217228_3_, p_217228_4_); + serverChunkProvider.addTicketWithRadius(type, pos, radius); } } @@ -494,7 +495,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, } @Inject(method = "levelEvent", at = @At("HEAD"), cancellable = true) - private void impl$throwBroadcastEvent(final Player player, final int eventID, final BlockPos pos, final int dataID, CallbackInfo ci) { + private void impl$throwBroadcastEvent(final Entity player, final int eventID, final BlockPos pos, final int dataID, CallbackInfo ci) { if(eventID == Constants.WorldEvents.PLAY_RECORD_EVENT && ShouldFire.PLAY_SOUND_EVENT_FROM_JUKEBOX) { try (final CauseStackManager.StackFrame frame = Sponge.server().causeStackManager().pushCauseFrame()) { final BlockEntity tileEntity = this.shadow$getBlockEntity(pos); @@ -527,7 +528,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, } } - @Redirect(method = "lambda$onBlockStateChange$14", + @Redirect(method = "lambda$updatePOIOnBlockStateChange$14", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;add(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;)V" diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 5663c94a37e..71063f089af 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -230,7 +230,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr final var thisPlayer = ((net.minecraft.server.level.ServerPlayer) (Object) this); final ChunkPos chunkPos = new ChunkPos(VecHelper.toBlockPos(pos)); - level.getChunkSource().addRegionTicket(TicketType.FORCED, chunkPos, 1, chunkPos); + level.getChunkSource().addTicketWithRadius(TicketType.FORCED, chunkPos, 1); thisPlayer.stopRiding(); if (thisPlayer.isSleeping()) { @@ -427,7 +427,7 @@ public boolean teleportTo(final ServerLevel world, } return this.bridge$changeDimension(new TeleportTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, - e -> world.getChunkSource().addRegionTicket(TicketType.FORCED, e.chunkPosition(), 1, e.chunkPosition()))) != null; + e -> world.getChunkSource().addTicketWithRadius(TicketType.FORCED, e.chunkPosition(), 1))) != null; } } @@ -653,7 +653,7 @@ public void die(final DamageSource cause) { final String s = component.getString(256); final net.minecraft.network.chat.Component itextcomponent1 = net.minecraft.network.chat.Component.translatable("death.attack.message_too_long", net.minecraft.network.chat.Component.literal(s).withStyle(ChatFormatting.YELLOW)); final net.minecraft.network.chat.Component itextcomponent2 = net.minecraft.network.chat.Component.translatable("death.attack.even_more_magic", this.shadow$getDisplayName()) - .withStyle((p_212357_1_) -> p_212357_1_.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, itextcomponent1))); + .withStyle((p_212357_1_) -> p_212357_1_.withHoverEvent(new HoverEvent.ShowText(itextcomponent1))); return new ClientboundPlayerCombatKillPacket(this.shadow$getId(), itextcomponent2); })); final Team team = this.shadow$getTeam(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketMixin.java index c344c2f7197..81055fd79bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketMixin.java @@ -26,13 +26,16 @@ import net.minecraft.server.level.Ticket; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.bridge.world.server.TicketBridge; @Mixin(Ticket.class) public abstract class TicketMixin implements TicketBridge { + @Unique private long impl$chunkPosition; - private Ticket impl$parent; + @Unique + private Ticket impl$parent; @Override public long bridge$chunkPosition() { @@ -54,7 +57,7 @@ public abstract class TicketMixin implements TicketBridge { } @Override - public void bridge$setParentTicket(final Ticket parentTicket) { + public void bridge$setParentTicket(final Ticket parentTicket) { this.impl$parent = parentTicket; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketStorageMixin.java new file mode 100644 index 00000000000..eea5de41298 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/TicketStorageMixin.java @@ -0,0 +1,66 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.server.level; + +import net.minecraft.server.level.Ticket; +import net.minecraft.world.level.TicketStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.bridge.world.server.TicketBridge; + +@Mixin(TicketStorage.class) +public class TicketStorageMixin { + + @SuppressWarnings("ConstantConditions") + @Inject(method = "addTicket(JLnet/minecraft/server/level/Ticket;)Z", at = @At("HEAD")) + private void impl$addChunkPosToTicket(final long chunkPos, final net.minecraft.server.level.Ticket ticket, final CallbackInfoReturnable ci) { + ((TicketBridge) (Object) ticket).bridge$setChunkPosition(chunkPos); + } + + @SuppressWarnings("ConstantConditions") + @ModifyVariable(method = "addTicket(JLnet/minecraft/server/level/Ticket;)Z", + at = @At(value = "LOAD"), + slice = @Slice( + from = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/TicketStorage;isTicketSameTypeAndLevel(Lnet/minecraft/server/level/Ticket;Lnet/minecraft/server/level/Ticket;)Z"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/Ticket;resetTicksLeft()V") + ), + index = 6 + ) + private Ticket impl$associateTicketWithParent(final Ticket storedTicket, final long pos, final Ticket originalTicket) { + // We do this because we want to return the original ticket that will actually be operated on, but avoid a + // potentially costly search on an array - because addTicket doesn't return the ticket that is actually + // in the manager. + if (storedTicket != originalTicket) { + ((TicketBridge) (Object) originalTicket).bridge$setParentTicket(storedTicket); + } + return storedTicket; + } + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index d07e784cb6c..a6d600f0ec4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -202,8 +202,9 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ServerboundMovePlayerPacket;getYRot(F)F"), cancellable = true, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isPassenger()Z"))) + // TODO - confirm we are injecting at the right spot given the subtle changes + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;hasClientLoaded()Z"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z"))) private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) { final boolean fireMoveEvent = packetIn.hasPosition(); final boolean fireRotationEvent = packetIn.hasRotation(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index ffdf5b5fb9b..51f0f6a13b3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -743,7 +743,7 @@ public void stopRiding() { } - @Redirect(method = "checkInsideBlocks(Ljava/util/List;Ljava/util/Set;)V", + @Redirect(method = "checkInsideBlocks(Ljava/util/List;Ljava/util/List;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 4f8bacb5f5e..0513071ffa5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -146,8 +146,8 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen /** * Capture the old values to reset if we end up cancelling or blocking. */ - @Inject(method = "hurtServer", at = @At(value = "FIELD", - target = "Lnet/minecraft/world/entity/LivingEntity;walkAnimation:Lnet/minecraft/world/entity/WalkAnimationState;")) + @Inject(method = "hurtServer", at = @At(value = "INVOKE", + target = "Ljava/lang/Float;isNaN(F)Z")) private void attackImpl$beforeActuallyHurt(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { // Save old values this.attackImpl$lastHurt = this.lastHurt; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 976768bf6d5..c8973d45c24 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -231,11 +231,11 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri }, at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V" + target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V" ) ) private void impl$ignoreExperienceLevelSoundsWhileVanished(final Level world, - final net.minecraft.world.entity.player.Player player, final double x, final double y, final double z, + final Entity player, final double x, final double y, final double z, final SoundEvent sound, final SoundSource category, final float volume, final float pitch ) { if (!this.bridge$vanishState().createsSounds()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index 6bcc120f9a5..636bfcf3759 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -146,9 +146,11 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I @Redirect(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 0), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - public void attackImpl$preventSprintingAttackSound(final Level instance, final Player $$0, final double $$1, final double $$2, final double $$3, final SoundEvent $$4, - final SoundSource $$5, final float $$6, final float $$7) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) + public void attackImpl$preventSprintingAttackSound( + final Level instance, final Entity $$0, final double $$1, final double $$2, final double $$3, + final SoundEvent $$4, final SoundSource $$5, final float $$6, final float $$7 + ) { // prevent sound this.attackImpl$isStrongSprintAttack = true; } @@ -233,8 +235,8 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I */ @Redirect(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - public void attackImpl$onNoDamageSound(final Level instance, final Player $$0, final double $$1, final double $$2, final double $$3, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) + public void attackImpl$onNoDamageSound(final Level instance, final Entity $$0, final double $$1, final double $$2, final double $$3, final SoundEvent $$4, final SoundSource $$5, final float $$6, final float $$7) { if (!this.attackImpl$attackEvent.isCancelled()) { this.impl$playAttackSound((Player) (Object) this, SoundEvents.PLAYER_ATTACK_NODAMAGE); @@ -285,9 +287,11 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I * Redirect {@link LivingEntity#knockback} to use modified event knockback */ @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) + slice = @Slice(from = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z"), + to = @At(value = "INVOKE", + target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;doPostAttackEffects(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)V")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) public void attackImpl$modifyKnockback(final LivingEntity instance, final double $$0, final double $$1, final double $$2) { instance.knockback($$0 * this.attackImpl$attackEvent.knockbackModifier(), $$1, $$2); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java index da7ae4469ed..3d25f0d2755 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java @@ -41,6 +41,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -48,19 +49,27 @@ @Mixin(FishingRodItem.class) public abstract class FishingRodItemMixin { - @Nullable private FishingHook impl$fishHook; + @Nullable + private FishingHook impl$fishHook; @Inject(method = "use", at = @At(value = "INVOKE", shift = At.Shift.AFTER, - target = "Lnet/minecraft/world/entity/projectile/FishingHook;retrieve(Lnet/minecraft/world/item/ItemStack;)I"), cancellable = true) + target = "Lnet/minecraft/world/entity/projectile/FishingHook;retrieve(Lnet/minecraft/world/item/ItemStack;)I"), cancellable = true) private void cancelHookRetraction(Level world, Player player, InteractionHand hand, CallbackInfoReturnable cir) { if (player.fishing != null) { cir.setReturnValue(InteractionResult.SUCCESS); // Event was cancelled } } - @Inject(method = "use", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V", ordinal = 1), - cancellable = true) + @Inject(method = "use", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V" + ), + slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/gameevent/GameEvent;ITEM_INTERACT_FINISH:Lnet/minecraft/core/Holder$Reference;"), + to = @At(value = "CONSTANT", args = "classValue=net/minecraft/server/level/ServerLevel") + ), + cancellable = true) private void onThrowEvent(Level level, Player player, InteractionHand hand, CallbackInfoReturnable cir) { if (level.isClientSide) { // Only fire event on server-side to avoid crash on client @@ -69,7 +78,7 @@ private void onThrowEvent(Level level, Player player, InteractionHand hand, Call ItemStack itemstack = player.getItemInHand(hand); if (level instanceof ServerLevel serverLevel) { - int $$6 = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemstack, player) * 20.0F); + int $$6 = (int) (EnchantmentHelper.getFishingTimeReduction(serverLevel, itemstack, player) * 20.0F); int $$7 = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemstack, player); FishingHook fishHook = new FishingHook(player, level, $$7, $$6); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java index 0fa9a035e4f..30411b096b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java @@ -27,6 +27,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingTransformRecipe; +import net.minecraft.world.item.crafting.TransmuteResult; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -41,7 +42,7 @@ public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBrid @Shadow @Final Optional template; @Shadow @Final Optional base; @Shadow @Final Optional addition; - @Shadow @Final ItemStack result; + @Shadow @Final TransmuteResult result; // @formatter=on @Override @@ -61,7 +62,7 @@ public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBrid @Override public ItemStack bridge$result() { - return this.result; + return new ItemStack(this.result.item(), this.result.count(), this.result.components()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NoteBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NoteBlockMixin.java index c39884d4022..acd87a88877 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NoteBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NoteBlockMixin.java @@ -50,8 +50,11 @@ public abstract class NoteBlockMixin extends BlockMixin { @SuppressWarnings("ConstantConditions") - @Inject(method = "trigge rEvent", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSeededSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;FFJ)V"), + @Inject(method = "triggerEvent", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/Level;playSeededSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;FFJ)V" + ), cancellable = true) // TODO mixin earlier to cancel tuning particles private void impl$throwNoteBlockSoundEvent(BlockState state, Level worldIn, BlockPos pos, int id, int param, CallbackInfoReturnable callbackInfo) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java index ad866c991ee..5dbd5d0748a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java @@ -60,7 +60,7 @@ public abstract class TntBlockMixin extends BlockMixin { return removed; } - @Inject(method = "explode(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V", + @Inject(method = "prime(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), locals = LocalCapture.CAPTURE_FAILSOFT, cancellable = true diff --git a/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java b/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java index d7394ce4112..314fc868ffc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java +++ b/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java @@ -25,22 +25,24 @@ package org.spongepowered.common.mixin.optimization.world.entity; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.mixin.core.world.entity.AgableMobMixin; import java.util.Optional; -import java.util.UUID; @Mixin(TamableAnimal.class) public abstract class TamableAnimalMixin_Optimization_Owner extends AgableMobMixin { - @Shadow @Final protected static EntityDataAccessor> DATA_OWNERUUID_ID; - @Nullable private UUID cachedOwner$OwnerId; + @Shadow @Final protected static EntityDataAccessor>> DATA_OWNERUUID_ID; + @Nullable @Unique private EntityReference cachedOwner$OwnerId; /** * @author gabizou - July 26th, 2016 @@ -50,13 +52,26 @@ public abstract class TamableAnimalMixin_Optimization_Owner extends AgableMobMix */ @Nullable @Overwrite - public UUID getOwnerUUID() { + public EntityReference getOwnerReference() { if (this.cachedOwner$OwnerId == null) { this.cachedOwner$OwnerId = this.entityData.get(TamableAnimalMixin_Optimization_Owner.DATA_OWNERUUID_ID).orElse(null); } return this.cachedOwner$OwnerId; } + /** + * @author gabizou - January 12th, 2025 + * @reason stores the cached owner id to save constant lookups from the data watcher + * + * @param entity The entity to set as the owner + */ + @Overwrite + public void setOwner(final @javax.annotation.Nullable LivingEntity entity) { + final var reference = Optional.ofNullable(entity).map(EntityReference::new); + this.cachedOwner$OwnerId = reference.orElse(null); + this.entityData.set(DATA_OWNERUUID_ID, reference); + } + /** * @author gabizou - July 26th, 2016 * @reason stores the cached owner id @@ -64,7 +79,7 @@ public UUID getOwnerUUID() { * @param ownerUuid The owner id to set */ @Overwrite - public void setOwnerUUID(@Nullable final UUID ownerUuid) { + public void setOwnerReference(@Nullable final EntityReference ownerUuid) { this.cachedOwner$OwnerId = ownerUuid; this.entityData.set(TamableAnimalMixin_Optimization_Owner.DATA_OWNERUUID_ID, Optional.ofNullable(ownerUuid)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index cfaee3f54c7..a391c8918e8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -169,14 +169,14 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { method = "tickEffects", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/effect/MobEffectInstance;tick(Lnet/minecraft/world/entity/LivingEntity;Ljava/lang/Runnable;)Z" + target = "Lnet/minecraft/world/effect/MobEffectInstance;tickServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;Ljava/lang/Runnable;)Z" ) ) private boolean impl$wrapEffectWithFrame( - final MobEffectInstance instance, final LivingEntity thisEntity, final Runnable runnable) { + final MobEffectInstance instance, final ServerLevel level, final LivingEntity thisEntity, final Runnable runnable) { try { PhaseTracker.getInstance().pushCause(instance); // push the PotionEffect - return instance.tick(thisEntity, runnable); + return instance.tickServer(level, thisEntity, runnable); } finally { PhaseTracker.getInstance().popCause(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java index 266ada0ee0e..7ae5a191847 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java @@ -80,7 +80,7 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i private @MonotonicNonNull PhaseContext<@NonNull ?> tracker$postProcessContext = null; @Inject(method = "setBlockState", at = @At("HEAD"), cancellable = true) - private void tracker$sanityCheckServerWorldSetBlockState(final BlockPos pos, final BlockState state, final boolean isMoving, + private void tracker$sanityCheckServerWorldSetBlockState(final BlockPos pos, final BlockState state, final int flag, final CallbackInfoReturnable cir ) { if (!((LevelBridge) this.level).bridge$isFake()) { diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index d7739f84900..f52f41f1da3 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -367,7 +367,6 @@ "minecraft.world.level.biome.Climate_ParameterPointMixin_API", "minecraft.world.level.biome.FixedBiomeSourceMixin_API", "minecraft.world.level.biome.MobSpawnSettings_MobSpawnCostMixin_API", - "minecraft.world.level.biome.MobSpawnSettings_SpawnerDataMixin_API", "minecraft.world.level.biome.MultiNoiseBiomeSourceMixin_API", "minecraft.world.level.biome.TheEndBiomeSourceMixin_API", "minecraft.world.level.block.MirrorMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 59a85456dc7..15e1cd7c835 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -1,316 +1,317 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.mixin.core", - "mixinPriority": 1101, - "mixins": [ - "advancements.AdvancementMixin", - "advancements.AdvancementProgressMixin", - "advancements.CriteriaTriggersMixin", - "advancements.CriterionMixin", - "advancements.CriterionProgressMixin", - "advancements.CriterionTrigger_ListenerMixin", - "advancements.DisplayInfoMixin", - "advancements.TreeNodePositionMixin", - "adventure.KeyMixin", - "adventure.bossbar.HackyBossBarPlatformBridgeMixin", - "adventure.chat.SignedMessageMixin", - "adventure.text.AbstractComponentMixin", - "adventure.text.format.StyleImplMixin", - "block.BedBlockMixin", - "block.BlockMixin", - "block.DyeColorBlockPropertiesMixin", - "commands.CommandsMixin", - "commands.CommandSourceMixin", - "commands.CommandSourceStackMixin", - "commands.arguments.ComponentArgumentMixin", - "commands.arguments.DimensionArgumentMixin", - "commands.arguments.selector.EntitySelectorParserMixin", - "commands.execution.tasks.ExecuteCommandMixin", - "core.MappedRegistryMixin", - "core.Vec3iMixin", - "core.dispenser.ProjectileDispenseBehaviorMixin", - "data.SpongeDataHolderMixin", - "item.EmptyMapItemMixin", - "item.ThrowableInaccurateItemMixin", - "item.YeetableInaccurateItemMixin", - "nbt.CompoundTagMixin", - "network.ConnectionMixin", - "network.PacketEncoderMixin", - "network.chat.Component_SerializerMixin", - "network.chat.ComponentSerializationMixin", - "network.chat.StyleMixin", - "network.chat.TranslatableContentsMixin", - "network.protocol.PacketMixin", - "network.protocol.common.ServerboundCustomPayloadPacketMixin", - "network.protocol.game.ClientboundResourcePackPushPacketMixin", - "network.protocol.game.ClientboundSetObjectivePacketMixin", - "network.protocol.game.ServerboundChunkBatchReceivedPacketMixin", - "network.protocol.game.ServerboundClientCommandPacketMixin", - "network.protocol.login.ClientboundCustomQueryPacketMixin", - "network.protocol.login.ServerboundCustomQueryAnswerPacketMixin", - "network.syncher.EntityDataAccessorMixin", - "network.syncher.SynchedEntityData_BuilderMixin", - "network.syncher.SynchedEntityDataMixin", - "registries.BuiltInRegistriesMixin", - "resources.RegistryDataLoaderMixin", - "server.MainMixin", - "server.MinecraftServerMixin", - "server.PlayerAdvancementsMixin", - "server.ReloadableServerRegistriesMixin", - "server.ServerFunctionManagerMixin", - "server.ServerScoreboardMixin", - "server.WorldLoaderMixin", - "server.bossevents.CustomBossEventMixin", - "server.commands.BossBarCommandsMixin", - "server.commands.DifficultyCommandMixin", - "server.commands.GameRuleCommandMixin", - "server.commands.KickCommandMixin", - "server.commands.SaveAllCommandMixin", - "server.commands.TeleportCommandMixin", - "server.commands.WeatherCommandMixin", - "server.commands.WorldBorderCommandMixin", - "server.dedicated.DedicatedPlayerListMixin", - "server.level.ChunkHolderMixin", - "server.level.ChunkMap_TrackedEntityMixin", - "server.level.ChunkMapMixin", - "server.level.DistanceManagerMixin", - "server.level.GenerationChunkHolderMixin", - "server.level.ServerBossEventMixin", - "server.level.ServerChunkCacheMixin", - "server.level.ServerEntityMixin", - "server.level.ServerLevelMixin", - "server.level.ServerPlayer_ContainerListenerMixin", - "server.level.ServerPlayerGameModeMixin", - "server.level.ServerPlayerMixin", - "server.level.ServerPlayerMixin_HealthScale", - "server.level.TicketMixin", - "server.network.LegacyQueryHandlerMixin", - "server.network.ServerCommonPacketListenerImplMixin", - "server.network.ServerConfigurationPacketListenerImplMixin", - "server.network.ServerGamePacketListenerImpl_1Mixin", - "server.network.ServerGamePacketListenerImplMixin", - "server.network.ServerHandshakePacketListenerImplMixin", - "server.network.ServerLoginPacketListenerImplMixin", - "server.network.ServerStatusPacketListenerImplMixin", - "server.players.BanListEntryMixin", - "server.players.GameProfileCache_GameProfileInfoMixin", - "server.players.GameProfileCacheMixin", - "server.players.IpBanListEntryMixin", - "server.players.PlayerListMixin", - "server.players.SleepStatusMixin", - "server.players.StoredUserEntryMixin", - "server.players.StoredUserListMixin", - "server.rcon.RconConsoleSourceMixin", - "server.rcon.thread.QueryThreadGs4Mixin", - "server.rcon.thread.RconClientMixin", - "service.permission.SubjectMixin", - "util.ClassInstanceMultiMapMixin", - "util.datafix.schemas.V1125Mixin", - "world.BaseCommandBlockMixin", - "world.BossEventMixin", - "world.damagesource.DamageSourceMixin", - "world.damagesource.DamageSourcesMixin", - "world.entity.ActiveChunkReferentMixin", - "world.entity.AgableMobMixin", - "world.entity.EntityMaxAirMixin", - "world.entity.EntityMixin", - "world.entity.EntitySelectorMixin", - "world.entity.EntityTypeMixin", - "world.entity.ExperienceOrbMixin", - "world.entity.GrieferBridgeMixin", - "world.entity.LeashableMixin", - "world.entity.LightningBoltMixin", - "world.entity.LivingEntityMixin", - "world.entity.LivingEntityMixin_Attack_Impl", - "world.entity.MobMixin", - "world.entity.MobMixin_Attack_Impl", - "world.entity.PortalProcessorMixin", - "world.entity.ai.goal.BreakDoorGoalMixin", - "world.entity.ai.goal.BreedGoalMixin", - "world.entity.ai.goal.EatBlockGoalMixin", - "world.entity.ai.goal.GoalMixin", - "world.entity.ai.goal.GoalSelectorMixin", - "world.entity.ai.goal.RangedAttackGoalMixin", - "world.entity.ai.goal.RunAroundLikeCrazyGoalMixin", - "world.entity.ai.sensing.NearestLivingEntitySensorMixin", - "world.entity.ai.sensing.SensorMixin", - "world.entity.animal.AnimalMixin", - "world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin", - "world.entity.animal.OcelotMixin", - "world.entity.animal.ParrotMixin", - "world.entity.animal.Rabbit_RaidGardenGoalMixin", - "world.entity.animal.WolfMixin", - "world.entity.animal.horse.AbstractHorseMixin", - "world.entity.boss.enderdragon.EndCrystalMixin", - "world.entity.decoration.ArmorStandMixin", - "world.entity.decoration.BlockAttachedEntityMixin", - "world.entity.decoration.HangingEntityMixin", - "world.entity.decoration.ItemFrameMixin", - "world.entity.item.ItemEntityMixin", - "world.entity.item.PrimedTntMixin", - "world.entity.monster.Blaze_BlazeAttackGoalMixin", - "world.entity.monster.CreeperMixin", - "world.entity.monster.EnderMan_EndermanLeaveBlockGoalMixin", - "world.entity.monster.EnderMan_EndermanTakeBlockGoalMixin", - "world.entity.monster.EnderManMixin", - "world.entity.monster.EndermiteMixin", - "world.entity.monster.Ghast_GhastShootFireballGoalMixin", - "world.entity.monster.MonsterMixin", - "world.entity.monster.ShulkerMixin", - "world.entity.monster.Silverfish_SilverfishMergeWithStoneGoalMixin", - "world.entity.monster.Silverfish_SilverfishWakeUpFriendsGoalMixin", - "world.entity.monster.ZombifiedPiglinMixin", - "world.entity.npc.AbstractVillagerMixin", - "world.entity.npc.VillagerMixin", - "world.entity.npc.WanderingTraderMixin", - "world.entity.player.PlayerMixin", - "world.entity.player.PlayerMixin_Attack_Impl", - "world.entity.projectile.AbstractArrowMixin", - "world.entity.projectile.AbstractHurtingProjectileMixin", - "world.entity.projectile.EyeOfEnderMixin", - "world.entity.projectile.FireworkRocketEntityMixin", - "world.entity.projectile.FishingHookMixin", - "world.entity.projectile.LargeFireballMixin", - "world.entity.projectile.LlamaSpitMixin", - "world.entity.projectile.ProjectileMixin", - "world.entity.projectile.ProjectileUtilMixin", - "world.entity.projectile.ShulkerBulletMixin", - "world.entity.projectile.SmallFireballMixin", - "world.entity.projectile.SnowballMixin", - "world.entity.projectile.ThrowableProjectileMixin", - "world.entity.projectile.ThrownEggMixin", - "world.entity.projectile.ThrownEnderpearlMixin", - "world.entity.projectile.ThrownTridentMixin", - "world.entity.projectile.WitherSkullMixin", - "world.entity.vehicle.AbstractBoatMixin", - "world.entity.vehicle.AbstractMinecartContainerMixin", - "world.entity.vehicle.AbstractMinecartMixin", - "world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin", - "world.entity.vehicle.MinecartCommandBlockMixin", - "world.entity.vehicle.MinecartFurnaceMixin", - "world.entity.vehicle.MinecartTNTMixin", - "world.entity.vehicle.OldMinecartBehaviourMixin", - "world.entity.vehicle.VehicleEntityMixin", - "world.food.FoodDataMixin", - "world.inventory.StonecutterMenuMixin", - "world.item.ConsumableMixin", - "world.item.EnderEyeItemMixin", - "world.item.FireworkRocketItemMixin", - "world.item.FishingRodItemMixin", - "world.item.ItemCooldownsMixin", - "world.item.ItemMixin", - "world.item.ItemStackMixin", - "world.item.MapItemMixin", - "world.item.ServerItemCooldownsMixin", - "world.item.TeleportRandomlyConsumeEffectMixin", - "world.item.crafting.AbstractCookingRecipeMixin", - "world.item.crafting.IngredientMixin", - "world.item.crafting.RecipeManagerMixin", - "world.item.crafting.ShapedRecipe_SerializerMixin", - "world.item.crafting.ShapedRecipeMixin", - "world.item.crafting.ShapelessRecipe_SerializerMixin", - "world.item.crafting.ShapelessRecipeMixin", - "world.item.crafting.AbstractCookingRecipeSerializerMixin", - "world.item.crafting.CustomRecipeSerializerMixin", - "world.item.crafting.SingleItemRecipeMixin", - "world.item.crafting.SmithingTransformRecipe_SerializerMixin", - "world.item.crafting.SmithingTransformRecipeMixin", - "world.item.crafting.StonecutterRecipe_SerializerMixin", - "world.item.enchantment.EnchantmentMixin", - "world.level.BaseSpawnerMixin", - "world.level.BlockGetterMixin", - "world.level.Explosion_BlockInteractionMixin", - "world.level.LevelMixin", - "world.level.NaturalSpawner_SpawnStateMixin", - "world.level.NaturalSpawnerMixin", - "world.level.SavedDataMixin", - "world.level.ServerExplosionMixin", - "world.level.biome.BiomeSourceMixin", - "world.level.block.BaseFireBlockMixin", - "world.level.block.CactusBlockMixin", - "world.level.block.CampfireBlockMixin", - "world.level.block.CarvedPumpkinBlockMixin", - "world.level.block.CommandBlockMixin", - "world.level.block.EndPortalBlockMixin", - "world.level.block.FallingBlockMixin", - "world.level.block.FarmBlockMixin", - "world.level.block.FireBlockMixin", - "world.level.block.LeavesBlockMixin", - "world.level.block.MagmaBlockMixin", - "world.level.block.NetherPortalBlockMixin", - "world.level.block.NoteBlockMixin", - "world.level.block.PointedDripstoneBlockMixin", - "world.level.block.SweetBerryBushBlockMixin", - "world.level.block.TntBlockMixin", - "world.level.block.entity.AbstractFurnaceBlockEntityMixin", - "world.level.block.entity.BannerBlockEntityMixin", - "world.level.block.entity.BaseContainerBlockEntityMixin", - "world.level.block.entity.BeaconBlockEntityMixin", - "world.level.block.entity.BellBLockEntityMixin", - "world.level.block.entity.BlockEntityMixin", - "world.level.block.entity.BrewingStandBlockEntityMixin", - "world.level.block.entity.CampfireBlockEntityMixin", - "world.level.block.entity.CommandBlockEntity_Mixin", - "world.level.block.entity.CommandBlockEntityMixin", - "world.level.block.entity.EnchantmentTableBlockEntityMixin", - "world.level.block.entity.LecternBlockEntityMixin", - "world.level.block.entity.SignBlockEntityMixin", - "world.level.block.entity.SkullBlockEntityMixin", - "world.level.block.piston.PistonMovingBlockEntityMixin", - "world.level.block.state.BlockBehaviour_PropertiesMixin", - "world.level.block.state.BlockStateMixin", - "world.level.border.WorldBorderMixin", - "world.level.chunk.ChunkGeneratorMixin", - "world.level.chunk.ChunkStatusTasksMixin", - "world.level.chunk.LevelChunkMixin", - "world.level.chunk.SerializableChunkDataMixin", - "world.level.chunk.storage.EntityStorageMixin", - "world.level.chunk.storage.IOWorkerMixin", - "world.level.chunk.storage.RegionFileMixin", - "world.level.dimension.DimensionTypeMixin", - "world.level.dimension.LevelStemMixin", - "world.level.entity.PersistentEntitySectionManagerMixin", - "world.level.levelgen.NoiseGeneratorSettingsMixin", - "world.level.levelgen.WorldDimensionsMixin", - "world.level.levelgen.WorldOptionsMixin", - "world.level.levelgen.flat.FlatLayerInfoMixin", - "world.level.levelgen.flat.FlatLevelGeneratorSettingsMixin", - "world.level.levelgen.structure.LegacyStructureDataHandlerMixin", - "world.level.saveddata.MapIdTrackerMixin", - "world.level.storage.DimensionDataStorageMixin", - "world.level.storage.LevelDataMixin", - "world.level.storage.LevelStorageSource_LevelStorageAccessMixin", - "world.level.storage.PlayerDataStorageMixin", - "world.level.storage.PrimaryLevelDataMixin", - "world.level.storage.ServerLevelDataMixin", - "world.scores.ObjectiveMixin", - "world.scores.PlayerTeamMixin", - "world.scores.ScoreboardMixin", - "world.ticks.LevelChunkTicksMixin", - "world.ticks.LevelTicksMixin", - "world.ticks.ScheduledTickMixin" - ], - "client": [ - "client.MinecraftMixin", - "client.multiplayer.ClientCommonPacketListenerImplMixin", - "client.multiplayer.ClientHandshakePacketListenerImplMixin", - "client.multiplayer.ClientLevelMixin", - "client.network.chat.TranslatableContentsMixin", - "client.player.AbstractClientPlayerMixin", - "client.player.LocalPlayerMixin", - "client.server.IntegratedPlayerListMixin", - "client.server.IntegratedServerMixin", - "server.network.MemoryServerHandshakePacketListenerImplMixin" - ], - "server": [ - "server.dedicated.DedicatedServerMixin", - "server.dedicated.ServerWatchdogMixin" - ], - "injectors": { - "maxShiftBy": 3 - }, - "overwrites": { - "conformVisibility": true + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.mixin.core", + "mixinPriority": 1101, + "mixins": [ + "advancements.AdvancementMixin", + "advancements.AdvancementProgressMixin", + "advancements.CriteriaTriggersMixin", + "advancements.CriterionMixin", + "advancements.CriterionProgressMixin", + "advancements.CriterionTrigger_ListenerMixin", + "advancements.DisplayInfoMixin", + "advancements.TreeNodePositionMixin", + "adventure.KeyMixin", + "adventure.bossbar.HackyBossBarPlatformBridgeMixin", + "adventure.chat.SignedMessageMixin", + "adventure.text.AbstractComponentMixin", + "adventure.text.format.StyleImplMixin", + "block.BedBlockMixin", + "block.BlockMixin", + "block.DyeColorBlockPropertiesMixin", + "commands.CommandsMixin", + "commands.CommandSourceMixin", + "commands.CommandSourceStackMixin", + "commands.arguments.ComponentArgumentMixin", + "commands.arguments.DimensionArgumentMixin", + "commands.arguments.selector.EntitySelectorParserMixin", + "commands.execution.tasks.ExecuteCommandMixin", + "core.MappedRegistryMixin", + "core.Vec3iMixin", + "core.dispenser.ProjectileDispenseBehaviorMixin", + "data.SpongeDataHolderMixin", + "item.EmptyMapItemMixin", + "item.ThrowableInaccurateItemMixin", + "item.YeetableInaccurateItemMixin", + "nbt.CompoundTagMixin", + "network.ConnectionMixin", + "network.PacketEncoderMixin", + "network.chat.Component_SerializerMixin", + "network.chat.ComponentSerializationMixin", + "network.chat.StyleMixin", + "network.chat.TranslatableContentsMixin", + "network.protocol.PacketMixin", + "network.protocol.common.ServerboundCustomPayloadPacketMixin", + "network.protocol.game.ClientboundResourcePackPushPacketMixin", + "network.protocol.game.ClientboundSetObjectivePacketMixin", + "network.protocol.game.ServerboundChunkBatchReceivedPacketMixin", + "network.protocol.game.ServerboundClientCommandPacketMixin", + "network.protocol.login.ClientboundCustomQueryPacketMixin", + "network.protocol.login.ServerboundCustomQueryAnswerPacketMixin", + "network.syncher.EntityDataAccessorMixin", + "network.syncher.SynchedEntityData_BuilderMixin", + "network.syncher.SynchedEntityDataMixin", + "registries.BuiltInRegistriesMixin", + "resources.RegistryDataLoaderMixin", + "server.MainMixin", + "server.MinecraftServerMixin", + "server.PlayerAdvancementsMixin", + "server.ReloadableServerRegistriesMixin", + "server.ServerFunctionManagerMixin", + "server.ServerScoreboardMixin", + "server.WorldLoaderMixin", + "server.bossevents.CustomBossEventMixin", + "server.commands.BossBarCommandsMixin", + "server.commands.DifficultyCommandMixin", + "server.commands.GameRuleCommandMixin", + "server.commands.KickCommandMixin", + "server.commands.SaveAllCommandMixin", + "server.commands.TeleportCommandMixin", + "server.commands.WeatherCommandMixin", + "server.commands.WorldBorderCommandMixin", + "server.dedicated.DedicatedPlayerListMixin", + "server.level.ChunkHolderMixin", + "server.level.ChunkMap_TrackedEntityMixin", + "server.level.ChunkMapMixin", + "server.level.DistanceManagerMixin", + "server.level.GenerationChunkHolderMixin", + "server.level.ServerBossEventMixin", + "server.level.ServerChunkCacheMixin", + "server.level.ServerEntityMixin", + "server.level.ServerLevelMixin", + "server.level.ServerPlayer_ContainerListenerMixin", + "server.level.ServerPlayerGameModeMixin", + "server.level.ServerPlayerMixin", + "server.level.ServerPlayerMixin_HealthScale", + "server.level.TicketMixin", + "server.level.TicketStorageMixin", + "server.network.LegacyQueryHandlerMixin", + "server.network.ServerCommonPacketListenerImplMixin", + "server.network.ServerConfigurationPacketListenerImplMixin", + "server.network.ServerGamePacketListenerImpl_1Mixin", + "server.network.ServerGamePacketListenerImplMixin", + "server.network.ServerHandshakePacketListenerImplMixin", + "server.network.ServerLoginPacketListenerImplMixin", + "server.network.ServerStatusPacketListenerImplMixin", + "server.players.BanListEntryMixin", + "server.players.GameProfileCache_GameProfileInfoMixin", + "server.players.GameProfileCacheMixin", + "server.players.IpBanListEntryMixin", + "server.players.PlayerListMixin", + "server.players.SleepStatusMixin", + "server.players.StoredUserEntryMixin", + "server.players.StoredUserListMixin", + "server.rcon.RconConsoleSourceMixin", + "server.rcon.thread.QueryThreadGs4Mixin", + "server.rcon.thread.RconClientMixin", + "service.permission.SubjectMixin", + "util.ClassInstanceMultiMapMixin", + "util.datafix.schemas.V1125Mixin", + "world.BaseCommandBlockMixin", + "world.BossEventMixin", + "world.damagesource.DamageSourceMixin", + "world.damagesource.DamageSourcesMixin", + "world.entity.ActiveChunkReferentMixin", + "world.entity.AgableMobMixin", + "world.entity.EntityMaxAirMixin", + "world.entity.EntityMixin", + "world.entity.EntitySelectorMixin", + "world.entity.EntityTypeMixin", + "world.entity.ExperienceOrbMixin", + "world.entity.GrieferBridgeMixin", + "world.entity.LeashableMixin", + "world.entity.LightningBoltMixin", + "world.entity.LivingEntityMixin", + "world.entity.LivingEntityMixin_Attack_Impl", + "world.entity.MobMixin", + "world.entity.MobMixin_Attack_Impl", + "world.entity.PortalProcessorMixin", + "world.entity.ai.goal.BreakDoorGoalMixin", + "world.entity.ai.goal.BreedGoalMixin", + "world.entity.ai.goal.EatBlockGoalMixin", + "world.entity.ai.goal.GoalMixin", + "world.entity.ai.goal.GoalSelectorMixin", + "world.entity.ai.goal.RangedAttackGoalMixin", + "world.entity.ai.goal.RunAroundLikeCrazyGoalMixin", + "world.entity.ai.sensing.NearestLivingEntitySensorMixin", + "world.entity.ai.sensing.SensorMixin", + "world.entity.animal.AnimalMixin", + "world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin", + "world.entity.animal.OcelotMixin", + "world.entity.animal.ParrotMixin", + "world.entity.animal.Rabbit_RaidGardenGoalMixin", + "world.entity.animal.WolfMixin", + "world.entity.animal.horse.AbstractHorseMixin", + "world.entity.boss.enderdragon.EndCrystalMixin", + "world.entity.decoration.ArmorStandMixin", + "world.entity.decoration.BlockAttachedEntityMixin", + "world.entity.decoration.HangingEntityMixin", + "world.entity.decoration.ItemFrameMixin", + "world.entity.item.ItemEntityMixin", + "world.entity.item.PrimedTntMixin", + "world.entity.monster.Blaze_BlazeAttackGoalMixin", + "world.entity.monster.CreeperMixin", + "world.entity.monster.EnderMan_EndermanLeaveBlockGoalMixin", + "world.entity.monster.EnderMan_EndermanTakeBlockGoalMixin", + "world.entity.monster.EnderManMixin", + "world.entity.monster.EndermiteMixin", + "world.entity.monster.Ghast_GhastShootFireballGoalMixin", + "world.entity.monster.MonsterMixin", + "world.entity.monster.ShulkerMixin", + "world.entity.monster.Silverfish_SilverfishMergeWithStoneGoalMixin", + "world.entity.monster.Silverfish_SilverfishWakeUpFriendsGoalMixin", + "world.entity.monster.ZombifiedPiglinMixin", + "world.entity.npc.AbstractVillagerMixin", + "world.entity.npc.VillagerMixin", + "world.entity.npc.WanderingTraderMixin", + "world.entity.player.PlayerMixin", + "world.entity.player.PlayerMixin_Attack_Impl", + "world.entity.projectile.AbstractArrowMixin", + "world.entity.projectile.AbstractHurtingProjectileMixin", + "world.entity.projectile.EyeOfEnderMixin", + "world.entity.projectile.FireworkRocketEntityMixin", + "world.entity.projectile.FishingHookMixin", + "world.entity.projectile.LargeFireballMixin", + "world.entity.projectile.LlamaSpitMixin", + "world.entity.projectile.ProjectileMixin", + "world.entity.projectile.ProjectileUtilMixin", + "world.entity.projectile.ShulkerBulletMixin", + "world.entity.projectile.SmallFireballMixin", + "world.entity.projectile.SnowballMixin", + "world.entity.projectile.ThrowableProjectileMixin", + "world.entity.projectile.ThrownEggMixin", + "world.entity.projectile.ThrownEnderpearlMixin", + "world.entity.projectile.ThrownTridentMixin", + "world.entity.projectile.WitherSkullMixin", + "world.entity.vehicle.AbstractBoatMixin", + "world.entity.vehicle.AbstractMinecartContainerMixin", + "world.entity.vehicle.AbstractMinecartMixin", + "world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin", + "world.entity.vehicle.MinecartCommandBlockMixin", + "world.entity.vehicle.MinecartFurnaceMixin", + "world.entity.vehicle.MinecartTNTMixin", + "world.entity.vehicle.OldMinecartBehaviourMixin", + "world.entity.vehicle.VehicleEntityMixin", + "world.food.FoodDataMixin", + "world.inventory.StonecutterMenuMixin", + "world.item.ConsumableMixin", + "world.item.EnderEyeItemMixin", + "world.item.FireworkRocketItemMixin", + "world.item.FishingRodItemMixin", + "world.item.ItemCooldownsMixin", + "world.item.ItemMixin", + "world.item.ItemStackMixin", + "world.item.MapItemMixin", + "world.item.ServerItemCooldownsMixin", + "world.item.TeleportRandomlyConsumeEffectMixin", + "world.item.crafting.AbstractCookingRecipeMixin", + "world.item.crafting.AbstractCookingRecipeSerializerMixin", + "world.item.crafting.CustomRecipeSerializerMixin", + "world.item.crafting.IngredientMixin", + "world.item.crafting.RecipeManagerMixin", + "world.item.crafting.ShapedRecipe_SerializerMixin", + "world.item.crafting.ShapedRecipeMixin", + "world.item.crafting.ShapelessRecipe_SerializerMixin", + "world.item.crafting.ShapelessRecipeMixin", + "world.item.crafting.SingleItemRecipeMixin", + "world.item.crafting.SmithingTransformRecipe_SerializerMixin", + "world.item.crafting.SmithingTransformRecipeMixin", + "world.item.crafting.StonecutterRecipe_SerializerMixin", + "world.item.enchantment.EnchantmentMixin", + "world.level.BaseSpawnerMixin", + "world.level.BlockGetterMixin", + "world.level.Explosion_BlockInteractionMixin", + "world.level.LevelMixin", + "world.level.NaturalSpawner_SpawnStateMixin", + "world.level.NaturalSpawnerMixin", + "world.level.SavedDataMixin", + "world.level.ServerExplosionMixin", + "world.level.biome.BiomeSourceMixin", + "world.level.block.BaseFireBlockMixin", + "world.level.block.CactusBlockMixin", + "world.level.block.CampfireBlockMixin", + "world.level.block.CarvedPumpkinBlockMixin", + "world.level.block.CommandBlockMixin", + "world.level.block.EndPortalBlockMixin", + "world.level.block.FallingBlockMixin", + "world.level.block.FarmBlockMixin", + "world.level.block.FireBlockMixin", + "world.level.block.LeavesBlockMixin", + "world.level.block.MagmaBlockMixin", + "world.level.block.NetherPortalBlockMixin", + "world.level.block.NoteBlockMixin", + "world.level.block.PointedDripstoneBlockMixin", + "world.level.block.SweetBerryBushBlockMixin", + "world.level.block.TntBlockMixin", + "world.level.block.entity.AbstractFurnaceBlockEntityMixin", + "world.level.block.entity.BannerBlockEntityMixin", + "world.level.block.entity.BaseContainerBlockEntityMixin", + "world.level.block.entity.BeaconBlockEntityMixin", + "world.level.block.entity.BellBLockEntityMixin", + "world.level.block.entity.BlockEntityMixin", + "world.level.block.entity.BrewingStandBlockEntityMixin", + "world.level.block.entity.CampfireBlockEntityMixin", + "world.level.block.entity.CommandBlockEntity_Mixin", + "world.level.block.entity.CommandBlockEntityMixin", + "world.level.block.entity.EnchantmentTableBlockEntityMixin", + "world.level.block.entity.LecternBlockEntityMixin", + "world.level.block.entity.SignBlockEntityMixin", + "world.level.block.entity.SkullBlockEntityMixin", + "world.level.block.piston.PistonMovingBlockEntityMixin", + "world.level.block.state.BlockBehaviour_PropertiesMixin", + "world.level.block.state.BlockStateMixin", + "world.level.border.WorldBorderMixin", + "world.level.chunk.ChunkGeneratorMixin", + "world.level.chunk.ChunkStatusTasksMixin", + "world.level.chunk.LevelChunkMixin", + "world.level.chunk.SerializableChunkDataMixin", + "world.level.chunk.storage.EntityStorageMixin", + "world.level.chunk.storage.IOWorkerMixin", + "world.level.chunk.storage.RegionFileMixin", + "world.level.dimension.DimensionTypeMixin", + "world.level.dimension.LevelStemMixin", + "world.level.entity.PersistentEntitySectionManagerMixin", + "world.level.levelgen.NoiseGeneratorSettingsMixin", + "world.level.levelgen.WorldDimensionsMixin", + "world.level.levelgen.WorldOptionsMixin", + "world.level.levelgen.flat.FlatLayerInfoMixin", + "world.level.levelgen.flat.FlatLevelGeneratorSettingsMixin", + "world.level.levelgen.structure.LegacyStructureDataHandlerMixin", + "world.level.saveddata.MapIdTrackerMixin", + "world.level.storage.DimensionDataStorageMixin", + "world.level.storage.LevelDataMixin", + "world.level.storage.LevelStorageSource_LevelStorageAccessMixin", + "world.level.storage.PlayerDataStorageMixin", + "world.level.storage.PrimaryLevelDataMixin", + "world.level.storage.ServerLevelDataMixin", + "world.scores.ObjectiveMixin", + "world.scores.PlayerTeamMixin", + "world.scores.ScoreboardMixin", + "world.ticks.LevelChunkTicksMixin", + "world.ticks.LevelTicksMixin", + "world.ticks.ScheduledTickMixin" + ], + "client": [ + "client.MinecraftMixin", + "client.multiplayer.ClientCommonPacketListenerImplMixin", + "client.multiplayer.ClientHandshakePacketListenerImplMixin", + "client.multiplayer.ClientLevelMixin", + "client.network.chat.TranslatableContentsMixin", + "client.player.AbstractClientPlayerMixin", + "client.player.LocalPlayerMixin", + "client.server.IntegratedPlayerListMixin", + "client.server.IntegratedServerMixin", + "server.network.MemoryServerHandshakePacketListenerImplMixin" + ], + "server": [ + "server.dedicated.DedicatedServerMixin", + "server.dedicated.ServerWatchdogMixin" + ], + "injectors": { + "maxShiftBy": 3 + }, + "overwrites": { + "conformVisibility": true } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/chat/ChatFormatter.java b/vanilla/src/main/java/org/spongepowered/vanilla/chat/ChatFormatter.java index 7922090389c..5e85e22e6cb 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/chat/ChatFormatter.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/chat/ChatFormatter.java @@ -73,11 +73,13 @@ public static MutableComponent format(final String s) { final String displayUrl = s.substring(start, end); String url = displayUrl; + final URI toOpen; try { if (new URI(url).getScheme() == null) { url = ChatFormatter.DEFAULT_SCHEME + url; } + toOpen = new URI(url); } catch (final URISyntaxException e) { continue; // Invalid URL so just ignore it } @@ -93,7 +95,7 @@ public static MutableComponent format(final String s) { pos = end; final MutableComponent link = Component.literal(displayUrl); - link.setStyle(link.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); + link.setStyle(link.getStyle().withClickEvent(new ClickEvent.OpenUrl(toOpen))); if (result == null) { result = Component.literal(""); diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index e1eb98debb0..73e36cc4d27 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -328,6 +328,7 @@ public static Component newChatWithLinks(final String string, final boolean allo lastEnd = end; String url = string.substring(start, end); final MutableComponent link = Component.literal(url); + final URI toOpen; try { // Add schema so client doesn't crash. @@ -340,8 +341,9 @@ public static Component newChatWithLinks(final String string, final boolean allo } continue; } - url = "http://" + url; + url = "https://" + url; } + toOpen = new URI(url); } catch (final URISyntaxException e) { // Bad syntax bail out! if (ichat == null) { @@ -353,7 +355,7 @@ public static Component newChatWithLinks(final String string, final boolean allo } // Set the click event and append the link. - final ClickEvent click = new ClickEvent(ClickEvent.Action.OPEN_URL, url); + final ClickEvent click = new ClickEvent.OpenUrl(toOpen); link.withStyle(style -> style.withClickEvent(click) .withUnderlined(true) .withColor(ChatFormatting.BLUE)); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index ccb7d33c84a..873ed2d1964 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -26,6 +26,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.animal.Wolf; @@ -53,9 +54,9 @@ public abstract class LivingEntityMixin_Attack_Impl { } @Redirect(method = "resolvePlayerResponsibleForDamage", - at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwner()Lnet/minecraft/world/entity/LivingEntity;")) - private LivingEntity attackImpl$onWolfGetOwner(@Coerce final Object instance) { - return ((TamableAnimal)instance).getOwner(); + at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwnerReference()Lnet/minecraft/world/entity/EntityReference;")) + private EntityReference attackImpl$onWolfGetOwner(@Coerce final Object instance) { + return ((TamableAnimal)instance).getOwnerReference(); } /** From 6539a0c4f7bb5456db81f60bab5d4fbf858d9650 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 13 Jan 2025 02:59:10 +0200 Subject: [PATCH 175/586] spotlessApply --- .../event/server/level/ServerPlayerMixin_Inventory.java | 2 +- .../server/level/ServerPlayerMixin_Shared_Inventory.java | 2 +- .../server/level/ServerPlayerGameModeMixin_Tracker.java | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 8a1e775dec9..29c6c199e2c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; -import net.minecraft.server.level.ServerLevel; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; @@ -32,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; import net.minecraft.network.protocol.game.ClientboundHorseScreenOpenPacket; import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.Container; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java index dbb9965f1fd..3009ea343da 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; -import net.minecraft.server.level.ServerLevel; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Cancellable; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.EntityType; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 6607d034325..e258b443cae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -39,7 +39,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -57,9 +56,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.accessor.server.level.ServerPlayerAccessor; import org.spongepowered.common.bridge.server.level.ServerPlayerGameModeBridge; -import org.spongepowered.common.bridge.world.inventory.container.ContainerBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; -import org.spongepowered.common.event.inventory.InventoryEventFactory; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; @@ -71,7 +68,6 @@ import org.spongepowered.common.registry.provider.DirectionFacingProvider; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; -import org.spongepowered.math.vector.Vector3i; @Mixin(ServerPlayerGameMode.class) public abstract class ServerPlayerGameModeMixin_Tracker { From 68d8ce703e5cc0205e00383511dc746949100890 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 13 Jan 2025 22:26:54 +0100 Subject: [PATCH 176/586] Fix merge --- .../mixin/tracker/server/level/ServerLevelMixin_Tracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 47920777f33..79538adcfa0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -534,7 +534,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final WorldPipeline pipeline = pipelineBuilder .addEffect((pipeline1, oldState, newState, flag, limit1) -> { - pipeline1.getServerWorld().gameEvent(GameEvent.BLOCK_DESTROY, oldState.pos, GameEvent.Context.of(p_241212_3_, oldState.state)); + pipeline1.getServerWorld().gameEvent(GameEvent.BLOCK_DESTROY, oldState.pos(), GameEvent.Context.of(p_241212_3_, oldState.state())); return EffectResult.NULL_PASS; }) .addEffect(WorldBlockChangeCompleteEffect.getInstance()) From e55b332d35f7ad02d836b05ad24a2aacd9b3ed2c Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 15 Jan 2025 00:46:36 +0200 Subject: [PATCH 177/586] Update verification metadata --- gradle/verification-metadata.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 68e8994380f..918b263ca53 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -718,6 +718,9 @@ + + + @@ -1032,6 +1035,9 @@ + + + @@ -7413,6 +7419,9 @@ + + + From 83fc2ca358555e9466ab440ea840ffdac430e8b0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 15 Jan 2025 19:06:16 -0800 Subject: [PATCH 178/586] feat: update api content and changes for 25w03a Changes: - Entity.moveTo is renamed snapTo - Entities are moving slowly to components and hiding their data accessors, but nothing monumental yet on this front. There will be more developments in the future to harness the usage of the now-fully-included GameTest framework from Mojang. We'll be able to use this to our better advantage to verify several thousand interactions that otherwise manual testing will often forget. See https://minecraft.wiki/w/Java_Edition_25w03a --- SpongeAPI | 2 +- .../BlockStatePropertiesGenerator.java | 2 + .../BlockStatePropertyKeysGenerator.java | 2 + .../vanilla/generator/GeneratorMain.java | 17 +++++++++ gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++ .../entity/animal/frog/FrogAccessor.java | 37 ++++++++++++++++++ .../util/datafix/schemas/V100Accessor.java | 2 +- .../world/entity/ExperienceOrbAccessor.java | 6 +-- .../world/entity/animal/CatAccessor.java | 5 +++ .../world/entity/animal/FoxAccessor.java | 2 + .../entity/animal/MooshroomAccessor.java | 35 +++++++++++++++++ .../world/entity/animal/ParrotAccessor.java | 35 +++++++++++++++++ .../world/entity/animal/PigAccessor.java | 12 ++---- .../world/entity/animal/RabbitAccessor.java | 35 +++++++++++++++++ .../entity/animal/TropicalFishAccessor.java | 5 +++ .../entity/animal/horse/LlamaAccessor.java | 1 + .../entity/decoration/PaintingAccessor.java | 38 +++++++++++++++++++ .../resources/mixins.sponge.accessors.json | 7 +++- .../adventure/ComponentFlattenerProvider.java | 10 +++-- .../GsonComponentSerializerProviderImpl.java | 6 +-- .../adventure/NativeComponentRenderer.java | 2 +- .../NbtLegacyHoverEventSerializer.java | 2 +- .../common/adventure/SpongeAdventure.java | 6 ++- .../entity/SpongeBlockEntityArchetype.java | 1 + .../command/SpongeParameterizedCommand.java | 3 +- .../data/fixer/entity/EntityTrackedUser.java | 1 + .../data/fixer/world/SpongeLevelFixer.java | 1 + .../provider/block/entity/BannerData.java | 11 +----- .../common/data/provider/entity/CatData.java | 2 +- .../provider/entity/EnderCrystalData.java | 7 +++- .../common/data/provider/entity/FoxData.java | 2 +- .../common/data/provider/entity/FrogData.java | 3 +- .../data/provider/entity/LivingData.java | 8 +++- .../data/provider/entity/LlamaData.java | 2 +- .../data/provider/entity/MooshroomData.java | 3 +- .../data/provider/entity/PaintingData.java | 5 ++- .../data/provider/entity/ParrotData.java | 3 +- .../common/data/provider/entity/PigData.java | 19 +++++++++- .../data/provider/entity/RabbitData.java | 3 +- .../provider/entity/TropicalFishData.java | 18 ++------- .../data/provider/entity/VillagerData.java | 26 +++++++++---- .../provider/entity/ZombieVillagerData.java | 20 +++++++--- .../item/stack/SpawnEggItemStackData.java | 2 +- .../common/entity/SpongeEntityArchetype.java | 2 +- .../event/SpongeCommonEventFactory.java | 4 +- .../inventory/InventoryEventFactory.java | 2 +- .../event/manager/SpongeEventManager.java | 1 + .../effect/OldBlockOnReplaceEffect.java | 2 +- .../phase/packet/PacketPhaseUtil.java | 6 --- .../SpongeViewableInventoryBuilder.java | 2 +- .../item/ItemStackDataComponentsUpdater.java | 1 + ...ckSnapshotDuplicateManipulatorUpdater.java | 1 + .../common/item/SpongeItemStack.java | 4 +- .../packet/SpongeBasicPacketChannel.java | 1 + .../profile/UncachedGameProfileProvider.java | 3 +- .../loader/CommandRegistryLoader.java | 7 ++-- .../loader/VanillaRegistryLoader.java | 27 +++++++------ .../server/ServerConsoleSystemSubject.java | 1 + .../game/pagination/PaginationCalculator.java | 7 ++-- .../SpongeStructurePlacementBuilder.java | 1 + .../world/server/SpongeWorldManager.java | 1 + .../world/entity/SaddleableMixin_API.java | 11 ++++-- .../text/AbstractComponentMixin.java | 1 + .../core/server/PlayerAdvancementsMixin.java | 1 + .../server/commands/TeleportCommandMixin.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 1 + .../ServerGamePacketListenerImplMixin.java | 13 ++++--- .../core/server/players/PlayerListMixin.java | 3 +- .../mixin/core/world/entity/EntityMixin.java | 26 +++++-------- .../mixin/core/world/entity/MobMixin.java | 6 ++- .../animal/horse/AbstractHorseMixin.java | 7 +--- .../entity/vehicle/MinecartTNTMixin.java | 1 - .../mixin/core/world/item/ItemStackMixin.java | 1 + .../mixin/core/world/level/LevelMixin.java | 6 +-- .../block/PointedDripstoneBlockMixin.java | 2 +- .../block/entity/BannerBlockEntityMixin.java | 6 ++- ...StorageSource_LevelStorageAccessMixin.java | 1 + .../level/storage/PrimaryLevelDataMixin.java | 2 +- .../entity/LivingEntityMixin_Inventory.java | 22 +++++------ ...PacketListenerImplMixin_MovementCheck.java | 2 +- 81 files changed, 441 insertions(+), 167 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java diff --git a/SpongeAPI b/SpongeAPI index 2807da58dfa..dda072f463d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 2807da58dfafb891c0372b1efedec6473ffb64c0 +Subproject commit dda072f463df48ed60f275d55a0f966b2280d449 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 1c33db93fca..42c43f0c7db 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -59,6 +59,7 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; +import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; @@ -150,6 +151,7 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertiesGenerator.inDataTypePkg("TrialSpawnerState")); vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertiesGenerator.inDataTypePkg("VaultState")); vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeartState")); + vanillaEnumTypeMapping.put(TestBlockMode.class, BlockStatePropertiesGenerator.inDataTypePkg("TestBlockMode")); // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertiesGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index cfde2f85d61..2950b25a61b 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -60,6 +60,7 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; +import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import net.minecraft.world.level.block.state.properties.WallSide; import org.tinylog.Logger; @@ -148,6 +149,7 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("TrialSpawnerState")); vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("VaultState")); vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CreakingHeartState")); + vanillaEnumTypeMapping.put(TestBlockMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("TestBlockMode")); // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertyKeysGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 477370e700c..de1e17da8c1 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -75,6 +75,7 @@ import net.minecraft.world.level.block.state.properties.DripstoneThickness; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; +import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.scores.DisplaySlot; @@ -261,6 +262,13 @@ private static List generators(final Context context) { "getSerializedName", "sponge" ), + new EnumEntriesValidator<>( + "data.type", + "TestBlockModes", + TestBlockMode.class, + "getSerializedName", + "sponge" + ), new EnumEntriesValidator<>( "data.type", "DyeColors", @@ -710,6 +718,15 @@ private static List generators(final Context context) { Registries.PLACEMENT_MODIFIER_TYPE, $ -> true, RegistryScope.SERVER ), + new RegistryEntriesGenerator<>( + "data.type", + "PigTypes", + "PIG_TYPE", + context.relativeClass("data.type", "PigType"), + Registries.PIG_VARIANT, + $ -> true, + RegistryScope.SERVER + ), new TagGenerator( "BLOCK_TYPE", Registries.BLOCK, diff --git a/gradle.properties b/gradle.properties index afcbac45aa5..d8e926bfc54 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w02a +minecraftVersion=25w03a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 35039e990f4..e3dd6a8fa80 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1493,6 +1493,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java new file mode 100644 index 00000000000..74cf5206289 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.entity.animal.frog; + +import net.minecraft.core.Holder; +import net.minecraft.world.entity.animal.FrogVariant; +import net.minecraft.world.entity.animal.frog.Frog; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Frog.class) +public interface FrogAccessor { + + @Invoker("setVariant") void invoker$setVariant(Holder variant); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/util/datafix/schemas/V100Accessor.java b/src/accessors/java/org/spongepowered/common/accessor/util/datafix/schemas/V100Accessor.java index 86f40439adb..87a31ea054c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/util/datafix/schemas/V100Accessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/util/datafix/schemas/V100Accessor.java @@ -34,7 +34,7 @@ @Mixin(V100.class) public interface V100Accessor { - @Invoker("equipment") + @Invoker("lambda$registerTypes$0") static TypeTemplate invoker$equipment(final Schema schema) { throw new UntransformedInvokerError(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ExperienceOrbAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ExperienceOrbAccessor.java index c1e51d24e25..a923dcf2443 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/ExperienceOrbAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/ExperienceOrbAccessor.java @@ -26,13 +26,13 @@ import net.minecraft.world.entity.ExperienceOrb; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(ExperienceOrb.class) public interface ExperienceOrbAccessor { - @Accessor("value") int accessor$value(); + @Invoker("getValue") int accessor$value(); - @Accessor("value") void accessor$value(final int value); + @Invoker("setValue") void accessor$value(final int value); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java index 0612395f449..22d4b2e3cf4 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.accessor.world.entity.animal; +import net.minecraft.core.Holder; import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.animal.CatVariant; import net.minecraft.world.item.DyeColor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @@ -37,4 +39,7 @@ public interface CatAccessor { @Invoker("setRelaxStateOne") void invoker$setRelaxStateOne(boolean $$0); @Invoker("isRelaxStateOne") boolean invoker$isRelaxStateOne(); + + @Invoker("setVariant") void invoker$setVariant(Holder $$0); + } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java index 5fdf5b9ede6..60245abf302 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java @@ -54,4 +54,6 @@ public interface FoxAccessor { @Invoker("setSleeping") void invoker$setSleeping(final boolean sleeping); + @Invoker("setVariant") void invoker$setVariant(Fox.Variant v); + } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java new file mode 100644 index 00000000000..90a3a1b3400 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.animal; + +import net.minecraft.world.entity.animal.MushroomCow; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(MushroomCow.class) +public interface MooshroomAccessor { + + @Invoker("setVariant") void invoker$setVariant(MushroomCow.Variant type); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java new file mode 100644 index 00000000000..2a8964e32ee --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.animal; + +import net.minecraft.world.entity.animal.Parrot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Parrot.class) +public interface ParrotAccessor { + + @Invoker("setVariant") void invoker$setVariant(Parrot.Variant v); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java index 86fc53175d3..dfaef2f422e 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java @@ -24,19 +24,15 @@ */ package org.spongepowered.common.accessor.world.entity.animal; -import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.entity.ItemBasedSteering; +import net.minecraft.core.Holder; import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.entity.animal.PigVariant; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.common.UntransformedAccessorError; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Pig.class) public interface PigAccessor { - @Accessor("DATA_SADDLE_ID") static EntityDataAccessor accessor$DATA_SADDLE_ID() { - throw new UntransformedAccessorError(); - } + @Invoker("setVariant") void invoker$setVariant(Holder $$0x); - @Accessor("steering") ItemBasedSteering accessor$steering(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java new file mode 100644 index 00000000000..167e4e0ef4d --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.animal; + +import net.minecraft.world.entity.animal.Rabbit; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Rabbit.class) +public interface RabbitAccessor { + + @Invoker("setVariant") void invoker$setVariant(Rabbit.Variant v); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java index 5ba9a299527..1da1181ff1a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java @@ -41,5 +41,10 @@ public interface TropicalFishAccessor { @Invoker("setPackedVariant") void invoker$setPackedVariant(final int packedVariant); + @Invoker("setPattern") void invoker$setPattern(final TropicalFish.Pattern v); + + @Invoker("setBaseColor") void invoker$setBaseColor(DyeColor v); + + @Invoker("setPatternColor") void invoker$setPatternColor(DyeColor v); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java index 6f27f6078cc..71dbf4dce10 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java @@ -33,4 +33,5 @@ public interface LlamaAccessor { @Invoker("setStrength") void invoker$setStrength(final int strength); + @Invoker("setVariant") void invoker$setVariant(Llama.Variant v); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java new file mode 100644 index 00000000000..c9f442fadfa --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.decoration; + +import net.minecraft.core.Holder; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.decoration.PaintingVariant; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Painting.class) +public interface PaintingAccessor { + + @Invoker("setVariant") void invoker$setVariant(Holder newArt); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 6a7acd2180b..599efa99b8c 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -19,6 +19,7 @@ "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", "commands.arguments.selector.options.EntitySelectorOptionsAccessor", "core.MappedRegistryAccessor", + "entity.animal.frog.FrogAccessor", "entity.passive.AbstractChestedHorseEntityAccessor", "network.ConnectionAccessor", "network.chat.StyleAccessor", @@ -73,10 +74,13 @@ "world.entity.animal.AnimalAccessor", "world.entity.animal.CatAccessor", "world.entity.animal.FoxAccessor", + "world.entity.animal.MooshroomAccessor", "world.entity.animal.OcelotAccessor", "world.entity.animal.PandaAccessor", + "world.entity.animal.ParrotAccessor", "world.entity.animal.PigAccessor", "world.entity.animal.PufferfishAccessor", + "world.entity.animal.RabbitAccessor", "world.entity.animal.SheepAccessor", "world.entity.animal.TropicalFishAccessor", "world.entity.animal.TurtleAccessor", @@ -90,6 +94,7 @@ "world.entity.decoration.ArmorStandAccessor", "world.entity.decoration.HangingEntityAccessor", "world.entity.decoration.ItemFrameAccessor", + "world.entity.decoration.PaintingAccessor", "world.entity.item.FallingBlockEntityAccessor", "world.entity.item.PrimedTntAccessor", "world.entity.monster.BlazeAccessor", @@ -215,5 +220,5 @@ ], "server": [ "server.dedicated.DedicatedServerAccessor" - ] + ] } diff --git a/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java b/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java index 1ba92503998..f49e51a4931 100644 --- a/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java +++ b/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java @@ -25,8 +25,10 @@ package org.spongepowered.common.adventure; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.KeybindComponent; import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.TranslationArgument; import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.translation.TranslationRegistry; @@ -56,7 +58,7 @@ final class ComponentFlattenerProvider { builder.complexMapper(TranslatableComponent.class, (component, consumer) -> { final String key = component.key(); - for (final Translator registry : GlobalTranslator.get().sources()) { + for (final Translator registry : GlobalTranslator.translator().sources()) { if (registry instanceof TranslationRegistry && ((TranslationRegistry) registry).contains(key)) { consumer.accept(GlobalTranslator.render(component, Locale.getDefault())); return; @@ -65,7 +67,7 @@ final class ComponentFlattenerProvider { final /* @NonNull */ String translated = Language.getInstance().getOrDefault(key); final Matcher matcher = ComponentFlattenerProvider.LOCALIZATION_PATTERN.matcher(translated); - final List args = component.args(); + final List args = component.arguments(); int argPosition = 0; int lastIdx = 0; while (matcher.find()) { @@ -81,7 +83,7 @@ final class ComponentFlattenerProvider { try { final int idx = Integer.parseInt(argIdx); if (idx < args.size()) { - consumer.accept(args.get(idx)); + consumer.accept(ComponentLike.unbox(args.get(idx))); } } catch (final NumberFormatException ex) { // ignore, drop the format placeholder @@ -89,7 +91,7 @@ final class ComponentFlattenerProvider { } else { final int idx = argPosition++; if (idx < args.size()) { - consumer.accept(args.get(idx)); + consumer.accept(ComponentLike.unbox(args.get(idx))); } } } diff --git a/src/main/java/org/spongepowered/common/adventure/GsonComponentSerializerProviderImpl.java b/src/main/java/org/spongepowered/common/adventure/GsonComponentSerializerProviderImpl.java index f7a144772ae..02172530d05 100644 --- a/src/main/java/org/spongepowered/common/adventure/GsonComponentSerializerProviderImpl.java +++ b/src/main/java/org/spongepowered/common/adventure/GsonComponentSerializerProviderImpl.java @@ -29,13 +29,13 @@ import java.util.function.Consumer; -@SuppressWarnings("UnstableApiUsage") // permitted provider +@SuppressWarnings({"UnstableApiUsage", "deprecation"}) // permitted provider public final class GsonComponentSerializerProviderImpl implements GsonComponentSerializer.Provider { @Override public @NonNull GsonComponentSerializer gson() { return GsonComponentSerializer.builder() - .legacyHoverEventSerializer(NbtLegacyHoverEventSerializer.INSTANCE) - .build(); + .legacyHoverEventSerializer(NbtLegacyHoverEventSerializer.INSTANCE) + .build(); } @Override diff --git a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java index b740f9cae50..c849f111ae7 100644 --- a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java +++ b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java @@ -102,7 +102,7 @@ public Component render(@NonNull MutableComponent component, final @NonNull C co private HoverEvent renderHoverEvent(final HoverEvent input, final @NonNull C context) { return switch (input) { case HoverEvent.ShowText st -> { - final Component original = st.text(); + final Component original = st.value(); yield new HoverEvent.ShowText(this.render(original.copy(), context)); } case HoverEvent.ShowEntity se -> { diff --git a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java index db6a3a6aafe..b03bbdd8979 100644 --- a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java +++ b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java @@ -40,7 +40,7 @@ import java.io.IOException; import java.util.UUID; -@SuppressWarnings("PatternValidation") +@SuppressWarnings({"PatternValidation","deprecation"}) public final class NbtLegacyHoverEventSerializer implements LegacyHoverEventSerializer { public static final NbtLegacyHoverEventSerializer INSTANCE = new NbtLegacyHoverEventSerializer(); private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index cc81288b6e3..4e4ef4dcc4d 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -248,12 +248,13 @@ public static MutableComponent asVanillaMutable(final Component component) { return vanilla; } + @SuppressWarnings("deprecation") private static MutableComponent asVanillaMutable0(final Component component) { if (component instanceof TextComponent) { return net.minecraft.network.chat.Component.literal(((TextComponent) component).content()); } if (component instanceof final TranslatableComponent $this) { - final List with = new ArrayList<>($this.args().size()); + final List with = new ArrayList<>($this.arguments().size()); for (final Component arg : $this.args()) { with.add(((ComponentBridge) arg).bridge$asVanillaComponent()); } @@ -305,6 +306,7 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c return builder.build(); } + @SuppressWarnings("deprecation") private static ComponentBuilder asAdventureBuilder(final ComponentContents contents) { if (contents instanceof final PlainTextContents lc) { if (contents == PlainTextContents.EMPTY) { @@ -519,7 +521,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv SpongeAdventure.asAdventure(value.name) ); case net.minecraft.network.chat.HoverEvent.ShowText st: - yield HoverEvent.showText(SpongeAdventure.asAdventure(st.text())); + yield HoverEvent.showText(SpongeAdventure.asAdventure(st.value())); default: throw new IllegalStateException("Unexpected value: " + event); }; diff --git a/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java b/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java index f4331bc2054..08aaf25943d 100644 --- a/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java @@ -91,6 +91,7 @@ public DataContainer blockEntityData() { return NBTTranslator.INSTANCE.translateFrom(this.compound); } + @SuppressWarnings("deprecation") @Override public Optional apply(final ServerLocation location) { final BlockState currentState = location.block(); diff --git a/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java b/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java index 4fc69d8a08c..6c8483c6847 100644 --- a/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java +++ b/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java @@ -29,6 +29,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.tree.LiteralCommandNode; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; import net.minecraft.commands.CommandSourceStack; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -121,7 +122,7 @@ public boolean canExecute(final @NonNull CommandCause cause) { final Collection usage = Arrays.stream(this.getCachedDispatcher().getAllUsage(this.getCachedDispatcher().getRoot(), (CommandSourceStack) cause, true)) .map(Component::text).collect(Collectors.toList()); - return Component.join(Component.newline(), usage); + return Component.join(JoinConfiguration.separator(Component.newline()), usage); } @Override diff --git a/src/main/java/org/spongepowered/common/data/fixer/entity/EntityTrackedUser.java b/src/main/java/org/spongepowered/common/data/fixer/entity/EntityTrackedUser.java index 7dc5bc68a28..e42ae6c73b8 100644 --- a/src/main/java/org/spongepowered/common/data/fixer/entity/EntityTrackedUser.java +++ b/src/main/java/org/spongepowered/common/data/fixer/entity/EntityTrackedUser.java @@ -41,6 +41,7 @@ public EntityTrackedUser(Schema outputSchema, boolean changesType) { super(outputSchema, changesType); } + @SuppressWarnings("deprecation") @Override protected TypeRewriteRule makeRule() { final Type entityType = this.getInputSchema().getType(References.ENTITY); diff --git a/src/main/java/org/spongepowered/common/data/fixer/world/SpongeLevelFixer.java b/src/main/java/org/spongepowered/common/data/fixer/world/SpongeLevelFixer.java index 08aa997b8c3..e6ffbcbae8a 100644 --- a/src/main/java/org/spongepowered/common/data/fixer/world/SpongeLevelFixer.java +++ b/src/main/java/org/spongepowered/common/data/fixer/world/SpongeLevelFixer.java @@ -49,6 +49,7 @@ public TypeRewriteRule makeRule() { ); } + @SuppressWarnings("deprecation") private Typed fixPlayerIdTable(Typed typed, Type levelType) { Type fieldType = levelType.findFieldType(Constants.Sponge.LEGACY_SPONGE_PLAYER_UUID_TABLE); OpticFinder> listFinder = DSL.fieldFinder(Constants.Sponge.LEGACY_SPONGE_PLAYER_UUID_TABLE, (List.ListType)fieldType); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java index 8efdcc317bb..7f1533ab577 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java @@ -56,22 +56,15 @@ public static void register(final DataProviderRegistrator registrator) { } return false; }) + .asImmutable(BannerBlockEntity.class) .create(Keys.DYE_COLOR) .get(h -> ((BannerBlockEntityBridge) h).bridge$getBaseColor()) - .setAnd((h, v) -> { - final Level world = h.getLevel(); - if (world != null && !world.isClientSide) { - ((BannerBlockEntityBridge) h).bridge$setBaseColor(v); - return true; - } - return false; - }); + ; } // @formatter:on private static void applyBannerPatternLayers(final BannerBlockEntity h, final List v) { final DataComponentMap.Builder builder = DataComponentMap.builder(); builder.addAll(h.collectComponents()); - // TODO base color? builder.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers(v.stream().map(BannerPatternLayers.Layer.class::cast).toList())); final DataComponentMap components = builder.build(); h.applyComponents(components, DataComponentPatch.EMPTY); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java index e5b33daf25b..df121f7f3de 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java @@ -45,7 +45,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Cat.class) .create(Keys.CAT_TYPE) .get(h -> (CatType) (Object) h.getVariant().value()) - .set((h, v) -> h.setVariant(Holder.direct((CatVariant) (Object) v))) + .set((h, v) -> ((CatAccessor) h).invoker$setVariant(Holder.direct((CatVariant) (Object) v))) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) h.getCollarColor()) .set((h, v) -> ((CatAccessor)h).invoker$setCollarColor((net.minecraft.world.item.DyeColor) (Object) v)) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EnderCrystalData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EnderCrystalData.java index 44fa3a18e24..8cf97d1aa6b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EnderCrystalData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EnderCrystalData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import org.spongepowered.api.data.Keys; @@ -50,7 +51,11 @@ public static void register(final DataProviderRegistrator registrator) { return false; } if (v == 0) { - h.hurt((DamageSource) SpongeDamageSources.IGNORED, 1000F); + final var damageSource = (DamageSource) SpongeDamageSources.IGNORED; + switch (h.level()) { + case ServerLevel sl -> h.hurtServer(sl, damageSource, 1000F); + default -> h.hurtClient(damageSource); + } } else { ((EntityAccessor) h).invoker$unsetRemoved(); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java index 7d53c7a814f..7ee1a7afe41 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java @@ -47,7 +47,7 @@ public static void register(final DataProviderRegistrator registrator) { .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v).map(EntityReference::new))) .create(Keys.FOX_TYPE) .get(h -> (FoxType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((Fox.Variant) (Object) v)) + .set((h, v) -> ((FoxAccessor) h ).invoker$setVariant((Fox.Variant) (Object) v)) .create(Keys.IS_CROUCHING) .get(Fox::isCrouching) .set(Fox::setIsCrouching) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java index 2fef31a0006..eb73c266c42 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java @@ -29,6 +29,7 @@ import net.minecraft.world.entity.animal.frog.Frog; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.FrogType; +import org.spongepowered.common.accessor.entity.animal.frog.FrogAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class FrogData { @@ -42,7 +43,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Frog.class) .create(Keys.FROG_TYPE) .get(h -> (FrogType) (Object) h.getVariant().value()) - .set((h, v) -> h.setVariant(BuiltInRegistries.FROG_VARIANT.wrapAsHolder((FrogVariant) (Object) v))); + .set((h, v) -> ((FrogAccessor) h).invoker$setVariant(BuiltInRegistries.FROG_VARIANT.wrapAsHolder((FrogVariant) (Object) v))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/LivingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/LivingData.java index c26f30fd7de..b6a73bb93cf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/LivingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/LivingData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.entity; import com.google.common.collect.ImmutableMap; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; @@ -164,8 +165,11 @@ public static void register(final DataProviderRegistrator registrator) { } if (v == 0) { - // Cause DestructEntityEvent to fire first - h.hurt((DamageSource) SpongeDamageSources.IGNORED, Float.MAX_VALUE); + final var ignoredSource = (DamageSource) SpongeDamageSources.IGNORED; + switch (h.level()) { + case ServerLevel sl -> h.hurtServer(sl, ignoredSource, Float.MAX_VALUE); + default -> h.hurtClient(ignoredSource); + } } h.setHealth(v.floatValue()); return true; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java b/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java index c69b7e79fbf..9ef0758d1ca 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java @@ -45,7 +45,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Llama.class) .create(Keys.LLAMA_TYPE) .get(h -> (LlamaType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((Llama.Variant) (Object) v)); + .set((h, v) -> ((LlamaAccessor) h).invoker$setVariant((Llama.Variant) (Object) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java index 61fdd8ad81e..e340e1f6774 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.animal.MushroomCow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.MooshroomType; +import org.spongepowered.common.accessor.world.entity.animal.MooshroomAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class MooshroomData { @@ -40,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(MushroomCow.class) .create(Keys.MOOSHROOM_TYPE) .get(h -> (MooshroomType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((MushroomCow.Variant) (Object) v)); + .set((h, v) -> ((MooshroomAccessor) h).invoker$setVariant((MushroomCow.Variant) (Object) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java index 97771ab0dfc..c108c75cfaa 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java @@ -37,6 +37,7 @@ import org.spongepowered.common.accessor.server.level.ChunkMapAccessor; import org.spongepowered.common.accessor.server.level.ChunkMap_TrackedEntityAccessor; import org.spongepowered.common.accessor.world.entity.decoration.HangingEntityAccessor; +import org.spongepowered.common.accessor.world.entity.decoration.PaintingAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class PaintingData { @@ -54,10 +55,10 @@ public static void register(final DataProviderRegistrator registrator) { if (!h.level().isClientSide) { final Holder oldArt = h.getVariant(); var newArt = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); - h.setVariant(newArt); + ((PaintingAccessor) h).invoker$setVariant(newArt); ((HangingEntityAccessor) h).invoker$setDirection(h.getDirection()); if (!h.survives()) { - h.setVariant(oldArt); + ((PaintingAccessor) h).invoker$setVariant(oldArt); ((HangingEntityAccessor) h).invoker$setDirection(h.getDirection()); return false; } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java index fc944968918..b3b80751a6d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.animal.Parrot; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ParrotType; +import org.spongepowered.common.accessor.world.entity.animal.ParrotAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class ParrotData { @@ -40,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Parrot.class) .create(Keys.PARROT_TYPE) .get(h -> (ParrotType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((Parrot.Variant) (Object) v)); + .set((h, v) -> ((ParrotAccessor) h).invoker$setVariant((Parrot.Variant) (Object) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java index 310a184ba5a..557e6499dcc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java @@ -24,8 +24,14 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.entity.animal.PigVariant; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.PigType; import org.spongepowered.common.accessor.world.entity.animal.PigAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -42,11 +48,20 @@ public static void register(final DataProviderRegistrator registrator) { .get(Pig::isSaddled) .set((h, v) -> { if (v) { - h.equipSaddle(null, null); + h.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); } else { - ((PigAccessor) h).accessor$steering().setSaddle(false); + h.setItemSlot(EquipmentSlot.SADDLE, new ItemStack(Items.SADDLE)); } }) + .create(Keys.PIG_TYPE) + .get(p -> (PigType) p.getVariant().value()) + .setAnd((h, v) -> h.level().registryAccess().lookup(Registries.PIG_VARIANT) + .map(r -> { + var newPigType = r.wrapAsHolder((PigVariant) (Object) v); + ((PigAccessor) h).invoker$setVariant(newPigType); + return true; + }) + .orElse(false)) ; } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java b/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java index 0b46e9f5e36..ddf8e108a5d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.animal.Rabbit; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.RabbitType; +import org.spongepowered.common.accessor.world.entity.animal.RabbitAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class RabbitData { @@ -40,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Rabbit.class) .create(Keys.RABBIT_TYPE) .get(h -> (RabbitType) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((Rabbit.Variant) (Object) v)); + .set((h, v) -> ((RabbitAccessor) h).invoker$setVariant((Rabbit.Variant) (Object) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java index ee71f85dfaa..204556b1a10 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java @@ -42,24 +42,14 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(TropicalFish.class) // Fish variant is: size | pattern << 8 | bodyColor << 16 | patternColor << 24 .create(Keys.TROPICAL_FISH_SHAPE) - .get(h -> (TropicalFishShape) (Object) h.getVariant()) - .set((h, v) -> h.setVariant((TropicalFish.Pattern) (Object) v)) + .get(h -> (TropicalFishShape) (Object) h.getPattern()) + .set((h, v) -> ((TropicalFishAccessor) h).invoker$setPattern((TropicalFish.Pattern) (Object) v)) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) h.getBaseColor()) - .set((h, v) -> { - final net.minecraft.world.item.DyeColor patternColor = h.getPatternColor(); - final TropicalFish.Pattern type = h.getVariant(); - final int variant = TropicalFishAccessor.invoker$packVariant(type, (net.minecraft.world.item.DyeColor) (Object) v, patternColor); - ((TropicalFishAccessor) h).invoker$setPackedVariant(variant); - }) + .set((h, v) -> ((TropicalFishAccessor) h).invoker$setBaseColor((net.minecraft.world.item.DyeColor) (Object) v)) .create(Keys.PATTERN_COLOR) .get(h -> (DyeColor) (Object) h.getPatternColor()) - .set((h, v) -> { - final net.minecraft.world.item.DyeColor baseColor = h.getBaseColor(); - final TropicalFish.Pattern type = h.getVariant(); - final int variant = TropicalFishAccessor.invoker$packVariant(type, baseColor, (net.minecraft.world.item.DyeColor) (Object) v); - ((TropicalFishAccessor) h).invoker$setPackedVariant(variant); - }); + .set((h, v) -> ((TropicalFishAccessor) h).invoker$setPatternColor((net.minecraft.world.item.DyeColor) (Object) v)); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java index ea18f27364a..cc7a7f11909 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.WanderingTrader; @@ -33,6 +34,7 @@ import org.spongepowered.api.data.type.ProfessionType; import org.spongepowered.api.data.type.VillagerType; import org.spongepowered.api.item.merchant.TradeOffer; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.entity.npc.AbstractVillagerAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.SpongeTicks; @@ -49,30 +51,38 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(Villager.class) .create(Keys.PROFESSION_LEVEL) - .get(h -> h.getVillagerData().getLevel()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setLevel(v))) + .get(h -> h.getVillagerData().level()) + .set((h, v) -> h.setVillagerData(h.getVillagerData().withLevel(v))) .create(Keys.PROFESSION_TYPE) - .get(h -> (ProfessionType) (Object) h.getVillagerData().getProfession()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setProfession((VillagerProfession) (Object) v))) + .get(h -> (ProfessionType) (Object) h.getVillagerData().profession()) + .set((h, v) -> { + final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_PROFESSION) + .wrapAsHolder((VillagerProfession) (Object) v); + h.setVillagerData(h.getVillagerData().withProfession(villagerType)); + }) .create(Keys.EXPERIENCE) .get(Villager::getVillagerXp) .set(Villager::setVillagerXp) .delete(h -> h.setVillagerXp(0)) .create(Keys.EXPERIENCE_LEVEL) - .get(h -> h.getVillagerData().getLevel()) + .get(h -> h.getVillagerData().level()) .setAnd((h, v) -> { if (v < 1) { return false; } - h.setVillagerData(h.getVillagerData().setLevel(v)); + h.setVillagerData(h.getVillagerData().withLevel(v)); return true; }) .create(Keys.TRADE_OFFERS) .get(h -> h.getOffers().stream().map(TradeOffer.class::cast).collect(Collectors.toList())) .set((h, v) -> h.setOffers(v.stream().map(MerchantOffer.class::cast).collect(Collectors.toCollection(MerchantOffers::new)))) .create(Keys.VILLAGER_TYPE) - .get(h -> (VillagerType) (Object) h.getVillagerData().getType()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setType((net.minecraft.world.entity.npc.VillagerType) (Object) v))) + .get(h -> (VillagerType) (Object) h.getVillagerData().type()) + .set((h, v) -> { + final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE) + .wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); + h.setVillagerData(h.getVillagerData().withType(villagerType)); + }) .create(Keys.IS_UNHAPPY) .get(h -> h.getUnhappyCounter() > 0) .create(Keys.UNHAPPY_TIME) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java index 4810aad85aa..990da40d732 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java @@ -24,11 +24,13 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.monster.ZombieVillager; import net.minecraft.world.entity.npc.VillagerProfession; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ProfessionType; import org.spongepowered.api.data.type.VillagerType; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class ZombieVillagerData { @@ -41,14 +43,20 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(ZombieVillager.class) .create(Keys.PROFESSION_LEVEL) - .get(h -> h.getVillagerData().getLevel()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setLevel(v))) + .get(h -> h.getVillagerData().level()) + .set((h, v) -> h.setVillagerData(h.getVillagerData().withLevel(v))) .create(Keys.PROFESSION_TYPE) - .get(h -> (ProfessionType) (Object) h.getVillagerData().getProfession()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setProfession((VillagerProfession) (Object) v))) + .get(h -> (ProfessionType) (Object) h.getVillagerData().profession()) + .set((h, v) -> { + final var villagerProfession = SpongeCommon.vanillaRegistry(Registries.VILLAGER_PROFESSION).wrapAsHolder((VillagerProfession) (Object) v); + h.setVillagerData(h.getVillagerData().withProfession(villagerProfession)); + }) .create(Keys.VILLAGER_TYPE) - .get(h -> (VillagerType) (Object) h.getVillagerData().getType()) - .set((h, v) -> h.setVillagerData(h.getVillagerData().setType((net.minecraft.world.entity.npc.VillagerType) (Object) v))); + .get(h -> (VillagerType) (Object) h.getVillagerData().type()) + .set((h, v) -> { + final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE).wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); + h.setVillagerData(h.getVillagerData().withType(villagerType)); + }); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java index 56429297ddf..81f7b503cb3 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java @@ -39,7 +39,7 @@ public final class SpawnEggItemStackData { // @formatter:off - @SuppressWarnings({"rawTypes", "rawtypes"}) + @SuppressWarnings({"rawTypes", "rawtypes", "deprecation"}) public static void register(final DataProviderRegistrator registrator) { registrator.asMutable(ItemStack.class) .create(Keys.ENTITY_TO_SPAWN) diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java index bd111f30c4d..50251ac1fd8 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java @@ -148,7 +148,7 @@ public Optional apply(final ServerLocation compound.remove(Constants.Entity.ENTITY_UUID); final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, level, EntitySpawnReason.LOAD, e -> { - e.moveTo(location.x(), location.y(), location.z()); + e.snapTo(location.x(), location.y(), location.z()); if (e instanceof Mob mobentity) { mobentity.yHeadRot = mobentity.getYRot(); mobentity.yBodyRot = mobentity.getXRot(); diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 6ec6a447ce9..446335ceab3 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -396,9 +396,9 @@ public static void callNaturalMoveEntityEvent(final net.minecraft.world.entity.E originalToPosition); if (finalPosition == null) { - entity.moveTo(entity.xOld, entity.yOld, entity.zOld); + entity.snapTo(entity.xOld, entity.yOld, entity.zOld); } else if (!finalPosition.equals(originalToPosition)) { - entity.moveTo(finalPosition.x(), finalPosition.y(), finalPosition.z()); + entity.snapTo(finalPosition.x(), finalPosition.y(), finalPosition.z()); } } } diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index 0abee380cbd..f6bab0973cb 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -261,7 +261,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) int level = 0; if (merchant instanceof Villager villager) { display = villager.getDisplayName(); - level = villager.getVillagerData().getLevel(); + level = villager.getVillagerData().level(); } else if (merchant instanceof WanderingTrader trader) { display = trader.getDisplayName(); level = 1; diff --git a/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java b/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java index 10607676dfe..8531e3ce71e 100644 --- a/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java +++ b/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java @@ -322,6 +322,7 @@ public EventManager registerListener(final EventListenerRegist return this; } + @SuppressWarnings("deprecation") @Override public SpongeEventManager registerListeners(final PluginContainer plugin, final Object listener) { this.registerListener(plugin, listener, null); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java index 7f5cf00edf7..35771d72e8c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java @@ -88,7 +88,7 @@ public EffectResult processSideEffect( if (hasBlockEntity && !flag.structurePlacement() && flag.performBlockPhysics()) { final var blockEntity = oldState.tileEntity(); if (blockEntity != null) { - blockEntity.preRemoveSideEffects(pos, newState, flag.movingBlocks()); + blockEntity.preRemoveSideEffects(pos, newState); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index dbef0b36d06..dae3422044f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -39,7 +39,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Pig; import net.minecraft.world.entity.animal.Sheep; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; @@ -65,7 +64,6 @@ import org.spongepowered.common.accessor.entity.passive.AbstractChestedHorseEntityAccessor; import org.spongepowered.common.accessor.network.protocol.game.ServerboundMovePlayerPacketAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; -import org.spongepowered.common.accessor.world.entity.animal.PigAccessor; import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; import org.spongepowered.common.accessor.world.entity.animal.WolfAccessor; import org.spongepowered.common.accessor.world.inventory.SlotAccessor; @@ -309,10 +307,6 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n return entity instanceof LivingEntity && !(entity instanceof Player) && stack.has(DataComponents.CUSTOM_NAME) ? EntityAccessor.accessor$DATA_CUSTOM_NAME() : null; } - if (item == Items.SADDLE) { - // ItemSaddle.itemInteractionForEntity - return entity instanceof Pig ? PigAccessor.accessor$DATA_SADDLE_ID() : null; - } if (item instanceof BlockItem && ((BlockItem) item).getBlock() == Blocks.CHEST) { // AbstractChestHorse.processInteract diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java index 2f2a7bd8dfb..00455d01cda 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java @@ -381,7 +381,7 @@ public static Map containerTypeInfo() { (id, i, p, vi) -> { final Villager merchant = new Villager(EntityType.VILLAGER, p.level()); merchant.setPos(p.position()); - merchant.setVillagerData(merchant.getVillagerData().setLevel(5)); + merchant.setVillagerData(merchant.getVillagerData().withLevel(5)); return new MerchantMenu(id, i, vi.applyTradeOffers(merchant)); })); diff --git a/src/main/java/org/spongepowered/common/item/ItemStackDataComponentsUpdater.java b/src/main/java/org/spongepowered/common/item/ItemStackDataComponentsUpdater.java index fe0ed3442a8..cae3beddeaa 100644 --- a/src/main/java/org/spongepowered/common/item/ItemStackDataComponentsUpdater.java +++ b/src/main/java/org/spongepowered/common/item/ItemStackDataComponentsUpdater.java @@ -50,6 +50,7 @@ public int outputVersion() { return Constants.ItemStack.Data.DATA_COMPONENTS; } + @SuppressWarnings("deprecation") @Override public DataView update(final DataView content) { final int count = content.getInt(Constants.ItemStack.V2.COUNT).get(); diff --git a/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java b/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java index b9e54ff7435..b1b9bf09d87 100644 --- a/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java +++ b/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java @@ -44,6 +44,7 @@ public int outputVersion() { return Constants.ItemStack.Data.REMOVED_DUPLICATE_DATA; } + @SuppressWarnings("deprecation") @Override public DataView update(DataView content) { if (content.contains(Constants.Sponge.UNSAFE_NBT)) { diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java index 04adf4a5b78..ced0b591832 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java @@ -291,7 +291,6 @@ public static DataContainer getDataContainer(final net.minecraft.world.item.Item @NotNull public static EquipmentSlotGroup asEquipmentSlotGroup(final EquipmentType equipmentType) { - // TODO expose EquipmentSlotGroup? return switch (((EquipmentSlot) (Object) equipmentType)) { case MAINHAND -> EquipmentSlotGroup.MAINHAND; case OFFHAND -> EquipmentSlotGroup.OFFHAND; @@ -300,10 +299,11 @@ public static EquipmentSlotGroup asEquipmentSlotGroup(final EquipmentType equipm case CHEST -> EquipmentSlotGroup.CHEST; case HEAD -> EquipmentSlotGroup.HEAD; case BODY -> EquipmentSlotGroup.BODY; + case SADDLE -> EquipmentSlotGroup.SADDLE; }; } - + @SuppressWarnings("deprecation") private static void cleanupOldCustomData(final net.minecraft.world.item.ItemStack stack) { final CompoundTag unsafe = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe(); unsafe.remove(Constants.Sponge.Data.V2.SPONGE_DATA); // and its V2.CUSTOM_MANIPULATOR_TAG_LIST diff --git a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java index 68ad9ce8eb1..b941acfe6e6 100644 --- a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java @@ -186,6 +186,7 @@ public CompletableFuture sendToServer(final RequestPacket< "Request packets from the client to server are currently not supported for basic packet channels."); } + @SuppressWarnings("deprecation") @Override public CompletableFuture sendToServer(final Packet packet) { throw new UnsupportedOperationException( diff --git a/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java b/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java index e25c0215007..a682289cdf0 100644 --- a/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java +++ b/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java @@ -48,6 +48,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; import java.time.Duration; import java.time.Instant; @@ -218,7 +219,7 @@ public CompletableFuture> basicProfiles(final Iterable< } private @Nullable GameProfile requestBasicProfileAt(final String name, final Instant time) throws Exception { - final URL url = new URL("https://api.mojang.com/user/profiles/minecraft/" + name + "?at=" + time.getEpochSecond()); + final URL url = new URI("https://api.mojang.com/user/profiles/minecraft/" + name + "?at=" + time.getEpochSecond()).toURL(); final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.connect(); diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index f0c4ab3d9c8..c701a7fa170 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -127,7 +127,8 @@ import org.spongepowered.math.vector.Vector3d; import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.util.function.Function; import java.util.stream.Collectors; @@ -177,8 +178,8 @@ public static RegistryLoader> valueParameter(final CommandBuil l.add(ResourceKeyedValueParameters.URL, k -> ClientNativeArgumentParser.createConverter(k, StringArgumentType.string(), (reader, cause, input) -> { try { - return new URL(input); - } catch (final MalformedURLException ex) { + return new URI(input).toURL(); + } catch (final MalformedURLException | URISyntaxException ex) { throw new SimpleCommandExceptionType(net.minecraft.network.chat.Component.literal("Could not parse " + input + " as a URL")) .createWithContext(reader); } diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index ab2279e8cb9..434a60addee 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -59,6 +59,8 @@ import net.minecraft.world.item.Rarity; import net.minecraft.world.item.ToolMaterial; import net.minecraft.world.item.component.FireworkExplosion; +import net.minecraft.world.item.equipment.ArmorMaterial; +import net.minecraft.world.item.equipment.ArmorMaterials; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LightLayer; @@ -73,6 +75,7 @@ import net.minecraft.world.level.block.state.properties.BellAttachType; import net.minecraft.world.level.block.state.properties.ChestType; import net.minecraft.world.level.block.state.properties.ComparatorMode; +import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DripstoneThickness; import net.minecraft.world.level.block.state.properties.Half; @@ -84,6 +87,7 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; +import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import net.minecraft.world.level.block.state.properties.WallSide; import net.minecraft.world.level.levelgen.GenerationStep; @@ -144,17 +148,16 @@ private void loadInstanceRegistries() { map.put(EnderDragonPhase.HOVERING, "hover"); }, phase -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, ((EnderDragonPhaseAccessor) phase).accessor$name())); this.holder.createRegistry(RegistryTypes.FIREWORK_SHAPE, VanillaRegistryLoader.fireworkShape()); -// final var materials = new HashMap(); -// materials.put(ArmorMaterials.LEATHER, ArmorMaterials.LEATHER.modelId().toString()); -// materials.put(ArmorMaterials.CHAIN, ArmorMaterials.CHAIN.modelId().toString()); -// materials.put(ArmorMaterials.IRON, ArmorMaterials.IRON.modelId().toString()); -// materials.put(ArmorMaterials.GOLD, ArmorMaterials.GOLD.modelId().toString()); -// materials.put(ArmorMaterials.DIAMOND, ArmorMaterials.DIAMOND.modelId().toString()); -// materials.put(ArmorMaterials.TURTLE_SCUTE, ResourceKey.minecraft("turtle").toString()); -// materials.put(ArmorMaterials.NETHERITE, ArmorMaterials.NETHERITE.modelId().toString()); -// materials.put(ArmorMaterials.ARMADILLO_SCUTE, ArmorMaterials.ARMADILLO_SCUTE.modelId().toString()); -// -// this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); + final var materials = new HashMap(); + final var knownMaterials = new ArmorMaterial[]{ + ArmorMaterials.LEATHER,ArmorMaterials.CHAINMAIL, ArmorMaterials.IRON, ArmorMaterials.GOLD, ArmorMaterials.DIAMOND, + ArmorMaterials.TURTLE_SCUTE,ArmorMaterials.NETHERITE, ArmorMaterials.ARMADILLO_SCUTE, + }; + for (final ArmorMaterial armorMaterial : knownMaterials) { + materials.put(armorMaterial, armorMaterial.assetId().location().toString()); + } + + this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); this.knownName(RegistryTypes.GAME_RULE, GameRulesAccessor.accessor$GAME_RULE_TYPES().keySet(), rule -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, rule.getId())); this.holder.createRegistry(RegistryTypes.ITEM_TIER, VanillaRegistryLoader.itemTier()); } @@ -225,12 +228,14 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.ITEM_DISPLAY_TYPE, ItemDisplayContext.values()); this.automaticName(RegistryTypes.BILLBOARD_TYPE, Display.BillboardConstraints.values()); this.automaticName(RegistryTypes.TEXT_ALIGNMENT, Display.TextDisplay.Align.values()); + this.automaticName(RegistryTypes.TEST_BLOCK_MODE, TestBlockMode.values()); this.automaticName(RegistryTypes.LIGHT_TYPE, LightLayer.values()); this.automaticName(RegistryTypes.DISPLAY_SLOT, DisplaySlot.values()); this.automaticName(RegistryTypes.PUSH_REACTION, PushReaction.values()); this.automaticName(RegistryTypes.TRIAL_SPAWNER_STATE, TrialSpawnerState.values()); this.automaticName(RegistryTypes.VAULT_STATE, VaultState.values()); this.automaticName(RegistryTypes.EXPLOSION_BLOCK_INTERACTION, Explosion.BlockInteraction.values()); + this.automaticName(RegistryTypes.CREAKING_HEART_STATES, CreakingHeartState.values()); } private static RegistryLoader criterion() { diff --git a/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java b/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java index 41b3c4b16bb..2b3e2cf0fc9 100644 --- a/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java +++ b/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java @@ -43,6 +43,7 @@ import java.util.Locale; +@SuppressWarnings("deprecation") public final class ServerConsoleSystemSubject extends SpongeSystemSubject implements CommandSourceProviderBridge, CommandSource, CommandSourceBridge { @Override diff --git a/src/main/java/org/spongepowered/common/service/game/pagination/PaginationCalculator.java b/src/main/java/org/spongepowered/common/service/game/pagination/PaginationCalculator.java index 1936edd3969..7a17d7bd937 100644 --- a/src/main/java/org/spongepowered/common/service/game/pagination/PaginationCalculator.java +++ b/src/main/java/org/spongepowered/common/service/game/pagination/PaginationCalculator.java @@ -27,6 +27,7 @@ import com.google.common.annotations.VisibleForTesting; import net.kyori.adventure.text.BuildableComponent; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.format.Style; @@ -170,16 +171,16 @@ int getWidth(final Component text) { } else if (child instanceof TranslatableComponent) { final TranslatableComponent tl = (TranslatableComponent) child; // Try to find a value registered from Adventure - final MessageFormat global = GlobalTranslator.get().translate(tl.key(), Locales.EN_US); + final MessageFormat global = GlobalTranslator.translator().translate(tl.key(), Locales.EN_US); if (global != null) { i_it = global.toPattern().codePoints().iterator(); - children.addAll(tl.args()); + children.addAll(ComponentLike.asComponents(tl.arguments())); } else { // If there's no adventure translation, then fall back to native final String mc = Language.getInstance().getOrDefault(tl.key()); if (!mc.equals(tl.key())) { // we found a translation, so let's include the with elements - children.addAll(tl.args()); + children.addAll(ComponentLike.asComponents(tl.arguments())); } // Either way, this is the best we'll get for calculating width i_it = mc.codePoints().iterator(); diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java index 60ed58a9dad..0f4fe1c02e4 100644 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructurePlacementBuilder.java @@ -160,6 +160,7 @@ public ConcentricRings preferredBiomes(final Tag ci) { if (!this.impl$wasSuccess) { return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index 5e814d0e7cc..125d7f759de 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -129,7 +129,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, sp.connection.teleport( new PositionMoveRotation(new Vec3( actualX, actualY, actualZ), Vec3.ZERO, (float) actualYaw, (float) actualPitch), relativeList); } else { - entityIn.moveTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch); + entityIn.snapTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch); } entityIn.setYHeadRot((float) actualYaw); @@ -187,7 +187,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, } result.restoreFrom(entityIn); - result.moveTo(posEvent.destinationPosition().x(), posEvent.destinationPosition().y(), + result.snapTo(posEvent.destinationPosition().x(), posEvent.destinationPosition().y(), posEvent.destinationPosition().z(), (float) actualYaw, (float) actualPitch); result.setYHeadRot((float) actualYaw); worldIn.addDuringTeleport(result); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 71063f089af..a0e03ba69b2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -635,6 +635,7 @@ public boolean teleportTo(final ServerLevel world, * @reason SpongeForge requires an overwrite so we do it here instead. This handles player death events. */ @Overwrite + @SuppressWarnings("deprecation") public void die(final DamageSource cause) { // Sponge start - Call Destruct Death Event final DestructEntityEvent.Death event = SpongeCommonEventFactory.callDestructEntityEventDeath((net.minecraft.server.level.ServerPlayer) (Object) this, cause, diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index a6d600f0ec4..c6c2341eee4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -260,7 +260,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // The rotation is relative so the head movement is still smooth. // The client thinks its current rotation is originalToRotation so the new rotation is relative to that. // The rotation values can be out of "valid" range so set them directly to the same value the client has. - this.player.absMoveTo(fromPosition.x(), fromPosition.y(), fromPosition.z()); + this.player.absSnapTo(fromPosition.x(), fromPosition.y(), fromPosition.z()); this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); this.shadow$teleport(new PositionMoveRotation( @@ -280,7 +280,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // Both are relatives so the client will keep its momentum. // The client thinks its current position is originalToPosition so the new position is relative to that. // The rotation values can be out of "valid" range so set them directly to the same value the client has. - this.player.absMoveTo(originalToPosition.x(), originalToPosition.y(), originalToPosition.z()); + this.player.absSnapTo(originalToPosition.x(), originalToPosition.y(), originalToPosition.z()); this.player.setXRot((float) originalToRotation.x()); this.player.setYRot((float) originalToRotation.y()); this.shadow$teleport(new PositionMoveRotation( @@ -347,7 +347,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack if (toPosition == null) { // no point doing all that processing, just account for a potential rotation change. if (!fromRotation.equals(toRotation)) { - rootVehicle.absMoveTo(rootVehicle.getX(), rootVehicle.getY(), rootVehicle.getZ(), (float) toRotation.y(), (float) toRotation.x()); + rootVehicle.absSnapTo(rootVehicle.getX(), rootVehicle.getY(), rootVehicle.getZ(), (float) toRotation.y(), (float) toRotation.x()); } this.connection.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); ci.cancel(); @@ -356,7 +356,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack if (!toPosition.equals(originalToPosition) || !toRotation.equals(originalToRotation)) { // notify the client about the new position - rootVehicle.absMoveTo(toPosition.x(), toPosition.y(), toPosition.z(), (float) toRotation.y(), (float) toRotation.x()); + rootVehicle.absSnapTo(toPosition.x(), toPosition.y(), toPosition.z(), (float) toRotation.y(), (float) toRotation.x()); this.connection.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); // update the packet, let MC take care of the rest. @@ -447,6 +447,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack @Redirect(method = "removePlayerFromWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Z)V")) + @SuppressWarnings("deprecation") public void impl$handlePlayerDisconnect(final PlayerList instance, final net.minecraft.network.chat.Component $$0, final boolean $$1) { // If this happens, the connection has not been fully established yet so we've kicked them during ClientConnectionEvent.Login, // but FML has created this handler earlier to send their handshake. No message should be sent, no disconnection event should @@ -533,7 +534,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } - @Redirect(method = "lambda$handleChatCommand$7", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performUnsignedChatCommand(Ljava/lang/String;)V")) + @Redirect(method = "lambda$handleChatCommand$8", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performUnsignedChatCommand(Ljava/lang/String;)V")) public void impl$onPerformChatCommand(final ServerGamePacketListenerImpl instance, final String $$0) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.pushCause(this.player); @@ -542,7 +543,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } - @Redirect(method = "lambda$handleSignedChatCommand$8", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performSignedChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) + @Redirect(method = "lambda$handleSignedChatCommand$9", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performSignedChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) public void impl$onPerformSignedChatCommand(final ServerGamePacketListenerImpl instance, final ServerboundChatCommandSignedPacket $$0, final LastSeenMessages $$1) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { frame.pushCause(this.player); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 000a8b65c0a..7cc83f8a07f 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -312,7 +312,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final ServerLocation toLocation = event.toLocation(); final Vector3d toRotation = event.toRotation(); - mcPlayer.absMoveTo(toLocation.x(), toLocation.y(), toLocation.z(), + mcPlayer.absSnapTo(toLocation.x(), toLocation.y(), toLocation.z(), (float) toRotation.y(), (float) toRotation.x()); return (net.minecraft.server.level.ServerLevel) toLocation.world(); } @@ -428,6 +428,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { } @Inject(method = "placeNewPlayer", at = @At(value = "RETURN")) + @SuppressWarnings("deprecation") private void impl$onInitPlayer_join(final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer, final CommonListenerCookie $$2, final CallbackInfo ci) { final ServerPlayer player = (ServerPlayer) mcPlayer; final ServerSideConnection connection = player.connection(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 51f0f6a13b3..c3a8e3f9a85 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -46,7 +46,6 @@ import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; @@ -157,7 +156,6 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract void shadow$discard(); @Shadow public abstract boolean shadow$isRemoved(); @Shadow public abstract int shadow$getId(); - @Shadow public abstract boolean shadow$isVehicle(); @Shadow public abstract void shadow$playSound(SoundEvent soundIn, float volume, float pitch); @Shadow public abstract boolean shadow$isInvisible(); @Shadow public abstract void shadow$setInvisible(boolean invisible); @@ -184,17 +182,11 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract boolean shadow$onGround(); @Shadow @Nullable protected abstract String shadow$getEncodeId(); @Shadow @javax.annotation.Nullable public PortalProcessor portalProcess; - // @formatter:on - - @Shadow public abstract void move(final MoverType $$0, final Vec3 $$1); - @Shadow public abstract boolean save(final CompoundTag $$0); - - @Shadow public abstract Vec3 calculateViewVector(final float $$0, final float $$1); - @Shadow public abstract Level level(); + // @formatter:on + - @Shadow public abstract boolean startRiding(final Entity $$0); private boolean impl$isConstructing = true; private VanishState impl$vanishState = VanishState.unvanished(); @@ -289,7 +281,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, /** * {@link Entity#teleportTo(double, double, double)} - * {@link Entity#teleportTo(ServerLevel, double, double, double, Set, float, float)} + * {@link Entity#teleportTo(ServerLevel, double, double, double, Set, float, float, boolean)} */ protected boolean impl$setLocation(final boolean isChangeOfWorld, final ServerLevel level, final Vector3d pos) { // TODO post teleport ticket needed? @@ -310,7 +302,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, return false; } entity.restoreFrom((Entity) (Object) this); - entity.moveTo(pos.x(), pos.y(), pos.z()); + entity.snapTo(pos.x(), pos.y(), pos.z()); this.shadow$setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); level.addDuringTeleport(entity); // TODO old code had reset empty time? on original/new world @@ -425,7 +417,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, /** * @author faithcaio - * @reason handle dimension change events see {@link #bridge$changeDimension(DimensionTransition)} + * @reason handle dimension change events see {@link #bridge$changeDimension(TeleportTransition)} * * TODO we may need to separate into Vanilla and Forge again */ @@ -528,7 +520,7 @@ public Entity teleport(final TeleportTransition transition) { this.shadow$removeAfterChangingDimensions(); } - newEntity.moveTo(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), newEntity.getXRot()); + newEntity.snapTo(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), newEntity.getXRot()); newEntity.setDeltaMovement(transition.deltaMovement()); if (thisEntity != newEntity) { newLevel.addDuringTeleport(newEntity); @@ -709,8 +701,8 @@ public void stopRiding() { @Redirect(method = "checkFallDamage", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/Block;fallOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;F)V")) - private void impl$onFallOnCollide(final Block block, final Level world, final BlockState state, final BlockPos pos, final Entity entity, final float fallDistance) { + target = "Lnet/minecraft/world/level/block/Block;fallOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;D)V")) + private void impl$onFallOnCollide(final Block block, final Level world, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) { if (!ShouldFire.COLLIDE_BLOCK_EVENT_FALL || world.isClientSide) { block.fallOn(world, state, pos, entity, fallDistance); return; @@ -743,7 +735,7 @@ public void stopRiding() { } - @Redirect(method = "checkInsideBlocks(Ljava/util/List;Ljava/util/List;)V", + @Redirect(method = "checkInsideBlocks(Ljava/util/List;Lnet/minecraft/world/entity/Entity$StateVisitor;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 8062adfa50f..6c4b6c976bd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -24,11 +24,12 @@ */ package org.spongepowered.common.mixin.core.world.entity; -import net.minecraft.world.entity.Leashable; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.Entity; @@ -57,8 +58,9 @@ public abstract class MobMixin extends LivingEntityMixin { @Shadow @Final protected GoalSelector goalSelector; @Shadow @Final protected GoalSelector targetSelector; @Shadow @Nullable private LivingEntity target; - @Shadow public abstract Leashable.LeashData shadow$getLeashData(); @Shadow protected abstract void shadow$registerGoals(); + @Shadow public abstract boolean shadow$isSaddled(); + @Shadow public abstract void shadow$setItemSlot(EquipmentSlot $$0, ItemStack $$1); // @formatter:on @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;registerGoals()V")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java index a95b5af8bb9..c223d6299b1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java @@ -24,12 +24,11 @@ */ package org.spongepowered.common.mixin.core.world.entity.animal.horse; -import net.minecraft.sounds.SoundSource; import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.entity.animal.horse.AbstractHorseBridge; @@ -40,8 +39,6 @@ public abstract class AbstractHorseMixin extends AgableMobMixin implements Abstr // @formatter:off @Shadow protected SimpleContainer inventory; - @Shadow public abstract void shadow$equipSaddle(ItemStack stack, @Nullable SoundSource sound); - @Shadow public abstract boolean shadow$isSaddled(); // @formatter:on @Override @@ -52,7 +49,7 @@ public abstract class AbstractHorseMixin extends AgableMobMixin implements Abstr @Override public void bridge$setSaddled(boolean saddled) { if (!this.shadow$isSaddled() && saddled) { - this.shadow$equipSaddle(new ItemStack(Items.SADDLE), null); + this.shadow$setItemSlot(EquipmentSlot.SADDLE, new ItemStack(Items.SADDLE)); } else if (this.shadow$isSaddled() && !saddled){ this.inventory.setItem(0, ItemStack.EMPTY); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index 567b00b895e..6a3c21bc857 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -52,7 +52,6 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements // @formatter:off @Shadow private int fuse; @Shadow public abstract boolean shadow$isPrimed(); - @Shadow public abstract void shadow$primeFuse(); // @formatter:on @Nullable private Float impl$explosionRadius = null; // override for fixed radius diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java index 055f70d0451..5e828f0a0b5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java @@ -88,6 +88,7 @@ public abstract class ItemStackMixin implements SpongeDataHolderBridge, DataComp return DataHolderProcessor.bridge$remove(this, key); } + @SuppressWarnings("deprecation") @Override public CompoundTag data$getCompound() { final @Nullable CustomData customData = this.components.get(DataComponents.CUSTOM_DATA); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index 8bec5197a89..f511876a32c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -170,7 +170,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { dataFixed.remove("Dimension"); e.load((CompoundTag) dataFixed.getValue()); // position needs a reset - e.moveTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z()); + e.snapTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z()); }); if (rotation != null) { createdEntity.setRotation(rotation); @@ -198,7 +198,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { // Not all entities have a single World parameter as their constructor if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); - entity.moveTo(x, y, z); + entity.snapTo(x, y, z); ((LightningBolt) entity).setVisualOnly(false); } // TODO - archetypes should solve the problem of calling the correct constructor @@ -221,7 +221,7 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { final ResourceKey key = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getKey((net.minecraft.world.entity.EntityType) type); try { entity = ((net.minecraft.world.entity.EntityType) type).create(thisWorld, EntitySpawnReason.EVENT); - entity.moveTo(x, y, z); + entity.snapTo(x, y, z); } catch (final Exception e) { throw new RuntimeException("There was an issue attempting to construct " + key, e); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java index 1b8fb74d752..e1cbabb31b1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java @@ -45,7 +45,7 @@ public abstract class PointedDripstoneBlockMixin extends BlockMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;stalagmite()Lnet/minecraft/world/damagesource/DamageSource;")) private DamageSource impl$spongeRedirectForFireDamage( final DamageSources instance, final Level level, final BlockState state, - final BlockPos pos,final Entity ignored, final float distance + final BlockPos pos,final Entity ignored, final double distance ) { final DamageSource source = instance.stalagmite(); if (level.isClientSide) { // Short Circuit diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java index 2c71c51ae6e..62bfbedae59 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java @@ -29,8 +29,11 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.entity.BannerBlockEntity; import org.spongepowered.api.data.type.DyeColor; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.bridge.CustomNameableBridge; import org.spongepowered.common.bridge.world.level.block.entity.BannerBlockEntityBridge; @@ -41,9 +44,10 @@ @Mixin(BannerBlockEntity.class) public abstract class BannerBlockEntityMixin extends BlockEntityMixin implements BannerBlockEntityBridge, CustomNameableBridge { - @Shadow private net.minecraft.world.item.DyeColor baseColor; + @Shadow @Final @Mutable private net.minecraft.world.item.DyeColor baseColor; @Shadow @Nullable private Component name; + @Unique private void impl$markDirtyAndUpdate() { this.shadow$setChanged(); if (this.level != null && !this.level.isClientSide) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java index 665bf45c4ff..7017a15ca90 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java @@ -58,6 +58,7 @@ private String modifyMinecraftExceptionOutputIfNotInitializationTime(final Strin target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;" ) ) + @SuppressWarnings("deprecation") private Tag impl$saveSpongeLevelData(final CompoundTag root, final String path, final Tag data, final RegistryAccess p_237288_1_, final WorldData levelData) { root.put(Constants.Sponge.Data.V2.SPONGE_DATA, ((PrimaryLevelDataBridge) levelData).bridge$writeSpongeLevelData()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index d6d8f54f8db..4a55d75a2f6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -360,7 +360,7 @@ public ServerLevelData overworldData() { } @Override - @SuppressWarnings("deprecated") + @SuppressWarnings({"deprecated","deprecation"}) public void bridge$readSpongeLevelData(final Dynamic dynamic) { dynamic.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(value -> this.impl$uniqueId = value); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java index c1efdd8a2fb..a7f2a0478ce 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java @@ -37,6 +37,7 @@ import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -59,14 +60,13 @@ public abstract class LivingEntityMixin_Inventory extends Entity { // @formatter:off + @Shadow @Final private Map lastEquipmentItems; + @Shadow public abstract void shadow$setItemSlot(EquipmentSlot slotIn, ItemStack stack); - @Shadow protected abstract ItemStack shadow$getLastHandItem(EquipmentSlot p_241347_1_); - @Shadow protected abstract ItemStack shadow$getLastArmorItem(EquipmentSlot p_241346_1_); @Shadow protected abstract void shadow$completeUsingItem(); - - @Shadow private ItemStack lastBodyItemStack; // @formatter:on + protected LivingEntityMixin_Inventory(final EntityType param0, final Level param1) { super(param0, param1); } @@ -75,24 +75,22 @@ protected LivingEntityMixin_Inventory(final EntityType param0, final Level pa at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;broadcast(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/protocol/Packet;)V")) protected void inventory$onHandleHandSwap(final Map map, final CallbackInfo ci) { final Slot mainHand = this.impl$getSpongeSlot(EquipmentSlot.MAINHAND); - final boolean customMainHand = this.impl$throwEquipmentEvent(EquipmentSlot.MAINHAND, mainHand, map.get(EquipmentSlot.MAINHAND), this.shadow$getLastHandItem(EquipmentSlot.MAINHAND)); + final var lastMainHand = this.lastEquipmentItems.get(EquipmentSlot.MAINHAND); + final boolean customMainHand = this.impl$throwEquipmentEvent(EquipmentSlot.MAINHAND, mainHand, map.get(EquipmentSlot.MAINHAND), lastMainHand); + final var lastOffHand = this.lastEquipmentItems.get(EquipmentSlot.OFFHAND); final Slot offHand = this.impl$getSpongeSlot(EquipmentSlot.OFFHAND); - final boolean customOffHand = this.impl$throwEquipmentEvent(EquipmentSlot.OFFHAND, offHand, map.get(EquipmentSlot.OFFHAND), this.shadow$getLastHandItem(EquipmentSlot.OFFHAND)); + final boolean customOffHand = this.impl$throwEquipmentEvent(EquipmentSlot.OFFHAND, offHand, map.get(EquipmentSlot.OFFHAND), lastOffHand); if (customMainHand || customOffHand) { ci.cancel(); // If canceled or customized let handleEquipmentChanges send packets instead } } @Inject(method = "handleEquipmentChanges", - at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V")) + at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V")) protected void inventory$onHandleEquipmentChanges(final Map map, final CallbackInfo ci) { map.entrySet().forEach(entry -> { final Slot slotAdapter = this.impl$getSpongeSlot(entry.getKey()); - final ItemStack oldStack = switch (entry.getKey().getType()) { - case HAND -> this.shadow$getLastHandItem(entry.getKey()); - case HUMANOID_ARMOR -> this.shadow$getLastArmorItem(entry.getKey()); - case ANIMAL_ARMOR -> this.lastBodyItemStack; - }; + final ItemStack oldStack = this.lastEquipmentItems.get(entry.getKey()); entry.setValue(this.impl$callEquipmentEvent(entry.getKey(), slotAdapter, entry.getValue(), oldStack)); }); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java b/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java index acb2835c33a..1a2772c5ffa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java +++ b/src/mixins/java/org/spongepowered/common/mixin/movementcheck/server/network/ServerGamePacketListenerImplMixin_MovementCheck.java @@ -70,7 +70,7 @@ public abstract class ServerGamePacketListenerImplMixin_MovementCheck { @ModifyConstant(method = "handleMoveVehicle", constant = @Constant(doubleValue = 0.0625D, ordinal = 0), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;move(Lnet/minecraft/world/entity/MoverType;Lnet/minecraft/world/phys/Vec3;)V", ordinal = 0), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;absMoveTo(DDDFF)V") + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;absSnapTo(DDDFF)V") ) ) private double movementCheck$onVehicleMovedWronglyCheck(final double value) { From 3a3778cdb702da93fb92ef8b1685401cd918be69 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 19 Jan 2025 11:49:14 -0800 Subject: [PATCH 179/586] chore: bumpchore: bump forge and neo base dependencies To help reduce confusion around beta tags, we can depend on the latest releases from both. Signed-off-by: Gabriel Harris-Rouquette --- forge/gradle.properties | 2 +- gradle/verification-metadata.xml | 198 +++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 3 files changed, 200 insertions(+), 2 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index f3f921aae37..b8469f277ea 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=53.0.25 +forgeVersion=53.0.37 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e672d053232..fbc542989c9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2959,6 +2959,14 @@ + + + + + + + + @@ -3013,6 +3021,14 @@ + + + + + + + + @@ -3051,6 +3067,14 @@ + + + + + + + + @@ -3121,6 +3145,14 @@ + + + + + + + + @@ -3215,6 +3247,14 @@ + + + + + + + + @@ -3290,6 +3330,14 @@ + + + + + + + + @@ -3365,6 +3413,14 @@ + + + + + + + + @@ -3595,6 +3651,14 @@ + + + + + + + + @@ -3670,6 +3734,14 @@ + + + + + + + + @@ -3745,6 +3817,14 @@ + + + + + + + + @@ -3802,6 +3882,14 @@ + + + + + + + + @@ -3837,6 +3925,14 @@ + + + + + + + + @@ -4059,6 +4155,14 @@ + + + + + + + + @@ -4126,6 +4230,20 @@ + + + + + + + + + + + + + + @@ -4150,6 +4268,14 @@ + + + + + + + + @@ -4206,6 +4332,14 @@ + + + + + + + + @@ -4230,6 +4364,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -6128,6 +6286,14 @@ + + + + + + + + @@ -6209,6 +6375,14 @@ + + + + + + + + @@ -6365,6 +6539,14 @@ + + + + + + + + @@ -6417,6 +6599,14 @@ + + + + + + + + @@ -6469,6 +6659,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 834881bed03..7be93de69a7 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.3.35-beta +neoForgeVersion=21.3.58 loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file From 1fbcf498cc92d7fe794f96aeca3f04b594c758ea Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 19 Jan 2025 11:50:15 -0800 Subject: [PATCH 180/586] chore: make a minimum recommended 1.21.3 version Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index eb71a3a0c71..26693290c4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c superClassChanges=common.superclasschange minecraftVersion=1.21.3 -recommendedVersion=0-SNAPSHOT +recommendedVersion=0 org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 0d0366aa00b117b1f7d91b5cee890d6c5a89c6fd Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 19 Jan 2025 12:35:19 -0800 Subject: [PATCH 181/586] chore: make towards next recommended implementation version Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 26693290c4e..150a7604d2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c superClassChanges=common.superclasschange minecraftVersion=1.21.3 -recommendedVersion=0 +recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From ca5f8e41da17096743a8688f1046c52d8540935f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 19 Jan 2025 19:20:28 -0800 Subject: [PATCH 182/586] feat: upgrade adventure This makes the implementation match Adventure's update with shadow style and does a minimum of supporting VirtualComponents being rendered to text directly. --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 104 +++++- .../common/adventure/SpongeAdventure.java | 320 ++++++++---------- .../adventure/text/format/StyleImplMixin.java | 2 +- 4 files changed, 237 insertions(+), 191 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 34fdb7b5595..d87b95d677c 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 34fdb7b55950e1c477a6044382502288a3429317 +Subproject commit d87b95d677cfae3e5edf455d94ec61eb3b602018 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5a50eb5a394..160371bd240 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2771,6 +2771,14 @@ + + + + + + + + @@ -2787,6 +2795,14 @@ + + + + + + + + @@ -2812,6 +2828,14 @@ + + + + + + + + @@ -2834,6 +2858,14 @@ + + + + + + + + @@ -2859,6 +2891,14 @@ + + + + + + + + @@ -2881,6 +2921,14 @@ + + + + + + + + @@ -2906,6 +2954,14 @@ + + + + + + + + @@ -2931,6 +2987,14 @@ + + + + + + + + @@ -2956,6 +3020,14 @@ + + + + + + + + @@ -2981,6 +3053,14 @@ + + + + + + + + @@ -2992,6 +3072,14 @@ + + + + + + + + @@ -3452,14 +3540,6 @@ - - - - - - - - @@ -6445,6 +6525,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index afd8a7a3f8c..a45c769f7e5 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -39,20 +39,22 @@ import net.kyori.adventure.text.BlockNBTComponent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentBuilder; +import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.EntityNBTComponent; import net.kyori.adventure.text.KeybindComponent; -import net.kyori.adventure.text.NBTComponent; import net.kyori.adventure.text.NBTComponentBuilder; import net.kyori.adventure.text.ScoreComponent; import net.kyori.adventure.text.SelectorComponent; import net.kyori.adventure.text.StorageNBTComponent; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.VirtualComponent; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.DataComponentValue; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.ShadowColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; @@ -70,8 +72,6 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; import net.minecraft.nbt.TagParser; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ComponentContents; @@ -115,7 +115,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -165,8 +164,8 @@ public String toString() { }; public static final ConfigurateComponentSerializer CONFIGURATE = ConfigurateComponentSerializer.builder() - .scalarSerializer(GsonComponentSerializer.gson()) - .build(); + .scalarSerializer(GsonComponentSerializer.gson()) + .build(); private static final Set ACTIVE_BOSS_BARS = ConcurrentHashMap.newKeySet(); @@ -248,43 +247,35 @@ public static MutableComponent asVanillaMutable(final Component component) { } private static MutableComponent asVanillaMutable0(final Component component) { - if (component instanceof TextComponent) { - return net.minecraft.network.chat.Component.literal(((TextComponent) component).content()); - } - if (component instanceof final TranslatableComponent $this) { - final List with = new ArrayList<>($this.args().size()); - for (final Component arg : $this.args()) { - with.add(((ComponentBridge) arg).bridge$asVanillaComponent()); - } - return net.minecraft.network.chat.Component.translatable($this.key(), with.toArray(new Object[0])); - } - if (component instanceof KeybindComponent) { - return net.minecraft.network.chat.Component.keybind(((KeybindComponent) component).keybind()); - } - if (component instanceof final ScoreComponent $this) { - return net.minecraft.network.chat.Component.score($this.name(), $this.objective()); - } - if (component instanceof final SelectorComponent $this) { - return net.minecraft.network.chat.Component.selector(SelectorPattern.parse($this.pattern()).getOrThrow(), SpongeAdventure.asVanillaOpt($this.separator())); - } - if (component instanceof NBTComponent) { - if (component instanceof final BlockNBTComponent $this) { - return net.minecraft.network.chat.Component.nbt($this.nbtPath(), $this.interpret(), - SpongeAdventure.asVanillaOpt($this.separator()), - new BlockDataSource($this.pos().asString())); - } - if (component instanceof final EntityNBTComponent $this) { - return net.minecraft.network.chat.Component.nbt($this.nbtPath(), $this.interpret(), - SpongeAdventure.asVanillaOpt($this.separator()), - new EntityDataSource($this.selector())); - } - if (component instanceof final StorageNBTComponent $this) { - return net.minecraft.network.chat.Component.nbt($this.nbtPath(), $this.interpret(), - SpongeAdventure.asVanillaOpt($this.separator()), - new StorageDataSource(SpongeAdventure.asVanilla($this.storage()))); + return switch (component) { + case VirtualComponent virtual -> net.minecraft.network.chat.Component.literal(virtual.content()); + case TextComponent text -> net.minecraft.network.chat.Component.literal(text.content()); + case TranslatableComponent translatable -> { + final List with = new ArrayList<>(translatable.arguments().size()); + for (final Component arg : ComponentLike.asComponents(translatable.arguments())) { + with.add(((ComponentBridge) arg).bridge$asVanillaComponent()); + } + yield net.minecraft.network.chat.Component.translatable(translatable.key(), with.toArray(new Object[0])); } - } - throw new UnsupportedOperationException("Cannot convert Component of type " + component.getClass()); + case KeybindComponent keybind -> net.minecraft.network.chat.Component.keybind(keybind.keybind()); + case ScoreComponent score -> net.minecraft.network.chat.Component.score(score.name(), score.objective()); + case SelectorComponent selector -> net.minecraft.network.chat.Component.selector( + SelectorPattern.parse(selector.pattern()).getOrThrow(), SpongeAdventure.asVanillaOpt(selector.separator()) + ); + case BlockNBTComponent block -> net.minecraft.network.chat.Component.nbt(block.nbtPath(), block.interpret(), + SpongeAdventure.asVanillaOpt(block.separator()), + new BlockDataSource(block.pos().asString())); + case EntityNBTComponent entity -> + net.minecraft.network.chat.Component.nbt(entity.nbtPath(), entity.interpret(), + SpongeAdventure.asVanillaOpt(entity.separator()), + new EntityDataSource(entity.selector())); + case StorageNBTComponent storage -> + net.minecraft.network.chat.Component.nbt(storage.nbtPath(), storage.interpret(), + SpongeAdventure.asVanillaOpt(storage.separator()), + new StorageDataSource(SpongeAdventure.asVanilla(storage.storage()))); + default -> + throw new UnsupportedOperationException("Cannot convert Component of type " + component.getClass()); + }; } // no caching @@ -305,45 +296,40 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c } private static ComponentBuilder asAdventureBuilder(final ComponentContents contents) { - if (contents instanceof final PlainTextContents lc) { - if (contents == PlainTextContents.EMPTY) { - return Component.empty().toBuilder(); + return switch (contents) { + case PlainTextContents plain -> { + if (plain == PlainTextContents.EMPTY) { + yield Component.empty().toBuilder(); + } + yield Component.text().content(plain.text()); } - return Component.text().content(lc.text()); - } - if (contents instanceof final TranslatableContents tc) { - final List argList = Arrays.stream(tc.getArgs()) + case TranslatableContents tc -> { + final List argList = Arrays.stream(tc.getArgs()) .map(arg -> arg instanceof final net.minecraft.network.chat.Component argComponent ? - SpongeAdventure.asAdventure(argComponent) : Component.text(arg.toString())).toList(); - return Component.translatable().key(tc.getKey()).args(argList); - } - if (contents instanceof final KeybindContents kc) { - return Component.keybind().keybind(kc.getName()); - } - if (contents instanceof final ScoreContents sc) { - return Component.score().name(sc.name().mapLeft(SelectorPattern::pattern).orThrow()).objective(sc.objective()); - } - if (contents instanceof final SelectorContents sc) { - return Component.selector().pattern(sc.selector().pattern()) - .separator(SpongeAdventure.asAdventure(sc.separator())); - } - if (contents instanceof final NbtContents nc) { - NBTComponentBuilder nbtBuilder; - if (nc.getDataSource() instanceof final BlockDataSource ds) { - nbtBuilder = Component.blockNBT().pos(BlockNBTComponent.Pos.fromString(ds.posPattern())); - } else if (nc.getDataSource() instanceof final EntityDataSource ds) { - nbtBuilder = Component.entityNBT().selector(ds.selectorPattern()); - } else if (nc.getDataSource() instanceof final StorageDataSource ds) { - nbtBuilder = Component.storageNBT().storage(SpongeAdventure.asAdventure(ds.id())); - } else { - throw new UnsupportedOperationException("Cannot convert NBTContents with DataSource " + nc.getDataSource().getClass()); + SpongeAdventure.asAdventure(argComponent) : Component.text(arg.toString())).toList(); + yield Component.translatable().key(tc.getKey()).arguments(argList); } - return nbtBuilder.nbtPath(nc.getNbtPath()) - .interpret(nc.isInterpreting()) - .separator(SpongeAdventure.asAdventure(nc.getSeparator())); - } - - throw new UnsupportedOperationException("Cannot convert ComponentContents of type " + contents.getClass()); + case KeybindContents kc -> Component.keybind().keybind(kc.getName()); + case ScoreContents sc -> + Component.score().name(sc.name().mapLeft(SelectorPattern::pattern).orThrow()).objective(sc.objective()); + case SelectorContents sc -> + Component.selector().pattern(sc.selector().pattern()).separator(SpongeAdventure.asAdventure(sc.separator())); + case NbtContents nbt -> { + final NBTComponentBuilder nbtBuilder = switch (nbt.getDataSource()) { + case BlockDataSource bds -> + Component.blockNBT().pos(BlockNBTComponent.Pos.fromString(bds.posPattern())); + case EntityDataSource eds -> Component.entityNBT().selector(eds.selectorPattern()); + case StorageDataSource sds -> Component.storageNBT().storage(SpongeAdventure.asAdventure(sds.id())); + default -> + throw new UnsupportedOperationException("Cannot convert NBTContents with DataSource " + nbt.getDataSource().getClass()); + }; + yield nbtBuilder.nbtPath(nbt.getNbtPath()) + .interpret(nbt.isInterpreting()) + .separator(SpongeAdventure.asAdventure(nbt.getSeparator())); + } + default -> + throw new UnsupportedOperationException("Cannot convert ComponentContents of type " + contents.getClass()); + }; } public static @Nullable Component asAdventure(final Optional component) { @@ -352,7 +338,7 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c // no caching public static Style asAdventure(final net.minecraft.network.chat.Style mcStyle) { - final net.kyori.adventure.text.format.Style.Builder builder = net.kyori.adventure.text.format.Style.style(); + final Style.Builder builder = Style.style(); final StyleAccessor $access = (StyleAccessor) mcStyle; builder.font(SpongeAdventure.asAdventure($access.accessor$font())); // font @@ -455,38 +441,24 @@ public static ChatFormatting asVanilla(final NamedTextColor color) { if (color == null) { return null; } - if (color == ChatFormatting.BLACK) { - return NamedTextColor.BLACK; - } else if (color == ChatFormatting.DARK_BLUE) { - return NamedTextColor.DARK_BLUE; - } else if (color == ChatFormatting.DARK_GREEN) { - return NamedTextColor.DARK_GREEN; - } else if (color == ChatFormatting.DARK_AQUA) { - return NamedTextColor.DARK_AQUA; - } else if (color == ChatFormatting.DARK_RED) { - return NamedTextColor.DARK_RED; - } else if (color == ChatFormatting.DARK_PURPLE) { - return NamedTextColor.DARK_PURPLE; - } else if (color == ChatFormatting.GOLD) { - return NamedTextColor.GOLD; - } else if (color == ChatFormatting.GRAY) { - return NamedTextColor.GRAY; - } else if (color == ChatFormatting.DARK_GRAY) { - return NamedTextColor.DARK_GRAY; - } else if (color == ChatFormatting.BLUE) { - return NamedTextColor.BLUE; - } else if (color == ChatFormatting.GREEN) { - return NamedTextColor.GREEN; - } else if (color == ChatFormatting.AQUA) { - return NamedTextColor.AQUA; - } else if (color == ChatFormatting.RED) { - return NamedTextColor.RED; - } else if (color == ChatFormatting.LIGHT_PURPLE) { - return NamedTextColor.LIGHT_PURPLE; - } else if (color == ChatFormatting.YELLOW) { - return NamedTextColor.YELLOW; - } - return NamedTextColor.WHITE; + return switch (color) { + case BLACK -> NamedTextColor.BLACK; + case DARK_BLUE -> NamedTextColor.DARK_BLUE; + case DARK_GREEN -> NamedTextColor.DARK_GREEN; + case DARK_AQUA -> NamedTextColor.DARK_AQUA; + case DARK_RED -> NamedTextColor.DARK_RED; + case DARK_PURPLE -> NamedTextColor.DARK_PURPLE; + case GOLD -> NamedTextColor.GOLD; + case GRAY -> NamedTextColor.GRAY; + case DARK_GRAY -> NamedTextColor.DARK_GRAY; + case BLUE -> NamedTextColor.BLUE; + case GREEN -> NamedTextColor.GREEN; + case AQUA -> NamedTextColor.AQUA; + case RED -> NamedTextColor.RED; + case LIGHT_PURPLE -> NamedTextColor.LIGHT_PURPLE; + case YELLOW -> NamedTextColor.YELLOW; + default -> NamedTextColor.WHITE; // White color is also just defaulting to white + }; } public static @Nullable Boolean asVanillaNullable(final TextDecoration.State state) { @@ -622,15 +594,6 @@ public static List json(final List strings) { return components; } - public static ListTag listTagJson(final List components) { - final GsonComponentSerializer gcs = GsonComponentSerializer.gson(); - final ListTag nbt = new ListTag(); - for (final Component component : components) { - nbt.add(StringTag.valueOf(gcs.serialize(component))); - } - return nbt; - } - // ----------------- // ---- BossBar ---- // ----------------- @@ -644,38 +607,38 @@ public static ServerBossEvent asVanillaServer(final BossBar bar) { } public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) { - if(color == BossBar.Color.PINK) { + if (color == BossBar.Color.PINK) { return BossEvent.BossBarColor.PINK; - } else if(color == BossBar.Color.BLUE) { + } else if (color == BossBar.Color.BLUE) { return BossEvent.BossBarColor.BLUE; - } else if(color == BossBar.Color.RED) { + } else if (color == BossBar.Color.RED) { return BossEvent.BossBarColor.RED; - } else if(color == BossBar.Color.GREEN) { + } else if (color == BossBar.Color.GREEN) { return BossEvent.BossBarColor.GREEN; - } else if(color == BossBar.Color.YELLOW) { + } else if (color == BossBar.Color.YELLOW) { return BossEvent.BossBarColor.YELLOW; - } else if(color == BossBar.Color.PURPLE) { + } else if (color == BossBar.Color.PURPLE) { return BossEvent.BossBarColor.PURPLE; - } else if(color == BossBar.Color.WHITE) { + } else if (color == BossBar.Color.WHITE) { return BossEvent.BossBarColor.WHITE; } throw new IllegalArgumentException(color.name()); } public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) { - if(color == BossEvent.BossBarColor.PINK) { + if (color == BossEvent.BossBarColor.PINK) { return BossBar.Color.PINK; - } else if(color == BossEvent.BossBarColor.BLUE) { + } else if (color == BossEvent.BossBarColor.BLUE) { return BossBar.Color.BLUE; - } else if(color == BossEvent.BossBarColor.RED) { + } else if (color == BossEvent.BossBarColor.RED) { return BossBar.Color.RED; - } else if(color == BossEvent.BossBarColor.GREEN) { + } else if (color == BossEvent.BossBarColor.GREEN) { return BossBar.Color.GREEN; - } else if(color == BossEvent.BossBarColor.YELLOW) { + } else if (color == BossEvent.BossBarColor.YELLOW) { return BossBar.Color.YELLOW; - } else if(color == BossEvent.BossBarColor.PURPLE) { + } else if (color == BossEvent.BossBarColor.PURPLE) { return BossBar.Color.PURPLE; - } else if(color == BossEvent.BossBarColor.WHITE) { + } else if (color == BossEvent.BossBarColor.WHITE) { return BossBar.Color.WHITE; } throw new IllegalArgumentException(color.name()); @@ -725,15 +688,15 @@ public static Set asAdventureFlags(final boolean darkenScreen, fin return flags; } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({"rawtypes", "unchecked" }) public static DataComponentPatch asVanilla(final Map componentMap) { if (componentMap == null) { return DataComponentPatch.EMPTY; } final DataComponentPatch.Builder builder = DataComponentPatch.builder(); componentMap.forEach((key, value) -> BuiltInRegistries.DATA_COMPONENT_TYPE.getOptional(SpongeAdventure.asVanilla(key)).ifPresent(type -> { - if (value instanceof SpongeDataComponentValue dcv) { - builder.set((DataComponentType) type, dcv.value.orElse(null)); + if (value instanceof SpongeDataComponentValue(Optional value1)) { + builder.set((DataComponentType) type, value1.orElse(null)); } })); return builder.build(); @@ -752,6 +715,14 @@ public static Map asAdventure(final DataComponentPatch return map; } + public static @Nullable Integer asVanillaNullable(@Nullable ShadowColor shadowColor) { + if (shadowColor == null) { + return null; + } + + return shadowColor.value(); + } + private record SpongeDataComponentValue(Optional value) implements DataComponentValue { } @@ -775,35 +746,33 @@ public static ResourceLocation asVanilla(final Key key) { // Sound public static Sound.Source asAdventure(final SoundSource source) { - switch (source) { - case MASTER: return Sound.Source.MASTER; - case MUSIC: return Sound.Source.MUSIC; - case RECORDS: return Sound.Source.RECORD; - case WEATHER: return Sound.Source.WEATHER; - case BLOCKS: return Sound.Source.BLOCK; - case HOSTILE: return Sound.Source.HOSTILE; - case NEUTRAL: return Sound.Source.NEUTRAL; - case PLAYERS: return Sound.Source.PLAYER; - case AMBIENT: return Sound.Source.AMBIENT; - case VOICE: return Sound.Source.VOICE; - } - throw new IllegalArgumentException(source.name()); + return switch (source) { + case MASTER -> Sound.Source.MASTER; + case MUSIC -> Sound.Source.MUSIC; + case RECORDS -> Sound.Source.RECORD; + case WEATHER -> Sound.Source.WEATHER; + case BLOCKS -> Sound.Source.BLOCK; + case HOSTILE -> Sound.Source.HOSTILE; + case NEUTRAL -> Sound.Source.NEUTRAL; + case PLAYERS -> Sound.Source.PLAYER; + case AMBIENT -> Sound.Source.AMBIENT; + case VOICE -> Sound.Source.VOICE; + }; } public static SoundSource asVanilla(final Sound.Source source) { - switch (source) { - case MASTER: return SoundSource.MASTER; - case MUSIC: return SoundSource.MUSIC; - case RECORD: return SoundSource.RECORDS; - case WEATHER: return SoundSource.WEATHER; - case BLOCK: return SoundSource.BLOCKS; - case HOSTILE: return SoundSource.HOSTILE; - case NEUTRAL: return SoundSource.NEUTRAL; - case PLAYER: return SoundSource.PLAYERS; - case AMBIENT: return SoundSource.AMBIENT; - case VOICE: return SoundSource.VOICE; - } - throw new IllegalArgumentException(source.name()); + return switch (source) { + case MASTER -> SoundSource.MASTER; + case MUSIC -> SoundSource.MUSIC; + case RECORD -> SoundSource.RECORDS; + case WEATHER -> SoundSource.WEATHER; + case BLOCK -> SoundSource.BLOCKS; + case HOSTILE -> SoundSource.HOSTILE; + case NEUTRAL -> SoundSource.NEUTRAL; + case PLAYER -> SoundSource.PLAYERS; + case AMBIENT -> SoundSource.AMBIENT; + case VOICE -> SoundSource.VOICE; + }; } public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { @@ -813,17 +782,6 @@ public static SoundSource asVanilla(final Sound.Source source) { return SpongeAdventure.asVanilla(source); } - public static Iterable unpackAudiences(final Audience audience) { - if (audience instanceof ForwardingAudience) { - final List list = new ArrayList<>(); - for (final Audience subAudience : ((ForwardingAudience) audience).audiences()) { - SpongeAdventure.unpackAudiences(subAudience).forEach(list::add); - } - return list; - } - return Collections.singletonList(audience); - } - public static class Factory implements SpongeComponents.Factory { @Override public @NonNull ClickEvent callbackClickEvent(final @NonNull Consumer callback) { @@ -839,18 +797,18 @@ public static class Factory implements SpongeComponents.Factory { final @NonNull CommandCause senderContext, @Nullable Audience viewer, final @NonNull DefaultedRegistryReference firstOperation, - final @NonNull DefaultedRegistryReference@NonNull... otherOperations + final @NonNull DefaultedRegistryReference @NonNull ... otherOperations ) { Component output = Objects.requireNonNull(component, "component"); Objects.requireNonNull(senderContext, "senderContext"); // Unwrap the Audience to an entity - while (viewer instanceof ForwardingAudience.Single && !(viewer instanceof Entity)) { - viewer = ((ForwardingAudience.Single) viewer).audience(); + while (viewer instanceof ForwardingAudience.Single single && !(viewer instanceof Entity)) { + viewer = single.audience(); } - final Entity backing; - if (viewer instanceof Entity) { - backing = (Entity) viewer; + final @Nullable Entity backing; + if (viewer instanceof Entity entity) { + backing = entity; } else { backing = null; } @@ -870,7 +828,7 @@ public static class Factory implements SpongeComponents.Factory { final @NonNull Component component, final @NonNull CommandCause senderContext, final @NonNull DefaultedRegistryReference firstOperation, - final @NonNull DefaultedRegistryReference@NonNull... otherOperations + final @NonNull DefaultedRegistryReference @NonNull ... otherOperations ) { return this.render(component, senderContext, null, firstOperation, otherOperations); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java index ca7a8065c0d..bb26db49f6d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java @@ -47,7 +47,7 @@ public abstract class StyleImplMixin implements StyleBridge { this.bridge$vanilla = StyleAccessor.invoker$new( // color SpongeAdventure.asVanillaNullable($this.color()), - null, + SpongeAdventure.asVanillaNullable($this.shadowColor()), // decorations SpongeAdventure.asVanillaNullable($this.decoration(TextDecoration.BOLD)), SpongeAdventure.asVanillaNullable($this.decoration(TextDecoration.ITALIC)), From 6e48bc875aaa29e2ce27a195c781686a161d872c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:49:12 +0200 Subject: [PATCH 183/586] Rework custom_model_data representation for 1.21.4 changes (#4172) --- SpongeAPI | 2 +- .../provider/item/stack/ItemStackData.java | 38 +++++++++++++++++-- .../org/spongepowered/test/data/DataTest.java | 5 ++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index c94741a80e0..5586e8b6a41 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c94741a80e0f8a1683344a8ef1c019dbd977436c +Subproject commit 5586e8b6a4191952199a92301176754e3902a83d diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 49581493d78..d802365838e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -42,6 +42,7 @@ import net.minecraft.world.item.Rarity; import net.minecraft.world.item.component.ChargedProjectiles; import net.minecraft.world.item.component.Consumable; +import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.DamageResistant; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; @@ -64,6 +65,7 @@ import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.Slot; +import org.spongepowered.api.util.Color; import org.spongepowered.api.util.Ticks; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; @@ -116,10 +118,38 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (ItemType) h.getItem().getCraftingRemainder().getItem()) .create(Keys.DISPLAY_NAME) .get(h -> SpongeAdventure.asAdventure(h.getDisplayName())) -// .create(Keys.CUSTOM_MODEL_DATA) -// .get(h -> h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY)) -// .set((h, v) -> h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(v))) -// .delete(h -> h.remove(DataComponents.CUSTOM_MODEL_DATA)) + .create(Keys.CUSTOM_MODEL_DATA_FLOATS) + .get(h -> List.copyOf(h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY).floats())) + .set((h, v) -> { + final CustomModelData current = h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY); + + h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(List.copyOf(v), current.flags(), current.strings(), current.colors())); + }) + .create(Keys.CUSTOM_MODEL_DATA_FLAGS) + .get(h -> List.copyOf(h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY).flags())) + .set((h, v) -> { + final CustomModelData current = h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY); + + h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(current.floats(), List.copyOf(v), current.strings(), current.colors())); + }) + .create(Keys.CUSTOM_MODEL_DATA_STRINGS) + .get(h -> List.copyOf(h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY).strings())) + .set((h, v) -> { + final CustomModelData current = h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY); + + h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(current.floats(), current.flags(), List.copyOf(v), current.colors())); + }) + .create(Keys.CUSTOM_MODEL_DATA_COLORS) + .get(h -> h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY).colors().stream() + .map(Color::ofRgb) + .toList()) + .set((h, v) -> { + final CustomModelData current = h.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, CustomModelData.EMPTY); + + h.set(DataComponents.CUSTOM_MODEL_DATA, new CustomModelData(current.floats(), current.flags(), current.strings(), v.stream() + .map(Color::rgb) + .toList())); + }) .create(Keys.CUSTOM_NAME) .get(h -> { if (h.has(DataComponents.CUSTOM_NAME)) { diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 76aa88949ef..8a2fa01995b 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -435,7 +435,10 @@ public void testData(final ServerPlayer player) { this.checkOfferData(shulkerBullet, Keys.CUSTOM_NAME, Component.text("Angry Shulker Bullet")); final ItemStack redFlard = ItemStack.of(ItemTypes.SLIME_BLOCK); - this.checkOfferData(redFlard, Keys.CUSTOM_MODEL_DATA, 123456); + this.checkOfferListData(redFlard, Keys.CUSTOM_MODEL_DATA_FLOATS, List.of(0.5f, 1.0f, 1.5f)); + this.checkOfferListData(redFlard, Keys.CUSTOM_MODEL_DATA_FLAGS, List.of(true, false, true)); + this.checkOfferListData(redFlard, Keys.CUSTOM_MODEL_DATA_STRINGS, List.of("abc", "bce")); + this.checkOfferListData(redFlard, Keys.CUSTOM_MODEL_DATA_COLORS, List.of(Color.LIME, Color.ofRgb(123, 231, 90))); redFlard.offer(Keys.CUSTOM_NAME, Component.text("Red FLARD", NamedTextColor.DARK_RED)); redFlard.offer(Keys.LORE, Arrays.asList(Component.text("May ignite holder! Handle with care", NamedTextColor.GOLD))); player.inventory().offer(redFlard); From bdfd8fc646293c4d0826cf76c5f45f7a72b80c5b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 23 Jan 2025 01:11:12 -0800 Subject: [PATCH 184/586] feat!: update for 25w04a Notable changes: - Several client related resources now are built as ClientAssets - SmithingRecipes now require a base ingredient - Hidden attributes for items is now in a separated component so Data needs to be fixed in several places - GameProfile lookups seems to have changed, need to fix our cache - Attack Events need to handle capturing the BlockDamage component - Hidden Flags are a new component that uses component keys to hide tooltips. --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 + .../entity/animal/frog/FrogAccessor.java | 2 +- .../enchantment/ItemEnchantmentsAccessor.java | 3 +- .../resources/mixins.sponge.accessors.json | 442 +++++++++--------- .../advancement/SpongeAdvancementBuilder.java | 4 +- .../NbtLegacyHoverEventSerializer.java | 8 +- .../common/adventure/SpongeAdventure.java | 20 - .../common/block/SpongeBlockSnapshot.java | 1 + .../item/crafting/SmithingRecipeBridge.java | 2 +- .../command/brigadier/SpongeStringReader.java | 5 +- .../data/persistence/SNBTDataFormat.java | 6 +- .../common/data/provider/entity/CatData.java | 4 +- .../common/data/provider/entity/FrogData.java | 11 +- .../common/data/provider/entity/PigData.java | 2 +- .../data/provider/entity/PotionData.java | 4 +- .../item/stack/BlockTypeItemStackData.java | 9 +- .../provider/item/stack/CompassItemData.java | 3 +- .../item/stack/DyeableItemStackData.java | 2 +- .../item/stack/HideFlagsItemStackData.java | 100 ++-- .../provider/item/stack/ItemStackData.java | 3 +- .../entity/projectile/ProjectileUtil.java | 17 +- .../merchant/SpongeTradeOfferBuilder.java | 4 +- .../recipe/smithing/SpongeSmithingRecipe.java | 6 +- .../SpongeSmithingRecipeRegistration.java | 4 +- .../spongepowered/common/util/Constants.java | 18 - .../entity/animal/FrogVariantMixin_API.java | 2 +- .../entity/animal/PigVariantMixin_API.java | 34 ++ .../projectile/ThrownPotionMixin_API.java | 4 +- .../SmithingTransformRecipeMixin_API.java | 4 +- .../server/players/GameProfileCacheMixin.java | 44 +- .../entity/LivingEntityMixin_Attack_Impl.java | 32 +- .../entity/npc/WanderingTraderMixin.java | 9 +- .../player/PlayerMixin_Attack_Impl.java | 2 +- .../SmithingTransformRecipeMixin.java | 4 +- src/mixins/resources/mixins.sponge.api.json | 1 + .../org/spongepowered/test/data/DataTest.java | 2 +- .../test/projectile/ProjectileTest.java | 3 +- 39 files changed, 420 insertions(+), 413 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 7d39d1a780f..0b462f55486 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 7d39d1a780f95b4a8cec0df02564c605ae09d88f +Subproject commit 0b462f55486375b32bbe947f7e134e4e1ddef735 diff --git a/gradle.properties b/gradle.properties index d8e926bfc54..b6faf8262e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w03a +minecraftVersion=25w04a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c6bba2f5da3..ef3609f9656 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1359,6 +1359,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java index 74cf5206289..00dc414e649 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/frog/FrogAccessor.java @@ -25,8 +25,8 @@ package org.spongepowered.common.accessor.entity.animal.frog; import net.minecraft.core.Holder; -import net.minecraft.world.entity.animal.FrogVariant; import net.minecraft.world.entity.animal.frog.Frog; +import net.minecraft.world.entity.animal.frog.FrogVariant; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/item/enchantment/ItemEnchantmentsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/enchantment/ItemEnchantmentsAccessor.java index d3a86c01221..66b55ba858a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/item/enchantment/ItemEnchantmentsAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/enchantment/ItemEnchantmentsAccessor.java @@ -36,11 +36,10 @@ @Mixin(ItemEnchantments.class) public interface ItemEnchantmentsAccessor { - @Accessor("showInTooltip") boolean accessor$showInTooltip(); @Accessor("enchantments") Object2IntOpenHashMap> accessor$enchantments(); - @Invoker("") static ItemEnchantments invoker$new(Object2IntOpenHashMap> $$0, boolean $$1) { + @Invoker("") static ItemEnchantments invoker$new(Object2IntOpenHashMap> $$0) { throw new UntransformedInvokerError(); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 599efa99b8c..bbc23a61eb2 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -1,224 +1,224 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.accessor", - "client": [ - "client.KeyMappingAccessor", - "client.multiplayer.ClientLevelAccessor", - "world.level.entity.TransientEntitySectionManagerAccessor" - ], - "mixins": [ - "ChatFormattingAccessor", - "advancements.CriteriaTriggersAccessor", - "advancements.critereon.MinMaxBounds_DoublesAccessor", - "advancements.critereon.MinMaxBounds_IntsAccessor", - "commands.CommandSourceStackAccessor", - "commands.arguments.DimensionArgumentAccessor", - "commands.arguments.OperationArgumentAccessor", - "commands.arguments.selector.EntitySelectorParserAccessor", - "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", - "commands.arguments.selector.options.EntitySelectorOptionsAccessor", - "core.MappedRegistryAccessor", - "entity.animal.frog.FrogAccessor", - "entity.passive.AbstractChestedHorseEntityAccessor", - "network.ConnectionAccessor", - "network.chat.StyleAccessor", - "network.protocol.game.ClientboundAddEntityPacketAccessor", - "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", - "network.protocol.game.ServerboundInteractPacketAccessor", - "network.protocol.game.ServerboundMovePlayerPacketAccessor", - "network.protocol.game.ServerboundMoveVehiclePacketAccessor", - "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.ResourceKeyAccessor", - "server.MinecraftServerAccessor", - "server.level.ChunkMap_TrackedEntityAccessor", - "server.level.ChunkMapAccessor", - "server.level.ServerChunkCacheAccessor", - "server.level.ServerLevelAccessor", - "server.level.ServerPlayer_ContainerListenerAccessor", - "server.level.ServerPlayerAccessor", - "server.level.ServerPlayerGameModeAccessor", - "server.level.TicketAccessor", - "server.network.ServerCommonPacketListenerImplAccessor", - "server.network.ServerGamePacketListenerImplAccessor", - "server.network.ServerLoginPacketListenerImplAccessor", - "server.players.GameProfileCache_GameProfileInfoAccessor", - "server.players.IpBanListAccessor", - "server.players.PlayerListAccessor", - "server.players.StoredUserEntryAccessor", - "server.players.StoredUserListAccessor", - "server.rcon.thread.RconClientAccessor", - "sounds.SoundEventAccessor", - "stats.StatsCounterAccessor", - "util.datafix.schemas.V100Accessor", - "util.thread.AbstractConsecutiveExecutorAccessor", - "world.CompoundContainerAccessor", - "world.damagesource.CombatTrackerAccessor", - "world.entity.AgableMobAccessor", - "world.entity.AreaEffectCloudAccessor", - "world.entity.Display_BlockDisplayAccessor", - "world.entity.Display_ItemDisplayAccessor", - "world.entity.Display_TextDisplayAccessor", - "world.entity.DisplayAccessor", - "world.entity.EntityAccessor", - "world.entity.EntityTypeAccessor", - "world.entity.ExperienceOrbAccessor", - "world.entity.InteractionAccessor", - "world.entity.LightningBoltAccessor", - "world.entity.LivingEntityAccessor", - "world.entity.MobAccessor", - "world.entity.PortalProcessorAccessor", - "world.entity.ai.targeting.TargetingConditionsAccessor", - "world.entity.animal.AnimalAccessor", - "world.entity.animal.CatAccessor", - "world.entity.animal.FoxAccessor", - "world.entity.animal.MooshroomAccessor", - "world.entity.animal.OcelotAccessor", - "world.entity.animal.PandaAccessor", - "world.entity.animal.ParrotAccessor", - "world.entity.animal.PigAccessor", - "world.entity.animal.PufferfishAccessor", - "world.entity.animal.RabbitAccessor", - "world.entity.animal.SheepAccessor", - "world.entity.animal.TropicalFishAccessor", - "world.entity.animal.TurtleAccessor", - "world.entity.animal.WolfAccessor", - "world.entity.animal.horse.AbstractHorseAccessor", - "world.entity.animal.horse.HorseAccessor", - "world.entity.animal.horse.LlamaAccessor", - "world.entity.animal.horse.TraderLlamaAccessor", - "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", - "world.entity.boss.wither.WitherBossAccessor", - "world.entity.decoration.ArmorStandAccessor", - "world.entity.decoration.HangingEntityAccessor", - "world.entity.decoration.ItemFrameAccessor", - "world.entity.decoration.PaintingAccessor", - "world.entity.item.FallingBlockEntityAccessor", - "world.entity.item.PrimedTntAccessor", - "world.entity.monster.BlazeAccessor", - "world.entity.monster.CreeperAccessor", - "world.entity.monster.EnderManAccessor", - "world.entity.monster.EndermiteAccessor", - "world.entity.monster.EvokerAccessor", - "world.entity.monster.GuardianAccessor", - "world.entity.monster.PatrollingMonsterAccessor", - "world.entity.monster.PhantomAccessor", - "world.entity.monster.PillagerAccessor", - "world.entity.monster.RavagerAccessor", - "world.entity.monster.SlimeAccessor", - "world.entity.monster.SpellcasterIllagerAccessor", - "world.entity.monster.VexAccessor", - "world.entity.monster.VindicatorAccessor", - "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.npc.AbstractVillagerAccessor", - "world.entity.player.AbilitiesAccessor", - "world.entity.player.PlayerAccessor", - "world.entity.projectile.AbstractArrowAccessor", - "world.entity.projectile.ArrowAccessor", - "world.entity.projectile.EyeOfEnderAccessor", - "world.entity.projectile.FireworkRocketEntityAccessor", - "world.entity.projectile.FishingHookAccessor", - "world.entity.projectile.ProjectileAccessor", - "world.entity.projectile.ShulkerBulletAccessor", - "world.entity.raid.RaidAccessor", - "world.entity.raid.RaiderAccessor", - "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.AbstractBoatAccessor", - "world.entity.vehicle.MinecartFurnaceAccessor", - "world.food.FoodDataAccessor", - "world.inventory.AbstractContainerMenuAccessor", - "world.inventory.AbstractCraftingMenuAccessor", - "world.inventory.AbstractFurnaceMenuAccessor", - "world.inventory.BeaconMenuAccessor", - "world.inventory.BrewingStandMenuAccessor", - "world.inventory.DispenserMenuAccessor", - "world.inventory.HopperMenuAccessor", - "world.inventory.HorseInventoryMenuAccessor", - "world.inventory.ItemCombinerMenuAccessor", - "world.inventory.MerchantMenuAccessor", - "world.inventory.ResultSlotAccessor", - "world.inventory.SlotAccessor", - "world.inventory.SmithingMenuAccessor", - "world.item.AdventureModePredicateAccessor", - "world.item.ItemCooldowns_CooldownInstanceAccessor", - "world.item.component.CustomDataAccessor", - "world.item.crafting.RecipeMapAccessor", - "world.item.crafting.ShapelessRecipeAccessor", - "world.item.enchantment.ItemEnchantmentsAccessor", - "world.item.trading.MerchantOfferAccessor", - "world.level.BaseCommandBlockAccessor", - "world.level.BaseSpawnerAccessor", - "world.level.GameRules_ValueAccessor", - "world.level.GameRulesAccessor", - "world.level.LevelAccessor", - "world.level.LevelSettingsAccessor", - "world.level.NaturalSpawner_SpawnStateAccessor", - "world.level.NaturalSpawnerAccessor", - "world.level.ServerExplosionAccessor", - "world.level.TicketStorageAccessor", - "world.level.biome.Biome_ClimateSettingsAccessor", - "world.level.biome.BiomeAccessor", - "world.level.biome.MobSpawnSettingsAccessor", - "world.level.biome.MultiNoiseBiomeSourceAccessor", - "world.level.biome.OverworldBiomeBuilderAccessor", - "world.level.biome.TheEndBiomeSourceAccessor", - "world.level.block.AbstractSkullBlockAccessor", - "world.level.block.BaseFireBlockAccessor", - "world.level.block.BedBlockAccessor", - "world.level.block.CrafterBlockAccessor", - "world.level.block.CropBlockAccessor", - "world.level.block.DispenserBlockAccessor", - "world.level.block.EnderChestBlockAccessor", - "world.level.block.StemBlockAccessor", - "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", - "world.level.block.entity.BaseContainerBlockEntityAccessor", - "world.level.block.entity.BeaconBlockEntityAccessor", - "world.level.block.entity.BlockEntityAccessor", - "world.level.block.entity.BrewingStandBlockEntityAccessor", - "world.level.block.entity.ConduitBlockEntityAccessor", - "world.level.block.entity.CrafterBlockEntityAccessor", - "world.level.block.entity.DecoratedPotBlockEntityAccessor", - "world.level.block.entity.EnchantingTableBlockEntityAccessor", - "world.level.block.entity.HopperBlockEntityAccessor", - "world.level.block.entity.LecternBlockEntity_Accessor", - "world.level.block.entity.SkullBlockEntityAccessor", - "world.level.block.entity.SpawnerBlockEntityAccessor", - "world.level.block.entity.StructureBlockEntityAccessor", - "world.level.block.entity.TheEndGatewayBlockEntityAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", - "world.level.block.piston.PistonBaseBlockAccessor", - "world.level.block.state.BlockBehaviour_PropertiesAccessor", - "world.level.block.state.BlockBehaviourAccessor", - "world.level.block.state.StateHolderAccessor", - "world.level.border.WorldBorder_SettingsAccessor", - "world.level.border.WorldBorderAccessor", - "world.level.chunk.ChunkAccessAccessor", - "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", - "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", - "world.level.chunk.LevelChunkAccessor", - "world.level.chunk.storage.ChunkStorageAccessor", - "world.level.chunk.storage.IOWorker$PendingStoreAccessor", - "world.level.chunk.storage.RegionFileAccessor", - "world.level.chunk.storage.SimpleRegionStorageAccessor", - "world.level.dimension.DimensionTypeAccessor", - "world.level.dimension.end.EndDragonFightAccessor", - "world.level.entity.EntityTickListAccessor", - "world.level.entity.PersistentEntitySectionManagerAccessor", - "world.level.levelgen.NoiseSettingsAccessor", - "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", - "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", - "world.level.portal.TeleportTransitionAccessor", - "world.level.saveddata.maps.MapItemSavedDataAccessor", - "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", - "world.level.storage.PlayerDataStorageAccessor", - "world.phys.AABBAccessor", - "world.scores.PlayerTeamAccessor", - "world.scores.ScoreboardAccessor" - ], - "server": [ - "server.dedicated.DedicatedServerAccessor" + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.accessor", + "client": [ + "client.KeyMappingAccessor", + "client.multiplayer.ClientLevelAccessor", + "world.level.entity.TransientEntitySectionManagerAccessor" + ], + "mixins": [ + "ChatFormattingAccessor", + "advancements.CriteriaTriggersAccessor", + "advancements.critereon.MinMaxBounds_DoublesAccessor", + "advancements.critereon.MinMaxBounds_IntsAccessor", + "commands.CommandSourceStackAccessor", + "commands.arguments.DimensionArgumentAccessor", + "commands.arguments.OperationArgumentAccessor", + "commands.arguments.selector.EntitySelectorParserAccessor", + "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", + "commands.arguments.selector.options.EntitySelectorOptionsAccessor", + "core.MappedRegistryAccessor", + "entity.animal.frog.FrogAccessor", + "entity.passive.AbstractChestedHorseEntityAccessor", + "network.ConnectionAccessor", + "network.chat.StyleAccessor", + "network.protocol.game.ClientboundAddEntityPacketAccessor", + "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", + "network.protocol.game.ServerboundInteractPacketAccessor", + "network.protocol.game.ServerboundMovePlayerPacketAccessor", + "network.protocol.game.ServerboundMoveVehiclePacketAccessor", + "network.protocol.handshake.ClientIntentionPacketAccessor", + "resources.ResourceKeyAccessor", + "server.MinecraftServerAccessor", + "server.level.ChunkMap_TrackedEntityAccessor", + "server.level.ChunkMapAccessor", + "server.level.ServerChunkCacheAccessor", + "server.level.ServerLevelAccessor", + "server.level.ServerPlayer_ContainerListenerAccessor", + "server.level.ServerPlayerAccessor", + "server.level.ServerPlayerGameModeAccessor", + "server.level.TicketAccessor", + "server.network.ServerCommonPacketListenerImplAccessor", + "server.network.ServerGamePacketListenerImplAccessor", + "server.network.ServerLoginPacketListenerImplAccessor", + "server.players.GameProfileCache_GameProfileInfoAccessor", + "server.players.IpBanListAccessor", + "server.players.PlayerListAccessor", + "server.players.StoredUserEntryAccessor", + "server.players.StoredUserListAccessor", + "server.rcon.thread.RconClientAccessor", + "sounds.SoundEventAccessor", + "stats.StatsCounterAccessor", + "util.datafix.schemas.V100Accessor", + "util.thread.AbstractConsecutiveExecutorAccessor", + "world.CompoundContainerAccessor", + "world.damagesource.CombatTrackerAccessor", + "world.entity.AgableMobAccessor", + "world.entity.AreaEffectCloudAccessor", + "world.entity.Display_BlockDisplayAccessor", + "world.entity.Display_ItemDisplayAccessor", + "world.entity.Display_TextDisplayAccessor", + "world.entity.DisplayAccessor", + "world.entity.EntityAccessor", + "world.entity.EntityTypeAccessor", + "world.entity.ExperienceOrbAccessor", + "world.entity.InteractionAccessor", + "world.entity.LightningBoltAccessor", + "world.entity.LivingEntityAccessor", + "world.entity.MobAccessor", + "world.entity.PortalProcessorAccessor", + "world.entity.ai.targeting.TargetingConditionsAccessor", + "world.entity.animal.AnimalAccessor", + "world.entity.animal.CatAccessor", + "world.entity.animal.FoxAccessor", + "world.entity.animal.MooshroomAccessor", + "world.entity.animal.OcelotAccessor", + "world.entity.animal.PandaAccessor", + "world.entity.animal.ParrotAccessor", + "world.entity.animal.PigAccessor", + "world.entity.animal.PufferfishAccessor", + "world.entity.animal.RabbitAccessor", + "world.entity.animal.SheepAccessor", + "world.entity.animal.TropicalFishAccessor", + "world.entity.animal.TurtleAccessor", + "world.entity.animal.WolfAccessor", + "world.entity.animal.horse.AbstractHorseAccessor", + "world.entity.animal.horse.HorseAccessor", + "world.entity.animal.horse.LlamaAccessor", + "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", + "world.entity.boss.wither.WitherBossAccessor", + "world.entity.decoration.ArmorStandAccessor", + "world.entity.decoration.HangingEntityAccessor", + "world.entity.decoration.ItemFrameAccessor", + "world.entity.decoration.PaintingAccessor", + "world.entity.item.FallingBlockEntityAccessor", + "world.entity.item.PrimedTntAccessor", + "world.entity.monster.BlazeAccessor", + "world.entity.monster.CreeperAccessor", + "world.entity.monster.EnderManAccessor", + "world.entity.monster.EndermiteAccessor", + "world.entity.monster.EvokerAccessor", + "world.entity.monster.GuardianAccessor", + "world.entity.monster.PatrollingMonsterAccessor", + "world.entity.monster.PhantomAccessor", + "world.entity.monster.PillagerAccessor", + "world.entity.monster.RavagerAccessor", + "world.entity.monster.SlimeAccessor", + "world.entity.monster.SpellcasterIllagerAccessor", + "world.entity.monster.VexAccessor", + "world.entity.monster.VindicatorAccessor", + "world.entity.monster.ZombifiedPiglinAccessor", + "world.entity.npc.AbstractVillagerAccessor", + "world.entity.player.AbilitiesAccessor", + "world.entity.player.PlayerAccessor", + "world.entity.projectile.AbstractArrowAccessor", + "world.entity.projectile.ArrowAccessor", + "world.entity.projectile.EyeOfEnderAccessor", + "world.entity.projectile.FireworkRocketEntityAccessor", + "world.entity.projectile.FishingHookAccessor", + "world.entity.projectile.ProjectileAccessor", + "world.entity.projectile.ShulkerBulletAccessor", + "world.entity.raid.RaidAccessor", + "world.entity.raid.RaiderAccessor", + "world.entity.raid.RaidsAccessor", + "world.entity.vehicle.AbstractBoatAccessor", + "world.entity.vehicle.MinecartFurnaceAccessor", + "world.food.FoodDataAccessor", + "world.inventory.AbstractContainerMenuAccessor", + "world.inventory.AbstractCraftingMenuAccessor", + "world.inventory.AbstractFurnaceMenuAccessor", + "world.inventory.BeaconMenuAccessor", + "world.inventory.BrewingStandMenuAccessor", + "world.inventory.DispenserMenuAccessor", + "world.inventory.HopperMenuAccessor", + "world.inventory.HorseInventoryMenuAccessor", + "world.inventory.ItemCombinerMenuAccessor", + "world.inventory.MerchantMenuAccessor", + "world.inventory.ResultSlotAccessor", + "world.inventory.SlotAccessor", + "world.inventory.SmithingMenuAccessor", + "world.item.AdventureModePredicateAccessor", + "world.item.ItemCooldowns_CooldownInstanceAccessor", + "world.item.component.CustomDataAccessor", + "world.item.crafting.RecipeMapAccessor", + "world.item.crafting.ShapelessRecipeAccessor", + "world.item.enchantment.ItemEnchantmentsAccessor", + "world.item.trading.MerchantOfferAccessor", + "world.level.BaseCommandBlockAccessor", + "world.level.BaseSpawnerAccessor", + "world.level.GameRules_ValueAccessor", + "world.level.GameRulesAccessor", + "world.level.LevelAccessor", + "world.level.LevelSettingsAccessor", + "world.level.NaturalSpawner_SpawnStateAccessor", + "world.level.NaturalSpawnerAccessor", + "world.level.ServerExplosionAccessor", + "world.level.TicketStorageAccessor", + "world.level.biome.Biome_ClimateSettingsAccessor", + "world.level.biome.BiomeAccessor", + "world.level.biome.MobSpawnSettingsAccessor", + "world.level.biome.MultiNoiseBiomeSourceAccessor", + "world.level.biome.OverworldBiomeBuilderAccessor", + "world.level.biome.TheEndBiomeSourceAccessor", + "world.level.block.AbstractSkullBlockAccessor", + "world.level.block.BaseFireBlockAccessor", + "world.level.block.BedBlockAccessor", + "world.level.block.CrafterBlockAccessor", + "world.level.block.CropBlockAccessor", + "world.level.block.DispenserBlockAccessor", + "world.level.block.EnderChestBlockAccessor", + "world.level.block.StemBlockAccessor", + "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", + "world.level.block.entity.BaseContainerBlockEntityAccessor", + "world.level.block.entity.BeaconBlockEntityAccessor", + "world.level.block.entity.BlockEntityAccessor", + "world.level.block.entity.BrewingStandBlockEntityAccessor", + "world.level.block.entity.ConduitBlockEntityAccessor", + "world.level.block.entity.CrafterBlockEntityAccessor", + "world.level.block.entity.DecoratedPotBlockEntityAccessor", + "world.level.block.entity.EnchantingTableBlockEntityAccessor", + "world.level.block.entity.HopperBlockEntityAccessor", + "world.level.block.entity.LecternBlockEntity_Accessor", + "world.level.block.entity.SkullBlockEntityAccessor", + "world.level.block.entity.SpawnerBlockEntityAccessor", + "world.level.block.entity.StructureBlockEntityAccessor", + "world.level.block.entity.TheEndGatewayBlockEntityAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", + "world.level.block.piston.PistonBaseBlockAccessor", + "world.level.block.state.BlockBehaviour_PropertiesAccessor", + "world.level.block.state.BlockBehaviourAccessor", + "world.level.block.state.StateHolderAccessor", + "world.level.border.WorldBorder_SettingsAccessor", + "world.level.border.WorldBorderAccessor", + "world.level.chunk.ChunkAccessAccessor", + "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", + "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", + "world.level.chunk.LevelChunkAccessor", + "world.level.chunk.storage.ChunkStorageAccessor", + "world.level.chunk.storage.IOWorker$PendingStoreAccessor", + "world.level.chunk.storage.RegionFileAccessor", + "world.level.chunk.storage.SimpleRegionStorageAccessor", + "world.level.dimension.DimensionTypeAccessor", + "world.level.dimension.end.EndDragonFightAccessor", + "world.level.entity.EntityTickListAccessor", + "world.level.entity.PersistentEntitySectionManagerAccessor", + "world.level.levelgen.NoiseSettingsAccessor", + "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", + "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", + "world.level.portal.TeleportTransitionAccessor", + "world.level.saveddata.maps.MapItemSavedDataAccessor", + "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", + "world.level.storage.PlayerDataStorageAccessor", + "world.phys.AABBAccessor", + "world.scores.PlayerTeamAccessor", + "world.scores.ScoreboardAccessor" + ], + "server": [ + "server.dedicated.DedicatedServerAccessor" ] } diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index 79628a11ccd..36f15323f61 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -116,7 +116,9 @@ public AdvancementTemplate build0() { ItemStackUtil.fromSnapshotToNative(di.icon()), SpongeAdventure.asVanilla(di.title()), SpongeAdventure.asVanilla(di.description()), - Optional.ofNullable(this.backgroundPath), +// TODO - Define how we want to expose ClientResource that is a combo of resource location and asset location +// Optional.ofNullable(this.backgroundPath), + Optional.empty(), (net.minecraft.advancements.AdvancementType) (Object) di.type(), di.doesShowToast(), di.doesAnnounceToChat(), diff --git a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java index b03bbdd8979..ac4935667e1 100644 --- a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java +++ b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java @@ -29,7 +29,7 @@ import net.kyori.adventure.nbt.api.BinaryTagHolder; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; +import net.kyori.adventure.text.serializer.json.LegacyHoverEventSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.util.Codec; import net.minecraft.nbt.CompoundTag; @@ -43,7 +43,7 @@ @SuppressWarnings({"PatternValidation","deprecation"}) public final class NbtLegacyHoverEventSerializer implements LegacyHoverEventSerializer { public static final NbtLegacyHoverEventSerializer INSTANCE = new NbtLegacyHoverEventSerializer(); - private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); + private static final Codec SNBT_CODEC = Codec.codec(TagParser::parseCompoundFully, Tag::toString); static final String ITEM_TYPE = "id"; static final String ITEM_COUNT = "Count"; @@ -62,7 +62,7 @@ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOE try { final CompoundTag contents = NbtLegacyHoverEventSerializer.SNBT_CODEC.decode(rawContent); final CompoundTag tag = contents.getCompound(NbtLegacyHoverEventSerializer.ITEM_TAG); - return HoverEvent.ShowItem.of( + return HoverEvent.ShowItem.showItem( Key.key(contents.getString(NbtLegacyHoverEventSerializer.ITEM_TYPE)), contents.contains(NbtLegacyHoverEventSerializer.ITEM_COUNT) ? contents.getByte(NbtLegacyHoverEventSerializer.ITEM_COUNT) : 1, tag.isEmpty() ? null : BinaryTagHolder.encode(tag, NbtLegacyHoverEventSerializer.SNBT_CODEC) @@ -77,7 +77,7 @@ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOE final String raw = PlainTextComponentSerializer.plainText().serialize(input); try { final CompoundTag contents = NbtLegacyHoverEventSerializer.SNBT_CODEC.decode(raw); - return HoverEvent.ShowEntity.of( + return HoverEvent.ShowEntity.showEntity( Key.key(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_TYPE)), UUID.fromString(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_ID)), componentCodec.decode(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_NAME)) diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 965303d7ab5..1be29796530 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -25,7 +25,6 @@ package org.spongepowered.common.adventure; import com.mojang.brigadier.Message; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import com.mojang.serialization.codecs.PrimitiveCodec; @@ -60,7 +59,6 @@ import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.translation.GlobalTranslator; -import net.kyori.adventure.util.Codec; import net.kyori.adventure.util.TriState; import net.minecraft.ChatFormatting; import net.minecraft.commands.arguments.selector.SelectorPattern; @@ -71,8 +69,6 @@ import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.TagParser; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.HoverEvent.Action; @@ -110,7 +106,6 @@ import org.spongepowered.common.bridge.world.BossEventBridge; import org.spongepowered.common.launch.Launch; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -131,21 +126,6 @@ public final class SpongeAdventure { public static final AttributeKey CHANNEL_LOCALE = AttributeKey.newInstance("sponge:locale"); - public static final Codec NBT_CODEC = new Codec() { - @Override - public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException { - try { - return TagParser.parseTag(encoded); - } catch (final CommandSyntaxException e) { - throw new IOException(e); - } - } - - @Override - public @NonNull String encode(final @NonNull CompoundTag decoded) { - return decoded.toString(); - } - }; public static final PrimitiveCodec STRING_CODEC = new PrimitiveCodec() { @Override diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index b508e0bab40..6d51712c86f 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -165,6 +165,7 @@ public BlockSnapshot withLocation(final ServerLocation location) { return SpongeBlockSnapshot.BuilderImpl.pooled().from(this).position(location.blockPosition()).world(location.worldKey()).build(); } + @SuppressWarnings("deprecation") @Override public boolean restore(final boolean force, final BlockChangeFlag flag) { // TODO - rewrite with the PhaseTracker being the hook or use SpongeImplHooks to do the restore. diff --git a/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java index 43b0a377e4e..74960e4559b 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/item/crafting/SmithingRecipeBridge.java @@ -31,7 +31,7 @@ public interface SmithingRecipeBridge extends RecipeResultBridge { Optional bridge$template(); - Optional bridge$base(); + Ingredient bridge$base(); Optional bridge$addition(); } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java index 48a02a62b84..2191f63abd9 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java @@ -28,6 +28,7 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.text.Component; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.TagParser; import net.minecraft.resources.ResourceLocation; import org.checkerframework.checker.nullness.qual.NonNull; @@ -192,7 +193,7 @@ public boolean parseBoolean() throws ArgumentParseException { public String parseNBTString() throws ArgumentParseException { final int startCursor = this.getCursor(); try { - new TagParser(this).readStruct(); + TagParser.parseAsArgument(NbtOps.INSTANCE, this); } catch (final CommandSyntaxException ex) { this.setCursor(startCursor); throw new ArgumentParseException( @@ -208,7 +209,7 @@ public String parseNBTString() throws ArgumentParseException { @Override public DataContainer parseDataContainer() throws ArgumentParseException { try { - return NBTTranslator.INSTANCE.translate(new TagParser(this).readStruct()); + return NBTTranslator.INSTANCE.translate(TagParser.parseCompoundAsArgument(this)); } catch (final CommandSyntaxException e) { throw this.createException(SpongeAdventure.asAdventure(e.getRawMessage())); } diff --git a/src/main/java/org/spongepowered/common/data/persistence/SNBTDataFormat.java b/src/main/java/org/spongepowered/common/data/persistence/SNBTDataFormat.java index 7ebfc654bca..55150e7c6e6 100644 --- a/src/main/java/org/spongepowered/common/data/persistence/SNBTDataFormat.java +++ b/src/main/java/org/spongepowered/common/data/persistence/SNBTDataFormat.java @@ -55,7 +55,7 @@ private static BufferedReader createBufferedReader(final Reader reader) { @Override public DataContainer read(final String input) throws InvalidDataException, IOException { try { - return NBTTranslator.INSTANCE.translate(TagParser.parseTag(input)); + return NBTTranslator.INSTANCE.translate(TagParser.parseCompoundFully(input)); } catch (final CommandSyntaxException e) { throw new InvalidDataException(e); } @@ -65,7 +65,7 @@ public DataContainer read(final String input) throws InvalidDataException, IOExc public DataContainer readFrom(final Reader input) throws InvalidDataException { try { return NBTTranslator.INSTANCE.translate( - TagParser.parseTag(SNBTDataFormat.createBufferedReader(input).lines().collect(Collectors.joining("\n")))); + TagParser.parseCompoundFully(SNBTDataFormat.createBufferedReader(input).lines().collect(Collectors.joining("\n")))); } catch (final CommandSyntaxException e) { throw new InvalidDataException(e); } @@ -74,7 +74,7 @@ public DataContainer readFrom(final Reader input) throws InvalidDataException { @Override public DataContainer readFrom(final InputStream input) throws InvalidDataFormatException { try { - return NBTTranslator.INSTANCE.translate(TagParser.parseTag( + return NBTTranslator.INSTANCE.translate(TagParser.parseCompoundFully( new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n")))); } catch (final CommandSyntaxException e) { throw new InvalidDataException(e); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java index df121f7f3de..b8b0442bc8d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java @@ -67,9 +67,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(Cat::isLying) .set(Cat::setLying) .create(Keys.IS_PURRING) - .get(h -> { - throw new MissingImplementationException("CatData", "IS_PURRING::getter"); - }) + .get(h -> h.isLying() || ((CatAccessor) h).invoker$isRelaxStateOne()) .set((h, v) -> { throw new MissingImplementationException("CatData", "IS_PURRING::setter"); }) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java index eb73c266c42..1b8b3a7d86a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FrogData.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.entity.animal.FrogVariant; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.animal.frog.Frog; +import net.minecraft.world.entity.animal.frog.FrogVariant; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.FrogType; import org.spongepowered.common.accessor.entity.animal.frog.FrogAccessor; @@ -43,7 +43,12 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Frog.class) .create(Keys.FROG_TYPE) .get(h -> (FrogType) (Object) h.getVariant().value()) - .set((h, v) -> ((FrogAccessor) h).invoker$setVariant(BuiltInRegistries.FROG_VARIANT.wrapAsHolder((FrogVariant) (Object) v))); + .set((h, v) -> { + final var holder = h.level().registryAccess().lookup(Registries.FROG_VARIANT) + .orElseThrow() + .wrapAsHolder(((FrogVariant) (Object) v)); + ((FrogAccessor) h).invoker$setVariant(holder); + }); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java index 557e6499dcc..539849f5758 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { } }) .create(Keys.PIG_TYPE) - .get(p -> (PigType) p.getVariant().value()) + .get(p -> (PigType) (Object) p.getVariant().value()) .setAnd((h, v) -> h.level().registryAccess().lookup(Registries.PIG_VARIANT) .map(r -> { var newPigType = r.wrapAsHolder((PigVariant) (Object) v); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java index 8a4699c6344..b800abdf95d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java @@ -26,7 +26,7 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.AbstractThrownPotion; import net.minecraft.world.item.alchemy.PotionContents; import org.apache.commons.lang3.stream.Streams; import org.spongepowered.api.data.Keys; @@ -41,7 +41,7 @@ private PotionData() { // @formatter:off public static void register(final DataProviderRegistrator registrator) { registrator - .asMutable(ThrownPotion.class) + .asMutable(AbstractThrownPotion.class) .create(Keys.POTION_EFFECTS) .get(h -> Streams.of(h.getItem().getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getAllEffects()).map(PotionEffect.class::cast).toList()) .set((h, v) -> { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java index 18306b9294b..f065fb38278 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java @@ -33,6 +33,7 @@ import net.minecraft.world.item.AdventureModePredicate; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.Keys; import org.spongepowered.common.accessor.world.item.AdventureModePredicateAccessor; @@ -53,14 +54,14 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.BREAKABLE_BLOCK_TYPES) .get(h -> BlockTypeItemStackData.get(h, DataComponents.CAN_BREAK)) - .set((h, v) -> BlockTypeItemStackData.set(h, DataComponents.CAN_BREAK, v)) + .setAnd((h, v) -> BlockTypeItemStackData.set(h, DataComponents.CAN_BREAK, v)) .create(Keys.PLACEABLE_BLOCK_TYPES) .get(h -> BlockTypeItemStackData.get(h, DataComponents.CAN_PLACE_ON)) - .set((h, v) -> BlockTypeItemStackData.set(h, DataComponents.CAN_PLACE_ON, v)); + .setAnd((h, v) -> BlockTypeItemStackData.set(h, DataComponents.CAN_PLACE_ON, v)); } // @formatter:on - private static Set get(final ItemStack stack, final DataComponentType component) { + private static @Nullable Set get(final ItemStack stack, final DataComponentType component) { // TODO change API type to predicates final AdventureModePredicate predicate = stack.get(component); if (predicate != null) { @@ -81,7 +82,7 @@ private static boolean set(final ItemStack stack, final DataComponentType { - final LodestoneTracker component = stack.get(DataComponents.LODESTONE_TRACKER); + final @Nullable LodestoneTracker component = stack.get(DataComponents.LODESTONE_TRACKER); if (component == null) { return null; } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java index 0308c122358..dba8988f85f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java @@ -43,7 +43,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.COLOR) .get(h -> h.has(DataComponents.DYED_COLOR) ? Color.ofRgb(h.get(DataComponents.DYED_COLOR).rgb()) : null) - .set((h, v) -> h.update(DataComponents.DYED_COLOR, new DyedItemColor(0, true), prev -> new DyedItemColor(v.rgb(), prev.showInTooltip()))) + .set((h, v) -> h.update(DataComponents.DYED_COLOR, new DyedItemColor(0), prev -> new DyedItemColor(v.rgb()))) .delete(h -> h.set(DataComponents.DYED_COLOR, null)) .supports(h -> h.is(ItemTags.DYEABLE)); } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java index 5938e51050d..9d61ffddc93 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java @@ -24,22 +24,14 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.advancements.critereon.BlockPredicate; import net.minecraft.core.component.DataComponents; -import net.minecraft.util.Unit; -import net.minecraft.world.item.AdventureModePredicate; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.ItemAttributeModifiers; -import net.minecraft.world.item.component.Unbreakable; -import net.minecraft.world.item.enchantment.ItemEnchantments; -import org.jetbrains.annotations.NotNull; +import net.minecraft.world.item.component.TooltipDisplay; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.item.AdventureModePredicateAccessor; -import org.spongepowered.common.accessor.world.item.enchantment.ItemEnchantmentsAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; -import java.util.Collections; -import java.util.List; +import java.util.Map; + public final class HideFlagsItemStackData { @@ -48,62 +40,48 @@ private HideFlagsItemStackData() { // @formatter:off public static void register(final DataProviderRegistrator registrator) { - registrator - .asMutable(ItemStack.class) - .create(Keys.HIDE_ATTRIBUTES) - .get(h -> h.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY).showInTooltip()) - .set((h, v) -> h.update(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY, p -> new ItemAttributeModifiers(p.modifiers(), !v))) - .create(Keys.HIDE_CAN_DESTROY) - .get(h -> h.has(DataComponents.CAN_BREAK) && !h.get(DataComponents.CAN_BREAK).showInTooltip()) - .set((h, v) -> h.set(DataComponents.CAN_BREAK, HideFlagsItemStackData.newAdventureModePredicate(h, !v))) - .create(Keys.HIDE_CAN_PLACE) - .get(h -> { - final var predicate = h.get(DataComponents.CAN_BREAK); - if (predicate == null) { - return false; - } - return !predicate.showInTooltip(); - }) - .set((h, v) -> h.set(DataComponents.CAN_PLACE_ON, HideFlagsItemStackData.newAdventureModePredicate(h, !v))) - .create(Keys.HIDE_ENCHANTMENTS) - .get(h -> ((ItemEnchantmentsAccessor)h.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY)).accessor$showInTooltip()) - .set((h, v) -> h.set(DataComponents.ENCHANTMENTS, HideFlagsItemStackData.newItemEnchantments(h, !v))) - .create(Keys.HIDE_STORED_ENCHANTMENTS) - .get(h -> ((ItemEnchantmentsAccessor)h.getOrDefault(DataComponents.STORED_ENCHANTMENTS, ItemEnchantments.EMPTY)).accessor$showInTooltip()) - .set((h, v) -> h.set(DataComponents.STORED_ENCHANTMENTS, HideFlagsItemStackData.newItemEnchantments(h, !v))) - .create(Keys.HIDE_MISCELLANEOUS) - .get(h -> h.get(DataComponents.HIDE_ADDITIONAL_TOOLTIP) != Unit.INSTANCE) - .set((h, v) -> h.set(DataComponents.HIDE_ADDITIONAL_TOOLTIP, v ? Unit.INSTANCE : null)) - .create(Keys.HIDE_UNBREAKABLE) - .get(h -> h.has(DataComponents.UNBREAKABLE) && !h.get(DataComponents.UNBREAKABLE).showInTooltip()) - .set((h, v) -> { - if (h.has(DataComponents.UNBREAKABLE)) { - h.set(DataComponents.UNBREAKABLE, new Unbreakable(v)); - } // else TODO not supported? - }) + final var keyToComponentMapping = Map.of( + Keys.HIDE_ATTRIBUTES, DataComponents.ATTRIBUTE_MODIFIERS, + Keys.HIDE_ENCHANTMENTS, DataComponents.ENCHANTMENTS, + Keys.HIDE_CAN_DESTROY, DataComponents.CAN_BREAK, + Keys.HIDE_CAN_PLACE, DataComponents.CAN_PLACE_ON, + Keys.HIDE_STORED_ENCHANTMENTS, DataComponents.STORED_ENCHANTMENTS, + Keys.HIDE_UNBREAKABLE, DataComponents.UNBREAKABLE, + Keys.HIDE_MISCELLANEOUS, DataComponents.CUSTOM_DATA + ); + + final var mutableItem = registrator + .asMutable(ItemStack.class); + for (final var entry : keyToComponentMapping.entrySet()) { + mutableItem + .create(entry.getKey()) + .get(h -> h.has(DataComponents.TOOLTIP_DISPLAY) && !h.getOrDefault(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT).shows(entry.getValue())) + .set((h, v) -> h.update(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT, p -> p.withHidden(entry.getValue(), v))); + } + mutableItem .create(Keys.HIDE_TOOLTIP) - .get(h -> h.get(DataComponents.HIDE_ADDITIONAL_TOOLTIP) != Unit.INSTANCE) - .set((h, v) -> h.set(DataComponents.HIDE_ADDITIONAL_TOOLTIP, v ? Unit.INSTANCE : null)) + .get(h -> h.getOrDefault(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT).hideTooltip()) + .set((h, v) -> h.update(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT, p -> new TooltipDisplay(v, p.hiddenComponents()))) ; // TODO missing show_in_tooltip (DYED_COLOR, more?) } // @formatter:on - - @NotNull - private static AdventureModePredicate newAdventureModePredicate(final ItemStack h, final boolean showInTooltip) { - if (h.has(DataComponents.CAN_BREAK)) { - final List $$0 = ((AdventureModePredicateAccessor) h.get(DataComponents.CAN_BREAK)).accessor$predicates(); - return new AdventureModePredicate($$0, showInTooltip); - } - return new AdventureModePredicate(Collections.emptyList(), showInTooltip); - } - - @NotNull - private static ItemEnchantments newItemEnchantments(final ItemStack h, final boolean showInTooltip) { - final ItemEnchantmentsAccessor enchantments = (ItemEnchantmentsAccessor) h.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY);; - return ItemEnchantmentsAccessor.invoker$new(enchantments.accessor$enchantments(), showInTooltip); - } +// +// @NotNull +// private static AdventureModePredicate newAdventureModePredicate(final ItemStack h, final boolean showInTooltip) { +// if (h.has(DataComponents.CAN_BREAK)) { +// final List $$0 = ((AdventureModePredicateAccessor) h.get(DataComponents.CAN_BREAK)).accessor$predicates(); +// return new AdventureModePredicate($$0, showInTooltip); +// } +// return new AdventureModePredicate(Collections.emptyList(), showInTooltip); +// } +// +// @NotNull +// private static ItemEnchantments newItemEnchantments(final ItemStack h, final boolean showInTooltip) { +// final ItemEnchantmentsAccessor enchantments = (ItemEnchantmentsAccessor) h.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY);; +// return ItemEnchantmentsAccessor.invoker$new(enchantments.accessor$enchantments(), showInTooltip); +// } } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 49581493d78..88a7fad3590 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -45,7 +45,6 @@ import net.minecraft.world.item.component.DamageResistant; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; -import net.minecraft.world.item.component.Unbreakable; import net.minecraft.world.item.component.UseCooldown; import net.minecraft.world.item.component.UseRemainder; import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; @@ -354,7 +353,7 @@ private static Inventory inventoryFromItemContainerContents(final ItemContainerC private static void setIsUnbrekable(final ItemStack stack, final Boolean value) { if (value) { - stack.set(DataComponents.UNBREAKABLE, new Unbreakable(true)); + stack.set(DataComponents.UNBREAKABLE, Unit.INSTANCE); } else { stack.remove(DataComponents.UNBREAKABLE); } diff --git a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java index ffaf66d44e5..ac10e3be464 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java @@ -38,7 +38,8 @@ import net.minecraft.world.entity.projectile.ThrownEgg; import net.minecraft.world.entity.projectile.ThrownEnderpearl; import net.minecraft.world.entity.projectile.ThrownExperienceBottle; -import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.ThrownLingeringPotion; +import net.minecraft.world.entity.projectile.ThrownSplashPotion; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.entity.DispenserBlockEntity; @@ -303,16 +304,26 @@ protected Optional createProjectile(final LivingEntity source, fi return super.createProjectile(source, loc); } }); - ProjectileUtil.registerProjectileLogic(EntityTypes.POTION, new SimpleItemLaunchLogic(EntityTypes.POTION, Items.SPLASH_POTION) { + ProjectileUtil.registerProjectileLogic(EntityTypes.SPLASH_POTION, new SimpleItemLaunchLogic(EntityTypes.SPLASH_POTION, Items.SPLASH_POTION) { @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final ThrownPotion potion = new ThrownPotion(source.level(), source, new ItemStack(this.item)); + final ThrownSplashPotion potion = new ThrownSplashPotion(source.level(), source, new ItemStack(this.item)); potion.setItem(new ItemStack(Items.SPLASH_POTION, 1)); potion.shoot(source.getXRot(), source.getYRot(), -20.0F, 0.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (Potion) potion); } }); + ProjectileUtil.registerProjectileLogic(EntityTypes.LINGERING_POTION, new SimpleItemLaunchLogic(EntityTypes.SPLASH_POTION, Items.SPLASH_POTION) { + + @Override + protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { + final ThrownLingeringPotion potion = new ThrownLingeringPotion(source.level(), source, new ItemStack(this.item)); + potion.setItem(new ItemStack(Items.LINGERING_POTION, 1)); + potion.shoot(source.getXRot(), source.getYRot(), -20.0F, 0.5F, 0); + return ProjectileUtil.doLaunch(loc.world(), (Potion) potion); + } + }); ProjectileUtil.registerProjectileLogic(EntityTypes.LLAMA_SPIT, new SimpleEntityLaunchLogic(EntityTypes.LLAMA_SPIT) { @Override diff --git a/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java b/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java index c189fd8f13d..7c8070a5c09 100644 --- a/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java +++ b/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java @@ -25,7 +25,7 @@ package org.spongepowered.common.item.merchant; -import net.minecraft.core.component.DataComponentPredicate; +import net.minecraft.core.component.DataComponentExactPredicate; import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -146,7 +146,7 @@ public TradeOffer build() throws IllegalStateException { @NotNull private static ItemCost itemCostOf(final net.minecraft.world.item.ItemStack stack) { - return new ItemCost(stack.getItemHolder(), stack.getCount(), DataComponentPredicate.allOf(stack.getComponents()), stack); + return new ItemCost(stack.getItemHolder(), stack.getCount(), DataComponentExactPredicate.allOf(stack.getComponents()), stack); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index ce46ab28c13..3b1e62bbe80 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -49,7 +49,7 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe implements Res $$0 -> $$0.group( Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_TEMPLATE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$template()), - Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_BASE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$base()), + Ingredient.CODEC.fieldOf(Constants.Recipe.SMITHING_BASE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$base()), Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_ADDITION_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$addition()), ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge) $$0x).bridge$result()), IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) @@ -59,13 +59,13 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe implements Res private final String resultFunctionId; - public static SpongeSmithingRecipe of(final String spongeType, final Optional template, final Optional base, + public static SpongeSmithingRecipe of(final String spongeType, final Optional template, final Ingredient base, final Optional addition, final ItemStack resultIn, final Optional resultFunctionId) { return new SpongeSmithingRecipe(template, base, addition, resultIn, resultFunctionId.orElse(null)); } - public SpongeSmithingRecipe(final Optional template, final Optional base, + public SpongeSmithingRecipe(final Optional template, final Ingredient base, final Optional addition, final ItemStack spongeResult, final String resultFunctionId) { super(template, base, addition, new TransmuteResult(spongeResult.getItemHolder(), spongeResult.getCount(), spongeResult.getComponentsPatch())); this.resultFunctionId = resultFunctionId; diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java index fcee7525f4a..0313706ab6d 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java @@ -70,14 +70,14 @@ public SpongeSmithingRecipeRegistration(ResourceLocation key, String group, fina public Recipe recipe() { this.ensureCached(); if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, List.of(this.template, this.base, this.addition))) { - return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), new TransmuteResult( + return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), this.base, Optional.of(this.addition), new TransmuteResult( this.spongeResult.getItemHolder(), this.spongeResult.getCount(), this.spongeResult.getComponentsPatch() )); } - return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), Optional.ofNullable(this.base), Optional.ofNullable(this.addition), + return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), this.base, Optional.ofNullable(this.addition), this.spongeResult, this.resultFunction == null ? null : this.key.toString()); } diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index 39eb98f36fb..a6627d1b2fc 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -50,8 +50,6 @@ import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.data.type.ArtType; import org.spongepowered.api.data.type.ArtTypes; -import org.spongepowered.api.data.type.CatType; -import org.spongepowered.api.data.type.CatTypes; import org.spongepowered.api.data.type.ComparatorMode; import org.spongepowered.api.data.type.ComparatorModes; import org.spongepowered.api.data.type.DyeColor; @@ -64,8 +62,6 @@ import org.spongepowered.api.data.type.HorseStyles; import org.spongepowered.api.data.type.LlamaType; import org.spongepowered.api.data.type.LlamaTypes; -import org.spongepowered.api.data.type.ParrotType; -import org.spongepowered.api.data.type.ParrotTypes; import org.spongepowered.api.data.type.RabbitType; import org.spongepowered.api.data.type.RabbitTypes; import org.spongepowered.api.data.type.StructureMode; @@ -843,20 +839,6 @@ public static final class Minecart { public static final int DEFAULT_FUSE_DURATION = 80; } - public static final class Cat { - - public static final Supplier DEFAULT_TYPE = CatTypes.WHITE; - } - - public static final class Panda { - - public static final int UNHAPPY_TIME = 32; - } - - public static final class Parrot { - - public static final Supplier DEFAULT_TYPE = ParrotTypes.RED_BLUE; - } public static final class Player { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java index dad1a167076..6de70dbb983 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; -import net.minecraft.world.entity.animal.FrogVariant; +import net.minecraft.world.entity.animal.frog.FrogVariant; import org.spongepowered.api.data.type.FrogType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java new file mode 100644 index 00000000000..cd55ac4eed2 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import net.minecraft.world.entity.animal.PigVariant; +import org.spongepowered.api.data.type.PigType; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(PigVariant.class) +public class PigVariantMixin_API implements PigType { + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java index 9df79854b24..96450dea666 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; -import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.AbstractThrownPotion; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.Potion; @@ -32,7 +32,7 @@ import java.util.Set; -@Mixin(ThrownPotion.class) +@Mixin(AbstractThrownPotion.class) public abstract class ThrownPotionMixin_API extends ThrowableItemProjectileMixin_API implements Potion { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java index 8ff0d95e645..24b553d5fb6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/SmithingTransformRecipeMixin_API.java @@ -39,7 +39,7 @@ public abstract class SmithingTransformRecipeMixin_API implements SmithingRecipe // @formatter:off @Shadow @Final Optional addition; @Shadow @Final Optional template; - @Shadow @Final Optional base; + @Shadow @Final net.minecraft.world.item.crafting.Ingredient base; // @formatter:on @Override @@ -49,7 +49,7 @@ public Optional templateIngredient() { @Override public Optional baseIngredient() { - return this.base.map(Ingredient.class::cast); + return Optional.of((Ingredient) (Object) this.base); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index 5a5b5295035..0d5c70af339 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -24,18 +24,14 @@ */ package org.spongepowered.common.mixin.core.server.players; -import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.ProfileLookupCallback; import net.minecraft.server.players.GameProfileCache; import org.spongepowered.api.Sponge; import org.spongepowered.api.profile.GameProfile; -import org.spongepowered.api.profile.GameProfileManager; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.SpongeServer; import org.spongepowered.common.accessor.server.players.GameProfileCache_GameProfileInfoAccessor; @@ -146,26 +142,26 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { } } - @Redirect(method = "lookupGameProfile", - at = @At( - value = "INVOKE", - target = "Lcom/mojang/authlib/GameProfileRepository;findProfilesByNames([Ljava/lang/String;Lcom/mojang/authlib/ProfileLookupCallback;)V", - remap = false - ) - ) - private static void impl$lookUpViaSponge(final GameProfileRepository repository, final String[] names, - final ProfileLookupCallback callback) { - final GameProfileManager profileManager = Sponge.server().gameProfileManager(); - profileManager.basicProfile(names[0]) - .whenComplete((profile, ex) -> { - if (ex != null) { - callback.onProfileLookupFailed(names[0], - ex instanceof Exception ? (Exception) ex : new RuntimeException(ex)); - } else { - callback.onProfileLookupSucceeded(SpongeGameProfile.toMcProfile(profile)); - } - }); - } + // TODO - 25w04a - This changed, it looks like the path itself has changed +// @Redirect(method = "lookupGameProfile", +// at = @At( +// value = "INVOKE", +// target = "Lcom/mojang/authlib/GameProfileRepository;findProfileByName(Ljava/lang/String;)Ljava/util/Optional;", +// remap = false +// ) +// ) +// private static void impl$lookUpViaSponge(final GameProfileRepository repository, final String names) { +// final GameProfileManager profileManager = Sponge.server().gameProfileManager(); +// profileManager.basicProfile(names[0]) +// .whenComplete((profile, ex) -> { +// if (ex != null) { +// callback.onProfileLookupFailed(names[0], +// ex instanceof Exception ? (Exception) ex : new RuntimeException(ex)); +// } else { +// callback.onProfileLookupSucceeded(SpongeGameProfile.toMcProfile(profile)); +// } +// }); +// } @Inject(method = "save", at = @At("HEAD"), cancellable = true) private void impl$ignoreSavingIfCancelled(final CallbackInfo ci) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 88a160ea77c..0e709f2e9b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -31,12 +31,14 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.stats.Stats; import net.minecraft.tags.DamageTypeTags; +import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.BlocksAttacks; import org.apache.logging.log4j.Level; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Mixin; @@ -59,8 +61,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen //@formatter:off @Shadow protected abstract void shadow$playHurtSound(DamageSource param0); @Shadow protected abstract void shadow$hurtHelmet(final DamageSource $$0, final float $$1); - @Shadow protected abstract void shadow$hurtCurrentlyUsedShield(final float $$0); - @Shadow protected abstract void shadow$blockUsingShield(final LivingEntity $$0); + @Shadow protected abstract void shadow$blockUsingItem(ServerLevel $$0, LivingEntity $$1);private float attackImpl$baseDamage; @Shadow protected abstract void shadow$hurtArmor(DamageSource source, float damage); @Shadow protected abstract float shadow$getKnockback(final Entity $$0, final DamageSource $$1); @Shadow public abstract float shadow$getAbsorptionAmount(); @@ -68,7 +69,6 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen @Shadow public abstract void setAbsorptionAmount(final float $$0); @Shadow protected int attackStrengthTicker; @Shadow protected float lastHurt; - private float attackImpl$baseDamage; // @formatter:on private float attackImpl$lastHurt; @@ -112,17 +112,22 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * Prevents shield usage before event * Captures the blocked damage as a function */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V")) - private void attackImpl$preventEarlyBlock1(final LivingEntity instance, final float damageToShield) { + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) + private void attackImpl$preventEarlyBlock1( + final BlocksAttacks instance, final net.minecraft.world.level.Level level, + final ItemStack stack, final LivingEntity target, final InteractionHand hand, final float damage) { // this.hurtCurrentlyUsedShield(damageToShield); - this.attackImpl$hurt.functions().add(DamageEventUtil.createShieldFunction(instance)); + // $$6.hurtBlockingItem(this.level(), this.getUseItem(), this, this.getUsedItemHand(), $$5); + this.attackImpl$hurt.functions().add(DamageEventUtil.createShieldFunction(target)); } /** * Prevents shield usage before event */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V")) - private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final LivingEntity livingDamageSource) { + @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final ServerLevel level, final LivingEntity shooter) { + // TODO - 25w04a + // this.blockUsingItem($$0, $$8); // this.blockUsingShield(livingDamageSource); } @@ -339,7 +344,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen /** * Replay prevented - * {@link #shadow$hurtCurrentlyUsedShield} and {@link #shadow$blockUsingShield} + * {@link #shadow$hurtCurrentlyUsedShield} and {@link #shadow$blockUsingItem} * {@link #shadow$hurtHelmet} * {@link #shadow$hurtArmor} * {@link ServerPlayer#awardStat} for {@link Stats#DAMAGE_RESISTED} and {@link Stats#DAMAGE_DEALT} @@ -347,15 +352,16 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen *

* And capture inventory changes if needed */ - protected void attackImpl$handlePostDamage() { + protected void attackImpl$handlePostDamage(ServerLevel level) { final var result = this.attackImpl$actuallyHurtResult; if (result != null && !this.attackImpl$actuallyHurtCancelled) { final var damageSource = result.source(); result.damageToShield().ifPresent(dmg -> { - this.shadow$hurtCurrentlyUsedShield(dmg); + // TODO - figure out how to grab the blocksdamage component +// this.shadow$hurtCurrentlyUsedShield(dmg); if (!damageSource.is(DamageTypeTags.IS_PROJECTILE)) { if (damageSource.getDirectEntity() instanceof LivingEntity livingSource) { - this.shadow$blockUsingShield(livingSource); + this.shadow$blockUsingItem(level, livingSource); } } }); @@ -388,7 +394,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen */ @Inject(method = "actuallyHurt", at = @At("RETURN")) protected void attackImpl$cleanupActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { - this.attackImpl$handlePostDamage(); + this.attackImpl$handlePostDamage(level); this.attackImpl$actuallyHurt = null; this.attackImpl$actuallyHurtResult = null; this.lastHurt = this.attackImpl$lastHurt; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java index c083ec4f6d9..e29a9d7bf5a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java @@ -24,12 +24,13 @@ */ package org.spongepowered.common.mixin.core.world.entity.npc; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.npc.WanderingTraderSpawner; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.util.Constants; @Mixin(WanderingTraderSpawner.class) @@ -40,9 +41,11 @@ public abstract class WanderingTraderMixin { // @formatter:on @Inject(method = "tick", at = @At("HEAD"), cancellable = true) - private void impl$checkInfiniteTickDelay(final CallbackInfoReturnable cir) { + private void impl$checkInfiniteTickDelay( + final ServerLevel $$0, final boolean $$1, final boolean $$2, final CallbackInfo cir + ) { if (this.tickDelay == Constants.TickConversions.INFINITE_TICKS) { - cir.setReturnValue(0); + cir.cancel(); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index eea94d4d26a..d9aa889c127 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -313,7 +313,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I */ @Inject(method = "actuallyHurt", at = @At("RETURN")) protected void attackImpl$afterActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { - this.attackImpl$handlePostDamage(); + this.attackImpl$handlePostDamage(level); this.attackImpl$actuallyHurt = null; this.attackImpl$actuallyHurtResult = null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java index 30411b096b9..d40ff2d2be8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java @@ -40,7 +40,7 @@ public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBrid // @formatter=off @Shadow @Final Optional template; - @Shadow @Final Optional base; + @Shadow @Final Ingredient base; @Shadow @Final Optional addition; @Shadow @Final TransmuteResult result; // @formatter=on @@ -51,7 +51,7 @@ public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBrid } @Override - public Optional bridge$base() { + public Ingredient bridge$base() { return this.base; } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index d899f7fe74e..162b4b4659b 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -163,6 +163,7 @@ "minecraft.world.entity.animal.Parrot_VariantMixin_API", "minecraft.world.entity.animal.ParrotMixin_API", "minecraft.world.entity.animal.PigMixin_API", + "minecraft.world.entity.animal.PigVariantMixin_API", "minecraft.world.entity.animal.PolarBearMixin_API", "minecraft.world.entity.animal.PufferfishMixin_API", "minecraft.world.entity.animal.Rabbit_VariantMixin_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 76aa88949ef..feca937fe91 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -980,7 +980,7 @@ public void testData(final ServerPlayer player) { // this.checkOfferData(itemFrame, Keys.ITEM_STACK_SNAPSHOT, stoneStack.asImmutable()); // TODO JukeBox // TODO Lectern - final Entity potionEntity = world.createEntity(EntityTypes.POTION.get(), position); + final Entity potionEntity = world.createEntity(EntityTypes.SPLASH_POTION.get(), position); this.checkOfferData(potionEntity, Keys.ITEM_STACK_SNAPSHOT, splashPotion.asImmutable()); // TODO unset original value causes logging error // TODO Keys.KNOCKBACK_STRENGTH diff --git a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java index 1f70e0e6626..645583e0ec8 100644 --- a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java @@ -201,7 +201,8 @@ public ProjectileTestListener() { this.projectileTypes.add(EntityTypes.WITHER_SKULL.get()); this.projectileTypes.add(EntityTypes.EYE_OF_ENDER.get()); // this.projectileTypes.add(EntityTypes.FISHING_BOBBER.get()); - this.projectileTypes.add(EntityTypes.POTION.get()); + this.projectileTypes.add(EntityTypes.SPLASH_POTION.get()); + this.projectileTypes.add(EntityTypes.LINGERING_POTION.get()); this.projectileTypes.add(EntityTypes.LLAMA_SPIT.get()); this.projectileTypes.add(EntityTypes.DRAGON_FIREBALL.get()); this.projectileTypes.add(EntityTypes.SHULKER_BULLET.get()); From 0ab192d55f33334c1bbf80ca3c7cc4ce829fce32 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 31 Jan 2025 19:03:22 -0800 Subject: [PATCH 185/586] feat!: update content api to 25w05a Breaking Changes - Raids no longer have a ServerWorld link Additions - Mainly new type entries and tag entries are updated --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 9 +++++ gradle.properties | 2 +- .../world/entity/LivingEntityAccessor.java | 5 --- .../world/entity/raid/RaidsAccessor.java | 5 ++- .../saveddata/maps/MapIndexAccessor.java | 36 ++++++++++++++++++ .../resources/mixins.sponge.accessors.json | 1 + .../event/SpongeCommonEventFactory.java | 2 +- .../common/map/SpongeMapStorage.java | 6 +-- .../common/raid/SpongeRaidWave.java | 22 +++++------ .../world/server/SpongeWorldManager.java | 2 +- .../world/entity/raid/RaidMixin_API.java | 8 ---- .../entity/LivingEntityMixin_Attack_Impl.java | 4 +- .../level/saveddata/MapIdTrackerMixin.java | 15 +++----- .../DimensionDataSotrageMixin.java} | 37 ++++++++++++------- .../storage/DimensionDataStorageMixin.java | 32 ++++++++-------- src/mixins/resources/mixins.sponge.core.json | 2 +- 17 files changed, 113 insertions(+), 77 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/level/saveddata/maps/MapIndexAccessor.java rename src/mixins/java/org/spongepowered/common/mixin/core/world/level/{SavedDataMixin.java => storage/DimensionDataSotrageMixin.java} (56%) diff --git a/SpongeAPI b/SpongeAPI index 0b462f55486..700c16b498d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 0b462f55486375b32bbe947f7e134e4e1ddef735 +Subproject commit 700c16b498d1197c09a54a0b36abb38aee88c2d4 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 78f41162c36..e7586fabde6 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -229,6 +229,15 @@ public static List registryEntries(final Context context) { Registries.PIG_VARIANT, $ -> true, RegistryScope.SERVER + ), + new RegistryEntriesGenerator<>( + "data.type", + "CowVariants", + "COW_VARIANT", + context.relativeClass("data.type", "CowVariant"), + Registries.COW_VARIANT, + $ -> true, + RegistryScope.SERVER ) ); } diff --git a/gradle.properties b/gradle.properties index b6faf8262e9..e68d8455f81 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w04a +minecraftVersion=25w05a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java index 6299d45af17..55e5ae7a68a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/LivingEntityAccessor.java @@ -27,7 +27,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; @@ -76,8 +75,6 @@ public interface LivingEntityAccessor { throw new UntransformedAccessorError(); } - @Accessor("dead") boolean accessor$dead(); - @Accessor("lastHurt") float accessor$lastHurt(); @Accessor("lastHurt") void accessor$lastHurt(final float lastHurt); @@ -91,6 +88,4 @@ public interface LivingEntityAccessor { @Accessor("useItem") void accessor$useItem(final ItemStack useItem); - @Invoker("isDamageSourceBlocked") boolean invoker$isDamageSourceBlocked(final DamageSource source); - } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/raid/RaidsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/raid/RaidsAccessor.java index 149e320e1eb..a606054143a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/raid/RaidsAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/raid/RaidsAccessor.java @@ -24,16 +24,17 @@ */ package org.spongepowered.common.accessor.world.entity.raid; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.world.entity.raid.Raid; import net.minecraft.world.entity.raid.Raids; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.Map; @Mixin(Raids.class) public interface RaidsAccessor { - @Accessor("raidMap") Map accessor$raidMap(); + @Accessor("raidMap") + Int2ObjectMap accessor$raidMap(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/saveddata/maps/MapIndexAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/saveddata/maps/MapIndexAccessor.java new file mode 100644 index 00000000000..fecca3eaddd --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/saveddata/maps/MapIndexAccessor.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.level.saveddata.maps; + +import net.minecraft.world.level.saveddata.maps.MapIndex; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MapIndex.class) +public interface MapIndexAccessor { + + @Accessor("lastMapId") int accessor$getLastIndexID(); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index bbc23a61eb2..afacaf4597f 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -211,6 +211,7 @@ "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", "world.level.portal.TeleportTransitionAccessor", + "world.level.saveddata.maps.MapIndexAccessor", "world.level.saveddata.maps.MapItemSavedDataAccessor", "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", "world.level.storage.PlayerDataStorageAccessor", diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 56d84ab2a83..7f5417ee0b6 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -743,7 +743,7 @@ public static Optional fireCreateMapEvent(final Cause cause, final Set< final ServerLevel defaultWorld = (ServerLevel) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); final MapIdTrackerBridge mapIdTrackerBridge = (MapIdTrackerBridge) defaultWorld.getDataStorage() - .computeIfAbsent(MapIndex.factory(), Constants.Map.MAP_INDEX_DATA_NAME); + .computeIfAbsent(MapIndex.TYPE); final MapItemSavedData mapData = MapItemSavedData.createFresh(0, 0, (byte) 0, false, false, Level.END); diff --git a/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java b/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java index 1c5e2cf1106..c85fd6c9992 100644 --- a/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java +++ b/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java @@ -34,11 +34,10 @@ import org.spongepowered.api.map.MapStorage; import org.spongepowered.api.world.DefaultWorldKeys; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.bridge.map.MapIdTrackerBridge; +import org.spongepowered.common.accessor.world.level.saveddata.maps.MapIndexAccessor; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.util.Constants; import java.util.Collection; import java.util.HashMap; @@ -64,8 +63,7 @@ public Collection allMapInfos() { final Set mapInfos = new HashSet<>(); final ServerLevel defaultWorld = (ServerLevel) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); - final int highestId = ((MapIdTrackerBridge) defaultWorld.getDataStorage() - .computeIfAbsent(MapIndex.factory(), Constants.Map.MAP_INDEX_DATA_NAME)).bridge$getHighestMapId().orElse(-1); + final int highestId = ((MapIndexAccessor) defaultWorld.getDataStorage().computeIfAbsent(MapIndex.TYPE)).accessor$getLastIndexID(); for (int i = 0; i <= highestId; i++) { final @Nullable MapInfo mapInfo = (MapInfo) defaultWorld.getMapData(new MapId(i)); if (mapInfo == null) { diff --git a/src/main/java/org/spongepowered/common/raid/SpongeRaidWave.java b/src/main/java/org/spongepowered/common/raid/SpongeRaidWave.java index 880c2d79647..4c63019a205 100644 --- a/src/main/java/org/spongepowered/common/raid/SpongeRaidWave.java +++ b/src/main/java/org/spongepowered/common/raid/SpongeRaidWave.java @@ -25,6 +25,7 @@ package org.spongepowered.common.raid; +import net.minecraft.server.level.ServerLevel; import org.spongepowered.api.entity.living.monster.raider.Raider; import org.spongepowered.api.raid.Raid; import org.spongepowered.api.raid.RaidWave; @@ -56,11 +57,7 @@ public boolean isBonus() { * If the wave is not a final wave, the bonus waves occur after the final wave. * If our wave was before the final wave, the amount of normal raids (which is set by the difficulty) would be greater than our wave's id. */ - if (this.isFinal() || this.waveId < ((RaidAccessor) this.raid).accessor$numGroups()) { - return false; - } - - return true; + return !this.isFinal() && this.waveId >= ((RaidAccessor) this.raid).accessor$numGroups(); } @Override @@ -78,14 +75,18 @@ public Optional leader() { @Override public boolean addRaider(Raider raider, boolean addToRaidHealth) { Objects.requireNonNull(raider, "Raider cannot be null."); - return this.raid.addWaveMob(this.waveId, (net.minecraft.world.entity.raid.Raider) raider, addToRaidHealth); + // We only support adding raiders to server worlds + if (raider.world() instanceof ServerLevel sl) { + return this.raid.addWaveMob(sl, this.waveId, (net.minecraft.world.entity.raid.Raider) raider, addToRaidHealth); + } + return false; } @Override public boolean removeRaider(Raider raider) { Objects.requireNonNull(raider, "Raider cannot be null."); - if (raider.raidWave().isPresent() && this.equals(raider.raidWave().get().get())) { - this.raid.removeFromRaid((net.minecraft.world.entity.raid.Raider) raider, true); + if (raider.raidWave().isPresent() && this.equals(raider.raidWave().get().get()) && raider.world() instanceof ServerLevel sl) { + this.raid.removeFromRaid(sl, (net.minecraft.world.entity.raid.Raider) raider, true); return true; } @@ -94,11 +95,10 @@ public boolean removeRaider(Raider raider) { @Override public boolean equals(Object obj) { - if (obj instanceof SpongeRaidWave) { - SpongeRaidWave other = (SpongeRaidWave) obj; + if (obj instanceof SpongeRaidWave other) { // Minecraft Tracks it's raids via an ID which is handled by the RaidManager. // Each world has it's own raid manager so we have to verify that the world the raids are in is also equal. - if (this.waveId == other.waveId && this.raid.getLevel() == other.raid.getLevel() && this.raid.getId() == other.raid.getId()) { + if (this.waveId == other.waveId && this.raid == other.raid && this.raid.getCenter() == other.raid.getCenter()) { return true; } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 95b14962d56..c88ab6827cb 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -1035,7 +1035,7 @@ private void loadSpawnChunks(final ServerLevel world) { } private void updateForcedChunks(final ServerLevel world, final ServerChunkCache serverChunkProvider) { - final @Nullable TicketStorage forcedChunksSaveData = world.getDataStorage().get(TicketStorage.factory(), "chunks"); + final @Nullable TicketStorage forcedChunksSaveData = world.getDataStorage().get(TicketStorage.TYPE); if (forcedChunksSaveData != null) { final LongIterator longIterator = forcedChunksSaveData.getForceLoadedChunks().iterator(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/raid/RaidMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/raid/RaidMixin_API.java index feb2b13a32d..6c66244d85c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/raid/RaidMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/raid/RaidMixin_API.java @@ -29,10 +29,8 @@ import net.minecraft.server.level.ServerBossEvent; import net.minecraft.world.entity.raid.Raid; import net.minecraft.world.entity.raid.Raider; -import net.minecraft.world.level.Level; import org.spongepowered.api.data.type.RaidStatus; import org.spongepowered.api.raid.RaidWave; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -53,16 +51,10 @@ public abstract class RaidMixin_API implements org.spongepowered.api.raid.Raid { @Shadow @Final private ServerBossEvent raidEvent; @Shadow private Raid.RaidStatus status; - @Shadow public abstract Level shadow$getLevel(); @Shadow public abstract float shadow$getHealthOfLivingRaiders(); @Shadow public abstract int shadow$getGroupsSpawned(); //@formatter:on - @Override - public ServerWorld world() { - return (ServerWorld) this.shadow$getLevel(); - } - @Override public BossBar bossBar() { return SpongeAdventure.asAdventure(this.raidEvent); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 0e709f2e9b4..47e93bf9558 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -112,7 +112,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * Prevents shield usage before event * Captures the blocked damage as a function */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) + @Redirect(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) private void attackImpl$preventEarlyBlock1( final BlocksAttacks instance, final net.minecraft.world.level.Level level, final ItemStack stack, final LivingEntity target, final InteractionHand hand, final float damage) { @@ -124,7 +124,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen /** * Prevents shield usage before event */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)V")) + @Redirect(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)V")) private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final ServerLevel level, final LivingEntity shooter) { // TODO - 25w04a // this.blockUsingItem($$0, $$8); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/saveddata/MapIdTrackerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/saveddata/MapIdTrackerMixin.java index bde3db475a7..e3467b1bd73 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/saveddata/MapIdTrackerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/saveddata/MapIdTrackerMixin.java @@ -24,33 +24,30 @@ */ package org.spongepowered.common.mixin.core.world.level.saveddata; -import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.world.level.saveddata.maps.MapIndex; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.map.MapIdTrackerBridge; -import org.spongepowered.common.util.Constants; import java.util.OptionalInt; @Mixin(MapIndex.class) public abstract class MapIdTrackerMixin implements MapIdTrackerBridge { - @Shadow @Final private Object2IntMap usedAuxIds; + @Shadow + private int lastMapId; @Override public void bridge$setHighestMapId(final int id) { - this.usedAuxIds.put(Constants.Map.ID_COUNTS_KEY, id); + this.lastMapId = id; } @Override public OptionalInt bridge$getHighestMapId() { - final int id = this.usedAuxIds.getInt(Constants.Map.ID_COUNTS_KEY); - if (id == this.usedAuxIds.defaultReturnValue()) { - return OptionalInt.empty(); // Default return value is -1 + if (this.lastMapId == -1) { + return OptionalInt.empty(); } - return OptionalInt.of(id); + return OptionalInt.of(this.lastMapId); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java similarity index 56% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java index 1efb73a8c2c..da13a3800b3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/SavedDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java @@ -22,30 +22,39 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.level; +package org.spongepowered.common.mixin.core.world.level.storage; -import net.minecraft.core.HolderLookup; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.RegistryOps; import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.saveddata.SavedDataType; +import net.minecraft.world.level.storage.DimensionDataStorage; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; -@Mixin(SavedData.class) -public abstract class SavedDataMixin { +@Mixin(DimensionDataStorage.class) +public abstract class DimensionDataSotrageMixin { - @Inject(method = "save(Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/SavedData;save(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;"), - locals = LocalCapture.CAPTURE_FAILHARD) - public void impl$writeAdditionalMapNBT(HolderLookup.Provider registry, final CallbackInfoReturnable cir, CompoundTag compound) { - if (this instanceof DataCompoundHolder) { - if (DataUtil.syncDataToTag(this)) { - compound.merge(((DataCompoundHolder) this).data$getCompound()); + @WrapOperation(method = "encodeUnchecked", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;" + ) + ) + public Tag impl$writeAdditionalMapNBT( + final CompoundTag instance, final String key, final Tag encoded, + final Operation original, final SavedDataType type, + final SavedData data, final RegistryOps registry + ) { + if (data instanceof DataCompoundHolder dch) { + if (DataUtil.syncDataToTag(dch)) { + instance.merge(dch.data$getCompound()); } } + return original.call(instance, key, encoded); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java index ddde9ac9d2b..598d0e538da 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java @@ -24,34 +24,32 @@ */ package org.spongepowered.common.mixin.core.world.level.storage; -import net.minecraft.core.HolderLookup; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.datafix.DataFixTypes; -import net.minecraft.world.level.saveddata.SavedData; import net.minecraft.world.level.storage.DimensionDataStorage; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; -import java.nio.file.Path; -import java.util.function.BiFunction; +import java.util.Optional; @Mixin(DimensionDataStorage.class) public abstract class DimensionDataStorageMixin { - @Inject(method = "readSavedData", at = @At(value = "RETURN", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) - public void readSpongeMapData(BiFunction var1, DataFixTypes $$1, String var2, - CallbackInfoReturnable cir, - Path var3, CompoundTag rootTag) { - final SavedData savedData = cir.getReturnValue(); - if (savedData instanceof DataCompoundHolder) { - ((DataCompoundHolder) savedData).data$setCompound(rootTag); - DataUtil.syncTagToData(savedData); - ((DataCompoundHolder) savedData).data$setCompound(null); + @WrapOperation(method = "readSavedData", at = @At(value = "INVOKE", target = "Ljava/util/Optional;orElse(Ljava/lang/Object;)Ljava/lang/Object;")) + public T readSpongeMapData( + final Optional instance, final T other, final Operation original, + final @Local CompoundTag rootTag + ) { + final var result = original.call(instance, other); + if (result instanceof DataCompoundHolder dch) { + dch.data$setCompound(rootTag); + DataUtil.syncTagToData(dch); + dch.data$setCompound(null); } + return null; } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index f966a2ea3b8..98f1cfab1e1 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -226,7 +226,7 @@ "world.level.LevelMixin", "world.level.NaturalSpawner_SpawnStateMixin", "world.level.NaturalSpawnerMixin", - "world.level.SavedDataMixin", + "world.level.storage.DimensionDataSotrageMixin", "world.level.ServerExplosionMixin", "world.level.biome.BiomeSourceMixin", "world.level.block.BaseFireBlockMixin", From 44122fcf4028ca47fc3cd3157ad04fdf061547dd Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 3 Feb 2025 01:39:10 +0200 Subject: [PATCH 186/586] Fix missed per world phase tracker change This was missed during the CompositeEvent related changes --- .../mixin/tracker/server/level/ServerLevelMixin_Tracker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 4cd67a5d34f..598d33bb49c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -646,7 +646,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable return null; } final var instance = PhaseTracker.getWorldInstance(this); - if (instance.getSidedThread() != PhaseTracker.getServerInstanceExplicitly().getSidedThread() && instance != PhaseTracker.getServerInstanceExplicitly()) { + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } return instance; @@ -689,7 +689,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable *

    *
  • This world instance is managed and verified by Sponge
  • *
  • This world must {@link LevelBridge#bridge$isFake()} return {@code false}
  • - *
  • The {@link PhaseTracker#getServerInstanceExplicitly}'s {@link PhaseTracker#getSidedThread()} must be {@code ==} {@link Thread#currentThread()}
  • The {@link PhaseTracker#getWorldInstance}'s {@link PhaseTracker#onSidedThread()} ()} must be {@code true}The current {@link IPhaseState} must be allowing to record transactions with an applicable {@link org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier} *
* After which, we may be able to appropriately associate the {@link net.minecraft.world.level.block.entity.BlockEntity} From 589b89c21a96d1c72f2389a3c07dd7577ed5343a Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 4 Feb 2025 00:40:13 +0200 Subject: [PATCH 187/586] Update metadata --- gradle/verification-metadata.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c4d79753249..916d5e394d6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -7433,7 +7433,9 @@
- + + + From 6883cfd18863de031f0f3130a26d9562a30a829f Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 4 Feb 2025 21:27:27 +0200 Subject: [PATCH 188/586] Implement SpongeComponents#receiverVirtualComponent --- SpongeAPI | 2 +- .../adventure/AdventureTextComponent.java | 24 +++++--- .../AudienceVirtualComponentRenderer.java | 46 +++++++++++++++ .../adventure/NativeComponentRenderer.java | 5 +- .../common/adventure/SpongeAdventure.java | 43 +++++++++++++- .../adventure/SpongeRendererContext.java | 59 +++++++++++++++++++ .../chat/TranslatableContentsMixin.java | 2 +- .../core/network/PacketEncoderMixin.java | 7 +++ .../chat/ComponentSerializationMixin.java | 4 +- .../core/server/MinecraftServerMixin.java | 4 +- .../chat/ReusableComponentMessageFactory.java | 4 +- 11 files changed, 184 insertions(+), 16 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java create mode 100644 src/main/java/org/spongepowered/common/adventure/SpongeRendererContext.java diff --git a/SpongeAPI b/SpongeAPI index 2781035831e..c4ed14f2f8e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 2781035831e208c9a66c8861f61804bfefb9b4da +Subproject commit c4ed14f2f8e015a89283585c85d2c0c97522b10a diff --git a/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java b/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java index fe4f7f0e926..a822080efdc 100644 --- a/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java +++ b/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.adventure; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.renderer.ComponentRenderer; import net.minecraft.client.Minecraft; @@ -48,16 +50,16 @@ public class AdventureTextComponent implements net.minecraft.network.chat.Compon private net.minecraft.network.chat.@MonotonicNonNull Component converted; private @Nullable Locale deepConvertedLocalized; private final net.kyori.adventure.text.Component wrapped; - private final @Nullable ComponentRenderer renderer; + private final @Nullable ComponentRenderer renderer; private @Nullable Locale lastLocale; private @Nullable AdventureTextComponent lastRendered; - public AdventureTextComponent(final net.kyori.adventure.text.Component wrapped, final @Nullable ComponentRenderer renderer) { + public AdventureTextComponent(final net.kyori.adventure.text.Component wrapped, final @Nullable ComponentRenderer renderer) { this.wrapped = wrapped; this.renderer = renderer; } - public @Nullable ComponentRenderer renderer() { + public @Nullable ComponentRenderer renderer() { return this.renderer; } @@ -65,12 +67,20 @@ public net.kyori.adventure.text.Component wrapped() { return this.wrapped; } - public synchronized AdventureTextComponent rendered(final Locale locale) { + public synchronized AdventureTextComponent rendered(final Locale locale, final @Nullable Audience audience) { + if (this.renderer == null) { + return this; + } + final SpongeRendererContext context = new SpongeRendererContext(locale, audience); + final Component component = this.renderer.render(this.wrapped, context); + if (context.containsVirtualComponents()) { + return new AdventureTextComponent(component, null); + } if (Objects.equals(locale, this.lastLocale)) { return this.lastRendered; } this.lastLocale = locale; - return this.lastRendered = this.renderer == null ? this : new AdventureTextComponent(this.renderer.render(this.wrapped, locale), null); + return this.lastRendered = new AdventureTextComponent(component, null); } net.minecraft.network.chat.Component deepConverted() { @@ -87,7 +97,7 @@ net.minecraft.network.chat.Component deepConvertedLocalized() { net.minecraft.network.chat.Component converted = this.converted; final Locale target = LocaleCache.getLocale(Minecraft.getInstance().options.languageCode); if (converted == null || this.deepConvertedLocalized != target) { - converted = this.converted = this.rendered(target).deepConverted(); + converted = this.converted = this.rendered(target, null).deepConverted(); this.deepConvertedLocalized = target; } return converted; @@ -104,7 +114,7 @@ public Style getStyle() { @Override public String getString() { - return this.rendered(Locale.getDefault()).deepConverted().getString(); + return this.rendered(Locale.getDefault(), null).deepConverted().getString(); } @Override diff --git a/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java b/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java new file mode 100644 index 00000000000..f5e63433c95 --- /dev/null +++ b/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java @@ -0,0 +1,46 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.adventure; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.VirtualComponentRenderer; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.function.Function; + +public final class AudienceVirtualComponentRenderer implements VirtualComponentRenderer { + + private final Function apply; + + AudienceVirtualComponentRenderer(final Function apply) { + this.apply = apply; + } + + @Override + public @NonNull ComponentLike apply(final @NonNull Audience context) { + return this.apply.apply(context); + } +} diff --git a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java index bb0d6e3abfa..15b96fbfa85 100644 --- a/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java +++ b/src/main/java/org/spongepowered/common/adventure/NativeComponentRenderer.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.adventure; +import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.translation.TranslationRegistry; @@ -57,9 +58,9 @@ public MessageFormat translate(final @NonNull String key, final @NonNull Locale } }; - public static @NonNull Component apply(final Component input, final Locale locale) { + public static @NonNull Component apply(final Component input, final Locale locale, final @Nullable Audience audience) { if (input instanceof AdventureTextComponent) { - return ((AdventureTextComponent) input).rendered(locale); + return ((AdventureTextComponent) input).rendered(locale, audience); } else { return NativeComponentRenderer.get().render(input.copy(), locale); } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index a45c769f7e5..b226624fc24 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -58,6 +58,8 @@ import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.renderer.ComponentRenderer; +import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.util.Codec; @@ -101,6 +103,7 @@ import org.spongepowered.api.adventure.SpongeComponents; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.registry.DefaultedRegistryReference; import org.spongepowered.api.util.Tristate; import org.spongepowered.common.SpongeCommon; @@ -113,6 +116,7 @@ import org.spongepowered.common.launch.Launch; import java.io.IOException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -126,6 +130,7 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; +import java.util.function.Function; public final class SpongeAdventure { @@ -163,6 +168,36 @@ public String toString() { } }; + public static final ComponentRenderer SPONGE_COMPONENT_RENDERER = new TranslatableComponentRenderer<>() { + + @Override + protected @NonNull Component renderVirtual(final @NonNull VirtualComponent component, final @NonNull SpongeRendererContext context) { + context.markContainsVirtualComponents(); + if (component.renderer() instanceof final AudienceVirtualComponentRenderer audienceVirtualComponentRenderer + && context.audience() != null) { + return audienceVirtualComponentRenderer.apply(context.audience()).asComponent(); + } + return super.renderVirtual(component, context); + } + + @Override + protected @Nullable MessageFormat translate(final @NonNull String key, final @NonNull SpongeRendererContext context) { + return GlobalTranslator.translator().translate(key, context.locale()); + } + + @Override + protected @NonNull Component renderTranslatable(final @NonNull TranslatableComponent component, final @NonNull SpongeRendererContext context) { + final TriState anyTranslations = GlobalTranslator.translator().hasAnyTranslations(); + if (anyTranslations == TriState.TRUE || anyTranslations == TriState.NOT_SET) { + final @Nullable Component translated = GlobalTranslator.translator().translate(component, context.locale()); + return translated != null + ? translated + : super.renderTranslatable(component, context); + } + return component; + } + }; + public static final ConfigurateComponentSerializer CONFIGURATE = ConfigurateComponentSerializer.builder() .scalarSerializer(GsonComponentSerializer.gson()) .build(); @@ -170,6 +205,7 @@ public String toString() { private static final Set ACTIVE_BOSS_BARS = ConcurrentHashMap.newKeySet(); public static final ThreadLocal ENCODING_LOCALE = new ThreadLocal<>(); + public static final ThreadLocal ENCODING_PLAYER = new ThreadLocal<>(); // -------------- // ---- Core ---- @@ -229,7 +265,7 @@ public static ChatType.Bound asVanilla(final RegistryAccess access, final net.ky } public static net.minecraft.network.chat.Component asVanilla(final Component component) { - return new AdventureTextComponent(component, GlobalTranslator.renderer()); + return new AdventureTextComponent(component, SpongeAdventure.SPONGE_COMPONENT_RENDERER); } public static Optional asVanillaOpt(final @Nullable Component component) { @@ -837,6 +873,11 @@ public static class Factory implements SpongeComponents.Factory { public ComponentFlattener flattener() { return ComponentFlattenerProvider.INSTANCE; } + + @Override + public VirtualComponent receiverVirtualComponent(final @NonNull Function apply) { + return Component.virtual(Audience.class, new AudienceVirtualComponentRenderer(apply)); + } } // Boss bar tracking diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeRendererContext.java b/src/main/java/org/spongepowered/common/adventure/SpongeRendererContext.java new file mode 100644 index 00000000000..60d56de5a96 --- /dev/null +++ b/src/main/java/org/spongepowered/common/adventure/SpongeRendererContext.java @@ -0,0 +1,59 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.adventure; + +import net.kyori.adventure.audience.Audience; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Locale; + +public final class SpongeRendererContext { + + private final Locale locale; + private final @Nullable Audience audience; + + private boolean containsVirtualComponents; + + public SpongeRendererContext(final Locale locale, final @Nullable Audience audience) { + this.locale = locale; + this.audience = audience; + } + + public Locale locale() { + return this.locale; + } + + public @Nullable Audience audience() { + return this.audience; + } + + public boolean containsVirtualComponents() { + return this.containsVirtualComponents; + } + + public void markContainsVirtualComponents() { + this.containsVirtualComponents = true; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/network/chat/TranslatableContentsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/network/chat/TranslatableContentsMixin.java index 55e8b462d6c..b1e161ffd6f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/network/chat/TranslatableContentsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/network/chat/TranslatableContentsMixin.java @@ -65,7 +65,7 @@ public abstract class TranslatableContentsMixin { // Only do a deep copy if actually necessary if (GlobalTranslator.translator().translate(this.key, actualLocale) != null) { - this.impl$translated = NativeComponentRenderer.apply(toTranslate, actualLocale); + this.impl$translated = NativeComponentRenderer.apply(toTranslate, actualLocale, null); } else { this.impl$translated = toTranslate; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/PacketEncoderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/PacketEncoderMixin.java index 9e6c9c09ca8..9dae20a9a44 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/PacketEncoderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/PacketEncoderMixin.java @@ -26,9 +26,12 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import net.minecraft.network.Connection; import net.minecraft.network.PacketEncoder; import net.minecraft.network.PacketListener; import net.minecraft.network.protocol.Packet; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -42,6 +45,9 @@ public class PacketEncoderMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/network/codec/StreamCodec;encode(Ljava/lang/Object;Ljava/lang/Object;)V")) private void impl$setLocaleBeforeEncode(final ChannelHandlerContext ctx, final Packet $$1, final ByteBuf $$2, final CallbackInfo ci) { SpongeAdventure.ENCODING_LOCALE.set(ctx.channel().attr(SpongeAdventure.CHANNEL_LOCALE).get()); + if (ctx.pipeline().get(Connection.class).getPacketListener() instanceof final ServerGamePacketListenerImpl serverGamePacketListener) { + SpongeAdventure.ENCODING_PLAYER.set((ServerPlayer) serverGamePacketListener.player); + } } @Inject(method = "encode(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/protocol/Packet;Lio/netty/buffer/ByteBuf;)V", @@ -49,5 +55,6 @@ public class PacketEncoderMixin { shift = At.Shift.AFTER)) private void impl$clearLocaleAfterEncode(final ChannelHandlerContext ctx, final Packet $$1, final ByteBuf $$2, final CallbackInfo ci) { SpongeAdventure.ENCODING_LOCALE.remove(); + SpongeAdventure.ENCODING_PLAYER.remove(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java index a21715d0188..4039d41a694 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java @@ -26,6 +26,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentSerialization; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.util.locale.Locales; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -41,7 +42,8 @@ public abstract class ComponentSerializationMixin { @ModifyVariable(method = "lambda$createCodec$6", at = @At(value = "HEAD"), argsOnly = true) private static Component impl$localizeComponent(final Component input) { final Locale locale = SpongeAdventure.ENCODING_LOCALE.get(); - return NativeComponentRenderer.apply(input, locale == null ? Locales.DEFAULT : locale); + final ServerPlayer player = SpongeAdventure.ENCODING_PLAYER.get(); + return NativeComponentRenderer.apply(input, locale == null ? Locales.DEFAULT : locale, player); } //TODO: Do this for ItemStacks too diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index f8f3f8f75be..50507b35c77 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -70,6 +70,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; +import org.spongepowered.common.adventure.NativeComponentRenderer; import org.spongepowered.common.applaunch.config.core.SpongeConfigs; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; @@ -87,6 +88,7 @@ import java.io.IOException; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; @@ -225,7 +227,7 @@ public String getServerModName() { */ @Inject(method = "sendSystemMessage", at = @At("HEAD"), cancellable = true) private void impl$useTranslatingLogger(final Component input, final CallbackInfo ci) { - MinecraftServerMixin.LOGGER.info(input.getString()); + MinecraftServerMixin.LOGGER.info(NativeComponentRenderer.apply(input, Locale.getDefault(), Sponge.game().systemSubject()).getString()); ci.cancel(); } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/chat/ReusableComponentMessageFactory.java b/vanilla/src/main/java/org/spongepowered/vanilla/chat/ReusableComponentMessageFactory.java index b55f5f184e0..c190e50331d 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/chat/ReusableComponentMessageFactory.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/chat/ReusableComponentMessageFactory.java @@ -145,7 +145,7 @@ public String getFormattedMessage() { ComponentMessage.RENDERER.render(((ComponentLike) param).asComponent(), Locale.getDefault()) ); } else if (param instanceof net.minecraft.network.chat.Component) { - return NativeComponentRenderer.apply((Component) param, Locale.getDefault()).getString(); + return NativeComponentRenderer.apply((Component) param, Locale.getDefault(), null).getString(); } return super.getFormattedMessage(); } @@ -160,7 +160,7 @@ public void formatTo(final StringBuilder buffer) { buffer::append ); } else if (param instanceof net.minecraft.network.chat.Component) { - buffer.append(NativeComponentRenderer.apply((Component) param, Locale.getDefault()).getString()); + buffer.append(NativeComponentRenderer.apply((Component) param, Locale.getDefault(), null).getString()); } else { super.formatTo(buffer); } From 3bdfc3c4aa3c7a36c237121046a8c55cfb42a804 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 5 Feb 2025 17:55:37 +0200 Subject: [PATCH 189/586] Fix sky light --- .../context/transaction/effect/UpdateLightSideEffect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index b8962419f59..8f7f5f75d6e 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -77,7 +77,7 @@ public EffectResult processSideEffect( // this.skyLightSources.update(this, $$6, $$3, $$8); final var pos = oldState.pos(); final var x = pos.getX() & 15; - final var y = pos.getY() & 15; + final var y = pos.getY(); final var z = pos.getZ() & 15; final var levelChunk = serverWorld.getChunk(pos); From d2a4ac97d169b9e9673ba0ab284061626bc62f7a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Feb 2025 10:29:29 -0800 Subject: [PATCH 190/586] chore: update to 25w06a Notable changes: - EntityEquipment now contains item slots/data for non-player inventory - This has a change with how slots are tracked I believe, we could consider reviewing the current transaction operations to verify if we need as many slot index based tracking as we currently do. - Ticking weather is now written as wrap operations or WrapMethods - Entity dropping items is centered in LivingEntity, a better mixing in opportunity --- gradle.properties | 2 +- .../parameter/SpongeParameterValue.java | 2 +- .../inventory/SetCarriedItemTransaction.java | 4 +- .../phase/packet/PacketPhaseUtil.java | 9 ++-- .../lens/impl/slot/HeldHandSlotLens.java | 6 +-- .../network/packet/SpongePacketHandler.java | 3 +- .../game/pagination/ActivePagination.java | 2 +- .../game/pagination/SpongePaginationList.java | 2 +- .../spongepowered/common/util/BookUtil.java | 4 +- .../core/server/level/ServerLevelMixin.java | 16 ++++--- .../core/world/entity/LivingEntityMixin.java | 1 + .../mixin/core/world/entity/MobMixin.java | 1 - .../core/world/entity/player/PlayerMixin.java | 1 - .../entity/LivingEntityMixin_Inventory.java | 8 ++++ .../entity/player/PlayerMixin_Inventory.java | 7 --- .../level/ServerPlayerMixin_Inventory.java | 10 ++-- .../InventoryMixin_Bridge_Inventory.java | 48 ++++--------------- .../level/ServerChunkCacheMixin_Tracker.java | 30 ++++++------ .../level/ServerLevelMixin_Tracker.java | 35 ++++---------- .../level/ServerPlayerMixin_Tracker.java | 28 +++-------- .../entity/LivingEntityMixin_Tracker.java | 34 +++++++++++++ .../entity/player/PlayerMixin_Tracker.java | 12 ----- .../client/gui/widget/ScrollPanel.java | 21 ++++++-- 23 files changed, 131 insertions(+), 155 deletions(-) diff --git a/gradle.properties b/gradle.properties index e68d8455f81..af3b77f3590 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w05a +minecraftVersion=25w06a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/command/parameter/SpongeParameterValue.java b/src/main/java/org/spongepowered/common/command/parameter/SpongeParameterValue.java index b6a38e5b994..2020f381d98 100644 --- a/src/main/java/org/spongepowered/common/command/parameter/SpongeParameterValue.java +++ b/src/main/java/org/spongepowered/common/command/parameter/SpongeParameterValue.java @@ -134,7 +134,7 @@ private void parseInternal( // If we get this far, we failed to parse, return the exceptions if (currentExceptions == null) { - final var component = Component.translatable("command.exception").args(Component.text("Could not parse element")); + final var component = Component.translatable("command.exception").arguments(Component.text("Could not parse element")); throw new ArgumentParseException(component, args.input(), args.cursor()); } else if (currentExceptions.size() == 1) { throw currentExceptions.get(0); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java index 00657ace3cc..9087d789e01 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/SetCarriedItemTransaction.java @@ -54,7 +54,7 @@ public SetCarriedItemTransaction(final Player player, int newSlot) { super((Inventory) player.getInventory()); this.player = (ServerPlayer) player; final PlayerInventory inventory = (PlayerInventory) this.player.getInventory(); - this.prevSlotId = this.player.getInventory().selected; + this.prevSlotId = this.player.getInventory().getSelectedSlot(); this.prevSlot = inventory.hotbar().slot(this.prevSlotId).orElse(null); this.newSlot = inventory.hotbar().slot(newSlot).orElse(null); } @@ -77,7 +77,7 @@ Optional createInventoryEvent(final List @Override public void restore(final PhaseContext<@NonNull ?> context, final ChangeInventoryEvent event) { this.player.connection.send(new ClientboundSetHeldSlotPacket(this.prevSlotId)); - this.player.getInventory().selected = this.prevSlotId; + this.player.getInventory().setSelectedSlot(this.prevSlotId); this.handleEventResults(this.player, event); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index e0909a7df47..5f7a7af6552 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -170,13 +170,14 @@ public static void handlePlayerSlotRestore(final net.minecraft.server.level.Serv player.containerMenu.suppressRemoteUpdates(); int slotId = 0; if (hand == InteractionHand.OFF_HAND) { - player.getInventory().offhand.set(0, itemStack); - slotId = (player.getInventory().items.size() + Inventory.getSelectionSize()); + player.getInventory().setItem(Inventory.SLOT_OFFHAND, itemStack); + slotId = (Inventory.INVENTORY_SIZE + Inventory.getSelectionSize()); } else { - player.getInventory().items.set(player.getInventory().selected, itemStack); + final var selected = player.getInventory().getSelectedSlot(); + player.getInventory().setSelectedItem(itemStack); // TODO check if window id -2 and slotid = player.getInventory().currentItem works instead of this: for (Slot containerSlot : player.containerMenu.slots) { - if (containerSlot.container == player.getInventory() && ((SlotAccessor) containerSlot).accessor$slot() == player.getInventory().selected) { + if (containerSlot.container == player.getInventory() && ((SlotAccessor) containerSlot).accessor$slot() == selected) { slotId = containerSlot.index; break; } diff --git a/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/HeldHandSlotLens.java b/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/HeldHandSlotLens.java index 92e0b4ec5eb..ed343baefb0 100644 --- a/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/HeldHandSlotLens.java +++ b/src/main/java/org/spongepowered/common/inventory/lens/impl/slot/HeldHandSlotLens.java @@ -69,20 +69,20 @@ private net.minecraft.world.entity.player.Inventory getInventoryPlayer(Fabric fa @Override public ItemStack getStack(Fabric fabric) { net.minecraft.world.entity.player.Inventory inv = this.getInventoryPlayer(fabric); - return inv.getSelected(); + return inv.getSelectedItem(); } @Override public boolean setStack(Fabric fabric, ItemStack stack) { net.minecraft.world.entity.player.Inventory inv = this.getInventoryPlayer(fabric); - inv.items.set(inv.selected, stack); + inv.setSelectedItem(stack); return true; } @Override public int getOrdinal(Fabric fabric) { net.minecraft.world.entity.player.Inventory inv = this.getInventoryPlayer(fabric); - return inv.selected; + return inv.getSelectedSlot(); } @Override diff --git a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java index 7c611271f66..ed0bf11cd26 100644 --- a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java +++ b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java @@ -29,6 +29,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.dimension.DimensionType; @@ -63,7 +64,7 @@ public static void init(final SpongeChannelManager registry) { final net.minecraft.server.level.ServerPlayer sender = (net.minecraft.server.level.ServerPlayer) player; final BlockPos pos = new BlockPos(requestPacket.x, requestPacket.y, requestPacket.z); - if (!sender.level().hasChunkAt(pos)) { + if (!sender.level().getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()))) { return; } diff --git a/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java b/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java index 40dc2e94aa1..971d6d56655 100644 --- a/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java +++ b/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java @@ -153,7 +153,7 @@ public void specificPage(final int page) throws CommandException { } for (final Component line : toSend) { - src.sendMessage(Identity.nil(), line); + src.sendMessage(line); } } diff --git a/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java b/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java index 5357f3a8e05..66b8c53350e 100644 --- a/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java +++ b/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java @@ -142,7 +142,7 @@ public void sendTo(final Audience receiver, final int page) { } catch (final CommandException e) { final Component text = e.componentMessage(); if (text != null) { - receiver.sendMessage(Identity.nil(), text.color(NamedTextColor.RED)); + receiver.sendMessage(text.color(NamedTextColor.RED)); } } } diff --git a/src/main/java/org/spongepowered/common/util/BookUtil.java b/src/main/java/org/spongepowered/common/util/BookUtil.java index f92441d1a91..365c9ec5de5 100644 --- a/src/main/java/org/spongepowered/common/util/BookUtil.java +++ b/src/main/java/org/spongepowered/common/util/BookUtil.java @@ -50,8 +50,8 @@ public static ClientboundBundlePacket createFakeBookViewPacket(final Player play item.offer(Keys.PAGES, book.pages()); final Inventory inventory = ((net.minecraft.world.entity.player.Player) player).getInventory(); - final int bookSlot = inventory.selected; - final net.minecraft.world.item.ItemStack oldItem = inventory.getSelected(); + final int bookSlot = inventory.getSelectedSlot(); + final net.minecraft.world.item.ItemStack oldItem = inventory.getSelectedItem(); final List> packets = new ArrayList<>(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 57668d9039b..45c134deecc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.core.server.level; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -147,7 +149,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow @Final private MinecraftServer server; @Shadow @Nullable private EndDragonFight dragonFight; - @Shadow @Final private List players; + @Shadow @Final List players; // @formatter:on @@ -386,9 +388,9 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, levelData.setWorldBorder(this.getWorldBorder().createSettings()); - levelData.setCustomBossEvents(((ServerLevelBridge) this).bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); + levelData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); - ((ServerLevelBridge) this).bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess() + this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess() , (PrimaryLevelData) this.shadow$getLevelData(), this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList() .getSingleplayerData() : null); @@ -453,10 +455,12 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, } - @Redirect(method = "tickChunk", + @WrapOperation(method = "tickThunder", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;isRainingAt(Lnet/minecraft/core/BlockPos;)Z")) - private boolean impl$onBeforeThunder(final ServerLevel serverLevel, final BlockPos param0) { - final boolean rainingAt = serverLevel.isRainingAt(param0); + private boolean impl$onBeforeThunder( + final ServerLevel serverLevel, final BlockPos param0, final Operation wrapped + ) { + final boolean rainingAt = wrapped.call(serverLevel, param0); if (rainingAt) { final LightningEvent.Pre strike = SpongeEventFactory.createLightningEventPre(PhaseTracker.getInstance().currentCause()); if (Sponge.eventManager().post(strike)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index d9954089c55..9df4af654ab 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -116,6 +116,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public abstract AttributeMap shadow$getAttributes(); @Shadow public abstract void shadow$clearSleepingPos(); @Shadow public abstract void shadow$setHealth(final float $$0); + @Shadow public abstract void shadow$setItemSlot(EquipmentSlot $$0, ItemStack $$1); // @formatter:on diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 6c4b6c976bd..eaf6daca170 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -60,7 +60,6 @@ public abstract class MobMixin extends LivingEntityMixin { @Shadow @Nullable private LivingEntity target; @Shadow protected abstract void shadow$registerGoals(); @Shadow public abstract boolean shadow$isSaddled(); - @Shadow public abstract void shadow$setItemSlot(EquipmentSlot $$0, ItemStack $$1); // @formatter:on @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;registerGoals()V")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 2e7fa72a251..27819ee55fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -102,7 +102,6 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri @Shadow public abstract boolean shadow$isSpectator(); @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract int shadow$getXpNeededForNextLevel(); - @Shadow @Nullable public abstract ItemEntity shadow$drop(final ItemStack droppedItem, final boolean dropAround, final boolean traceItem); @Shadow public abstract FoodData shadow$getFoodData(); @Shadow public abstract Scoreboard shadow$getScoreboard(); @Shadow public abstract boolean shadow$isCreative(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java index a7f2a0478ce..b7a44af5cb8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.inventory.event.entity; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; @@ -71,6 +73,12 @@ protected LivingEntityMixin_Inventory(final EntityType param0, final Level pa super(param0, param1); } + + @WrapMethod(method = "setItemSlot") + protected void inventory$wrapSetSlotWithTransaction(EquipmentSlot slot, ItemStack item, Operation original) { + original.call(slot, item); + } + @Inject(method = "handleHandSwap", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;broadcast(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/protocol/Packet;)V")) protected void inventory$onHandleHandSwap(final Map map, final CallbackInfo ci) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java index f946a609a84..f0693e9d59d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java @@ -70,13 +70,6 @@ protected PlayerMixin_Inventory(final EntityType param0, final Level param1) super.inventory$onHandleEquipmentChanges(map, ci); } - @Inject(method = "setItemSlot", at = @At(value = "HEAD")) - protected void impl$beforeSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { - } - - @Inject(method = "setItemSlot", at = @At(value = "RETURN")) - protected void impl$afterSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 29c6c199e2c..88a55e76fb8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -95,7 +95,6 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Shadow public ServerGamePacketListenerImpl connection; @Nullable private EffectTransactor inventory$effectTransactor = null; @Nullable private Object inventory$menuProvider; - // @formatter:on @Shadow public abstract ServerLevel shadow$serverLevel(); // @formatter:on @@ -108,17 +107,14 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory // -- Overrides from PlayerMixin_Inventory @Override - protected void impl$beforeSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { + protected void inventory$wrapSetSlotWithTransaction(EquipmentSlot slot, ItemStack item, Operation original) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final PlayerInventoryTransaction.EventCreator eventCreator = context.getState() instanceof SwapHandItemsState ? - PlayerInventoryTransaction.EventCreator.SWAP_HAND : PlayerInventoryTransaction.EventCreator.STANDARD; + PlayerInventoryTransaction.EventCreator.SWAP_HAND : PlayerInventoryTransaction.EventCreator.STANDARD; this.inventory$effectTransactor = transactor.logPlayerInventoryChangeWithEffect((Player) (Object) this, eventCreator); - } - - @Override - protected void impl$afterSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { try (final EffectTransactor ignored = this.inventory$effectTransactor) { + original.call(slot, item); this.inventoryMenu.broadcastChanges(); // for capture } finally { this.inventory$effectTransactor = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java index 267bc686dcb..24ed5f49b31 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/entity/player/InventoryMixin_Bridge_Inventory.java @@ -24,69 +24,41 @@ */ package org.spongepowered.common.mixin.inventory.impl.world.entity.player; -import net.minecraft.core.NonNullList; import net.minecraft.network.protocol.game.ClientboundSetHeldSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.bridge.world.entity.player.PlayerInventoryBridge; import org.spongepowered.common.inventory.adapter.InventoryAdapter; -import java.util.List; - @Mixin(Inventory.class) public abstract class InventoryMixin_Bridge_Inventory implements PlayerInventoryBridge, InventoryAdapter { - @Shadow public int selected; + @Shadow private int selected; @Shadow @Final public Player player; - @Shadow @Final public NonNullList items; - @Shadow @Final public NonNullList armor; - @Shadow @Final public NonNullList offhand; - @Shadow @Final private List> compartments; - @Shadow private int timesChanged; - - private int impl$lastTimesChanged = this.timesChanged; - - private int impl$offhandIndex; - - @Inject(method = "*", at = @At("RETURN"), remap = false) - private void onConstructed(final Player playerIn, final CallbackInfo ci) { - // Find offhand slot - for (final NonNullList inventory : this.compartments) { - if (inventory == this.offhand) { - break; - } - this.impl$offhandIndex += inventory.size(); - } - } + @Unique private int impl$lastTimesChanged = this.timesChanged; @Override public int bridge$getHeldItemIndex(final InteractionHand hand) { - switch (hand) { - case MAIN_HAND: - return this.selected; - case OFF_HAND: - return this.impl$offhandIndex; - default: - throw new AssertionError(hand); - } + return switch (hand) { + case MAIN_HAND -> this.selected; + case OFF_HAND -> Inventory.SLOT_OFFHAND; + default -> throw new AssertionError(hand); + }; } @Override public void bridge$setSelectedItem(int itemIndex, final boolean notify) { itemIndex = itemIndex % 9; - if (notify && this.player instanceof ServerPlayer) { + if (notify && this.player instanceof ServerPlayer sp) { final var packet = new ClientboundSetHeldSlotPacket(itemIndex); - ((ServerPlayer)this.player).connection.send(packet); + sp.connection.send(packet); } this.selected = itemIndex; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java index bdcf5b3f7ae..afcd93db052 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.tracker.server.level; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.MobCategory; @@ -32,7 +34,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.generation.GenerationPhase; @@ -42,28 +43,27 @@ @Mixin(ServerChunkCache.class) public abstract class ServerChunkCacheMixin_Tracker { - @Redirect( - method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V", + @WrapOperation( + method = "tickSpawningChunk", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/NaturalSpawner;spawnForChunk(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/world/level/NaturalSpawner$SpawnState;Ljava/util/List;)V" ) ) private void tracker$wrapEntitySpawner( - final ServerLevel serverWorld, - final LevelChunk targetChunk, - final NaturalSpawner.SpawnState spawnState, - final List mobCategories + final ServerLevel serverWorld, final LevelChunk targetChunk, final NaturalSpawner.SpawnState spawnState, + final List mobCategories, final Operation original ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING + .createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); - NaturalSpawner.spawnForChunk(serverWorld, targetChunk, spawnState, mobCategories); + original.call(serverWorld, targetChunk, spawnState, mobCategories); } } - @Redirect( - method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V", + @WrapOperation( + method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tickCustomSpawners(ZZ)V" @@ -72,12 +72,14 @@ public abstract class ServerChunkCacheMixin_Tracker { private void tracker$wrapGeneratorEntitySpawner( final ServerLevel serverWorld, final boolean spawnHostileMobs, - final boolean spawnPeacefulMobs + final boolean spawnPeacefulMobs, + final Operation wrapped ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING + .createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); - serverWorld.tickCustomSpawners(spawnHostileMobs, spawnPeacefulMobs); + wrapped.call(serverWorld, spawnHostileMobs, spawnPeacefulMobs); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 598d33bb49c..e003846fac5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.tracker.server.level; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; @@ -31,6 +32,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.PacketListener; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.server.level.ServerLevel; @@ -213,33 +215,12 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem TrackingUtil.randomTickFluid(this, fluidState, pos, this.random, () -> tick.call(fluidState, worldIn, pos, random)); } - @Inject( - method = "tickChunk", - at = @At( - value = "INVOKE_STRING", - target = "Lnet/minecraft/util/profiling/ProfilerFiller;push(Ljava/lang/String;)V", - args = "ldc=thunder" - ) - ) - private void tracker$startWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) (Object) this)) - .buildAndSwitch(); - } - - @Inject( - method = "tickChunk", - at = @At( - value = "INVOKE_STRING", - target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", - args = "ldc=tickBlocks" - ) - ) - private void tracker$closeWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); - if (context.getState() != TickPhase.Tick.WEATHER) { - throw new IllegalStateException("Expected to be in a Weather ticking state, but we aren't."); + @WrapMethod(method = "tickThunder") + private void tracker$startWeatherTickPhase(LevelChunk chunk, Operation original) { + try (final var ignored = TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) (Object) this)) + .buildAndSwitch()) { + original.call(chunk); } - context.close(); } @WrapOperation(method = "doBlockEvent(Lnet/minecraft/world/level/BlockEventData;)Z", @@ -407,7 +388,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem */ @Redirect(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) - private void tracker$onClientboundExplodePacket(final ServerGamePacketListenerImpl instance, final Packet packet) { + private void tracker$onClientboundExplodePacket(final ServerGamePacketListenerImpl instance, final Packet packet) { final var originalPacket = (ClientboundExplodePacket) packet; ((ServerLevelBridge) this).bridge$handleExplosionPacket(instance, this.tracker$apiExplosion, originalPacket); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java index a699a6c5870..7b3ac74fb0d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerMixin_Tracker.java @@ -25,15 +25,14 @@ package org.spongepowered.common.mixin.tracker.server.level; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.common.bridge.world.entity.PlatformEntityBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; @@ -47,33 +46,20 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Tracker extends PlayerMixin_Tracker { - /** - * @author gabizou - June 4th, 2016 - * @author i509VCB - February 17th, 2020 - 1.14.4 - * @author gabizou - December 31st, 2021 - 1.16.5 - * @reason We inject a construct event for the item drop and conveniently - * can redirect the super call. - */ - @WrapOperation( - method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;createItemStackToDrop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;" - ) - ) - @Nullable - private ItemEntity tracker$throwItemDrop( - final ServerPlayer instance, final ItemStack droppedItem, final boolean dropAround, + + @Override + protected @Nullable ItemEntity tracker$throwItemDrop( + final LivingEntity instance, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem, final Operation wrapped ) { if (droppedItem.isEmpty()) { return null; } if (((PlatformEntityBridge) this).bridge$isFakePlayer()) { - return super.shadow$drop(droppedItem, dropAround, traceItem); + return wrapped.call(instance, droppedItem, dropAround, traceItem); } if (((LevelBridge) this.shadow$level()).bridge$isFake()) { - return super.shadow$drop(droppedItem, dropAround, traceItem); + return wrapped.call(instance, droppedItem, dropAround, traceItem); } final double posX1 = this.shadow$getX(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index a391c8918e8..a5b25c2196c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -24,27 +24,38 @@ */ package org.spongepowered.common.mixin.tracker.world.entity; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.CombatEntry; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.accessor.world.damagesource.CombatTrackerAccessor; +import org.spongepowered.common.bridge.world.entity.PlatformEntityBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; +import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.phase.entity.EntityPhase; import org.spongepowered.common.event.tracking.phase.tick.EntityTickContext; +import org.spongepowered.common.item.util.ItemStackUtil; +import java.util.ArrayList; import java.util.List; @Mixin(LivingEntity.class) @@ -63,6 +74,29 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { // @formatter:on + /** + * @author gabizou - June 4th, 2016 + * @author i509VCB - February 17th, 2020 - 1.14.4 + * @author gabizou - December 31st, 2021 - 1.16.5 + * @author gabizou - February 8th, 2025 - 25w06a + * + * @reason We wrap the original call to allow for throwing events for the server player instance + */ + @WrapOperation( + method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;createItemStackToDrop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;" + ) + ) + @Nullable + protected ItemEntity tracker$throwItemDrop( + final LivingEntity instance, final ItemStack droppedItem, final boolean dropAround, + final boolean traceItem, final Operation wrapped + ) { + return wrapped.call(instance, droppedItem, dropAround, traceItem); + } + @Override protected void tracker$populateDeathContextIfNeeded( final CauseStackManager.StackFrame frame, final EntityTickContext context diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/player/PlayerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/player/PlayerMixin_Tracker.java index 96792660301..da0e81c6005 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/player/PlayerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/player/PlayerMixin_Tracker.java @@ -24,15 +24,10 @@ */ package org.spongepowered.common.mixin.tracker.world.entity.player; -import net.minecraft.network.chat.Component; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.entity.DestructEntityEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -42,13 +37,6 @@ @Mixin(Player.class) public abstract class PlayerMixin_Tracker extends LivingEntityMixin_Tracker { - //@formatter:off - @Shadow public abstract Component shadow$getDisplayName(); - @Shadow @Nullable public ItemEntity shadow$drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) { - return null; // SHADOWED - } - //@formatter:on - @Inject(method = "die", at = @At("HEAD"), cancellable = true) public void impl$callDestructEntityDeath(final DamageSource cause, final CallbackInfo ci) { if (this.shadow$isEffectiveAi()) { diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 60c70d1ca23..87311e8201d 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -26,9 +26,9 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.BufferUploader; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -201,7 +201,11 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, .setColor(0x20, 0x20, 0x20, 0xFF); worldr.addVertex(this.left, this.top, 0.0f).setUv(this.left / texScale, (this.top + (int) this.scrollDistance) / texScale) .setColor(0x20, 0x20, 0x20, 0xFF); - BufferUploader.drawWithShader(worldr.buildOrThrow()); + + VertexBuffer $$3 = RenderSystem.getQuadVertices(); + $$3.upload(worldr.buildOrThrow()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + final int baseY = this.top + this.border - (int) this.scrollDistance; this.drawPanel(stack, this.right, baseY, tess, mouseX, mouseY); @@ -224,19 +228,26 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.barLeft + this.barWidth, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); worldr.addVertex(this.barLeft, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); - BufferUploader.drawWithShader(worldr.buildOrThrow()); + $$3 = RenderSystem.getQuadVertices(); + $$3.upload(worldr.buildOrThrow()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + worldr =tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); - BufferUploader.drawWithShader(worldr.buildOrThrow()); + $$3 = RenderSystem.getQuadVertices(); + $$3.upload(worldr.buildOrThrow()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft + this.barWidth - 1, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft + this.barWidth - 1, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); - BufferUploader.drawWithShader(worldr.buildOrThrow()); + $$3 = RenderSystem.getQuadVertices(); + $$3.upload(worldr.buildOrThrow()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); } // RenderSystem.enableTexture(); From e6b498ac11c11020eddc538f6d412525f1dbe72b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Feb 2025 10:49:08 -0800 Subject: [PATCH 191/586] feat: add content for 25w06a --- SpongeAPI | 2 +- .../generator/world/entities/EntityRegistries.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index f78b07f7a65..c9ca7123f75 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit f78b07f7a65bd229dd0ea7d34db1f515de38130c +Subproject commit c9ca7123f756b29706c2a0fbf7a09f10e4b15fe8 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index e7586fabde6..7fdbe271b1f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -238,6 +238,15 @@ public static List registryEntries(final Context context) { Registries.COW_VARIANT, $ -> true, RegistryScope.SERVER + ), + new RegistryEntriesGenerator<>( + "data.type", + "ChickenVariants", + "CHICKEN_VARIANT", + context.relativeClass("data.type", "ChickenVariant"), + Registries.CHICKEN_VARIANT, + $-> true, + RegistryScope.SERVER ) ); } From 35709f3c3bd5363ad2f53fcf17c2b75e50b77de5 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 15 Feb 2025 00:28:51 -0800 Subject: [PATCH 192/586] feat: update implementation to 25w07a Notable changes: - Minecart fields are getting slowly inlined, likely the next targets to get components - Turtles are also experiencing a similar field change - BossEvents now persist data in a record, also codec'ed, so this should simplify the Adventure implementation. - Player respawn data is now a record/component-like, which required a few WrapOperations to sort out which World is used to resawn in. - Entities have a "functional" approach to applying "inside block effect interactions" which makes some of the mixins harder to interact with. - This was noticeable in the BaseFireBlockMixin where the consumer has to be replaced to properly support the BlockDamageSource. - All UUIDs are now set on CompoundTags via Codecs. - This has a greater feeling that defining the schema once via Codec is the way Mojang is going, since it means the data can be applied whether in NBT or in a binary stream payload via chunks. Time will tell. - A larger refactor of how SavedTicksMixin works to save custom data, as the above point mentioned, things are migrating to Codecs, which means we have to add on to the existing codec as well in certain places. --- gradle.properties | 2 +- gradle/verification-metadata.xml | 80 +++++++++++++++++++ .../vehicle/AbstractMinecartAccessor.java | 39 +++++++++ .../accessor/world/DamageSourcesAccessor.java | 37 +++++++++ .../world/entity/animal/TurtleAccessor.java | 15 ++-- .../animal/{ => sheep}/SheepAccessor.java | 4 +- .../world/entity/monster/EvokerAccessor.java | 2 +- .../resources/mixins.sponge.accessors.json | 6 +- .../command/manager/SpongeCommandManager.java | 2 +- .../provider/entity/AbstractMinecartData.java | 11 ++- .../data/provider/entity/EvokerData.java | 2 +- .../data/provider/entity/SheepData.java | 2 +- .../data/provider/entity/TurtleData.java | 3 +- .../entity/damage/SpongeDamageSources.java | 13 +++ .../phase/packet/PacketPhaseUtil.java | 4 +- .../game/pagination/ActivePagination.java | 1 - .../game/pagination/SpongePaginationList.java | 1 - .../spongepowered/common/util/MapUtil.java | 3 +- .../spongepowered/common/util/VecHelper.java | 2 +- .../animal/{ => sheep}/SheepMixin_API.java | 5 +- .../bossevents/CustomBossEventMixin.java | 17 +--- .../core/server/level/ServerPlayerMixin.java | 48 ++++++++++- .../core/server/players/PlayerListMixin.java | 2 +- .../mixin/core/world/entity/EntityMixin.java | 15 ++-- .../mixin/core/world/entity/MobMixin.java | 2 - .../ai/behavior/HarvestFarmlandMixin.java | 6 +- .../core/world/entity/player/PlayerMixin.java | 2 - .../world/level/block/BaseFireBlockMixin.java | 45 +++++++---- .../world/level/block/CactusBlockMixin.java | 16 ++-- .../world/level/block/MagmaBlockMixin.java | 13 ++- .../block/PointedDripstoneBlockMixin.java | 8 +- .../level/block/SweetBerryBushBlockMixin.java | 10 +-- .../block/entity/BeaconBlockEntityMixin.java | 6 +- .../level/storage/PrimaryLevelDataMixin.java | 2 +- .../core/world/ticks/SavedTickMixin.java | 60 ++++++++++---- .../entity/player/PlayerMixin_Inventory.java | 1 - .../EntityActivationRange.java | 2 +- .../entity/LivingEntityMixin_Tracker.java | 6 -- src/mixins/resources/mixins.sponge.api.json | 2 +- src/mixins/resources/mixins.sponge.core.json | 3 +- .../client/gui/widget/ScrollPanel.java | 8 +- 41 files changed, 366 insertions(+), 142 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/DamageSourcesAccessor.java rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => sheep}/SheepAccessor.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => sheep}/SheepMixin_API.java (92%) diff --git a/gradle.properties b/gradle.properties index af3b77f3590..31f0c5adb8a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w06a +minecraftVersion=25w07a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7e54a2bff8e..e464495c3d1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2218,6 +2218,14 @@
+ + + + + + + + @@ -2234,6 +2242,14 @@ + + + + + + + + @@ -2250,6 +2266,14 @@ + + + + + + + + @@ -2266,6 +2290,14 @@ + + + + + + + + @@ -2279,6 +2311,11 @@ + + + + + @@ -2292,6 +2329,14 @@ + + + + + + + + @@ -2308,6 +2353,14 @@ + + + + + + + + @@ -2324,6 +2377,14 @@ + + + + + + + + @@ -2343,6 +2404,17 @@ + + + + + + + + + + + @@ -2365,6 +2437,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java new file mode 100644 index 00000000000..49108ce7dcb --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.entity.vehicle; + +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.Optional; + +@Mixin(AbstractMinecart.class) +public interface AbstractMinecartAccessor { + + @Invoker("getCustomDisplayBlockState") Optional accessor$getCustomDisplayBlockState(); + +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/DamageSourcesAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/DamageSourcesAccessor.java new file mode 100644 index 00000000000..c4d1f14afef --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/DamageSourcesAccessor.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world; + +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageSources; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(DamageSources.class) +public interface DamageSourcesAccessor { + + @Accessor("inFire") @Mutable void accessor$setInFire(DamageSource source); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java index e812ef22e99..1ade4b94020 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java @@ -27,27 +27,24 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.animal.Turtle; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Turtle.class) public interface TurtleAccessor { - @Invoker("getHomePos") BlockPos invoker$getHomePos(); + @Accessor("homePos") BlockPos invoker$getHomePos(); - @Invoker("getTravelPos") BlockPos invoker$getTravelPos(); + @Accessor("travelPos") BlockPos invoker$getTravelPos(); - @Invoker("setTravelPos") void invoker$setTravelPos(final BlockPos travelPos); + @Accessor("travelPos") void invoker$setTravelPos(final BlockPos travelPos); @Invoker("setHasEgg") void invoker$setHasEgg(final boolean hasEgg); @Invoker("setLayingEgg") void invoker$setLayingEgg(final boolean layingEgg); - @Invoker("isGoingHome") boolean invoker$isGoingHome(); + @Accessor("goingHome") boolean invoker$isGoingHome(); - @Invoker("setGoingHome") void invoker$setGoingHome(final boolean goingHome); - - @Invoker("isTravelling") boolean invoker$isTravelling(); - - @Invoker("setTravelling") void invoker$setTravelling(final boolean travelling); + @Accessor("goingHome") void invoker$setGoingHome(final boolean goingHome); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/sheep/SheepAccessor.java similarity index 93% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/sheep/SheepAccessor.java index 9bbc8d32fb5..441882a66b9 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/SheepAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/sheep/SheepAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.sheep; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.animal.sheep.Sheep; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.common.UntransformedAccessorError; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java index c45b9993bda..0c4d871b379 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.world.entity.monster; -import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.animal.sheep.Sheep; import net.minecraft.world.entity.monster.Evoker; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 832662a7504..b91579108b3 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -21,6 +21,7 @@ "core.MappedRegistryAccessor", "entity.animal.frog.FrogAccessor", "entity.passive.AbstractChestedHorseEntityAccessor", + "entity.vehicle.AbstractMinecartAccessor", "network.ConnectionAccessor", "network.chat.StyleAccessor", "network.protocol.game.ClientboundAddEntityPacketAccessor", @@ -53,9 +54,10 @@ "sounds.SoundEventAccessor", "stats.StatsCounterAccessor", "tags.TagEntryAccessor", - "util.datafix.schemas.V100Accessor", + "util.datafix.schemas.V100Accessor", "util.thread.AbstractConsecutiveExecutorAccessor", "world.CompoundContainerAccessor", + "world.DamageSourcesAccessor", "world.damagesource.CombatTrackerAccessor", "world.entity.AgableMobAccessor", "world.entity.AreaEffectCloudAccessor", @@ -82,7 +84,6 @@ "world.entity.animal.PigAccessor", "world.entity.animal.PufferfishAccessor", "world.entity.animal.RabbitAccessor", - "world.entity.animal.SheepAccessor", "world.entity.animal.TropicalFishAccessor", "world.entity.animal.TurtleAccessor", "world.entity.animal.WolfAccessor", @@ -90,6 +91,7 @@ "world.entity.animal.horse.HorseAccessor", "world.entity.animal.horse.LlamaAccessor", "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.animal.sheep.SheepAccessor", "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", "world.entity.boss.wither.WitherBossAccessor", "world.entity.decoration.ArmorStandAccessor", diff --git a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java index 4db64cbf0c0..1f781837393 100644 --- a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java +++ b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java @@ -528,7 +528,7 @@ public Collection getAliasesThatStartWithForCause(final CommandCause cau final Object2BooleanMap testedMappings = new Object2BooleanOpenHashMap<>(); for (final Map.Entry mappingEntry : this.commandMappings.entrySet()) { if (mappingEntry.getKey().startsWith(toCompare)) { - if (testedMappings.computeBooleanIfAbsent(mappingEntry.getValue(), mapping -> mapping.registrar().canExecute(cause, mapping))) { + if (testedMappings.computeIfAbsent(mappingEntry.getValue(), (CommandMapping mapping) -> mapping.registrar().canExecute(cause, mapping))) { aliases.add(toCompare); } } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java index 6d9e9883400..da6a08db815 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java @@ -31,12 +31,15 @@ import org.spongepowered.api.block.BlockState; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.persistence.DataContentUpdater; +import org.spongepowered.common.accessor.entity.vehicle.AbstractMinecartAccessor; import org.spongepowered.common.bridge.world.entity.vehicle.AbstractMinecartBridge; import org.spongepowered.common.data.ByteToBooleanContentUpdater; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.Constants; +import java.util.Optional; + public final class AbstractMinecartData { private AbstractMinecartData() { @@ -49,9 +52,9 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(AbstractMinecart.class) .create(Keys.BLOCK_STATE) - .get(h -> h.hasCustomDisplay() ? (BlockState) h.getDisplayBlockState() : null) - .set((h, v) -> h.setDisplayBlockState((net.minecraft.world.level.block.state.BlockState) v)) - .delete(h -> h.setCustomDisplay(false)) + .get(h -> (BlockState) h.getDisplayBlockState()) + .set((h, v) -> h.setCustomDisplayBlockState(Optional.ofNullable((net.minecraft.world.level.block.state.BlockState) v))) + .delete(h -> h.setCustomDisplayBlockState(Optional.empty())) .create(Keys.IS_ON_RAIL) .get(h -> { final BlockPos pos = h.blockPosition(); @@ -90,7 +93,7 @@ public static void register(final DataProviderRegistrator registrator) { // @formatter:on private static boolean setBlockOffset(final AbstractMinecart holder, final Integer value) { - if (!holder.hasCustomDisplay()) { + if (((AbstractMinecartAccessor) holder).accessor$getCustomDisplayBlockState().isEmpty()) { return false; } holder.setDisplayOffset(value); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java index bcdfecdf72c..50ba45c0ba3 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java @@ -40,7 +40,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(EvokerAccessor.class) .create(Keys.WOLOLO_TARGET) .get(h -> (Sheep) h.accessor$wololoTarget()) - .set((h, v) -> h.accessor$wololoTarget((net.minecraft.world.entity.animal.Sheep) v)); + .set((h, v) -> h.accessor$wololoTarget((net.minecraft.world.entity.animal.sheep.Sheep) v)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SheepData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SheepData.java index ab56f4e9433..3194266a790 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/SheepData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SheepData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.animal.sheep.Sheep; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java index 8dd4c38c7d8..8a9f62cca76 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java @@ -53,8 +53,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(TurtleAccessor::invoker$isGoingHome) .set(TurtleAccessor::invoker$setGoingHome) .create(Keys.IS_TRAVELING) - .get(TurtleAccessor::invoker$isTravelling) - .set(TurtleAccessor::invoker$setTravelling) + .get(t -> t.invoker$getTravelPos() != null) .create(Keys.TARGET_POSITION) .get(h -> VecHelper.toVector3i(h.invoker$getTravelPos())) .set((h, v) -> h.invoker$setTravelPos(VecHelper.toBlockPos(v))); diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSources.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSources.java index 799529074ef..c989267b859 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSources.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSources.java @@ -24,7 +24,10 @@ */ package org.spongepowered.common.event.cause.entity.damage; +import net.minecraft.core.BlockPos; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; public final class SpongeDamageSources { @@ -42,6 +45,16 @@ public final class SpongeDamageSources { IGNORED = null; } + public static net.minecraft.world.damagesource.DamageSource createBlockBasedDamageSource( + final ServerWorld world, final BlockPos pos, final net.minecraft.world.damagesource.DamageSource original) { + final ServerLocation location = ServerLocation.of(world, pos.getX(), pos.getY(), pos.getZ()); + return (net.minecraft.world.damagesource.DamageSource) DamageSource.builder() + .from((DamageSource) original) + .block(location) + .block(location.createSnapshot()) + .build(); + } + // SORTFIELDS:OFF // @formatter:on diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 5f7a7af6552..d1d7da1bff5 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -39,9 +39,9 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Sheep; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.animal.sheep.Sheep; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -64,8 +64,8 @@ import org.spongepowered.common.accessor.entity.passive.AbstractChestedHorseEntityAccessor; import org.spongepowered.common.accessor.network.protocol.game.ServerboundMovePlayerPacketAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; -import org.spongepowered.common.accessor.world.entity.animal.SheepAccessor; import org.spongepowered.common.accessor.world.entity.animal.WolfAccessor; +import org.spongepowered.common.accessor.world.entity.animal.sheep.SheepAccessor; import org.spongepowered.common.accessor.world.inventory.SlotAccessor; import org.spongepowered.common.bridge.network.protocol.PacketBridge; import org.spongepowered.common.bridge.world.level.block.TrackableBlockBridge; diff --git a/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java b/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java index 971d6d56655..109895c9085 100644 --- a/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java +++ b/src/main/java/org/spongepowered/common/service/game/pagination/ActivePagination.java @@ -25,7 +25,6 @@ package org.spongepowered.common.service.game.pagination; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; diff --git a/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java b/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java index 66b8c53350e..e679be6331c 100644 --- a/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java +++ b/src/main/java/org/spongepowered/common/service/game/pagination/SpongePaginationList.java @@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/main/java/org/spongepowered/common/util/MapUtil.java b/src/main/java/org/spongepowered/common/util/MapUtil.java index 51b029e89bd..62be558c0bc 100644 --- a/src/main/java/org/spongepowered/common/util/MapUtil.java +++ b/src/main/java/org/spongepowered/common/util/MapUtil.java @@ -26,6 +26,7 @@ import com.google.common.primitives.Bytes; import net.minecraft.core.MappedRegistry; +import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.data.persistence.DataView; @@ -109,7 +110,7 @@ public static MapShade getMapShadeById(final int id) { public static void saveMapUUIDIndex(final CompoundTag tag, final Map index) { for (final Map.Entry entry : index.entrySet()) { - tag.putUUID(String.valueOf(entry.getKey()), entry.getValue()); + tag.store(String.valueOf(entry.getKey()), UUIDUtil.CODEC, entry.getValue()); } } diff --git a/src/main/java/org/spongepowered/common/util/VecHelper.java b/src/main/java/org/spongepowered/common/util/VecHelper.java index 5d3c5b9d34a..054b4a97dcd 100644 --- a/src/main/java/org/spongepowered/common/util/VecHelper.java +++ b/src/main/java/org/spongepowered/common/util/VecHelper.java @@ -87,7 +87,7 @@ public static org.spongepowered.math.vector.Vector3d toVector3d(final Rotations if (rotation == null) { return null; } - return new org.spongepowered.math.vector.Vector3d(rotation.getX(), rotation.getY(), rotation.getZ()); + return new org.spongepowered.math.vector.Vector3d(rotation.x(), rotation.y(), rotation.z()); } // === MC Vector3i --> Flow Vector3i === diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SheepMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/sheep/SheepMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SheepMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/sheep/SheepMixin_API.java index 6e08bb1f5f1..ffd86fe315f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SheepMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/sheep/SheepMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.sheep; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Sheep; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Sheep.class) +@Mixin(net.minecraft.world.entity.animal.sheep.Sheep.class) public abstract class SheepMixin_API extends AnimalMixin_API implements Sheep { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java index 2ab91a5237f..11d930abbeb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java @@ -24,35 +24,20 @@ */ package org.spongepowered.common.mixin.core.server.bossevents; -import net.minecraft.network.chat.Component; import net.minecraft.server.bossevents.CustomBossEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.mixin.core.server.level.ServerBossEventMixin; @Mixin(CustomBossEvent.class) public abstract class CustomBossEventMixin extends ServerBossEventMixin { @Shadow private int max; - @Redirect(method = {"getValue", "save"}, + @Redirect(method = {"getValue"}, at = @At(value = "FIELD", target = "Lnet/minecraft/server/bossevents/CustomBossEvent;value:I")) private int impl$valueRead(final CustomBossEvent $this) { return (int) (this.bridge$asAdventure().progress() * this.max); } - - @Redirect( - method = {"save"}, - at = @At( - value = "FIELD", - target = "Lnet/minecraft/server/bossevents/CustomBossEvent;name:Lnet/minecraft/network/chat/Component;" - ) - ) - private Component impl$nameRead(final CustomBossEvent $this) { - return SpongeAdventure.asVanilla(this.bridge$asAdventure().name()); - } - - // Value writes already update the percent field of superclasses, so we don't need to redirect } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index bbacf4479cc..6dad8add329 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -971,9 +971,19 @@ private boolean isPvpAllowed() { return this.bridge$changeDimension(transition); } - @Redirect(method = "findRespawnPositionAndUseSpawnBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getRespawnDimension()Lnet/minecraft/resources/ResourceKey;")) - private ResourceKey impl$callRespawnPlayerSelectWorld(final net.minecraft.server.level.ServerPlayer player) { - var playerRespawnDestination = this.server.getLevel(player.getRespawnDimension()); + @WrapOperation(method = "findRespawnPositionAndUseSpawnBlock", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerPlayer;getRespawnConfig()Lnet/minecraft/server/level/ServerPlayer$RespawnConfig;" + )) + private net.minecraft.server.level.ServerPlayer.RespawnConfig impl$callRespawnPlayerSelectWorld( + final net.minecraft.server.level.ServerPlayer player, + final Operation original, + @Share("sponge:overridden-respawn") final LocalRef> dimension + ) { + final var config = original.call(player); + final var defaulted = config == null ? Level.OVERWORLD : config.dimension(); + + var playerRespawnDestination = this.server.getLevel(defaulted); if (playerRespawnDestination == null) { SpongeCommon.logger().warn("The player '{}' respawn location was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", player.getGameProfile().getName()); @@ -985,7 +995,37 @@ private boolean isPvpAllowed() { SpongeCommon.post(event); this.impl$respawnLevel = (ServerLevel) event.destinationWorld(); - return ((ServerLevel) event.destinationWorld()).dimension(); + dimension.set(((ServerLevel) event.destinationWorld()).dimension()); + return config; + } + + @WrapOperation( + method = "findRespawnPositionAndUseSpawnBlock", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;") + ) + private ServerLevel impl$useOverriddenLevel( + final MinecraftServer instance, final ResourceKey key, final Operation original, + @Share("sponge:overridden-respawn") final LocalRef> dimension + ) { + if (dimension.get() != null) { + return original.call(instance, dimension.get()); + } + + return original.call(instance, key); + } + + @WrapOperation( + method = "findRespawnPositionAndUseSpawnBlock", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;") + ) + private ServerLevel impl$callRespawnPlayerSelectWorld( + final MinecraftServer instance, final Operation original, + @Share("sponge:overridden-respawn") final LocalRef> dimension + ) { + if (dimension.get() != null) { + return instance.getLevel(dimension.get()); + } + return original.call(instance); } @Inject(method = "findRespawnPositionAndUseSpawnBlock", at = @At("RETURN")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index b37872a7b1d..504cdca5e8a 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -500,7 +500,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ) private void impl$flagIfRespawnPositionIsGameMechanic(final net.minecraft.server.level.ServerPlayer $$0, final boolean $$1, final Entity.RemovalReason $$2, final CallbackInfoReturnable cir) { - this.impl$isRespawnWithPosition = $$0.getRespawnPosition() != null; + this.impl$isRespawnWithPosition = $$0.getRespawnConfig() != null; } @Redirect( diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index a9780f95a12..d7239c8e12f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -25,6 +25,8 @@ package org.spongepowered.common.mixin.core.world.entity; import com.google.common.collect.ImmutableList; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -46,6 +48,7 @@ import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.InsideBlockEffectApplier; import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; @@ -733,20 +736,22 @@ public void stopRiding() { } - @Redirect(method = "checkInsideBlocks(Ljava/util/List;Lnet/minecraft/world/entity/Entity$StateVisitor;)V", + @WrapOperation(method = "lambda$checkInsideBlocks$0", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V" + target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/InsideBlockEffectApplier;)V" ) ) // doBlockCollisions - private void impl$onCheckInsideBlocksCollide(final BlockState blockState, final Level worldIn, final BlockPos pos, final Entity entityIn) { + private void impl$onCheckInsideBlocksCollide( + final BlockState blockState, final Level worldIn, final BlockPos pos, final Entity entityIn, + final InsideBlockEffectApplier insideBlockEffectApplier, final Operation original) { if (!ShouldFire.COLLIDE_BLOCK_EVENT_INSIDE || worldIn.isClientSide || blockState.isAir()) { - blockState.entityInside(worldIn, pos, entityIn); + original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier); return; } final org.spongepowered.api.util.Direction dir = org.spongepowered.api.util.Direction.NONE; if (!SpongeCommonEventFactory.handleCollideBlockEvent(blockState.getBlock(), worldIn, pos, blockState, entityIn, dir, SpongeCommonEventFactory.CollisionType.INSIDE)) { - blockState.entityInside(worldIn, pos, entityIn); + original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier); this.impl$lastCollidedBlockPos = pos; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index eaf6daca170..5f98ec106a0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -24,12 +24,10 @@ */ package org.spongepowered.common.mixin.core.world.entity; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.Entity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java index 140f7542326..93b201f05d6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.entity.ai.behavior; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.ai.behavior.HarvestFarmland; import net.minecraft.world.entity.npc.Villager; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -42,8 +42,8 @@ public abstract class HarvestFarmlandMixin { * would fail in forge environments. This changes the injection to a predictable * place where we still can forcibly call things but still cancel as needed. */ - @Inject(method = "canStillUse", at = @At(value = "HEAD"), cancellable = true) - private void onCanGrief(final CallbackInfoReturnable cir, ServerWorld worldIn, Villager owner) { + @Inject(method = "canStillUse(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)Z", at = @At(value = "HEAD"), cancellable = true) + private void onCanGrief(ServerLevel level, Villager owner, long $$2, CallbackInfoReturnable cir) { if (!((GrieferBridge) owner).bridge$canGrief()) { cir.setReturnValue(false); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 27819ee55fa..8a4507c47af 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -39,7 +39,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player.BedSleepingProblem; import net.minecraft.world.food.FoodData; @@ -51,7 +50,6 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Team; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.event.CauseStackManager; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/BaseFireBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/BaseFireBlockMixin.java index fa2bc78788e..4c5323300be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/BaseFireBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/BaseFireBlockMixin.java @@ -24,34 +24,49 @@ */ package org.spongepowered.common.mixin.core.world.level.block; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.InsideBlockEffectApplier; +import net.minecraft.world.entity.InsideBlockEffectType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BaseFireBlock; import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.accessor.world.DamageSourcesAccessor; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; import org.spongepowered.common.mixin.core.block.BlockMixin; +import java.util.function.Consumer; + @Mixin(BaseFireBlock.class) public abstract class BaseFireBlockMixin extends BlockMixin { - @Redirect(method = "entityInside", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;inFire()Lnet/minecraft/world/damagesource/DamageSource;")) - private DamageSource impl$spongeRedirectForFireDamage(final DamageSources instance, final BlockState blockState, final Level world, final BlockPos blockPos, final Entity entity) { - final DamageSource source = instance.inFire(); - if (world.isClientSide) { // Short Circuit - return source; + @WrapOperation(method = "entityInside", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/InsideBlockEffectApplier;runAfter(Lnet/minecraft/world/entity/InsideBlockEffectType;Ljava/util/function/Consumer;)V" + )) + private void impl$spongeRedirectForFireDamage( + final InsideBlockEffectApplier instance, final InsideBlockEffectType insideBlockEffectType, + final Consumer entityConsumer, final Operation original, final BlockState state, + final Level world, BlockPos pos, Entity entity, InsideBlockEffectApplier sameApplier + ) { + if (world.isClientSide()) { + original.call(instance, insideBlockEffectType, entityConsumer); + return; + } + // We'll be replacing the DamageSources.inFire() with our own temporarily then roll it back... + final var originalInFire = world.damageSources().inFire(); + final var blockSource = SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) world, pos, originalInFire); + try { + ((DamageSourcesAccessor) world.damageSources()).accessor$setInFire(blockSource); + original.call(instance, insideBlockEffectType, entityConsumer); + } finally { + ((DamageSourcesAccessor) world.damageSources()).accessor$setInFire(originalInFire); } - final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); - var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() - .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) - .block(location.createSnapshot()).build(); - return (DamageSource) blockSource; } + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CactusBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CactusBlockMixin.java index d02dd28bcb5..b0ae94cdbf6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CactusBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CactusBlockMixin.java @@ -31,27 +31,27 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.CactusBlock; import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; import org.spongepowered.common.mixin.core.block.BlockMixin; @Mixin(CactusBlock.class) public abstract class CactusBlockMixin extends BlockMixin { @Redirect(method = "entityInside", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;cactus()Lnet/minecraft/world/damagesource/DamageSource;")) - private DamageSource impl$reAssignForBlockDamageSource(final DamageSources instance, final BlockState $$0, final Level world, final BlockPos pos, final Entity $$3) { + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/damagesource/DamageSources;cactus()Lnet/minecraft/world/damagesource/DamageSource;" + )) + private DamageSource impl$reAssignForBlockDamageSource( + final DamageSources instance, final BlockState $$0, final Level world, + final BlockPos pos, final Entity $$3) { final DamageSource source = instance.cactus(); if (world.isClientSide()) { return source; } - final ServerLocation location = ServerLocation.of((ServerWorld) world, pos.getX(), pos.getY(), pos.getZ()); - var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() - .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) - .block(location.createSnapshot()).build(); - return (DamageSource) blockSource; + return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) world, pos, source); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java index 6dd01f2334f..ceafbdb938e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java @@ -31,11 +31,11 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.MagmaBlock; import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; import org.spongepowered.common.mixin.core.block.BlockMixin; @Mixin(MagmaBlock.class) @@ -43,15 +43,14 @@ public abstract class MagmaBlockMixin extends BlockMixin { @Redirect(method = "stepOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;hotFloor()Lnet/minecraft/world/damagesource/DamageSource;")) - private DamageSource impl$spongeRedirectForFireDamage(final DamageSources instance, final Level world, final BlockPos blockPos, final BlockState blockState, final Entity entity) { + private DamageSource impl$spongeRedirectForFireDamage( + final DamageSources instance, final Level world, final BlockPos blockPos, + final BlockState blockState, final Entity entity + ) { final DamageSource source = instance.hotFloor(); if (world.isClientSide) { // Short Circuit return source; } - final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); - var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() - .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) - .block(location.createSnapshot()).build(); - return (DamageSource) blockSource; + return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) world, blockPos, source); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java index e1cbabb31b1..8a14da2e824 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java @@ -31,11 +31,11 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.PointedDripstoneBlock; import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; import org.spongepowered.common.mixin.core.block.BlockMixin; @Mixin(PointedDripstoneBlock.class) @@ -51,11 +51,7 @@ public abstract class PointedDripstoneBlockMixin extends BlockMixin { if (level.isClientSide) { // Short Circuit return source; } - final ServerLocation location = ServerLocation.of((ServerWorld) level, pos.getX(), pos.getY(), pos.getZ()); - var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() - .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) - .block(location.createSnapshot()).build(); - return (DamageSource) blockSource; + return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) level, pos, source); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java index f66127926c0..fd54083550a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java @@ -31,17 +31,17 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.SweetBerryBushBlock; import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; import org.spongepowered.common.mixin.core.block.BlockMixin; @Mixin(SweetBerryBushBlock.class) public abstract class SweetBerryBushBlockMixin extends BlockMixin { - @Redirect(method = "entityInside(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)V", + @Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;sweetBerryBush()Lnet/minecraft/world/damagesource/DamageSource;")) private DamageSource impl$spongeRedirectForFireDamage( final DamageSources instance, final BlockState state, @@ -51,11 +51,7 @@ public abstract class SweetBerryBushBlockMixin extends BlockMixin { if (level.isClientSide) { // Short Circuit return source; } - final ServerLocation location = ServerLocation.of((ServerWorld) level, pos.getX(), pos.getY(), pos.getZ()); - var blockSource = org.spongepowered.api.event.cause.entity.damage.source.DamageSource.builder() - .from((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) source).block(location) - .block(location.createSnapshot()).build(); - return (DamageSource) blockSource; + return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) level, pos, source); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java index 6bfb95f10fd..719bcb7bed5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BeaconBlockEntityMixin.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import java.util.Optional; -import java.util.function.Function; +import java.util.function.Predicate; @Mixin(BeaconBlockEntity.class) public abstract class BeaconBlockEntityMixin extends BlockEntityMixin { @@ -47,11 +47,11 @@ public abstract class BeaconBlockEntityMixin extends BlockEntityMixin { */ @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "rawtypes"}) @Redirect(method = "loadEffect", - at = @At(value = "INVOKE", target = "Ljava/util/Optional;map(Ljava/util/function/Function;)Ljava/util/Optional;") + at = @At(value = "INVOKE", target = "Ljava/util/Optional;filter(Ljava/util/function/Predicate;)Ljava/util/Optional;") ) @Nullable private static Optional impl$UsePotionUtilInsteadOfCheckingValidPotions( - Optional instance, Function mapper) { + Optional instance, Predicate predicate) { return instance; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 48576cbe086..6dbfeeca928 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -391,7 +391,7 @@ public ServerLevelData overworldData() { @Override public CompoundTag bridge$writeSpongeLevelData() { final CompoundTag data = new CompoundTag(); - data.putUUID(Constants.Sponge.World.UNIQUE_ID, this.impl$uniqueId); + data.store(Constants.Sponge.World.UNIQUE_ID, UUIDUtil.CODEC, this.impl$uniqueId); // Map Storage final CompoundTag mapUUIDIndexTag = new CompoundTag(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java index 3e317a36d53..e3e0edad8a5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java @@ -24,20 +24,28 @@ */ package org.spongepowered.common.mixin.core.world.ticks; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.datafixers.Products; +import com.mojang.datafixers.kinds.App; +import com.mojang.datafixers.kinds.Applicative; +import com.mojang.datafixers.util.Function4; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.ticks.SavedTick; +import net.minecraft.world.ticks.TickPriority; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; import org.spongepowered.common.data.holder.SpongeMutableDataHolder; import java.util.Optional; -import java.util.function.Function; @Mixin(SavedTick.class) public abstract class SavedTickMixin implements SpongeMutableDataHolder, DataCompoundHolder, CreatorTrackedBridge { @@ -54,19 +62,39 @@ public abstract class SavedTickMixin implements SpongeMutableDataHolder, Data this.impl$compound = nbt; } - @Inject(method = "save", at = @At("RETURN")) - private void impl$onSaveTick(final CallbackInfoReturnable cir) { - if (DataUtil.syncDataToTag(this)) { - cir.getReturnValue().merge(this.data$getCompound()); - } - } - - @Inject(method = "loadTick", at = @At("RETURN")) - private static void impl$onLoad(final CompoundTag $$0, final Function> $$1, final CallbackInfoReturnable>> cir) { - cir.getReturnValue().ifPresent(tick -> { - ((DataCompoundHolder) (Object) tick).data$setCompound($$0); - DataUtil.syncTagToData(tick); - ((DataCompoundHolder) (Object) tick).data$setCompound(null); + /** + * @return The codec + * @author gabizou - 25w07a - February 15th, 2025 + * @reason Because SavedTicks are now saved via Codec, we have to modify the codec to inject our + * custom data alongside it. This means that we're explicitly not going to be calling the original + * operation, but merely adding the existing products and instantiation function. It is why we use + * a {@link Redirect} instead of a {@link WrapOperation}. Unless there is a better way to modify + * the codec to support the data field additions. + */ + @SuppressWarnings("deprecation") + @Redirect(method = "lambda$codec$1", at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/Products$P4;apply(Lcom/mojang/datafixers/kinds/Applicative;Lcom/mojang/datafixers/util/Function4;)Lcom/mojang/datafixers/kinds/App;")) + private static App>, SavedTick> lambda$codec$1( + final Products.P4>, T, BlockPos, Integer, TickPriority> products, + final Applicative>, ?> instance, + final Function4> function + ) { + final RecordCodecBuilder, Optional> spongeCustomData = Codec.optionalField("customData", CustomData.CODEC, true).forGetter(t -> { + final var bridge = ((SavedTickMixin) (Object) t); + DataUtil.syncDataToTag(bridge); + if (bridge.impl$compound != null) { + return Optional.of(CustomData.of(bridge.impl$compound)); + } + return Optional.empty(); }); + return products.and(spongeCustomData) + .apply(instance, (t, blockPos, integer, tickPriority, customData) -> { + final var tick = function.apply(t, blockPos, integer, tickPriority); + customData.ifPresent(data -> { + ((DataCompoundHolder) (Object) tick).data$setCompound(data.getUnsafe()); + DataUtil.syncTagToData(tick); + ((DataCompoundHolder) (Object) tick).data$setCompound(null); + }); + return tick; + }); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java index f0693e9d59d..27af0116a21 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/player/PlayerMixin_Inventory.java @@ -36,7 +36,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.mixin.inventory.event.entity.LivingEntityMixin_Inventory; diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index 6f123326cde..dbf675e3c3e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -36,8 +36,8 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ambient.AmbientCreature; import net.minecraft.world.entity.animal.Animal; -import net.minecraft.world.entity.animal.Sheep; import net.minecraft.world.entity.animal.WaterAnimal; +import net.minecraft.world.entity.animal.sheep.Sheep; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index a5b25c2196c..c8b3c0fdd52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -27,7 +27,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.CombatEntry; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; @@ -39,23 +38,18 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.accessor.world.damagesource.CombatTrackerAccessor; -import org.spongepowered.common.bridge.world.entity.PlatformEntityBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.phase.entity.EntityPhase; import org.spongepowered.common.event.tracking.phase.tick.EntityTickContext; -import org.spongepowered.common.item.util.ItemStackUtil; -import java.util.ArrayList; import java.util.List; @Mixin(LivingEntity.class) diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 12fcac940a1..4f406885775 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -169,7 +169,7 @@ "minecraft.world.entity.animal.Rabbit_VariantMixin_API", "minecraft.world.entity.animal.RabbitMixin_API", "minecraft.world.entity.animal.SalmonMixin_API", - "minecraft.world.entity.animal.SheepMixin_API", + "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.ShoulderRidingEntityMixin_API", "minecraft.world.entity.animal.SnowGolemMixin_API", "minecraft.world.entity.animal.SquidMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 859a1414637..3ea2c47c83a 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -229,7 +229,6 @@ "world.level.LevelMixin", "world.level.NaturalSpawner_SpawnStateMixin", "world.level.NaturalSpawnerMixin", - "world.level.storage.DimensionDataSotrageMixin", "world.level.ServerExplosionMixin", "world.level.biome.BiomeSourceMixin", "world.level.block.BaseFireBlockMixin", @@ -260,6 +259,7 @@ "world.level.block.entity.CommandBlockEntityMixin", "world.level.block.entity.EnchantmentTableBlockEntityMixin", "world.level.block.entity.LecternBlockEntityMixin", + "world.level.block.entity.RandomizableContainerBlockEntityMixin", "world.level.block.entity.SignBlockEntityMixin", "world.level.block.entity.SkullBlockEntityMixin", "world.level.block.piston.PistonMovingBlockEntityMixin", @@ -283,6 +283,7 @@ "world.level.levelgen.flat.FlatLevelGeneratorSettingsMixin", "world.level.levelgen.structure.LegacyStructureDataHandlerMixin", "world.level.saveddata.MapIdTrackerMixin", + "world.level.storage.DimensionDataSotrageMixin", "world.level.storage.DimensionDataStorageMixin", "world.level.storage.LevelDataMixin", "world.level.storage.LevelStorageSource_LevelStorageAccessMixin", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 87311e8201d..f7583e381c1 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -204,7 +204,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, VertexBuffer $$3 = RenderSystem.getQuadVertices(); $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); final int baseY = this.top + this.border - (int) this.scrollDistance; @@ -230,7 +230,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.barLeft, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); $$3 = RenderSystem.getQuadVertices(); $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); worldr =tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); @@ -239,7 +239,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); $$3 = RenderSystem.getQuadVertices(); $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft + this.barWidth - 1, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); @@ -247,7 +247,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); $$3 = RenderSystem.getQuadVertices(); $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); } // RenderSystem.enableTexture(); From d3cdbf4f915755a1153a271251f52a99d70c5393 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 15 Feb 2025 00:36:18 -0800 Subject: [PATCH 193/586] feat: add content for 25w07a --- SpongeAPI | 2 +- .../data/provider/block/state/BlockStateDataProvider.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 6314841c4e2..71d8ed3d371 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 6314841c4e2ecc78e9a670d7b22e20e38e75f968 +Subproject commit 71d8ed3d371e8087d69c0f5b9fe1cabf99da5413 diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index 013ad9849f0..6449fab5911 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -112,6 +112,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.LEVEL_HONEY, BlockStateProperties.LEVEL_HONEY); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.LIT, BlockStateProperties.LIT); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.LOCKED, BlockStateProperties.LOCKED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.MAP, BlockStateProperties.MAP); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.MODE_COMPARATOR, BlockStateProperties.MODE_COMPARATOR); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.MOISTURE, BlockStateProperties.MOISTURE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.NATURAL, BlockStateProperties.NATURAL); From f2274c156fe63c277450b2e503473d50bc6cd046 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 15 Feb 2025 20:47:06 +0200 Subject: [PATCH 194/586] Generate SlotDisplay for SpongeIngredient --- .../common/item/recipe/ingredient/SpongeIngredient.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index 681ad55e969..85395c5ade9 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -32,6 +32,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.display.SlotDisplay; import org.apache.commons.lang3.NotImplementedException; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.item.inventory.ItemStackLike; @@ -132,6 +133,11 @@ public boolean test(final ItemStack testStack) { return this.itemList.test(testStack); } + @Override + public SlotDisplay display() { + return new SlotDisplay.Composite(this.itemList.getItems().stream().map(SlotDisplay.ItemStackSlotDisplay::new).map(SlotDisplay.class::cast).toList()); + } + public static SpongeIngredient spongeFromStacks(net.minecraft.world.item.ItemStack... stacks) { final SpongeStackItemList itemList = new SpongeStackItemList(stacks); return new SpongeIngredient(SpongeStackItemList.TYPE_STACK, itemList, null); From f01a93b937a83cf61c7865344ec82c693991ba57 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 22 Feb 2025 13:56:11 +0100 Subject: [PATCH 195/586] Remove call to genEventImpl because it no longer exists --- build.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8d1a7430952..6069cf4acd6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -443,10 +443,6 @@ tasks { check { dependsOn(gradle.includedBuild("SpongeAPI").task(":check")) } - - prepareWorkspace { - dependsOn(gradle.includedBuild("SpongeAPI").task(":genEventImpl")) - } } publishing { From 3d15ed21db5d2e2ecd4772f4b3f0376bbec3e2c9 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 22 Feb 2025 14:02:35 +0100 Subject: [PATCH 196/586] Rewrite dropper and hopper mixins with cross-platform injections. Fix #4176 --- ...opperBlockEntityMixin_Inventory_Forge.java | 87 ------------- .../mixins.spongeforge.inventory.json | 1 - gradle/verification-metadata.xml | 64 ++++++++++ neoforge/gradle.properties | 2 +- .../HopperBlockEntityMixin_Inventory_Neo.java | 87 ------------- .../resources/mixins.spongeneo.inventory.json | 3 +- .../block/DropperBlockMixin_Inventory.java | 100 ++++++--------- .../HopperBlockEntityMixin_Inventory.java | 118 +++++++++++------- ...perBlockEntityMixin_Inventory_Vanilla.java | 91 -------------- .../mixins.spongevanilla.inventory.json | 1 - 10 files changed, 174 insertions(+), 380 deletions(-) delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Forge.java delete mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Neo.java delete mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Vanilla.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Forge.java deleted file mode 100644 index 95a4aa58821..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Forge.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.inventory.event.world.level.block.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import org.spongepowered.api.item.inventory.Inventory; -import org.spongepowered.api.item.inventory.transaction.SlotTransaction; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.accessor.world.level.block.entity.HopperBlockEntityAccessor; -import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; -import org.spongepowered.common.event.ShouldFire; -import org.spongepowered.common.event.inventory.InventoryEventFactory; -import org.spongepowered.common.inventory.util.InventoryUtil; - -@Mixin(HopperBlockEntity.class) -public abstract class HopperBlockEntityMixin_Inventory_Forge { - - @Redirect(method = "ejectItems", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;isFullContainer(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)Z")) - private static boolean forge$throwTransferPreIfNotFull( - final Container attachedContainer, final Direction direction, final Level level, final BlockPos pos, final HopperBlockEntity block - ) { - final boolean result = HopperBlockEntityAccessor.invoker$isFullContainer(attachedContainer, direction); - if (result || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { - return result; - } - return InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(block), InventoryUtil.toInventory(attachedContainer)).isCancelled(); - } - -// Post Captured Transactions - - @Inject(method = "ejectItems", locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", - ordinal = 1)) - private static void forge$afterPutStackInSlots( - final Level var0, final BlockPos var1, final HopperBlockEntity var3, - final CallbackInfoReturnable cir, final Container iInventory, final Direction enumFacing, - final int i, final ItemStack itemStack, final int count,final ItemStack itemStack1 - ) { - // after putStackInInventoryAllSlots if the transfer worked - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && itemStack1.isEmpty()) { - // Capture Insert in Origin - final TrackedInventoryBridge capture = InventoryUtil.forCapture(var3); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, (Inventory) var3, i, itemStack); - // Call event - InventoryEventFactory.callTransferPost(capture, (Inventory) iInventory, InventoryUtil.toInventory(iInventory), itemStack, sourceSlotTransaction); - } - - InventoryUtil.updateInventoryNoEvents(var3); - InventoryUtil.updateInventoryNoEvents(iInventory); - } - -} diff --git a/forge/src/mixins/resources/mixins.spongeforge.inventory.json b/forge/src/mixins/resources/mixins.spongeforge.inventory.json index 21d0444a46e..890e2ee51d5 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.inventory.json +++ b/forge/src/mixins/resources/mixins.spongeforge.inventory.json @@ -5,6 +5,5 @@ "target": "@env(DEFAULT)", "priority": 1300, "mixins": [ - "event.world.level.block.entity.HopperBlockEntityMixin_Inventory_Forge" ] } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5ace055bcac..18baf083f27 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -187,6 +187,14 @@ + + + + + + + + @@ -233,6 +241,14 @@ + + + + + + + + @@ -4853,6 +4869,20 @@ + + + + + + + + + + + + + + @@ -4957,6 +4987,14 @@ + + + + + + + + @@ -4989,6 +5027,14 @@ + + + + + + + + @@ -5980,6 +6026,11 @@ + + + + + @@ -6012,6 +6063,14 @@ + + + + + + + + @@ -6040,6 +6099,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index ebc2e73e9d3..e3c2fd2274f 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.4.30-beta +neoForgeVersion=21.4.93-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Neo.java deleted file mode 100644 index 6ec63c229c9..00000000000 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Neo.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.mixin.inventory.event.world.level.block.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import org.spongepowered.api.item.inventory.Inventory; -import org.spongepowered.api.item.inventory.transaction.SlotTransaction; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.accessor.world.level.block.entity.HopperBlockEntityAccessor; -import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; -import org.spongepowered.common.event.ShouldFire; -import org.spongepowered.common.event.inventory.InventoryEventFactory; -import org.spongepowered.common.inventory.util.InventoryUtil; - -@Mixin(HopperBlockEntity.class) -public abstract class HopperBlockEntityMixin_Inventory_Neo { - - @Redirect(method = "ejectItems", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;isFullContainer(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)Z")) - private static boolean neo$throwTransferPreIfNotFull( - final Container attachedContainer, final Direction direction, final Level level, final BlockPos pos, final HopperBlockEntity block - ) { - final boolean result = HopperBlockEntityAccessor.invoker$isFullContainer(attachedContainer, direction); - if (result || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { - return result; - } - return InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(block), InventoryUtil.toInventory(attachedContainer)).isCancelled(); - } - -// Post Captured Transactions - - @Inject(method = "ejectItems", locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", - ordinal = 1)) - private static void neo$afterPutStackInSlots( - final Level var0, final BlockPos var1, final HopperBlockEntity var3, - final CallbackInfoReturnable cir, final Container iInventory, final Direction enumFacing, - final int i, final ItemStack itemStack, final int count,final ItemStack itemStack1 - ) { - // after putStackInInventoryAllSlots if the transfer worked - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && itemStack1.isEmpty()) { - // Capture Insert in Origin - final TrackedInventoryBridge capture = InventoryUtil.forCapture(var3); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, (Inventory) var3, i, itemStack); - // Call event - InventoryEventFactory.callTransferPost(capture, (Inventory) iInventory, InventoryUtil.toInventory(iInventory), itemStack, sourceSlotTransaction); - } - - InventoryUtil.updateInventoryNoEvents(var3); - InventoryUtil.updateInventoryNoEvents(iInventory); - } - -} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.inventory.json b/neoforge/src/mixins/resources/mixins.spongeneo.inventory.json index b42178d7290..3b57561e95e 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.inventory.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.inventory.json @@ -6,7 +6,6 @@ "priority": 1300, "mixins": [ "event.entity.PlayerMixin_Inventory_Neo", - "event.server.level.ServerPlayerMixin_Inventory_Neo", - "event.world.level.block.entity.HopperBlockEntityMixin_Inventory_Neo" + "event.server.level.ServerPlayerMixin_Inventory_Neo" ] } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/DropperBlockMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/DropperBlockMixin_Inventory.java index fa567e29bd6..2ddc535b2ef 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/DropperBlockMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/DropperBlockMixin_Inventory.java @@ -24,25 +24,22 @@ */ package org.spongepowered.common.mixin.inventory.event.world.level.block; -import net.minecraft.core.BlockPos; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.minecraft.core.Direction; -import net.minecraft.core.dispenser.BlockSource; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.DropperBlock; import net.minecraft.world.level.block.entity.DispenserBlockEntity; -import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.transaction.SlotTransaction; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Surrogate; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.accessor.world.level.block.entity.HopperBlockEntityAccessor; import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.inventory.InventoryEventFactory; @@ -51,69 +48,44 @@ @Mixin(DropperBlock.class) public abstract class DropperBlockMixin_Inventory { - @Inject(method = "dispenseFrom", cancellable = true, locals = LocalCapture.CAPTURE_FAILEXCEPTION, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/DispenserBlockEntity;setItem(ILnet/minecraft/world/item/ItemStack;)V")) - private void impl$afterDispense(final ServerLevel worldIn, final BlockState state, final BlockPos pos, final CallbackInfo callbackInfo, - final DispenserBlockEntity dispensertileentity, final BlockSource proxyblocksource, final int i, final ItemStack itemstack, - final Direction direction, final Container iinventory, final ItemStack itemstack1) { - // after setItem - dispensertileentity.setItem(i, itemstack1); - - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST) { - // Transfer worked if remainder is one less than the original stack - if (itemstack1.getCount() == itemstack.getCount() - 1) { - final TrackedInventoryBridge capture = InventoryUtil.forCapture(dispensertileentity); - final Inventory sourceInv = ((Inventory) dispensertileentity); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, sourceInv, i, itemstack); - InventoryEventFactory.callTransferPost(capture, sourceInv, ((Inventory) iinventory), itemstack, sourceSlotTransaction); - } + @WrapOperation(method = "dispenseFrom", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;" + )) + private ItemStack impl$beforeDispense( + final Container dispenser, final Container container, final ItemStack stackToInsert, final Direction direction, + final Operation original, @Share("container") LocalRef containerRef + ) { + if (ShouldFire.TRANSFER_INVENTORY_EVENT_PRE && InventoryEventFactory.callTransferPre(((Inventory) dispenser), ((Inventory) container)).isCancelled()) { + return stackToInsert; } - - InventoryUtil.updateInventoryNoEvents(dispensertileentity); - InventoryUtil.updateInventoryNoEvents(iinventory); - - // dont call setItem twice - callbackInfo.cancel(); + containerRef.set(container); + return original.call(dispenser, container, stackToInsert, direction); } - @Surrogate - private void afterDispense(final ServerLevel worldIn, final BlockState state, final BlockPos pos, final CallbackInfo callbackInfo, - final DispenserBlockEntity dispensertileentity, final BlockSource proxyblocksource, final int i, final ItemStack itemstack, - final ItemStack itemstack1) { - // after setItem - dispensertileentity.setItem(i, itemstack1); - - final Direction enumfacing = worldIn.getBlockState(pos).getValue(DispenserBlock.FACING); - final BlockPos blockpos = pos.relative(enumfacing); - final Container iinventory = HopperBlockEntityAccessor.invoker$getContainerAt(worldIn, blockpos); - - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST) { + @Inject(method = "dispenseFrom", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/DispenserBlockEntity;setItem(ILnet/minecraft/world/item/ItemStack;)V", + shift = At.Shift.AFTER + )) + private void impl$afterDispense( + final CallbackInfo ci, @Local final DispenserBlockEntity dispenser, @Local final int index, + @Local(ordinal = 0) final ItemStack stack, @Local(ordinal = 1) final ItemStack remainingStack, + @Share("container") final LocalRef containerRef + ) { + final Container container = containerRef.get(); + if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && container != null) { // Transfer worked if remainder is one less than the original stack - if (itemstack1.getCount() == itemstack.getCount() - 1) { - final TrackedInventoryBridge capture = InventoryUtil.forCapture(dispensertileentity); - final Inventory sourceInv = ((Inventory) dispensertileentity); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, sourceInv, i, itemstack); - InventoryEventFactory.callTransferPost(capture, sourceInv, ((Inventory) iinventory), itemstack, sourceSlotTransaction); + if (remainingStack.getCount() == stack.getCount() - 1) { + final TrackedInventoryBridge capture = InventoryUtil.forCapture(dispenser); + final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, (Inventory) dispenser, index, stack); + InventoryEventFactory.callTransferPost(capture, (Inventory) dispenser, (Inventory) container, stack, sourceSlotTransaction); } } - InventoryUtil.updateInventoryNoEvents(dispensertileentity); - InventoryUtil.updateInventoryNoEvents(iinventory); - - // dont call setInventorySlotContents twice - callbackInfo.cancel(); - } - - @Inject(method = "dispenseFrom", cancellable = true, locals = LocalCapture.CAPTURE_FAILEXCEPTION, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) - private void onDispense(final ServerLevel world, final BlockState state, final BlockPos pos, final CallbackInfo ci, - final DispenserBlockEntity dispensertileentity, final BlockSource proxyblocksource, final int i, final ItemStack itemstack, - final Direction direction, final Container iinventory) { - // Before putStackInInventoryAllSlots - if (InventoryEventFactory.callTransferPre(((Inventory) dispensertileentity), ((Inventory) iinventory)).isCancelled()) { - ci.cancel(); + InventoryUtil.updateInventoryNoEvents(dispenser); + if (container != null) { + InventoryUtil.updateInventoryNoEvents(container); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java index bfaa6605e88..35d39ffa590 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java @@ -24,6 +24,11 @@ */ package org.spongepowered.common.mixin.inventory.event.world.level.block.entity; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.Container; import net.minecraft.world.entity.item.ItemEntity; @@ -38,7 +43,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.accessor.world.level.block.entity.HopperBlockEntityAccessor; import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.inventory.InventoryEventFactory; @@ -50,78 +54,100 @@ @Mixin(HopperBlockEntity.class) public abstract class HopperBlockEntityMixin_Inventory { - + @Redirect(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/item/ItemEntity;)Z", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) + private static ItemStack impl$transferFromEntity( + final Container sourceNull, final Container destination, final ItemStack stack, final Direction directionNull, @Local(argsOnly = true) final ItemEntity entity) { + return InventoryEventFactory.callHopperInventoryPickupEvent(destination, entity, stack); + } // Call PreEvents - @Redirect(method = "suckInItems", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;getSlots(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)[I")) - private static int[] impl$throwTransferPreIfNotEmpty(final Container inventory, final Direction facing, final Level level, final Hopper hopper) { - final var slots = HopperBlockEntityAccessor.invoker$getSlots(inventory, facing); - final boolean isEmpty = IntStream.of(slots).allMatch(slot -> inventory.getItem(slot).isEmpty()); - if (isEmpty || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { + @ModifyExpressionValue(method = "suckInItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;getSlots(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)[I")) + private static int[] impl$beforeTransferFrom(int[] slots, @Local(argsOnly = true) final Hopper hopper, @Local final Container container) { + final boolean empty = IntStream.of(slots).allMatch(slot -> container.getItem(slot).isEmpty()); + if (empty || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { return slots; } - if (InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(inventory), InventoryUtil.toInventory(hopper)).isCancelled()) { - return new int[]{}; + if (InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(container), InventoryUtil.toInventory(hopper)).isCancelled()) { + return new int[0]; } return slots; } + @ModifyExpressionValue(method = "ejectItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;isFullContainer(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)Z")) + private static boolean impl$beforeTransferTo(boolean full, @Local(argsOnly = true) final HopperBlockEntity hopper, @Local final Container container) { + if (full || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { + return full; + } + return InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(hopper), InventoryUtil.toInventory(container)).isCancelled(); + } + // Capture Transactions - @Redirect(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;tryMoveInItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;ILnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) - private static ItemStack impl$throwEventsForInsertion(final Container source, final Container destination, final ItemStack stack, - final int index, final Direction direction) { - // capture Transaction + @WrapOperation(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;tryMoveInItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;ILnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) + private static ItemStack impl$onTransfer( + final Container source, final Container destination, final ItemStack stack, final int index, final Direction direction, final Operation original + ) { if (!((source instanceof TrackedInventoryBridge || destination instanceof TrackedInventoryBridge) && destination instanceof InventoryAdapter)) { - return HopperBlockEntityAccessor.invoker$tryMoveInItem(source, destination, stack, index, direction); + return original.call(source, destination, stack, index, direction); } if (!ShouldFire.TRANSFER_INVENTORY_EVENT_POST) { - return HopperBlockEntityAccessor.invoker$tryMoveInItem(source, destination, stack, index, direction); + return original.call(source, destination, stack, index, direction); } - TrackedInventoryBridge captureIn = InventoryUtil.forCapture(source); - if (captureIn == null) { - captureIn = InventoryUtil.forCapture(destination); + TrackedInventoryBridge capture = InventoryUtil.forCapture(source); + if (capture == null) { + capture = InventoryUtil.forCapture(destination); } - return InventoryEventFactory.captureTransaction(captureIn, InventoryUtil.toInventory(destination), index, - () -> HopperBlockEntityAccessor.invoker$tryMoveInItem(source, destination, stack, index, direction)); + return InventoryEventFactory.captureTransaction(capture, InventoryUtil.toInventory(destination), index, + () -> original.call(source, destination, stack, index, direction)); } // Post Captured Transactions - @Inject(method = "tryTakeInItemFromSlot", - locals = LocalCapture.CAPTURE_FAILEXCEPTION, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", - ordinal = 1)) - private static void imlp$throwTransferEventsWhenPullingItems(final Hopper hopper, final Container iInventory, final int index, - final Direction direction, - final CallbackInfoReturnable cir, final ItemStack itemStack, final int oldCount, final ItemStack itemstack2) { - // after putStackInInventoryAllSlots if the transfer worked - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && itemstack2.isEmpty()) { + @Inject(method = "tryTakeInItemFromSlot", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1)) + private static void impl$afterTransferFrom( + final Hopper hopper, final Container container, final int index, final Direction direction, + final CallbackInfoReturnable cir, final ItemStack stack, final int originalCount, final ItemStack insertedStack + ) { + // If the transfer worked + if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && insertedStack.isEmpty()) { // Capture Insert in Origin final TrackedInventoryBridge capture = InventoryUtil.forCapture(hopper); - final int newCount = itemStack.getCount(); - itemstack2.setCount(oldCount); - var itemStack1 = itemstack2.copy(); - itemstack2.setCount(newCount); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, InventoryUtil.toInventory(iInventory), index, itemStack1); + final int newCount = stack.getCount(); + stack.setCount(originalCount); + final ItemStack originalStack = stack.copy(); + stack.setCount(newCount); + final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, InventoryUtil.toInventory(container), index, originalStack); // Call event - InventoryEventFactory.callTransferPost(capture, InventoryUtil.toInventory(iInventory), InventoryUtil.toInventory(hopper), itemStack1, sourceSlotTransaction); + InventoryEventFactory.callTransferPost(capture, InventoryUtil.toInventory(container), InventoryUtil.toInventory(hopper), originalStack, sourceSlotTransaction); } - InventoryUtil.updateInventoryNoEvents(iInventory); + InventoryUtil.updateInventoryNoEvents(container); InventoryUtil.updateInventoryNoEvents(hopper); } - @Redirect(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/item/ItemEntity;)Z", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) - private static ItemStack impl$onPutStackInInventoryAllSlots(final Container source, final Container destination, final ItemStack stack, final Direction direction, final Container d2, final ItemEntity entity) { - return InventoryEventFactory.callHopperInventoryPickupEvent(destination, entity, stack); + @Inject(method = "ejectItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1)) + private static void impl$afterTransferTo( + final Level level, final BlockPos pos, final HopperBlockEntity hopper, final CallbackInfoReturnable cir, + @Local final Container container, @Local(ordinal = 0) final int index, @Local(ordinal = 1) final int originalCount, + @Local(ordinal = 0) final ItemStack stack, @Local(ordinal = 1) final ItemStack insertedStack + ) { + // If the transfer worked + if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && insertedStack.isEmpty()) { + // Capture Insert in Origin + final TrackedInventoryBridge capture = InventoryUtil.forCapture(hopper); + final int newCount = stack.getCount(); + stack.setCount(originalCount); + final ItemStack originalStack = stack.copy(); + stack.setCount(newCount); + final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, InventoryUtil.toInventory(hopper), index, originalStack); + // Call event + InventoryEventFactory.callTransferPost(capture, InventoryUtil.toInventory(hopper), InventoryUtil.toInventory(container), originalStack, sourceSlotTransaction); + } + + InventoryUtil.updateInventoryNoEvents(hopper); + InventoryUtil.updateInventoryNoEvents(container); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Vanilla.java deleted file mode 100644 index e869ae9ca9f..00000000000 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory_Vanilla.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.vanilla.mixin.inventory.event.world.level.block.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import org.spongepowered.api.item.inventory.Inventory; -import org.spongepowered.api.item.inventory.transaction.SlotTransaction; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.accessor.world.level.block.entity.HopperBlockEntityAccessor; -import org.spongepowered.common.bridge.world.inventory.container.TrackedInventoryBridge; -import org.spongepowered.common.event.ShouldFire; -import org.spongepowered.common.event.inventory.InventoryEventFactory; -import org.spongepowered.common.inventory.util.InventoryUtil; - -@Mixin(HopperBlockEntity.class) -public abstract class HopperBlockEntityMixin_Inventory_Vanilla { - - @Redirect(method = "ejectItems", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;isFullContainer(Lnet/minecraft/world/Container;Lnet/minecraft/core/Direction;)Z")) - private static boolean vanilla$throwTransferPreIfNotFull( - final Container attachedContainer, final Direction direction, final Level level, final BlockPos pos, final HopperBlockEntity hopper) { - final boolean result = HopperBlockEntityAccessor.invoker$isFullContainer(attachedContainer, direction); - if (result || !ShouldFire.TRANSFER_INVENTORY_EVENT_PRE) { - return result; - } - return InventoryEventFactory.callTransferPre(InventoryUtil.toInventory(hopper), InventoryUtil.toInventory(attachedContainer)).isCancelled(); - } - - - // Post Captured Transactions - - @Inject(method = "ejectItems", locals = LocalCapture.CAPTURE_FAILEXCEPTION, - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", - ordinal = 1)) - private static void vanilla$afterPutStackInSlots( - final Level var0, final BlockPos var1, final HopperBlockEntity var3, - final CallbackInfoReturnable cir, final Container iInventory, final Direction enumFacing, - final int i, final ItemStack itemStack, final int count, final ItemStack itemStack1 - ) { - // after putStackInInventoryAllSlots if the transfer worked - if (ShouldFire.TRANSFER_INVENTORY_EVENT_POST && itemStack1.isEmpty()) { - // Capture Insert in Origin - final TrackedInventoryBridge capture = InventoryUtil.forCapture(var3); - int newCount = itemStack.getCount(); - itemStack.setCount(count); - var originalStack = itemStack.copy(); - itemStack.setCount(newCount); - final SlotTransaction sourceSlotTransaction = InventoryEventFactory.captureTransaction(capture, (Inventory) var3, i, originalStack); - // Call event - InventoryEventFactory.callTransferPost(capture, (Inventory) iInventory, InventoryUtil.toInventory(iInventory), originalStack, sourceSlotTransaction); - } - - InventoryUtil.updateInventoryNoEvents(var3); - InventoryUtil.updateInventoryNoEvents(iInventory); - } - -} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.inventory.json b/vanilla/src/mixins/resources/mixins.spongevanilla.inventory.json index 42d56a58e54..fb0d17bc139 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.inventory.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.inventory.json @@ -4,7 +4,6 @@ "package": "org.spongepowered.vanilla.mixin.inventory", "priority": 1200, "mixins": [ - "event.world.level.block.entity.HopperBlockEntityMixin_Inventory_Vanilla" ], "overwrites": { "conformVisibility": true From 350167edf4ccedd209d54319b0bd5cd49644c9f7 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 22 Feb 2025 14:27:03 +0100 Subject: [PATCH 197/586] Remove unused hopper invokers --- .../entity/HopperBlockEntityAccessor.java | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/HopperBlockEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/HopperBlockEntityAccessor.java index 2a6b9c55d25..95c1f423fae 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/HopperBlockEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/HopperBlockEntityAccessor.java @@ -24,17 +24,9 @@ */ package org.spongepowered.common.accessor.world.level.block.entity; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.HopperBlockEntity; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; @Mixin(HopperBlockEntity.class) public interface HopperBlockEntityAccessor { @@ -42,25 +34,4 @@ public interface HopperBlockEntityAccessor { @Accessor("cooldownTime") int accessor$cooldownTime(); @Accessor("cooldownTime") void accessor$cooldownTime(final int cooldownTime); - - @Invoker("tryMoveInItem") - static ItemStack invoker$tryMoveInItem(final @Nullable Container source, final Container destination, final ItemStack stack, final int index, - final @Nullable Direction direction) { - throw new UntransformedInvokerError(); - } - - @Invoker("getSlots") - static int[] invoker$getSlots(final Container inventory, final Direction side) { - throw new UntransformedInvokerError(); - } - - @Invoker("getContainerAt") - static Container invoker$getContainerAt(Level var0, BlockPos blockPos) { - throw new UntransformedInvokerError(); - } - - @Invoker("isFullContainer") - static boolean invoker$isFullContainer(Container param0, Direction param1) { - throw new UntransformedInvokerError(); - } } From 569507ecd3c05958f22930238c0c1e78eeb7b099 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 22 Feb 2025 21:19:14 -0800 Subject: [PATCH 198/586] feat(minecraft): update to 25w08a --- gradle.properties | 2 +- .../animal/{ => wolf}/WolfAccessor.java | 4 ++-- .../resources/mixins.sponge.accessors.json | 2 +- .../common/data/provider/entity/WolfData.java | 4 ++-- .../phase/packet/PacketPhaseUtil.java | 22 +++++++++---------- .../world/entity/EntityMixin_API.java | 2 +- .../animal/{ => wolf}/WolfMixin_API.java | 4 ++-- .../{ => wolf}/WollfVariantMixin_API.java | 4 ++-- .../entity/animal/{ => wolf}/WolfMixin.java | 12 +++++----- src/mixins/resources/mixins.sponge.api.json | 8 +++---- src/mixins/resources/mixins.sponge.core.json | 2 +- .../spongepowered/test/portal/PortalTest.java | 14 +++++++++++- .../entity/LivingEntityMixin_Attack_Impl.java | 6 ++--- 13 files changed, 49 insertions(+), 37 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => wolf}/WolfAccessor.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => wolf}/WolfMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => wolf}/WollfVariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => wolf}/WolfMixin.java (89%) diff --git a/gradle.properties b/gradle.properties index 31f0c5adb8a..506aeb1275d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w07a +minecraftVersion=25w08a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/WolfAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/wolf/WolfAccessor.java similarity index 94% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/WolfAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/wolf/WolfAccessor.java index 3c1ba1ae088..b1f854f78c0 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/WolfAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/wolf/WolfAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.wolf; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.entity.animal.Wolf; +import net.minecraft.world.entity.animal.wolf.Wolf; import net.minecraft.world.item.DyeColor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index b91579108b3..97f3d0015fd 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -86,7 +86,7 @@ "world.entity.animal.RabbitAccessor", "world.entity.animal.TropicalFishAccessor", "world.entity.animal.TurtleAccessor", - "world.entity.animal.WolfAccessor", + "world.entity.animal.wolf.WolfAccessor", "world.entity.animal.horse.AbstractHorseAccessor", "world.entity.animal.horse.HorseAccessor", "world.entity.animal.horse.LlamaAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java b/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java index 3328216b1f4..abc8e690300 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Wolf; +import net.minecraft.world.entity.animal.wolf.Wolf; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; -import org.spongepowered.common.accessor.world.entity.animal.WolfAccessor; +import org.spongepowered.common.accessor.world.entity.animal.wolf.WolfAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class WolfData { diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index d1d7da1bff5..1f0bc3e84b0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -39,9 +39,9 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; import net.minecraft.world.entity.animal.sheep.Sheep; +import net.minecraft.world.entity.animal.wolf.Wolf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -64,8 +64,8 @@ import org.spongepowered.common.accessor.entity.passive.AbstractChestedHorseEntityAccessor; import org.spongepowered.common.accessor.network.protocol.game.ServerboundMovePlayerPacketAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; -import org.spongepowered.common.accessor.world.entity.animal.WolfAccessor; import org.spongepowered.common.accessor.world.entity.animal.sheep.SheepAccessor; +import org.spongepowered.common.accessor.world.entity.animal.wolf.WolfAccessor; import org.spongepowered.common.accessor.world.inventory.SlotAccessor; import org.spongepowered.common.bridge.network.protocol.PacketBridge; import org.spongepowered.common.bridge.world.level.block.TrackableBlockBridge; @@ -99,11 +99,11 @@ public static void handleSlotRestore(@Nullable final Player player, final @Nulla if (containerMenu == null || slot.viewedSlot() instanceof Slot) { slot.set(snapshot); } else if (player instanceof ServerPlayer serverPlayer - && containerMenu != player.inventoryMenu && serverPlayer.inventory().containsInventory(slot)) { + && containerMenu != player.inventoryMenu && serverPlayer.inventory().containsInventory(slot)) { final org.spongepowered.api.item.inventory.ItemStack stack = snapshot.asMutable(); slot.set(stack); ((net.minecraft.server.level.ServerPlayer) player).connection.send( - new ClientboundSetPlayerInventoryPacket(((SlotAdapter) slot).getOrdinal(), ItemStackUtil.toNative(stack))); + new ClientboundSetPlayerInventoryPacket(((SlotAdapter) slot).getOrdinal(), ItemStackUtil.toNative(stack))); } else { final int slotNumber = ((SlotAdapter) slot).getOrdinal(); final Slot nmsSlot = containerMenu.getSlot(slotNumber); @@ -156,7 +156,7 @@ public static void validateCapturedTransactions(final int slotId, final Abstract if (slot != null) { final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(slot.getItem()); final SlotTransaction slotTransaction = new SlotTransaction( - ((InventoryAdapter) containerMenu).inventoryAdapter$getSlot(slotId).get(), snapshot, snapshot); + ((InventoryAdapter) containerMenu).inventoryAdapter$getSlot(slotId).get(), snapshot, snapshot); capturedTransactions.add(slotTransaction); } } @@ -236,9 +236,9 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n final BlockPos max = new BlockPos((int) (boundingBox.maxX - 0.001D), (int) (boundingBox.maxY - 0.001D), (int) (boundingBox.maxZ - 0.001D)); final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); if (packetPlayer.level().hasChunksAt(min, max)) { - for(int x = min.getX(); x <= max.getX(); ++x) { - for(int y = min.getY(); y <= max.getY(); ++y) { - for(int z = min.getZ(); z <= max.getZ(); ++z) { + for (int x = min.getX(); x <= max.getX(); ++x) { + for (int y = min.getY(); y <= max.getY(); ++y) { + for (int z = min.getZ(); z <= max.getZ(); ++z) { pos.set(x, y, z); final Block block = packetPlayer.level().getBlockState(pos).getBlock(); if (((TrackableBlockBridge) block).bridge$hasEntityInsideLogic()) { @@ -259,8 +259,8 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n // At the very least make an unknown packet state case. final PacketContext context = packetState.createPhaseContext(PhaseTracker.getWorldInstance(packetPlayer.serverLevel())); context.source(packetPlayer) - .packetPlayer(packetPlayer) - .packet(packetIn); + .packetPlayer(packetPlayer) + .packet(packetIn); if (!PacketPhase.getInstance().isPacketInvalid(packetIn, packetPlayer, packetState)) { PacketPhase.getInstance().populateContext(packetIn, packetPlayer, packetState, context); @@ -282,7 +282,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n * Attempts to find the {@link EntityDataAccessor} that was potentially modified * when a player interacts with an entity. * - * @param stack The item the player is holding + * @param stack The item the player is holding * @param entity The entity * @return A possible data parameter or null if unknown */ diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index ae8d346c17d..52e72093668 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -349,7 +349,7 @@ public EntityArchetype createArchetype() { public HoverEvent asHoverEvent(final UnaryOperator op) { final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); final ResourceLocation entityTypeKey = entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()); - return HoverEvent.showEntity(op.apply(HoverEvent.ShowEntity.of((Key) (Object) entityTypeKey, this.uniqueId(), this.displayName().get()))); + return HoverEvent.showEntity(op.apply(HoverEvent.ShowEntity.showEntity((Key) (Object) entityTypeKey, this.uniqueId(), this.displayName().get()))); } protected Set> api$getVanillaValues() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfMixin_API.java index 79fbc1d7f32..8ca6fbe1b2c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.wolf; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -32,7 +32,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Wolf.class) +@Mixin(net.minecraft.world.entity.animal.wolf.Wolf.class) public abstract class WolfMixin_API extends TamableAnimalMixin_API implements Wolf { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WollfVariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WollfVariantMixin_API.java index 9a9e8013290..b01af954129 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WollfVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.wolf; -import net.minecraft.world.entity.animal.WolfVariant; +import net.minecraft.world.entity.animal.wolf.WolfVariant; import org.spongepowered.asm.mixin.Mixin; @Mixin(WolfVariant.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/WolfMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/wolf/WolfMixin.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/WolfMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/wolf/WolfMixin.java index 6730b52a314..316dc61ce0a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/WolfMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/wolf/WolfMixin.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.wolf; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.NeutralMob; @@ -44,7 +44,7 @@ import org.spongepowered.common.mixin.core.world.entity.AgableMobMixin; -@Mixin(net.minecraft.world.entity.animal.Wolf.class) +@Mixin(net.minecraft.world.entity.animal.wolf.Wolf.class) public abstract class WolfMixin extends AgableMobMixin implements AggressiveEntityBridge { // @formatter:off @@ -65,8 +65,8 @@ public abstract class WolfMixin extends AgableMobMixin implements AggressiveEnti @Redirect(method = "mobInteract", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Wolf;tryToTame(Lnet/minecraft/world/entity/player/Player;)V")) - private void impl$onTame(final net.minecraft.world.entity.animal.Wolf instance, final Player player, final Player $$0, final InteractionHand $$1) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/wolf/Wolf;tryToTame(Lnet/minecraft/world/entity/player/Player;)V")) + private void impl$onTame(final net.minecraft.world.entity.animal.wolf.Wolf instance, final Player player, final Player $$0, final InteractionHand $$1) { try { final ItemStack handStack = player.getItemInHand($$1); handStack.grow(1); @@ -80,14 +80,14 @@ public abstract class WolfMixin extends AgableMobMixin implements AggressiveEnti } @Inject(method = "tryToTame", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Wolf;tame(Lnet/minecraft/world/entity/player/Player;)V"), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/wolf/Wolf;tame(Lnet/minecraft/world/entity/player/Player;)V"), cancellable = true) private void impl$onTame(final Player player, final CallbackInfo ci) { try { PhaseTracker.getInstance().pushCause(player); if (SpongeCommon.post(SpongeEventFactory.createTameEntityEvent(PhaseTracker.getInstance().currentCause(), (Wolf) this))) { - this.shadow$level().broadcastEntityEvent((net.minecraft.world.entity.animal.Wolf) (Object) this, (byte)6); + this.shadow$level().broadcastEntityEvent((net.minecraft.world.entity.animal.wolf.Wolf) (Object) this, (byte)6); ci.cancel(); } } finally { diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 4f406885775..00e820d9e4c 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -138,6 +138,7 @@ "minecraft.world.entity.ai.goal.target.TargetGoalMixin_API", "minecraft.world.entity.ambient.AmbientCreatureMixin_API", "minecraft.world.entity.ambient.BatMixin_API", + "minecraft.world.entity.animal.AbstractCowMixin_API", "minecraft.world.entity.animal.AbstractFishMixin_API", "minecraft.world.entity.animal.AbstractGolemMixin_API", "minecraft.world.entity.animal.AbstractSchoolingFishMixin_API", @@ -148,7 +149,6 @@ "minecraft.world.entity.animal.CatVariantMixin_API", "minecraft.world.entity.animal.ChickenMixin_API", "minecraft.world.entity.animal.CodMixin_API", - "minecraft.world.entity.animal.AbstractCowMixin_API", "minecraft.world.entity.animal.DolphinMixin_API", "minecraft.world.entity.animal.FlyingAnimalMixin_API", "minecraft.world.entity.animal.Fox_VariantMixin_API", @@ -169,7 +169,6 @@ "minecraft.world.entity.animal.Rabbit_VariantMixin_API", "minecraft.world.entity.animal.RabbitMixin_API", "minecraft.world.entity.animal.SalmonMixin_API", - "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.ShoulderRidingEntityMixin_API", "minecraft.world.entity.animal.SnowGolemMixin_API", "minecraft.world.entity.animal.SquidMixin_API", @@ -177,8 +176,6 @@ "minecraft.world.entity.animal.TropicalFishMixin_API", "minecraft.world.entity.animal.TurtleMixin_API", "minecraft.world.entity.animal.WaterAnimalMixin_API", - "minecraft.world.entity.animal.WolfMixin_API", - "minecraft.world.entity.animal.WollfVariantMixin_API", "minecraft.world.entity.animal.allay.AllayMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", @@ -198,7 +195,10 @@ "minecraft.world.entity.animal.horse.TraderLlamaMixin_API", "minecraft.world.entity.animal.horse.VariantMixin_API", "minecraft.world.entity.animal.horse.ZombieHorseMixin_API", + "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.sniffer.SnifferMixin_API", + "minecraft.world.entity.animal.wolf.WolfMixin_API", + "minecraft.world.entity.animal.wolf.WollfVariantMixin_API", "minecraft.world.entity.boss.EnderDragonPartMixin_API", "minecraft.world.entity.boss.enderdragon.EndCrystalMixin_API", "minecraft.world.entity.boss.enderdragon.EnderDragonMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 3ea2c47c83a..34e3cc67e1f 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -145,8 +145,8 @@ "world.entity.animal.OcelotMixin", "world.entity.animal.ParrotMixin", "world.entity.animal.Rabbit_RaidGardenGoalMixin", - "world.entity.animal.WolfMixin", "world.entity.animal.horse.AbstractHorseMixin", + "world.entity.animal.wolf.WolfMixin", "world.entity.boss.enderdragon.EndCrystalMixin", "world.entity.decoration.ArmorStandMixin", "world.entity.decoration.BlockAttachedEntityMixin", diff --git a/testplugins/src/main/java/org/spongepowered/test/portal/PortalTest.java b/testplugins/src/main/java/org/spongepowered/test/portal/PortalTest.java index 4d46920fa4f..8aab6784590 100644 --- a/testplugins/src/main/java/org/spongepowered/test/portal/PortalTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/portal/PortalTest.java @@ -48,12 +48,24 @@ import org.spongepowered.plugin.builtin.jvm.Plugin; import org.spongepowered.test.LoadableModule; +import java.lang.invoke.MethodHandles; import java.util.Optional; @Plugin("portaltest") public final class PortalTest implements LoadableModule { public final static class Holder { + private static final MethodHandles.Lookup HOLDER_LOOKUP = MethodHandles.publicLookup(); + private static final MethodHandles.Lookup PORTAL_TEST_LOOKUP; + + static { + try { + PORTAL_TEST_LOOKUP = MethodHandles.privateLookupIn(PortalTest.class, HOLDER_LOOKUP); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + public final static PortalTestListener INSTANCE = new PortalTestListener(); } @@ -66,7 +78,7 @@ public PortalTest(final PluginContainer pluginContainer) { @Override public void enable(final CommandContext ctx) { - Sponge.eventManager().registerListeners(this.pluginContainer, PortalTest.Holder.INSTANCE); + Sponge.eventManager().registerListeners(this.pluginContainer, PortalTest.Holder.INSTANCE, PortalTest.Holder.PORTAL_TEST_LOOKUP); ctx.cause().first(ServerPlayer.class).ifPresent(player -> { final var portalONE = PortalLogic.builder().addSimplePortal((from, fromPos, entity) -> Optional.of(entity.serverLocation().add(Vector3i.ONE))).build(); player.offer(Keys.PORTAL_LOGIC, portalONE); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 873ed2d1964..a5f47022690 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -29,7 +29,7 @@ import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; -import net.minecraft.world.entity.animal.Wolf; +import net.minecraft.world.entity.animal.wolf.Wolf; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Coerce; @@ -48,13 +48,13 @@ public abstract class LivingEntityMixin_Attack_Impl { } @Redirect(method = "resolvePlayerResponsibleForDamage", - at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;isTame()Z")) + at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/wolf/Wolf;isTame()Z")) private boolean attackImpl$onWolfIsTame(@Coerce final Object instance) { return ((TamableAnimal)instance).isTame(); } @Redirect(method = "resolvePlayerResponsibleForDamage", - at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwnerReference()Lnet/minecraft/world/entity/EntityReference;")) + at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/wolf/Wolf;getOwnerReference()Lnet/minecraft/world/entity/EntityReference;")) private EntityReference attackImpl$onWolfGetOwner(@Coerce final Object instance) { return ((TamableAnimal)instance).getOwnerReference(); } From 3bfedc30ea30716ea71d053b01c6dd65a4f736ea Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 22 Feb 2025 22:13:45 -0800 Subject: [PATCH 199/586] feat: implement Wolf Sound Variant Key A significant change is with Entity related data becoming DataComponent accessible. It's far higher likely to be able to access different pieces generically with the components, provided it's a flat mapping. --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 9 +++ .../provider/entity/EntityDataProviders.java | 67 +++++++++++++++++++ .../common/data/provider/entity/WolfData.java | 19 ++++-- .../wolf/WolfSoundVariantMixin_API.java | 33 +++++++++ src/mixins/resources/mixins.sponge.api.json | 1 + 6 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfSoundVariantMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 71d8ed3d371..19616ee8062 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 71d8ed3d371e8087d69c0f5b9fe1cabf99da5413 +Subproject commit 19616ee80621941f61e50b44ad2a1e8486990fab diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 7fdbe271b1f..daee8adea98 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -247,6 +247,15 @@ public static List registryEntries(final Context context) { Registries.CHICKEN_VARIANT, $-> true, RegistryScope.SERVER + ), + new RegistryEntriesGenerator<>( + "data.type", + "WolfSoundVariants", + "WOLF_SOUND_VARIANT", + context.relativeClass("data.type", "WolfSoundVariant"), + Registries.WOLF_SOUND_VARIANT, + $ -> true, + RegistryScope.SERVER ) ); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 55f80e64fb7..456a124c748 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -24,10 +24,77 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.Entity; +import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.registry.DefaultedRegistryValue; +import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.data.provider.DataProviderRegistratorBuilder; +import java.util.List; + public final class EntityDataProviders extends DataProviderRegistratorBuilder { + public sealed interface KeyComponentProvider { + void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator); + } + + public static List> of(KeyComponentProvider... providers) { + return List.of(providers); + } + + public static KeyComponentProvider holderOf( + Key> apiKey, + DataComponentType> componentType, + ResourceKey> resourceKey + ) { + return new HolderProvider<>(apiKey, componentType, resourceKey); + } + + public static > KeyComponentProvider enumOf( + Key> apiKey, + DataComponentType componentType + ) { + return new EnumProvider<>(apiKey, componentType); + } + + @SuppressWarnings("unchecked") + record HolderProvider( + Key> apiKey, + DataComponentType> componentType, + ResourceKey> resourceKey + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .get(h -> (A) h.get(this.componentType).value()) + .setAnd((h, v) -> { + final var holder = h.level().registryAccess().lookup(this.resourceKey) + .map(r -> r.wrapAsHolder((MC) (Object) v)); + if (holder.isEmpty()) { + return false; + } + h.setComponent(this.componentType, holder.get()); + return true; + }); + } + } + + @SuppressWarnings("unchecked") + record EnumProvider>( + Key> apiKey, + DataComponentType componentType + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .get(h -> (A) h.get(this.componentType)) + .set((h, v) -> h.setComponent(this.componentType, (MC) (Object) v)); + } + } + @Override public void registerProviders() { AbstractArrowData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java b/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java index abc8e690300..f355016aed5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/WolfData.java @@ -24,9 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.animal.wolf.Wolf; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.type.DyeColor; import org.spongepowered.common.accessor.world.entity.animal.wolf.WolfAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -39,9 +40,6 @@ private WolfData() { public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(Wolf.class) - .create(Keys.DYE_COLOR) - .get(h -> (DyeColor) (Object) h.getCollarColor()) - .set((h, v) -> ((WolfAccessor)h).invoker$setCollarColor((net.minecraft.world.item.DyeColor) (Object) v)) .create(Keys.IS_BEGGING_FOR_FOOD) .get(Wolf::isInterested) .set(Wolf::setIsInterested) @@ -54,6 +52,17 @@ public static void register(final DataProviderRegistrator registrator) { accessor.accessor$shakeAnim(0f); accessor.accessor$shakeAnimO(0f); }); + + // @formatter:on + final var wolf = registrator.asMutable(Wolf.class); + final var providers = EntityDataProviders.of( + EntityDataProviders.holderOf(Keys.WOLF_VARIANT, DataComponents.WOLF_VARIANT, Registries.WOLF_VARIANT), + EntityDataProviders.holderOf(Keys.WOLF_SOUND_VARIANT, DataComponents.WOLF_SOUND_VARIANT, Registries.WOLF_SOUND_VARIANT), + EntityDataProviders.enumOf(Keys.DYE_COLOR, DataComponents.WOLF_COLLAR) + ); + for (var provider : providers) { + provider.applyToRegistrator(wolf); + } } - // @formatter:on + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfSoundVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfSoundVariantMixin_API.java new file mode 100644 index 00000000000..ad15d496e5a --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/wolf/WolfSoundVariantMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.wolf; + +import net.minecraft.world.entity.animal.wolf.WolfSoundVariant; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(WolfSoundVariant.class) +public class WolfSoundVariantMixin_API implements org.spongepowered.api.data.type.WolfSoundVariant { + +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 00e820d9e4c..0ee091a6b02 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -198,6 +198,7 @@ "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.sniffer.SnifferMixin_API", "minecraft.world.entity.animal.wolf.WolfMixin_API", + "minecraft.world.entity.animal.wolf.WolfSoundVariantMixin_API", "minecraft.world.entity.animal.wolf.WollfVariantMixin_API", "minecraft.world.entity.boss.EnderDragonPartMixin_API", "minecraft.world.entity.boss.enderdragon.EndCrystalMixin_API", From 7ea90f4ff77081e1c5aa73e93bba19b3f31ffae1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 2 Mar 2025 22:00:10 -0800 Subject: [PATCH 200/586] chore(deps): update to 25w09b Notes: - nbt.Tag is now more consolidated and can be used in better switch statements - ComponentTag is now more directed to use Codecs to parse/store data, we may have to seriously look at migrating to Codecs in prior versions to have better support moving forward. - A seemingly archaic ComponentArgument fix no longer applies per Mojang fixes to command parsing tag components Issues: - Concurrent modifications occur on upgrading data from prior versions with respect to Sponge data specifically - Some odd behavior of the Client sending a movement packet that causes a NoSuchElementException when loading a signleplayer world. This is easily remedied by a mixin on Entity.removeLatestMovementRecordingBatch but more investigation is required whether this is a fundamental bug in Vanilla, or something that Sponge is introducing. --- gradle.properties | 2 +- .../NbtLegacyHoverEventSerializer.java | 12 +- .../common/block/SpongeBlockSnapshot.java | 8 +- .../command/brigadier/SpongeStringReader.java | 3 +- .../spongepowered/common/data/DataUtil.java | 11 +- .../data/persistence/NBTTranslator.java | 191 +++++++++--------- .../item/stack/SignItemStackData.java | 17 +- .../common/entity/EntityUtil.java | 9 +- .../common/entity/SpongeEntityArchetype.java | 17 +- .../common/entity/player/SpongeUserData.java | 34 ++-- .../entity/player/SpongeUserInventory.java | 9 +- ...ckSnapshotDuplicateManipulatorUpdater.java | 8 +- .../spongepowered/common/util/Constants.java | 24 ++- .../common/util/NBTCollectors.java | 122 ----------- .../spongepowered/common/util/NBTStreams.java | 65 ------ .../spongepowered/common/util/NBTUtil.java | 60 ------ .../spongepowered/common/util/VecHelper.java | 27 ++- .../storage/SpongePlayerDataManager.java | 24 ++- .../arguments/ComponentArgumentMixin.java | 54 ----- .../mixin/core/world/entity/EntityMixin.java | 11 +- .../SerializableChunkDataMixin_Tracker.java | 18 +- src/mixins/resources/mixins.sponge.core.json | 1 - .../client/gui/widget/ScrollPanel.java | 32 ++- .../LevelStorageSourceMixin_Vanilla.java | 2 +- 24 files changed, 259 insertions(+), 502 deletions(-) delete mode 100644 src/main/java/org/spongepowered/common/util/NBTCollectors.java delete mode 100644 src/main/java/org/spongepowered/common/util/NBTStreams.java delete mode 100644 src/main/java/org/spongepowered/common/util/NBTUtil.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/ComponentArgumentMixin.java diff --git a/gradle.properties b/gradle.properties index 506aeb1275d..a12a3d79ed5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w08a +minecraftVersion=25w09b recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java index ac4935667e1..41933670532 100644 --- a/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java +++ b/src/main/java/org/spongepowered/common/adventure/NbtLegacyHoverEventSerializer.java @@ -61,10 +61,10 @@ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOE final String rawContent = PlainTextComponentSerializer.plainText().serialize(input); try { final CompoundTag contents = NbtLegacyHoverEventSerializer.SNBT_CODEC.decode(rawContent); - final CompoundTag tag = contents.getCompound(NbtLegacyHoverEventSerializer.ITEM_TAG); + final CompoundTag tag = contents.getCompoundOrEmpty(NbtLegacyHoverEventSerializer.ITEM_TAG); return HoverEvent.ShowItem.showItem( - Key.key(contents.getString(NbtLegacyHoverEventSerializer.ITEM_TYPE)), - contents.contains(NbtLegacyHoverEventSerializer.ITEM_COUNT) ? contents.getByte(NbtLegacyHoverEventSerializer.ITEM_COUNT) : 1, + Key.key(contents.getStringOr(NbtLegacyHoverEventSerializer.ITEM_TYPE, "")), + contents.getByteOr(NbtLegacyHoverEventSerializer.ITEM_COUNT, (byte) 1), tag.isEmpty() ? null : BinaryTagHolder.encode(tag, NbtLegacyHoverEventSerializer.SNBT_CODEC) ); } catch (final CommandSyntaxException ex) { @@ -78,9 +78,9 @@ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOE try { final CompoundTag contents = NbtLegacyHoverEventSerializer.SNBT_CODEC.decode(raw); return HoverEvent.ShowEntity.showEntity( - Key.key(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_TYPE)), - UUID.fromString(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_ID)), - componentCodec.decode(contents.getString(NbtLegacyHoverEventSerializer.ENTITY_NAME)) + Key.key(contents.getStringOr(NbtLegacyHoverEventSerializer.ENTITY_TYPE, "")), + UUID.fromString(contents.getStringOr(NbtLegacyHoverEventSerializer.ENTITY_ID, UUID.randomUUID().toString())), + componentCodec.decode(contents.getStringOr(NbtLegacyHoverEventSerializer.ENTITY_NAME, "")) ); } catch (final CommandSyntaxException ex) { throw new IOException(ex); diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index 6d51712c86f..ccce158b495 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -266,7 +266,11 @@ public Optional createArchetype() { return Optional.empty(); } - final String blockEntityId = this.compound.getString(Constants.Item.BLOCK_ENTITY_ID); + final var blockEntityIDOpt = this.compound.getString(Constants.Item.BLOCK_ENTITY_ID); + if (blockEntityIDOpt.isEmpty()) { + return Optional.empty(); + } + final var blockEntityID = blockEntityIDOpt.get(); final CompoundTag compound = this.compound.copy(); compound.remove(Constants.Sponge.BlockSnapshot.TILE_ENTITY_POSITION_X); @@ -276,7 +280,7 @@ public Optional createArchetype() { return Optional.of(SpongeBlockEntityArchetypeBuilder.pooled() .state(this.state()) - .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).getOptional(ResourceLocation.tryParse(blockEntityId)).orElse(null)) + .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).getOptional(ResourceLocation.tryParse(blockEntityID)).orElse(null)) .blockEntityData(NBTTranslator.INSTANCE.translate(compound)) .build()); } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java index 2191f63abd9..f145d493300 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java @@ -193,7 +193,8 @@ public boolean parseBoolean() throws ArgumentParseException { public String parseNBTString() throws ArgumentParseException { final int startCursor = this.getCursor(); try { - TagParser.parseAsArgument(NbtOps.INSTANCE, this); + TagParser.create(NbtOps.INSTANCE) + .parseAsArgument(this); } catch (final CommandSyntaxException ex) { this.setCursor(startCursor); throw new ArgumentParseException( diff --git a/src/main/java/org/spongepowered/common/data/DataUtil.java b/src/main/java/org/spongepowered/common/data/DataUtil.java index 1ad411087e0..19bcf5a149e 100644 --- a/src/main/java/org/spongepowered/common/data/DataUtil.java +++ b/src/main/java/org/spongepowered/common/data/DataUtil.java @@ -164,11 +164,12 @@ private static void upgradeV2CustomData(final CompoundTag compound, final DataCo // cleanup v2 data on compound if (compound.contains(Constants.Forge.FORGE_DATA)) { - final CompoundTag forgeData = compound.getCompound(Constants.Forge.FORGE_DATA); - forgeData.remove(Constants.Sponge.Data.V2.SPONGE_DATA); - if (forgeData.isEmpty()) { - compound.remove(Constants.Forge.FORGE_DATA); - } + compound.getCompound(Constants.Forge.FORGE_DATA).ifPresent(f -> { + f.remove(Constants.Sponge.Data.V2.SPONGE_DATA); + if (f.isEmpty()) { + compound.remove(Constants.Forge.FORGE_DATA); + } + }); } } diff --git a/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java b/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java index da61d4edfbc..b4dccefe9d1 100644 --- a/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java +++ b/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java @@ -24,8 +24,6 @@ */ package org.spongepowered.common.data.persistence; -import static org.spongepowered.api.data.persistence.DataQuery.of; - import com.google.common.collect.Lists; import io.leangen.geantyref.TypeToken; import net.minecraft.nbt.ByteArrayTag; @@ -41,19 +39,21 @@ import net.minecraft.nbt.ShortTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.data.persistence.DataSerializable; import org.spongepowered.api.data.persistence.DataTranslator; import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.data.persistence.InvalidDataException; -import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.Preconditions; import java.util.List; import java.util.Map; import java.util.Objects; +import static org.spongepowered.api.data.persistence.DataQuery.of; + public final class NBTTranslator implements DataTranslator { public static final NBTTranslator INSTANCE = new NBTTranslator(); @@ -108,33 +108,42 @@ private static Tag getBaseFromObject(final Object value) { } else if (value instanceof String) { return StringTag.valueOf((String) value); } else if (value.getClass().isArray()) { - if (value instanceof byte[]) { - return new ByteArrayTag((byte[]) value); - } else if (value instanceof Byte[]) { - byte[] array = new byte[((Byte[]) value).length]; - int counter = 0; - for (Byte data : (Byte[]) value) { - array[counter++] = data; + switch (value) { + case byte[] bytes -> { + return new ByteArrayTag(bytes); + } + case Byte[] bytes -> { + byte[] array = new byte[bytes.length]; + int counter = 0; + for (Byte data : bytes) { + array[counter++] = data; + } + return new ByteArrayTag(array); + } + case int[] ints -> { + return new IntArrayTag(ints); } - return new ByteArrayTag(array); - } else if (value instanceof int[]) { - return new IntArrayTag((int[]) value); - } else if (value instanceof Integer[]) { - int[] array = new int[((Integer[]) value).length]; - int counter = 0; - for (Integer data : (Integer[]) value) { - array[counter++] = data; + case Integer[] integers -> { + int[] array = new int[integers.length]; + int counter = 0; + for (Integer data : integers) { + array[counter++] = data; + } + return new IntArrayTag(array); + } + case long[] longs -> { + return new LongArrayTag(longs); + } + case Long[] longs -> { + long[] array = new long[longs.length]; + int counter = 0; + for (Long data : longs) { + array[counter++] = data; + } + return new LongArrayTag(array); } - return new IntArrayTag(array); - } else if (value instanceof long[]) { - return new LongArrayTag((long[]) value); - } else if (value instanceof Long[]) { - long[] array = new long[((Long[]) value).length]; - int counter = 0; - for (Long data : (Long[]) value) { - array[counter++] = data; + default -> { } - return new LongArrayTag(array); } } else if (value instanceof List) { ListTag list = new ListTag(); @@ -176,108 +185,106 @@ private static DataContainer getViewFromCompound(CompoundTag compound) { } @SuppressWarnings({"unchecked", "rawtypes"}) - private static void setInternal(Tag base, byte type, DataView view, String key) { + private static void setInternal(Tag base, DataView view, String key) { Objects.requireNonNull(base, "base"); Objects.requireNonNull(view, "view"); Objects.requireNonNull(key, "key"); Preconditions.checkArgument(!key.isEmpty(), "key is empty"); - switch (type) { - case Constants.NBT.TAG_BYTE: + switch (base) { + case ByteTag bt: if (key.contains(NBTTranslator.BOOLEAN_IDENTIFIER)) { - view.set(of(key.replace(NBTTranslator.BOOLEAN_IDENTIFIER, "")), (((ByteTag) base).getAsByte() != 0)); + view.set(of(key.replace(NBTTranslator.BOOLEAN_IDENTIFIER, "")), ((bt.byteValue() != 0))); } else { - view.set(of(key), ((ByteTag) base).getAsByte()); + view.set(of(key), bt.byteValue()); } break; - case Constants.NBT.TAG_SHORT: - view.set(of(key), ((ShortTag) base).getAsShort()); + case ShortTag st: + view.set(of(key), st.shortValue()); break; - case Constants.NBT.TAG_INT: - view.set(of(key), ((IntTag) base).getAsInt()); + case IntTag it: + view.set(of(key), it.intValue()); break; - case Constants.NBT.TAG_LONG: - view.set(of(key), ((LongTag) base).getAsLong()); + case LongTag lt: + view.set(of(key), lt.longValue()); break; - case Constants.NBT.TAG_FLOAT: - view.set(of(key), ((FloatTag) base).getAsFloat()); + case FloatTag ft: + view.set(of(key), ft.floatValue()); break; - case Constants.NBT.TAG_DOUBLE: - view.set(of(key), ((DoubleTag) base).getAsDouble()); + case DoubleTag dt: + view.set(of(key), dt.doubleValue()); break; - case Constants.NBT.TAG_BYTE_ARRAY: - view.set(of(key), ((ByteArrayTag) base).getAsByteArray()); + case ByteArrayTag bat: + view.set(of(key), bat.getAsByteArray()); break; - case Constants.NBT.TAG_STRING: - view.set(of(key), base.getAsString()); + case StringTag st: + view.set(of(key), st.value()); break; - case Constants.NBT.TAG_LIST: + case ListTag lt: ListTag list = (ListTag) base; - byte listType = list.getElementType(); int count = list.size(); List objectList = Lists.newArrayListWithCapacity(count); for (final Tag inbt : list) { - objectList.add(NBTTranslator.fromTagBase(inbt, listType)); + objectList.add(NBTTranslator.fromTagBase(inbt)); } view.set(of(key), objectList); break; - case Constants.NBT.TAG_COMPOUND: + case CompoundTag ct: DataView internalView = view.createView(of(key)); - CompoundTag compound = (CompoundTag) base; - for (String internalKey : compound.getAllKeys()) { - Tag internalBase = compound.get(internalKey); - byte internalType = internalBase.getId(); + for (String internalKey : ct.keySet()) { + @Nullable Tag internalBase = ct.get(internalKey); + if (internalBase == null) { + continue; + } // Basically.... more recursion. // Reasoning: This avoids creating a new DataContainer which would // then be copied in to the owning DataView anyways. We can internally // set the actual data directly to the child view instead. - NBTTranslator.setInternal(internalBase, internalType, internalView, internalKey); + NBTTranslator.setInternal(internalBase, internalView, internalKey); } break; - case Constants.NBT.TAG_INT_ARRAY: - view.set(of(key), ((IntArrayTag) base).getAsIntArray()); + case IntArrayTag iat: + view.set(of(key), iat.getAsIntArray()); break; - case Constants.NBT.TAG_LONG_ARRAY: - view.set(of(key), ((LongArrayTag) base).getAsLongArray()); + case LongArrayTag lat: + view.set(of(key), lat.getAsLongArray()); break; default: - throw new IllegalArgumentException("Unknown NBT type " + type); + throw new IllegalArgumentException("Unknown NBT type " + base.getClass().getName()); } } @SuppressWarnings({"unchecked", "rawtypes"}) - private static Object fromTagBase(Tag base, byte type) { - switch (type) { - case Constants.NBT.TAG_BYTE: - return ((ByteTag) base).getAsByte(); - case Constants.NBT.TAG_SHORT: - return (((ShortTag) base)).getAsShort(); - case Constants.NBT.TAG_INT: - return ((IntTag) base).getAsInt(); - case Constants.NBT.TAG_LONG: - return ((LongTag) base).getAsLong(); - case Constants.NBT.TAG_FLOAT: - return ((FloatTag) base).getAsFloat(); - case Constants.NBT.TAG_DOUBLE: - return ((DoubleTag) base).getAsDouble(); - case Constants.NBT.TAG_BYTE_ARRAY: - return ((ByteArrayTag) base).getAsByteArray(); - case Constants.NBT.TAG_STRING: - return base.getAsString(); - case Constants.NBT.TAG_LIST: - ListTag list = (ListTag) base; - byte listType = list.getElementType(); - int count = list.size(); + private static Object fromTagBase(Tag base) { + switch (base) { + case ByteTag bt: + return bt.byteValue(); + case ShortTag st: + return st.shortValue(); + case IntTag it: + return it.intValue(); + case LongTag lt: + return lt.longValue(); + case FloatTag ft: + return ft.floatValue(); + case DoubleTag dt: + return dt.doubleValue(); + case ByteArrayTag bat: + return bat.getAsByteArray(); + case StringTag st: + return st.value(); + case ListTag lt: + int count = lt.size(); List objectList = Lists.newArrayListWithCapacity(count); - for (Tag inbt : list) { - objectList.add(NBTTranslator.fromTagBase(inbt, listType)); + for (Tag inbt : lt) { + objectList.add(NBTTranslator.fromTagBase(inbt)); } return objectList; - case Constants.NBT.TAG_COMPOUND: - return NBTTranslator.getViewFromCompound((CompoundTag) base); - case Constants.NBT.TAG_INT_ARRAY: - return ((IntArrayTag) base).getAsIntArray(); - case Constants.NBT.TAG_LONG_ARRAY: - return ((LongArrayTag) base).getAsLongArray(); + case CompoundTag ct: + return NBTTranslator.getViewFromCompound(ct); + case IntArrayTag iat: + return iat.getAsIntArray(); + case LongArrayTag lat: + return lat.getAsLongArray(); default : return null; } @@ -308,10 +315,10 @@ public DataContainer translate(CompoundTag obj) throws InvalidDataException { @Override public DataView addTo(CompoundTag compound, DataView container) { - for (String key : compound.getAllKeys()) { + for (String key : compound.keySet()) { Tag base = compound.get(key); byte type = base.getId(); - NBTTranslator.setInternal(base, type, container, key); // gotta love recursion + NBTTranslator.setInternal(base, container, key); // gotta love recursion } return container; } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java index 610c75fac81..fd42a2b5606 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java @@ -31,11 +31,14 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.block.entity.SignText; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; +import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.Constants; +import java.util.Arrays; import java.util.List; public final class SignItemStackData { @@ -53,16 +56,16 @@ public static void register(final DataProviderRegistrator registrator) { if (tag.isEmpty()) { return null; } - final String id = tag.getString(Constants.Item.BLOCK_ENTITY_ID); + + final String id = tag.getStringOr(Constants.Item.BLOCK_ENTITY_ID, ""); if (!id.equalsIgnoreCase(Constants.TileEntity.SIGN)) { return null; } - final GsonComponentSerializer gcs = GsonComponentSerializer.gson(); - final List texts = Lists.newArrayListWithCapacity(4); - for (int i = 0; i < 4; i++) { - texts.add(gcs.deserialize(tag.getString("Text" + (i + 1)))); - } - return texts; + return tag.read("front_text", SignText.DIRECT_CODEC).map(t -> t.getMessages(false)) + .stream() + .flatMap(Arrays::stream) + .map(SpongeAdventure::asAdventure) + .toList(); }) .set((h, v) -> { final GsonComponentSerializer gcs = GsonComponentSerializer.gson(); diff --git a/src/main/java/org/spongepowered/common/entity/EntityUtil.java b/src/main/java/org/spongepowered/common/entity/EntityUtil.java index 502ae8e1109..047ecb6a936 100644 --- a/src/main/java/org/spongepowered/common/entity/EntityUtil.java +++ b/src/main/java/org/spongepowered/common/entity/EntityUtil.java @@ -185,7 +185,7 @@ public static EntityArchetype toArchetype(final SpawnData logic) { final var tag = logic.entityToSpawn(); final var resourceLocation = tag.getString(Constants.Entity.ENTITY_TYPE_ID); final var entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - final var type = entityTypeRegistry.getOptional(ResourceLocation.parse(resourceLocation)) + final var type = resourceLocation.flatMap(location -> entityTypeRegistry.getOptional(ResourceLocation.parse(location))) .map(org.spongepowered.api.entity.EntityType.class::cast) .orElse(EntityTypes.PIG.get()); @@ -211,8 +211,11 @@ public static WeightedTable toWeightedArchetypes(final Weighted for (final var weightedEntity : spawnData.unwrap()) { final CompoundTag nbt = weightedEntity.value().entityToSpawn(); - final String resourceLocation = nbt.getString(Constants.Entity.ENTITY_TYPE_ID); - final var mcType = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getOptional(ResourceLocation.parse(resourceLocation)); + final Optional resourceLocation = nbt.getString(Constants.Entity.ENTITY_TYPE_ID); + if (resourceLocation.isEmpty()) { + continue; + } + final var mcType = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getOptional(ResourceLocation.parse(resourceLocation.get())); final var type = mcType.map(org.spongepowered.api.entity.EntityType.class::cast).orElse(EntityTypes.PIG.get()); final EntityArchetype archetype = SpongeEntityArchetypeBuilder.pooled() diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java index 50251ac1fd8..516b2caeef7 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java @@ -53,6 +53,7 @@ import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.util.Constants; import org.spongepowered.math.vector.Vector3d; +import org.spongepowered.math.vector.Vector3f; import java.util.Objects; import java.util.Optional; @@ -95,14 +96,14 @@ public Optional getPosition() { if (this.position != null) { return Optional.of(this.position); } - if (!this.compound.contains(Constants.Entity.ENTITY_POSITION, Constants.NBT.TAG_LIST)) { + if (!this.compound.contains(Constants.Entity.ENTITY_POSITION)) { return Optional.empty(); } try { - final ListTag pos = this.compound.getList(Constants.Entity.ENTITY_POSITION, Constants.NBT.TAG_DOUBLE); - final double x = pos.getDouble(0); - final double y = pos.getDouble(1); - final double z = pos.getDouble(2); + final ListTag pos = this.compound.getListOrEmpty(Constants.Entity.ENTITY_POSITION); + final double x = pos.getDoubleOr(0, 0); + final double y = pos.getDoubleOr(1, 0); + final double z = pos.getDoubleOr(2, 0); this.position = new Vector3d(x, y, z); return Optional.of(this.position); } catch (final Exception e) { @@ -183,9 +184,9 @@ public EntitySnapshot toSnapshot(final ServerLocation location) { } private Vector3d getRotation() { - final ListTag tag = this.compound.getList("Rotation", 5); - final float rotationYaw = tag.getFloat(0); - final float rotationPitch = tag.getFloat(1); + final var rotation = this.compound.read("Rotation", Constants.Entity.ROTATIONS_CODEC).orElse(Vector3f.ZERO); + final float rotationYaw = rotation.x(); + final float rotationPitch = rotation.z(); return new Vector3d(rotationPitch, rotationYaw, 0); } diff --git a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java index 6fe79650820..8efb348b388 100644 --- a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java +++ b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java @@ -27,10 +27,12 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.mojang.authlib.GameProfile; +import net.minecraft.core.Rotations; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.util.datafix.DataFixers; @@ -86,6 +88,7 @@ import org.spongepowered.common.util.FileUtil; import org.spongepowered.common.util.MissingImplementationException; import org.spongepowered.math.vector.Vector3d; +import org.spongepowered.math.vector.Vector3f; import java.io.IOException; import java.io.InputStream; @@ -154,7 +157,7 @@ public static SpongeUserData create(final GameProfile profile) throws IOExceptio compound = NbtIo.readCompressed(in, NbtAccounter.unlimitedHeap()); } // See PlayerDataAccess - keep this line up to date. - final int version = compound.contains("DataVersion", 3) ? compound.getInt("DataVersion") : -1; + final int version = compound.getIntOr("DataVersion", -1); DataFixTypes.PLAYER.updateToCurrentVersion(DataFixers.getDataFixer(), compound, version); return new SpongeUserData(profile, compound); } catch (final IOException e) { @@ -198,9 +201,10 @@ public DataHolder.Mutable getDataHolder(final boolean markDirty) { private UserInventory loadInventory() { if (this.inventory == null) { this.inventory = new SpongeUserInventory(this); - final ListTag listNBT = this.compound.getList(Constants.Entity.Player.INVENTORY, 10); + final ListTag listNBT = this.compound.getListOrEmpty(Constants.Entity.Player.INVENTORY); this.inventory.readList(listNBT); - this.inventory.currentItem = this.compound.getInt(Constants.Entity.Player.SELECTED_ITEM_SLOT); + this.compound.getInt(Constants.Entity.Player.SELECTED_ITEM_SLOT) + .ifPresent(slotId -> this.inventory.currentItem = slotId); } return (UserInventory) this.inventory; } @@ -208,8 +212,8 @@ private UserInventory loadInventory() { private SpongeUserData loadEnderInventory() { if (this.enderChest == null) { this.enderChest = new SpongeUserInventoryEnderchest(this); - if (this.compound.contains(Constants.Entity.Player.ENDERCHEST_INVENTORY, 9)) { - final ListTag nbttaglist1 = this.compound.getList(Constants.Entity.Player.ENDERCHEST_INVENTORY, 10); + if (this.compound.contains(Constants.Entity.Player.ENDERCHEST_INVENTORY)) { + final ListTag nbttaglist1 = this.compound.getListOrEmpty(Constants.Entity.Player.ENDERCHEST_INVENTORY); this.enderChest.fromTag(nbttaglist1, SpongeCommon.server().registryAccess()); } } @@ -220,16 +224,16 @@ public void readCompound(final CompoundTag compound) { this.reset(); this.compound = compound; - if (!compound.contains(Constants.Sponge.World.WORLD_KEY)) { - this.worldKey = ResourceKey.resolve(compound.getString(Constants.Sponge.World.WORLD_KEY)); - } - final ListTag position = compound.getList(Constants.Entity.ENTITY_POSITION, Constants.NBT.TAG_DOUBLE); - final ListTag rotation = compound.getList(Constants.Entity.ENTITY_ROTATION, Constants.NBT.TAG_FLOAT); - this.x = position.getDouble(0); - this.y = position.getDouble(1); - this.z = position.getDouble(2); - this.yaw = rotation.getFloat(0); - this.pitch = rotation.getFloat(1); + compound.read(Constants.Sponge.World.WORLD_KEY, ResourceLocation.CODEC) + .ifPresent(key -> this.worldKey = (ResourceKey) (Object) key); + + final var rotation = compound.read(Constants.Entity.ENTITY_ROTATION, Rotations.CODEC).orElse(new Rotations(0, 0, 0)); + final var position = compound.read(Constants.Entity.ENTITY_POSITION, Constants.Entity.ROTATIONS_CODEC).orElse(Vector3f.ZERO); + this.x = position.x(); + this.y = position.y(); + this.z = position.z(); + this.yaw = rotation.x(); + this.pitch = rotation.y(); this.isConstructing = true; DataUtil.syncTagToData(this); diff --git a/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java b/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java index 66d5d6c6595..c2181f78502 100644 --- a/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java +++ b/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java @@ -172,11 +172,10 @@ public void readList(final ListTag nbtTagListIn) { this.armorInventory.clear(); this.offHandInventory.clear(); - for (int i = 0; i < nbtTagListIn.size(); ++i) { - final CompoundTag nbttagcompound = nbtTagListIn.getCompound(i); - final int j = nbttagcompound.getByte("Slot") & 255; - final ItemStack itemstack = ItemStack.parse(SpongeCommon.server().registryAccess(), nbttagcompound).get(); - + for (int i = 0; i < nbtTagListIn.size(); i++) { + CompoundTag slotTag = nbtTagListIn.getCompoundOrEmpty(i); + int j = slotTag.getByteOr("Slot", (byte)0) & 255; + ItemStack itemstack = ItemStack.parse(SpongeCommon.server().registryAccess(), slotTag).orElse(ItemStack.EMPTY); if (!itemstack.isEmpty()) { if (j >= 0 && j < this.mainInventory.size()) { this.mainInventory.set(j, itemstack); diff --git a/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java b/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java index b1b9bf09d87..9ad9eb32c29 100644 --- a/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java +++ b/src/main/java/org/spongepowered/common/item/ItemStackSnapshotDuplicateManipulatorUpdater.java @@ -49,12 +49,8 @@ public int outputVersion() { public DataView update(DataView content) { if (content.contains(Constants.Sponge.UNSAFE_NBT)) { CompoundTag compound = NBTTranslator.INSTANCE.translate(content.getView(Constants.Sponge.UNSAFE_NBT).get()); - if (compound.contains(Constants.Sponge.Data.V2.SPONGE_DATA)) { - final CompoundTag spongeCompound = compound.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); - if (spongeCompound.contains(Constants.Sponge.Data.V2.CUSTOM_MANIPULATOR_TAG_LIST)) { - spongeCompound.remove(Constants.Sponge.Data.V2.CUSTOM_MANIPULATOR_TAG_LIST); - } - } + compound.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA) + .ifPresent(c -> c.remove(Constants.Sponge.Data.V2.CUSTOM_MANIPULATOR_TAG_LIST)); Constants.NBT.filterSpongeCustomData(compound); content.remove(Constants.Sponge.UNSAFE_NBT); if (!compound.isEmpty()) { diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index a6627d1b2fc..565158cf652 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -31,9 +31,12 @@ import com.google.common.collect.HashBiMap; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.serialization.Codec; +import net.minecraft.Util; import net.minecraft.commands.arguments.CompoundTagArgument; import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.core.BlockPos; +import net.minecraft.core.Rotations; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.FloatTag; @@ -70,12 +73,15 @@ import org.spongepowered.api.entity.living.player.gamemode.GameModes; import org.spongepowered.api.util.Axis; import org.spongepowered.api.util.Direction; +import org.spongepowered.math.vector.Vector3f; import org.spongepowered.math.vector.Vector3i; import java.net.InetSocketAddress; import java.time.Duration; +import java.time.Instant; import java.util.Comparator; import java.util.EnumSet; +import java.util.List; import java.util.Objects; import java.util.function.Supplier; @@ -200,6 +206,7 @@ public static int blockPosToInt(final BlockPos pos) { public static final class PlayerData { public static final DataQuery PLAYER_DATA_JOIN = of("FirstJoin"); + public static final Codec INSTANT_CODEC = Codec.LONG.xmap(Instant::ofEpochMilli, Instant::toEpochMilli); public static final DataQuery PLAYER_DATA_LAST = of("LastPlayed"); } @@ -736,6 +743,13 @@ public static final class Entity { public static final String ENTITY_POSITION = "Pos"; public static final String ENTITY_DIMENSION = "Dimension"; public static final String ENTITY_ROTATION = "Rotation"; + public static final Codec ROTATIONS_CODEC = Codec.FLOAT + .listOf() + .comapFlatMap( + $$0 -> Util.fixedSize($$0, 2).map($$0x -> new Vector3f($$0x.get(0), $$0x.get(1), 0)), + $$0 -> List.of($$0.x(), $$0.y()) + ); + public static final String ENTITY_UUID = "UUID"; // Entities public static final DataQuery CLASS = of("EntityClass"); @@ -1021,22 +1035,22 @@ public static final class NBT { public static final byte TAG_ANY_NUMERIC = 99; public static CompoundTag filterSpongeCustomData(final CompoundTag rootCompound) { - if (rootCompound.contains(Forge.FORGE_DATA, NBT.TAG_COMPOUND)) { - final CompoundTag forgeCompound = rootCompound.getCompound(Forge.FORGE_DATA); - if (forgeCompound.contains(Sponge.Data.V2.SPONGE_DATA, NBT.TAG_COMPOUND)) { + if (rootCompound.contains(Forge.FORGE_DATA)) { + final CompoundTag forgeCompound = rootCompound.getCompoundOrEmpty(Forge.FORGE_DATA); + if (forgeCompound.contains(Sponge.Data.V2.SPONGE_DATA)) { NBT.cleanseInnerCompound(forgeCompound); } if (forgeCompound.isEmpty()) { rootCompound.remove(Forge.FORGE_DATA); } - } else if (rootCompound.contains(Sponge.Data.V2.SPONGE_DATA, NBT.TAG_COMPOUND)) { + } else if (rootCompound.contains(Sponge.Data.V2.SPONGE_DATA)) { NBT.cleanseInnerCompound(rootCompound); } return rootCompound; } private static void cleanseInnerCompound(final CompoundTag compound) { - final CompoundTag inner = compound.getCompound(Sponge.Data.V2.SPONGE_DATA); + final CompoundTag inner = compound.getCompoundOrEmpty(Sponge.Data.V2.SPONGE_DATA); if (inner.isEmpty()) { compound.remove(Sponge.Data.V2.SPONGE_DATA); } diff --git a/src/main/java/org/spongepowered/common/util/NBTCollectors.java b/src/main/java/org/spongepowered/common/util/NBTCollectors.java deleted file mode 100644 index 3c8eeda6673..00000000000 --- a/src/main/java/org/spongepowered/common/util/NBTCollectors.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.util; - -import net.minecraft.nbt.ByteTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.FloatTag; -import net.minecraft.nbt.IntTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.LongTag; -import net.minecraft.nbt.ShortTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collector; - -public final class NBTCollectors { - - private static final Collector TO_TAG_LIST = NBTCollectors.toTagList(value -> value); - private static final Collector TO_LONG_TAG_LIST = NBTCollectors.toTagList(LongTag::valueOf); - private static final Collector TO_INT_TAG_LIST = NBTCollectors.toTagList(IntTag::valueOf); - private static final Collector TO_BYTE_TAG_LIST = NBTCollectors.toTagList(ByteTag::valueOf); - private static final Collector TO_SHORT_TAG_LIST = NBTCollectors.toTagList(ShortTag::valueOf); - private static final Collector TO_BOOLEAN_TAG_LIST = NBTCollectors.toTagList(ByteTag::valueOf); - private static final Collector TO_DOUBLE_TAG_LIST = NBTCollectors.toTagList(DoubleTag::valueOf); - private static final Collector TO_FLOAT_TAG_LIST = NBTCollectors.toTagList(FloatTag::valueOf); - private static final Collector TO_STRING_TAG_LIST = NBTCollectors.toTagList(StringTag::valueOf); - - private static final Collector> TO_STRING_LIST = NBTCollectors.toList(Tag::getAsString); - - private static Collector, List> toList0(final Function toValueFunction) { - return Collector.of(ArrayList::new, - (list, value) -> list.add(toValueFunction.apply(value)), - (first, second) -> { - first.addAll(second); - return first; - }, - list -> list); - } - - public static Collector> toList(final Function toValueFunction) { - return NBTCollectors.toList0(toValueFunction); - } - - public static Collector toTagList(final Function toTagFunction) { - return Collector.of(ListTag::new, - (list, value) -> list.add(toTagFunction.apply(value)), - (first, second) -> { - first.addAll(second); - return first; - }, - list -> list); - } - - public static Collector toTagList() { - return NBTCollectors.TO_TAG_LIST; - } - - public static Collector toBooleanTagList() { - return NBTCollectors.TO_BOOLEAN_TAG_LIST; - } - - public static Collector toByteTagList() { - return NBTCollectors.TO_BYTE_TAG_LIST; - } - - public static Collector toShortTagList() { - return NBTCollectors.TO_SHORT_TAG_LIST; - } - - public static Collector toIntTagList() { - return NBTCollectors.TO_INT_TAG_LIST; - } - - public static Collector toLongTagList() { - return NBTCollectors.TO_LONG_TAG_LIST; - } - - public static Collector toFloatTagList() { - return NBTCollectors.TO_FLOAT_TAG_LIST; - } - - public static Collector toDoubleTagList() { - return NBTCollectors.TO_DOUBLE_TAG_LIST; - } - - public static Collector toStringTagList() { - return NBTCollectors.TO_STRING_TAG_LIST; - } - - public static Collector> toStringList() { - return NBTCollectors.TO_STRING_LIST; - } - - private NBTCollectors() { - } -} diff --git a/src/main/java/org/spongepowered/common/util/NBTStreams.java b/src/main/java/org/spongepowered/common/util/NBTStreams.java deleted file mode 100644 index 062d1e64bea..00000000000 --- a/src/main/java/org/spongepowered/common/util/NBTStreams.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.util; - -import com.google.common.collect.Streams; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; - -import java.util.stream.IntStream; -import java.util.stream.LongStream; -import java.util.stream.Stream; - -public final class NBTStreams { - - public static Stream toCompounds(final Iterable iterable) { - return Streams.stream(iterable) - .filter(tag -> tag instanceof CompoundTag) - .map(tag -> (CompoundTag) tag); - } - - public static Stream toStrings(final Iterable iterable) { - return Streams.stream(iterable) - .filter(tag -> tag instanceof StringTag) - .map(Tag::getAsString); - } - - public static LongStream toLongs(final Iterable iterable) { - return Streams.stream(iterable) - .filter(tag -> tag instanceof NumericTag) - .mapToLong(tag -> ((NumericTag) tag).getAsLong()); - } - - public static IntStream toInts(final Iterable iterable) { - return Streams.stream(iterable) - .filter(tag -> tag instanceof NumericTag) - .mapToInt(tag -> ((NumericTag) tag).getAsInt()); - } - - private NBTStreams() { - } -} diff --git a/src/main/java/org/spongepowered/common/util/NBTUtil.java b/src/main/java/org/spongepowered/common/util/NBTUtil.java deleted file mode 100644 index 946fb5148f9..00000000000 --- a/src/main/java/org/spongepowered/common/util/NBTUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.util; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.Tag; -import org.checkerframework.checker.nullness.qual.Nullable; - -public final class NBTUtil { - - public static @Nullable Boolean getNullableBoolean(final CompoundTag compound, final String key) { - final Tag tag = compound.get(key); - if (tag instanceof NumericTag) { - return ((NumericTag) tag).getAsByte() != 0; - } - return null; - } - - public static @Nullable CompoundTag getNullableCompound(final CompoundTag compound, final String key) { - if (!compound.contains(key, Constants.NBT.TAG_COMPOUND)) { - return null; - } - return compound.getCompound(key); - } - - public static CompoundTag getOrCreateCompound(final CompoundTag compound, final String key) { - if (!compound.contains(key, Constants.NBT.TAG_COMPOUND)) { - final CompoundTag child = new CompoundTag(); - compound.put(key, child); - return child; - } - return compound.getCompound(key); - } - - private NBTUtil() { - } -} diff --git a/src/main/java/org/spongepowered/common/util/VecHelper.java b/src/main/java/org/spongepowered/common/util/VecHelper.java index 054b4a97dcd..e484d39761d 100644 --- a/src/main/java/org/spongepowered/common/util/VecHelper.java +++ b/src/main/java/org/spongepowered/common/util/VecHelper.java @@ -24,6 +24,9 @@ */ package org.spongepowered.common.util; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; import net.minecraft.core.Rotations; import net.minecraft.core.Vec3i; @@ -34,10 +37,28 @@ import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.common.world.server.SpongeServerLocation; import org.spongepowered.math.vector.Vector2i; +import org.spongepowered.math.vector.Vector3d; +import org.spongepowered.math.vector.Vector3f; import org.spongepowered.math.vector.Vector3i; public final class VecHelper { + public static final MapCodec VECTOR3F_CODEC = RecordCodecBuilder.mapCodec(i -> + i.group( + Codec.FLOAT.fieldOf("x").forGetter(Vector3f::x), + Codec.FLOAT.fieldOf("y").forGetter(Vector3f::y), + Codec.FLOAT.fieldOf("z").forGetter(Vector3f::z) + ).apply(i, Vector3f::new) + ); + + public static final MapCodec VECTOR3D_CODEC = RecordCodecBuilder.mapCodec(i -> + i.group( + Codec.DOUBLE.fieldOf("x").forGetter(Vector3d::x), + Codec.DOUBLE.fieldOf("y").forGetter(Vector3d::y), + Codec.DOUBLE.fieldOf("z").forGetter(Vector3d::z) + ).apply(i, Vector3d::new) + ); + // === Flow Vector3d --> BlockPos === public static BlockPos toBlockPos(final org.spongepowered.math.vector.Vector3d vector) { @@ -216,14 +237,12 @@ public static AABB toSpongeAABB(final net.minecraft.world.phys.AABB box) { public static CompoundTag toCompound(final org.spongepowered.math.vector.Vector3d vector) { final CompoundTag compound = new CompoundTag(); - compound.putDouble("x", vector.x()); - compound.putDouble("y", vector.y()); - compound.putDouble("z", vector.z()); + compound.store(VECTOR3D_CODEC, vector); return compound; } public static org.spongepowered.math.vector.Vector3d fromCompound(final CompoundTag compound) { - return new org.spongepowered.math.vector.Vector3d(compound.getDouble("x"), compound.getDouble("y"), compound.getDouble("z")); + return compound.read(VECTOR3D_CODEC).orElse(Vector3d.ZERO); } private VecHelper() { diff --git a/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java b/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java index 4e23d96b9ee..7202b5871de 100644 --- a/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java +++ b/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java @@ -58,24 +58,28 @@ public void readLegacyPlayerData(final ServerPlayer playerEntity, final Compound } Instant lastPlayed = creation; // first try to migrate bukkit join data stuff - if (compound.contains(Constants.Bukkit.BUKKIT, Constants.NBT.TAG_COMPOUND)) { - final CompoundTag bukkitCompound = compound.getCompound(Constants.Bukkit.BUKKIT); - creation = Instant.ofEpochMilli(bukkitCompound.getLong(Constants.Bukkit.BUKKIT_FIRST_PLAYED)); - lastPlayed = Instant.ofEpochMilli(bukkitCompound.getLong(Constants.Bukkit.BUKKIT_LAST_PLAYED)); + if (compound.contains(Constants.Bukkit.BUKKIT)) { + final CompoundTag bukkitCompound = compound.getCompoundOrEmpty(Constants.Bukkit.BUKKIT); + creation = Instant.ofEpochMilli(bukkitCompound.getLongOr(Constants.Bukkit.BUKKIT_FIRST_PLAYED, 0)); + lastPlayed = Instant.ofEpochMilli(bukkitCompound.getLongOr(Constants.Bukkit.BUKKIT_LAST_PLAYED, 0)); } // migrate canary join data - if (compound.contains(Constants.Canary.ROOT, Constants.NBT.TAG_COMPOUND)) { - final CompoundTag canaryCompound = compound.getCompound(Constants.Canary.ROOT); - creation = Instant.ofEpochMilli(canaryCompound.getLong(Constants.Canary.FIRST_JOINED)); - lastPlayed = Instant.ofEpochMilli(canaryCompound.getLong(Constants.Canary.LAST_JOINED)); + if (compound.contains(Constants.Canary.ROOT)) { + final CompoundTag canaryCompound = compound.getCompoundOrEmpty(Constants.Canary.ROOT); + creation = Instant.ofEpochMilli(canaryCompound.getLongOr(Constants.Canary.FIRST_JOINED, 0)); + lastPlayed = Instant.ofEpochMilli(canaryCompound.getLongOr(Constants.Canary.LAST_JOINED, 0)); } final Path playerFile = this.playersDirectory.resolve(playerEntity.uniqueId() + ".dat"); if (Files.isReadable(playerFile)) { final CompoundTag playerFileCompound; try (final InputStream stream = Files.newInputStream(playerFile)) { playerFileCompound = NbtIo.readCompressed(stream, NbtAccounter.unlimitedHeap()); - creation = Instant.ofEpochMilli(playerFileCompound.getLong(Constants.Sponge.PlayerData.PLAYER_DATA_JOIN.toString())); - lastPlayed = Instant.ofEpochMilli(playerFileCompound.getLong(Constants.Sponge.PlayerData.PLAYER_DATA_LAST.toString())); + creation = playerFileCompound + .read(Constants.Sponge.PlayerData.PLAYER_DATA_JOIN.toString(), Constants.Sponge.PlayerData.INSTANT_CODEC) + .orElse(Instant.now()); + lastPlayed = playerFileCompound + .read(Constants.Sponge.PlayerData.PLAYER_DATA_LAST.toString(), Constants.Sponge.PlayerData.INSTANT_CODEC) + .orElse(Instant.now()); } catch (final Exception e) { throw new RuntimeException("Failed to decompress playerdata for playerfile " + playerFile, e); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/ComponentArgumentMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/ComponentArgumentMixin.java deleted file mode 100644 index e441118005d..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/ComponentArgumentMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.commands.arguments; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.StringReader; -import net.minecraft.commands.arguments.ComponentArgument; -import net.minecraft.network.chat.Component; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ComponentArgument.class) -public abstract class ComponentArgumentMixin { - - @Inject(method = "parse", at = @At("RETURN")) - private void impl$correctForOffByOneErrorInReaderPosition(final StringReader var1, - final CallbackInfoReturnable cir) { - // If we're able to continue reading, the problem we have is that - // the JSON reader has advanced as far as the next element instead. - // We need to step back one, but only if: - // * There is more reading to do - // * The next character is not the argument separator - // * The preceding character is the argument separator - if (var1.canRead() && var1.peek() != CommandDispatcher.ARGUMENT_SEPARATOR_CHAR - && var1.peek(-1) == CommandDispatcher.ARGUMENT_SEPARATOR_CHAR) { - var1.setCursor(var1.getCursor() - 1); - } - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index ecf7c462114..e2dc0df2ed2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -715,22 +715,23 @@ public void stopRiding() { } } - @Redirect( - method = "applyEffectsFromBlocks(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;)V", + @WrapOperation( + method = "applyEffectsFromBlocks(Ljava/util/List;)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;stepOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/Entity;)V" ) ) - private void impl$onStepOnCollide(final Block block, final Level world, final BlockPos pos, final BlockState state, final Entity entity) { + private void impl$onStepOnCollide(final Block block, final Level world, final BlockPos pos, final BlockState state, + final Entity entity, Operation original) { if (!ShouldFire.COLLIDE_BLOCK_EVENT_STEP_ON || world.isClientSide) { - block.stepOn(world, pos, state, entity); + original.call(block, world, pos, state, entity); return; } final org.spongepowered.api.util.Direction dir = org.spongepowered.api.util.Direction.NONE; if (!SpongeCommonEventFactory.handleCollideBlockEvent(block, world, pos, state, entity, dir, SpongeCommonEventFactory.CollisionType.STEP_ON)) { - block.stepOn(world, pos, state, entity); + original.call(block, world, pos, state, entity); this.impl$lastCollidedBlockPos = pos; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java index 50e2973ce6d..dad3af2cb99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; @Mixin(SerializableChunkData.class) @@ -84,7 +85,7 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable @Override public void bridge$parseTrackerData(final CompoundTag fullTag) { - final CompoundTag spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); + final Optional spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); this.tracker$intPlayerPos = new HashMap<>(); this.tracker$shortPlayerPos = new HashMap<>(); @@ -92,22 +93,25 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable return; } - final ListTag list = spongeData.getList(Constants.Sponge.SPONGE_BLOCK_POS_TABLE, 10); - for (final Tag tag : list) { + final Optional list = spongeData.get().getList(Constants.Sponge.SPONGE_BLOCK_POS_TABLE); + if (list.isEmpty()) { + return; + } + for (final Tag tag : list.get()) { final PlayerTracker tracker = new PlayerTracker(); final CompoundTag data = (CompoundTag) tag; final boolean isShortPos = data.contains("pos"); if (data.contains("owner")) { - tracker.creatorindex = data.getInt("owner"); + tracker.creatorindex = data.getIntOr("owner", 0); } if (data.contains("notifier")) { - tracker.notifierIndex = data.getInt("notifier"); + tracker.notifierIndex = data.getIntOr("notifier", 0); } if (tracker.notifierIndex != -1 || tracker.creatorindex != -1) { if (isShortPos) { - this.tracker$shortPlayerPos.put(data.getShort("pos"), tracker); + this.tracker$shortPlayerPos.put(data.getShortOr("pos", (short) 0), tracker); } else { - this.tracker$intPlayerPos.put(data.getInt("ipos"), tracker); + this.tracker$intPlayerPos.put(data.getIntOr("ipos", 0), tracker); } } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 7503cc4e932..f838ca73fa6 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -23,7 +23,6 @@ "commands.CommandsMixin", "commands.CommandSourceMixin", "commands.CommandSourceStackMixin", - "commands.arguments.ComponentArgumentMixin", "commands.arguments.DimensionArgumentMixin", "commands.arguments.selector.EntitySelectorParserMixin", "commands.execution.tasks.ExecuteCommandMixin", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index f7583e381c1..b63f267d356 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -28,14 +28,12 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.screens.Screen; import java.util.Collections; import java.util.List; @@ -189,7 +187,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, (int) (this.height * scale)); // TODO fix me RenderSystem.setShader(GameRenderer::getPositionTexColorShader); - RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND); +// RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); final float texScale = 32.0F; BufferBuilder worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); @@ -202,15 +200,15 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.left, this.top, 0.0f).setUv(this.left / texScale, (this.top + (int) this.scrollDistance) / texScale) .setColor(0x20, 0x20, 0x20, 0xFF); - VertexBuffer $$3 = RenderSystem.getQuadVertices(); - $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); +// VertexBuffer $$3 = RenderSystem.getQuadVertices(); +// $$3.upload(worldr.buildOrThrow()); +// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); final int baseY = this.top + this.border - (int) this.scrollDistance; this.drawPanel(stack, this.right, baseY, tess, mouseX, mouseY); - RenderSystem.disableDepthTest(); +// RenderSystem.disableDepthTest(); final int extraHeight = (this.getContentHeight() + this.border) - this.height; if (extraHeight > 0) { @@ -228,30 +226,30 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, worldr.addVertex(this.barLeft + this.barWidth, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); worldr.addVertex(this.barLeft, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); - $$3 = RenderSystem.getQuadVertices(); - $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); +// $$3 = RenderSystem.getQuadVertices(); +// $$3.upload(worldr.buildOrThrow()); +// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); worldr =tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft + this.barWidth, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); - $$3 = RenderSystem.getQuadVertices(); - $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); +// $$3 = RenderSystem.getQuadVertices(); +// $$3.upload(worldr.buildOrThrow()); +// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); worldr.addVertex(this.barLeft, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft + this.barWidth - 1, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft + this.barWidth - 1, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); - $$3 = RenderSystem.getQuadVertices(); - $$3.upload(worldr.buildOrThrow()); - $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); +// $$3 = RenderSystem.getQuadVertices(); +// $$3.upload(worldr.buildOrThrow()); +// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); } // RenderSystem.enableTexture(); - RenderSystem.disableBlend(); +// RenderSystem.disableBlend(); RenderSystem.disableScissor(); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java index 7e8fd3b2cd5..532d07cbe46 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java @@ -48,7 +48,7 @@ public abstract class LevelStorageSourceMixin_Vanilla { method = "readLevelDataTagFixed", at = @At( value = "INVOKE", - target = "Lnet/minecraft/nbt/CompoundTag;getCompound(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;", + target = "Lnet/minecraft/nbt/CompoundTag;getCompoundOrEmpty(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;", ordinal = 0 ) ) From 15d146aec4b702c709966dc413c242e2aa44dbc9 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 5 Mar 2025 21:39:40 +0100 Subject: [PATCH 201/586] Update verification metadata --- gradle/verification-metadata.xml | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 429d6ece095..c214a468eef 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -367,6 +367,14 @@ + + + + + + + + @@ -427,6 +435,14 @@ + + + + + + + + @@ -3038,6 +3054,14 @@ + + + + + + + + @@ -4079,6 +4103,14 @@ + + + + + + + + @@ -4089,6 +4121,11 @@ + + + + + From b039b78fecee8e13fe1f77a3ee4b32a0e7624f39 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 19:07:59 -0800 Subject: [PATCH 202/586] fix(crash): avoid a possible movement-fix crash With the changes to eneity teleports, Mojang now attempts to clear any recorded movement packets, but this can lead to a NoSuchElementException being thrown at the server which crashes the game entirely. --- .../common/mixin/core/world/entity/EntityMixin.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index e2dc0df2ed2..7a8d9889fc8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -186,8 +186,9 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow @javax.annotation.Nullable public PortalProcessor portalProcess; @Shadow public abstract boolean save(final CompoundTag $$0); @Shadow public abstract Level level(); - // @formatter:on + @Shadow @Final private List movementThisTick; + // @formatter:on private boolean impl$isConstructing = true; @@ -734,7 +735,16 @@ public void stopRiding() { original.call(block, world, pos, state, entity); this.impl$lastCollidedBlockPos = pos; } + } + @Inject(method = "removeLatestMovementRecordingBatch", at = @At("HEAD"), cancellable = true) + private void impl$catchEmptyRemoval(CallbackInfo ci) { + // This prevents a no element exception leading to a crash. It is highly possible that + // this is a bug, but whether it's from Vanilla or Sponge, I'm not certain. It's also possible + // this can be triggered by a rogue client missending packets, leading to a player being + if (this.movementThisTick.isEmpty()) { + ci.cancel(); + } } @WrapOperation(method = "lambda$checkInsideBlocks$0", From ffd2fa443fe769d82a3dbd5d86fea082f0c4aba9 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 19:09:46 -0800 Subject: [PATCH 203/586] chore(nits): run spotlessApply --- .../spongepowered/common/data/persistence/NBTTranslator.java | 4 ++-- .../common/data/provider/item/stack/SignItemStackData.java | 2 -- src/main/java/org/spongepowered/common/util/Constants.java | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java b/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java index b4dccefe9d1..51b811311ed 100644 --- a/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java +++ b/src/main/java/org/spongepowered/common/data/persistence/NBTTranslator.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.data.persistence; +import static org.spongepowered.api.data.persistence.DataQuery.of; + import com.google.common.collect.Lists; import io.leangen.geantyref.TypeToken; import net.minecraft.nbt.ByteArrayTag; @@ -52,8 +54,6 @@ import java.util.Map; import java.util.Objects; -import static org.spongepowered.api.data.persistence.DataQuery.of; - public final class NBTTranslator implements DataTranslator { public static final NBTTranslator INSTANCE = new NBTTranslator(); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java index fd42a2b5606..552e3c6c9c7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.data.provider.item.stack; -import com.google.common.collect.Lists; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.core.component.DataComponents; @@ -39,7 +38,6 @@ import org.spongepowered.common.util.Constants; import java.util.Arrays; -import java.util.List; public final class SignItemStackData { diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index 565158cf652..db3dbb7b1f8 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -36,7 +36,6 @@ import net.minecraft.commands.arguments.CompoundTagArgument; import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.core.BlockPos; -import net.minecraft.core.Rotations; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.FloatTag; From 034aad33f53b596aa7352a100cae246709d8540f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 19:58:57 -0800 Subject: [PATCH 204/586] feat(content): update api for new features from 25w09a --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index a261bc4cca8..e0c1915dee7 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a261bc4cca8bce190f07e57914c1ee3a0568ed15 +Subproject commit e0c1915dee7981ae5ee0a0e5e7efb50319b366a9 From 99ebdc64e64e0d25fc64060e7cc86fece7fed36a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 20:48:16 -0800 Subject: [PATCH 205/586] feat(content): update to 25w10a --- gradle.properties | 2 +- .../mixin/core/nbt/CompoundTagMixin.java | 12 ++++----- .../core/world/level/block/TntBlockMixin.java | 26 +++++++++++-------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/gradle.properties b/gradle.properties index a12a3d79ed5..3248e710c96 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w09b +minecraftVersion=25w10a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java index b6e81cd0e8d..e0e06c41ec4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java @@ -25,7 +25,6 @@ package org.spongepowered.common.mixin.core.nbt; import com.google.common.collect.Maps; -import net.minecraft.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import org.apache.logging.log4j.Level; @@ -39,7 +38,7 @@ import org.spongepowered.common.util.PrettyPrinter; import java.util.Map; -import java.util.function.Function; +import java.util.function.BiConsumer; /** * @author Zidane - Minecraft 1.14.4 @@ -59,11 +58,11 @@ public abstract class CompoundTagMixin { @Redirect(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", - target ="Lnet/minecraft/Util;mapValues(Ljava/util/Map;Ljava/util/function/Function;)Ljava/util/Map;")) - private Map impl$checkForOverflowOnCopy(Map fromMap, Function function) { - return Util.mapValues(fromMap, (tag) -> { + target ="Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V")) + private void impl$checkForOverflowOnCopy(Map instance, BiConsumer consumer) { + instance.forEach((k, v) -> { try { - return tag == null ? null : tag.copy(); + consumer.accept(k, v); } catch (StackOverflowError e) { final PrettyPrinter printer = new PrettyPrinter(60) .add("StackOverflow from trying to copy this compound") @@ -90,7 +89,6 @@ public abstract class CompoundTagMixin { } printer.add(); printer.log(SpongeCommon.logger(), Level.ERROR); - return null; } }); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java index a2c56a157c9..f221c45e402 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/TntBlockMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.level.block; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; @@ -32,16 +33,17 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.TntBlock; import net.minecraft.world.level.block.state.BlockState; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; import org.spongepowered.common.bridge.world.entity.item.PrimedTntBridge; @@ -52,21 +54,23 @@ @Mixin(TntBlock.class) public abstract class TntBlockMixin extends BlockMixin { - private boolean primeCancelled; + @Unique + private boolean impl$primeCancelled; + @Unique private boolean impl$onRemove(Level world, BlockPos pos, boolean isMoving) { - final boolean removed = !this.primeCancelled && world.removeBlock(pos, isMoving); - this.primeCancelled = false; + final boolean removed = !this.impl$primeCancelled && world.removeBlock(pos, isMoving); + this.impl$primeCancelled = false; return removed; } - @Inject(method = "prime(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V", + @Inject(method = "prime(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), - locals = LocalCapture.CAPTURE_FAILSOFT, cancellable = true ) - private static void impl$ThrowPrimeAndMaybeCancel(final Level worldIn, final BlockPos pos, - @Nullable final LivingEntity igniter, final CallbackInfo ci, final PrimedTnt tnt) { + private static void impl$ThrowPrimeAndMaybeCancel( + final Level level, final BlockPos pos, final LivingEntity igniter, final CallbackInfoReturnable cir, + @Local final PrimedTnt tnt) { ((PrimedTntBridge) tnt).bridge$setDetonator(igniter); if (ShouldFire.PRIME_EXPLOSIVE_EVENT_PRE) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { @@ -74,7 +78,7 @@ public abstract class TntBlockMixin extends BlockMixin { frame.addContext(EventContextKeys.IGNITER, (Living) igniter); } if (!((FusedExplosiveBridge) tnt).bridge$shouldPrime()) { - ci.cancel(); + cir.setReturnValue(false); } } } @@ -115,8 +119,8 @@ public abstract class TntBlockMixin extends BlockMixin { target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) private boolean impl$removeActivated(final Level world, final BlockPos pos, final BlockState state, final int flag) { // Called when player manually ignites TNT - final boolean removed = !this.primeCancelled && world.setBlock(pos, state, flag); - this.primeCancelled = false; + final boolean removed = !this.impl$primeCancelled && world.setBlock(pos, state, flag); + this.impl$primeCancelled = false; return removed; } From 6c0cf290d43a11febe025f9129d04fee695de03e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 21:09:45 -0800 Subject: [PATCH 206/586] feat(content): update api for content from 25w10a --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index e0c1915dee7..8f4878d6289 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit e0c1915dee7981ae5ee0a0e5e7efb50319b366a9 +Subproject commit 8f4878d62894767efc137aa757352489bb5e83f2 From 7af5f6f68763db9e50aed099ffa34ac15252a181 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 24 Oct 2024 00:43:58 -0700 Subject: [PATCH 207/586] feat: add salmon size data Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 8 ++++ .../provider/entity/EntityDataProviders.java | 1 + .../data/provider/entity/SalmonData.java | 46 +++++++++++++++++++ .../loader/VanillaRegistryLoader.java | 2 + .../entity/animal/SalmonVariantMixin_API.java | 34 ++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 1 + 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index cc2de8fa824..381f7587735 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit cc2de8fa8244eb3ff5192f4500e72aa2cf246774 +Subproject commit 381f7587735a7c7a93437593e3969010cca552e8 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 5428c042cd6..9bad8f1e060 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -34,6 +34,7 @@ import net.minecraft.world.entity.animal.Panda; import net.minecraft.world.entity.animal.Parrot; import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.Salmon; import net.minecraft.world.entity.animal.TropicalFish; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.animal.horse.Markings; @@ -170,6 +171,13 @@ public static List enumEntries(final Context context) { EquipmentSlot.class, "getSerializedName", "sponge" + ), + new EnumEntriesValidator<>( + "data.type", + "SalmonSizes", + Salmon.Variant.class, + "getSerializedName", + "sponge" ) ); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 55f80e64fb7..0589389a7a2 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -103,6 +103,7 @@ public void registerProviders() { PufferfishData.register(this.registrator); RabbitData.register(this.registrator); RavagerData.register(this.registrator); + SalmonData.register(this.registrator); ServerPlayerData.register(this.registrator); SheepData.register(this.registrator); ShulkerBulletData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java new file mode 100644 index 00000000000..9dc5a937a6c --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java @@ -0,0 +1,46 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.animal.Salmon; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.SalmonSize; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public final class SalmonData { + + private SalmonData() {} + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(Salmon.class) + .create(Keys.SALMON_SIZE) + .get(h -> (SalmonSize) (Object) h.getVariant()) + .set((h, v) -> h.setVariant((Salmon.Variant) (Object) v)) + ; + } + // @formatter:on +} diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 78283b71cef..355e0092d1c 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -44,6 +44,7 @@ import net.minecraft.world.entity.animal.Panda; import net.minecraft.world.entity.animal.Parrot; import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.Salmon; import net.minecraft.world.entity.animal.TropicalFish; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.animal.horse.Markings; @@ -210,6 +211,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.WIRE_ATTACHMENT_TYPE, RedstoneSide.values()); this.automaticName(RegistryTypes.ADVANCEMENT_TYPE, AdvancementType.values()); this.automaticName(RegistryTypes.TROPICAL_FISH_SHAPE, TropicalFish.Pattern.values()); + this.automaticName(RegistryTypes.SALMON_SIZE, Salmon.Variant.values()); this.automaticName(RegistryTypes.HEIGHT_TYPE, Heightmap.Types.values()); this.automaticName(RegistryTypes.ENTITY_CATEGORY, MobCategory.values()); this.automaticName(RegistryTypes.WALL_CONNECTION_STATE, WallSide.values()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java new file mode 100644 index 00000000000..6830b15c2c1 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import net.minecraft.world.entity.animal.Salmon; +import org.spongepowered.api.data.type.SalmonSize; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Salmon.Variant.class) +public abstract class SalmonVariantMixin_API implements SalmonSize { + +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index abb7c76f751..49e32b0137d 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -168,6 +168,7 @@ "minecraft.world.entity.animal.Rabbit_VariantMixin_API", "minecraft.world.entity.animal.RabbitMixin_API", "minecraft.world.entity.animal.SalmonMixin_API", + "minecraft.world.entity.animal.SalmonVariantMixin_API", "minecraft.world.entity.animal.SheepMixin_API", "minecraft.world.entity.animal.ShoulderRidingEntityMixin_API", "minecraft.world.entity.animal.SnowGolemMixin_API", From 9123e1b14366b58c7c327ca815aea156b906f012 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 22:47:16 -0800 Subject: [PATCH 208/586] feat(data): implement pufferfish key Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../common/data/provider/entity/PufferfishData.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 381f7587735..4de6bde7b3a 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 381f7587735a7c7a93437593e3969010cca552e8 +Subproject commit 4de6bde7b3ae9b1b0d6b93bd0b971b3e280dff5e diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java index 6e62f127bf5..a637ed6ce87 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java @@ -39,7 +39,11 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(Pufferfish.class) .create(Keys.SCALE) - .get(h -> (double) PufferfishAccessor.invoker$getScale(h.getPuffState())); + .get(h -> (double) PufferfishAccessor.invoker$getScale(h.getPuffState())) + .create(Keys.PUFFER_FISH_PUFFINESS_STATE) + .get(Pufferfish::getPuffState) + .set(Pufferfish::setPuffState) + ; } // @formatter:on } From eebed1b05d8628ba7269ae8b651a16e8ad3d40e4 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 7 Mar 2025 22:58:55 -0800 Subject: [PATCH 209/586] feat(vanish): prevent vanished players from scaring puffers Signed-off-by: Gabriel Harris-Rouquette --- .../world/entity/animal/PufferfishMixin.java | 68 +++++++++++++++++++ src/mixins/resources/mixins.sponge.core.json | 3 +- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java new file mode 100644 index 00000000000..00b5dad232d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity.animal; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.data.VanishableBridge; + +@Mixin(Pufferfish.class) +public class PufferfishMixin { + + @WrapOperation(method = "lambda$static$0", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isCreative()Z")) + private static boolean impl$considerVanishedPlayers(final Player player, final Operation operation) { + if (player instanceof VanishableBridge vb) { + if (vb.bridge$isInvisible() && vb.bridge$vanishState().untargetable()) { + return false; + } + } + return operation.call(player); + } + + @WrapOperation(method = "lambda$static$0", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;is(Lnet/minecraft/tags/TagKey;)Z") + ) + private static boolean impl$considerVanishedEntitiesWithTyeps( + final EntityType entityType, final TagKey> tagKey, final Operation operation, + final LivingEntity entity, final ServerLevel level + ) { + if (entity instanceof VanishableBridge vb) { + if (vb.bridge$isInvisible() && vb.bridge$vanishState().untargetable()) { + // this is inverted because we want to return true to signify the "entity type is not scary" + return true; + } + } + return operation.call(entityType, tagKey); + } +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 77ad9fde356..1f02c86eda7 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -143,6 +143,7 @@ "world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin", "world.entity.animal.OcelotMixin", "world.entity.animal.ParrotMixin", + "world.entity.animal.PufferfishMixin", "world.entity.animal.Rabbit_RaidGardenGoalMixin", "world.entity.animal.WolfMixin", "world.entity.animal.horse.AbstractHorseMixin", @@ -217,10 +218,10 @@ "world.item.crafting.ShapedRecipeMixin", "world.item.crafting.ShapelessRecipe_SerializerMixin", "world.item.crafting.ShapelessRecipeMixin", + "world.item.crafting.SingleItemRecipe_SerializerMixin", "world.item.crafting.SingleItemRecipeMixin", "world.item.crafting.SmithingTransformRecipe_SerializerMixin", "world.item.crafting.SmithingTransformRecipeMixin", - "world.item.crafting.SingleItemRecipe_SerializerMixin", "world.item.enchantment.EnchantmentMixin", "world.level.BaseSpawnerMixin", "world.level.BlockGetterMixin", From 5f3a2b15dbcc1725661d3e238624f6b5fa131324 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Mar 2025 00:19:33 -0800 Subject: [PATCH 210/586] feat(data): implement axolotl variants Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 8 ++++ .../data/provider/entity/AxolotlData.java | 45 +++++++++++++++++++ .../provider/entity/EntityDataProviders.java | 1 + .../axolotl/AxolotlVariantMixin_API.java | 34 ++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 1 + 6 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/AxolotlData.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/axolotl/AxolotlVariantMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 4de6bde7b3a..a495efc5c62 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 4de6bde7b3ae9b1b0d6b93bd0b971b3e280dff5e +Subproject commit a495efc5c6214354941e81acab8b8905bb2b3600 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 9bad8f1e060..0a33a6c086c 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -36,6 +36,7 @@ import net.minecraft.world.entity.animal.Rabbit; import net.minecraft.world.entity.animal.Salmon; import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.axolotl.Axolotl; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.animal.horse.Markings; import net.minecraft.world.entity.animal.horse.Variant; @@ -178,6 +179,13 @@ public static List enumEntries(final Context context) { Salmon.Variant.class, "getSerializedName", "sponge" + ), + new EnumEntriesValidator<>( + "data.type", + "AxolotlVariants", + Axolotl.Variant.class, + "getSerializedName", + "sponge" ) ); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AxolotlData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AxolotlData.java new file mode 100644 index 00000000000..e9725db2498 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AxolotlData.java @@ -0,0 +1,45 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.AxolotlVariant; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public class AxolotlData { + private AxolotlData() { + } + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(Axolotl.class) + .create(Keys.AXOLOTL_VARIANT) + .get(a -> (AxolotlVariant) (Object) a.getVariant()) + .set((h, v) -> h.setVariant((Axolotl.Variant) (Object) v)); + } + // @formatter:on +} diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 0589389a7a2..07bf210e575 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -42,6 +42,7 @@ public void registerProviders() { AreaEffectCloudData.register(this.registrator); ArmorStandData.register(this.registrator); ArrowData.register(this.registrator); + AxolotlData.register(this.registrator); BatData.register(this.registrator); BedData.register(this.registrator); BlazeData.register(this.registrator); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/axolotl/AxolotlVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/axolotl/AxolotlVariantMixin_API.java new file mode 100644 index 00000000000..1724094625c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/axolotl/AxolotlVariantMixin_API.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.axolotl; + +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import org.spongepowered.api.data.type.AxolotlVariant; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Axolotl.Variant.class) +public abstract class AxolotlVariantMixin_API implements AxolotlVariant { + +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 49e32b0137d..0dfaca38272 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -182,6 +182,7 @@ "minecraft.world.entity.animal.allay.AllayMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", + "minecraft.world.entity.animal.axolotl.AxolotlVariantMixin_API", "minecraft.world.entity.animal.camel.CamelMixin_API", "minecraft.world.entity.animal.frog.FrogMixin_API", "minecraft.world.entity.animal.frog.TadpoleMixin_API", From a82ed7885f2e79cde54f347777198264a92b802a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Mar 2025 00:48:39 -0800 Subject: [PATCH 211/586] feat(data): implement tadpole baby ticks Signed-off-by: Gabriel Harris-Rouquette --- .../entity/animal/frog/TadpoleAccessor.java | 38 ++ .../resources/mixins.sponge.accessors.json | 439 +++++++++--------- .../provider/entity/EntityDataProviders.java | 1 + .../data/provider/entity/TadpoleData.java | 52 +++ 4 files changed, 311 insertions(+), 219 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/frog/TadpoleAccessor.java create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/TadpoleData.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/frog/TadpoleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/frog/TadpoleAccessor.java new file mode 100644 index 00000000000..9aeb7fcb798 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/frog/TadpoleAccessor.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.animal.frog; + +import net.minecraft.world.entity.animal.frog.Tadpole; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Tadpole.class) +public interface TadpoleAccessor { + + @Accessor("age") int accessor$getAge(); + + @Accessor("age") void accessor$setAge(int age); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index dae21c41108..6f226da9af7 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -1,221 +1,222 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.accessor", - "client": [ - "client.KeyMappingAccessor", - "client.multiplayer.ClientLevelAccessor", - "world.level.entity.TransientEntitySectionManagerAccessor" - ], - "mixins": [ - "ChatFormattingAccessor", - "advancements.CriteriaTriggersAccessor", - "advancements.critereon.MinMaxBounds_DoublesAccessor", - "advancements.critereon.MinMaxBounds_IntsAccessor", - "commands.CommandSourceStackAccessor", - "commands.arguments.DimensionArgumentAccessor", - "commands.arguments.OperationArgumentAccessor", - "commands.arguments.selector.EntitySelectorParserAccessor", - "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", - "commands.arguments.selector.options.EntitySelectorOptionsAccessor", - "core.MappedRegistryAccessor", - "entity.passive.AbstractChestedHorseEntityAccessor", - "network.ConnectionAccessor", - "network.chat.HoverEvent_ItemStackInfoAccessor", - "network.chat.StyleAccessor", - "network.protocol.game.ClientboundAddEntityPacketAccessor", - "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", - "network.protocol.game.ServerboundInteractPacketAccessor", - "network.protocol.game.ServerboundMovePlayerPacketAccessor", - "network.protocol.game.ServerboundMoveVehiclePacketAccessor", - "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.ResourceKeyAccessor", - "server.MinecraftServerAccessor", - "server.level.ChunkMap_TrackedEntityAccessor", - "server.level.ChunkMapAccessor", - "server.level.ServerChunkCacheAccessor", - "server.level.ServerLevelAccessor", - "server.level.ServerPlayer_ContainerListenerAccessor", - "server.level.ServerPlayerAccessor", - "server.level.ServerPlayerGameModeAccessor", - "server.level.TicketAccessor", - "server.level.TicketTypeAccessor", - "server.network.ServerCommonPacketListenerImplAccessor", - "server.network.ServerGamePacketListenerImplAccessor", - "server.network.ServerLoginPacketListenerImplAccessor", - "server.players.GameProfileCache_GameProfileInfoAccessor", - "server.players.IpBanListAccessor", - "server.players.PlayerListAccessor", - "server.players.StoredUserEntryAccessor", - "server.players.StoredUserListAccessor", - "server.rcon.thread.RconClientAccessor", - "sounds.SoundEventAccessor", - "stats.StatsCounterAccessor", - "tags.TagEntryAccessor", - "util.datafix.schemas.V100Accessor", - "util.thread.AbstractConsecutiveExecutorAccessor", - "world.CompoundContainerAccessor", - "world.damagesource.CombatTrackerAccessor", - "world.entity.AgableMobAccessor", - "world.entity.AreaEffectCloudAccessor", - "world.entity.Display_BlockDisplayAccessor", - "world.entity.Display_ItemDisplayAccessor", - "world.entity.Display_TextDisplayAccessor", - "world.entity.DisplayAccessor", - "world.entity.EntityAccessor", - "world.entity.EntityTypeAccessor", - "world.entity.ExperienceOrbAccessor", - "world.entity.InteractionAccessor", - "world.entity.LightningBoltAccessor", - "world.entity.LivingEntityAccessor", - "world.entity.MobAccessor", - "world.entity.PortalProcessorAccessor", - "world.entity.ai.targeting.TargetingConditionsAccessor", - "world.entity.animal.AnimalAccessor", - "world.entity.animal.CatAccessor", - "world.entity.animal.FoxAccessor", - "world.entity.animal.OcelotAccessor", - "world.entity.animal.PandaAccessor", - "world.entity.animal.PigAccessor", - "world.entity.animal.PufferfishAccessor", - "world.entity.animal.SheepAccessor", - "world.entity.animal.TropicalFishAccessor", - "world.entity.animal.TurtleAccessor", - "world.entity.animal.WolfAccessor", - "world.entity.animal.horse.HorseAccessor", - "world.entity.animal.horse.LlamaAccessor", - "world.entity.animal.horse.TraderLlamaAccessor", - "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", - "world.entity.boss.wither.WitherBossAccessor", - "world.entity.decoration.ArmorStandAccessor", - "world.entity.decoration.HangingEntityAccessor", - "world.entity.decoration.ItemFrameAccessor", - "world.entity.item.FallingBlockEntityAccessor", - "world.entity.item.PrimedTntAccessor", - "world.entity.monster.BlazeAccessor", - "world.entity.monster.CreeperAccessor", - "world.entity.monster.EnderManAccessor", - "world.entity.monster.EndermiteAccessor", - "world.entity.monster.EvokerAccessor", - "world.entity.monster.GuardianAccessor", - "world.entity.monster.PatrollingMonsterAccessor", - "world.entity.monster.PhantomAccessor", - "world.entity.monster.PillagerAccessor", - "world.entity.monster.RavagerAccessor", - "world.entity.monster.SlimeAccessor", - "world.entity.monster.SpellcasterIllagerAccessor", - "world.entity.monster.VexAccessor", - "world.entity.monster.VindicatorAccessor", - "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.monster.creaking.CreakingTransientAccessor", - "world.entity.npc.AbstractVillagerAccessor", - "world.entity.player.AbilitiesAccessor", - "world.entity.player.PlayerAccessor", - "world.entity.projectile.ArrowAccessor", - "world.entity.projectile.EyeOfEnderAccessor", - "world.entity.projectile.FireworkRocketEntityAccessor", - "world.entity.projectile.FishingHookAccessor", - "world.entity.projectile.ProjectileAccessor", - "world.entity.projectile.ShulkerBulletAccessor", - "world.entity.raid.RaidAccessor", - "world.entity.raid.RaiderAccessor", - "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.AbstractBoatAccessor", - "world.entity.vehicle.MinecartFurnaceAccessor", - "world.food.FoodDataAccessor", - "world.inventory.AbstractContainerMenuAccessor", - "world.inventory.AbstractCraftingMenuAccessor", - "world.inventory.AbstractFurnaceMenuAccessor", - "world.inventory.BeaconMenuAccessor", - "world.inventory.BrewingStandMenuAccessor", - "world.inventory.DispenserMenuAccessor", - "world.inventory.HopperMenuAccessor", - "world.inventory.HorseInventoryMenuAccessor", - "world.inventory.ItemCombinerMenuAccessor", - "world.inventory.MerchantMenuAccessor", - "world.inventory.ResultSlotAccessor", - "world.inventory.SlotAccessor", - "world.inventory.SmithingMenuAccessor", - "world.item.AdventureModePredicateAccessor", - "world.item.ItemCooldowns_CooldownInstanceAccessor", - "world.item.component.CustomDataAccessor", - "world.item.crafting.RecipeMapAccessor", - "world.item.crafting.ShapelessRecipeAccessor", - "world.item.enchantment.ItemEnchantmentsAccessor", - "world.item.trading.MerchantOfferAccessor", - "world.level.BaseCommandBlockAccessor", - "world.level.BaseSpawnerAccessor", - "world.level.GameRules_ValueAccessor", - "world.level.GameRulesAccessor", - "world.level.LevelAccessor", - "world.level.LevelSettingsAccessor", - "world.level.NaturalSpawner_SpawnStateAccessor", - "world.level.NaturalSpawnerAccessor", - "world.level.ServerExplosionAccessor", - "world.level.biome.Biome_ClimateSettingsAccessor", - "world.level.biome.BiomeAccessor", - "world.level.biome.MobSpawnSettingsAccessor", - "world.level.biome.MultiNoiseBiomeSourceAccessor", - "world.level.biome.OverworldBiomeBuilderAccessor", - "world.level.biome.TheEndBiomeSourceAccessor", - "world.level.block.AbstractSkullBlockAccessor", - "world.level.block.BaseFireBlockAccessor", - "world.level.block.BedBlockAccessor", - "world.level.block.CrafterBlockAccessor", - "world.level.block.CropBlockAccessor", - "world.level.block.DispenserBlockAccessor", - "world.level.block.EnderChestBlockAccessor", - "world.level.block.StemBlockAccessor", - "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", - "world.level.block.entity.BaseContainerBlockEntityAccessor", - "world.level.block.entity.BeaconBlockEntityAccessor", - "world.level.block.entity.BlockEntityAccessor", - "world.level.block.entity.BrewingStandBlockEntityAccessor", - "world.level.block.entity.ConduitBlockEntityAccessor", - "world.level.block.entity.CrafterBlockEntityAccessor", - "world.level.block.entity.DecoratedPotBlockEntityAccessor", - "world.level.block.entity.EnchantingTableBlockEntityAccessor", - "world.level.block.entity.HopperBlockEntityAccessor", - "world.level.block.entity.LecternBlockEntity_Accessor", - "world.level.block.entity.SkullBlockEntityAccessor", - "world.level.block.entity.SpawnerBlockEntityAccessor", - "world.level.block.entity.StructureBlockEntityAccessor", - "world.level.block.entity.TheEndGatewayBlockEntityAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerAccessor", - "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", - "world.level.block.piston.PistonBaseBlockAccessor", - "world.level.block.state.BlockBehaviour_PropertiesAccessor", - "world.level.block.state.BlockBehaviourAccessor", - "world.level.block.state.StateHolderAccessor", - "world.level.border.WorldBorder_SettingsAccessor", - "world.level.border.WorldBorderAccessor", - "world.level.chunk.ChunkAccessAccessor", - "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", - "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", - "world.level.chunk.LevelChunkAccessor", - "world.level.chunk.storage.ChunkStorageAccessor", - "world.level.chunk.storage.IOWorker$PendingStoreAccessor", - "world.level.chunk.storage.RegionFileAccessor", - "world.level.chunk.storage.SimpleRegionStorageAccessor", - "world.level.dimension.DimensionTypeAccessor", - "world.level.dimension.end.EndDragonFightAccessor", - "world.level.entity.EntityTickListAccessor", - "world.level.entity.PersistentEntitySectionManagerAccessor", - "world.level.levelgen.NoiseSettingsAccessor", - "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", - "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", - "world.level.portal.TeleportTransitionAccessor", - "world.level.saveddata.maps.MapItemSavedDataAccessor", - "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", - "world.level.storage.PlayerDataStorageAccessor", - "world.phys.AABBAccessor", - "world.scores.PlayerTeamAccessor", - "world.scores.ScoreboardAccessor", - "world.ticks.LevelChunkTicksAccessor" - ], - "server": [ - "server.dedicated.DedicatedServerAccessor" - ] + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.accessor", + "client": [ + "client.KeyMappingAccessor", + "client.multiplayer.ClientLevelAccessor", + "world.level.entity.TransientEntitySectionManagerAccessor" + ], + "mixins": [ + "ChatFormattingAccessor", + "advancements.CriteriaTriggersAccessor", + "advancements.critereon.MinMaxBounds_DoublesAccessor", + "advancements.critereon.MinMaxBounds_IntsAccessor", + "commands.CommandSourceStackAccessor", + "commands.arguments.DimensionArgumentAccessor", + "commands.arguments.OperationArgumentAccessor", + "commands.arguments.selector.EntitySelectorParserAccessor", + "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", + "commands.arguments.selector.options.EntitySelectorOptionsAccessor", + "core.MappedRegistryAccessor", + "entity.passive.AbstractChestedHorseEntityAccessor", + "network.ConnectionAccessor", + "network.chat.HoverEvent_ItemStackInfoAccessor", + "network.chat.StyleAccessor", + "network.protocol.game.ClientboundAddEntityPacketAccessor", + "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", + "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", + "network.protocol.game.ServerboundInteractPacketAccessor", + "network.protocol.game.ServerboundMovePlayerPacketAccessor", + "network.protocol.game.ServerboundMoveVehiclePacketAccessor", + "network.protocol.handshake.ClientIntentionPacketAccessor", + "resources.ResourceKeyAccessor", + "server.MinecraftServerAccessor", + "server.level.ChunkMap_TrackedEntityAccessor", + "server.level.ChunkMapAccessor", + "server.level.ServerChunkCacheAccessor", + "server.level.ServerLevelAccessor", + "server.level.ServerPlayer_ContainerListenerAccessor", + "server.level.ServerPlayerAccessor", + "server.level.ServerPlayerGameModeAccessor", + "server.level.TicketAccessor", + "server.level.TicketTypeAccessor", + "server.network.ServerCommonPacketListenerImplAccessor", + "server.network.ServerGamePacketListenerImplAccessor", + "server.network.ServerLoginPacketListenerImplAccessor", + "server.players.GameProfileCache_GameProfileInfoAccessor", + "server.players.IpBanListAccessor", + "server.players.PlayerListAccessor", + "server.players.StoredUserEntryAccessor", + "server.players.StoredUserListAccessor", + "server.rcon.thread.RconClientAccessor", + "sounds.SoundEventAccessor", + "stats.StatsCounterAccessor", + "tags.TagEntryAccessor", + "util.datafix.schemas.V100Accessor", + "util.thread.AbstractConsecutiveExecutorAccessor", + "world.CompoundContainerAccessor", + "world.damagesource.CombatTrackerAccessor", + "world.entity.AgableMobAccessor", + "world.entity.AreaEffectCloudAccessor", + "world.entity.Display_BlockDisplayAccessor", + "world.entity.Display_ItemDisplayAccessor", + "world.entity.Display_TextDisplayAccessor", + "world.entity.DisplayAccessor", + "world.entity.EntityAccessor", + "world.entity.EntityTypeAccessor", + "world.entity.ExperienceOrbAccessor", + "world.entity.InteractionAccessor", + "world.entity.LightningBoltAccessor", + "world.entity.LivingEntityAccessor", + "world.entity.MobAccessor", + "world.entity.PortalProcessorAccessor", + "world.entity.ai.targeting.TargetingConditionsAccessor", + "world.entity.animal.AnimalAccessor", + "world.entity.animal.CatAccessor", + "world.entity.animal.FoxAccessor", + "world.entity.animal.OcelotAccessor", + "world.entity.animal.PandaAccessor", + "world.entity.animal.PigAccessor", + "world.entity.animal.PufferfishAccessor", + "world.entity.animal.SheepAccessor", + "world.entity.animal.TropicalFishAccessor", + "world.entity.animal.TurtleAccessor", + "world.entity.animal.WolfAccessor", + "world.entity.animal.frog.TadpoleAccessor", + "world.entity.animal.horse.HorseAccessor", + "world.entity.animal.horse.LlamaAccessor", + "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", + "world.entity.boss.wither.WitherBossAccessor", + "world.entity.decoration.ArmorStandAccessor", + "world.entity.decoration.HangingEntityAccessor", + "world.entity.decoration.ItemFrameAccessor", + "world.entity.item.FallingBlockEntityAccessor", + "world.entity.item.PrimedTntAccessor", + "world.entity.monster.BlazeAccessor", + "world.entity.monster.CreeperAccessor", + "world.entity.monster.EnderManAccessor", + "world.entity.monster.EndermiteAccessor", + "world.entity.monster.EvokerAccessor", + "world.entity.monster.GuardianAccessor", + "world.entity.monster.PatrollingMonsterAccessor", + "world.entity.monster.PhantomAccessor", + "world.entity.monster.PillagerAccessor", + "world.entity.monster.RavagerAccessor", + "world.entity.monster.SlimeAccessor", + "world.entity.monster.SpellcasterIllagerAccessor", + "world.entity.monster.VexAccessor", + "world.entity.monster.VindicatorAccessor", + "world.entity.monster.ZombifiedPiglinAccessor", + "world.entity.monster.creaking.CreakingTransientAccessor", + "world.entity.npc.AbstractVillagerAccessor", + "world.entity.player.AbilitiesAccessor", + "world.entity.player.PlayerAccessor", + "world.entity.projectile.ArrowAccessor", + "world.entity.projectile.EyeOfEnderAccessor", + "world.entity.projectile.FireworkRocketEntityAccessor", + "world.entity.projectile.FishingHookAccessor", + "world.entity.projectile.ProjectileAccessor", + "world.entity.projectile.ShulkerBulletAccessor", + "world.entity.raid.RaidAccessor", + "world.entity.raid.RaiderAccessor", + "world.entity.raid.RaidsAccessor", + "world.entity.vehicle.AbstractBoatAccessor", + "world.entity.vehicle.MinecartFurnaceAccessor", + "world.food.FoodDataAccessor", + "world.inventory.AbstractContainerMenuAccessor", + "world.inventory.AbstractCraftingMenuAccessor", + "world.inventory.AbstractFurnaceMenuAccessor", + "world.inventory.BeaconMenuAccessor", + "world.inventory.BrewingStandMenuAccessor", + "world.inventory.DispenserMenuAccessor", + "world.inventory.HopperMenuAccessor", + "world.inventory.HorseInventoryMenuAccessor", + "world.inventory.ItemCombinerMenuAccessor", + "world.inventory.MerchantMenuAccessor", + "world.inventory.ResultSlotAccessor", + "world.inventory.SlotAccessor", + "world.inventory.SmithingMenuAccessor", + "world.item.AdventureModePredicateAccessor", + "world.item.ItemCooldowns_CooldownInstanceAccessor", + "world.item.component.CustomDataAccessor", + "world.item.crafting.RecipeMapAccessor", + "world.item.crafting.ShapelessRecipeAccessor", + "world.item.enchantment.ItemEnchantmentsAccessor", + "world.item.trading.MerchantOfferAccessor", + "world.level.BaseCommandBlockAccessor", + "world.level.BaseSpawnerAccessor", + "world.level.GameRules_ValueAccessor", + "world.level.GameRulesAccessor", + "world.level.LevelAccessor", + "world.level.LevelSettingsAccessor", + "world.level.NaturalSpawner_SpawnStateAccessor", + "world.level.NaturalSpawnerAccessor", + "world.level.ServerExplosionAccessor", + "world.level.biome.Biome_ClimateSettingsAccessor", + "world.level.biome.BiomeAccessor", + "world.level.biome.MobSpawnSettingsAccessor", + "world.level.biome.MultiNoiseBiomeSourceAccessor", + "world.level.biome.OverworldBiomeBuilderAccessor", + "world.level.biome.TheEndBiomeSourceAccessor", + "world.level.block.AbstractSkullBlockAccessor", + "world.level.block.BaseFireBlockAccessor", + "world.level.block.BedBlockAccessor", + "world.level.block.CrafterBlockAccessor", + "world.level.block.CropBlockAccessor", + "world.level.block.DispenserBlockAccessor", + "world.level.block.EnderChestBlockAccessor", + "world.level.block.StemBlockAccessor", + "world.level.block.entity.AbstractFurnaceBlockEntityAccessor", + "world.level.block.entity.BaseContainerBlockEntityAccessor", + "world.level.block.entity.BeaconBlockEntityAccessor", + "world.level.block.entity.BlockEntityAccessor", + "world.level.block.entity.BrewingStandBlockEntityAccessor", + "world.level.block.entity.ConduitBlockEntityAccessor", + "world.level.block.entity.CrafterBlockEntityAccessor", + "world.level.block.entity.DecoratedPotBlockEntityAccessor", + "world.level.block.entity.EnchantingTableBlockEntityAccessor", + "world.level.block.entity.HopperBlockEntityAccessor", + "world.level.block.entity.LecternBlockEntity_Accessor", + "world.level.block.entity.SkullBlockEntityAccessor", + "world.level.block.entity.SpawnerBlockEntityAccessor", + "world.level.block.entity.StructureBlockEntityAccessor", + "world.level.block.entity.TheEndGatewayBlockEntityAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerAccessor", + "world.level.block.entity.trialspawner.TrialSpawnerDataAccessor", + "world.level.block.piston.PistonBaseBlockAccessor", + "world.level.block.state.BlockBehaviour_PropertiesAccessor", + "world.level.block.state.BlockBehaviourAccessor", + "world.level.block.state.StateHolderAccessor", + "world.level.border.WorldBorder_SettingsAccessor", + "world.level.border.WorldBorderAccessor", + "world.level.chunk.ChunkAccessAccessor", + "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", + "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", + "world.level.chunk.LevelChunkAccessor", + "world.level.chunk.storage.ChunkStorageAccessor", + "world.level.chunk.storage.IOWorker$PendingStoreAccessor", + "world.level.chunk.storage.RegionFileAccessor", + "world.level.chunk.storage.SimpleRegionStorageAccessor", + "world.level.dimension.DimensionTypeAccessor", + "world.level.dimension.end.EndDragonFightAccessor", + "world.level.entity.EntityTickListAccessor", + "world.level.entity.PersistentEntitySectionManagerAccessor", + "world.level.levelgen.NoiseSettingsAccessor", + "world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor", + "world.level.levelgen.structure.pools.StructureTemplatePoolAccessor", + "world.level.portal.TeleportTransitionAccessor", + "world.level.saveddata.maps.MapItemSavedDataAccessor", + "world.level.storage.LevelStorageSource_LevelStorageAccessAccessor", + "world.level.storage.PlayerDataStorageAccessor", + "world.phys.AABBAccessor", + "world.scores.PlayerTeamAccessor", + "world.scores.ScoreboardAccessor", + "world.ticks.LevelChunkTicksAccessor" + ], + "server": [ + "server.dedicated.DedicatedServerAccessor" + ] } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 07bf210e575..3259e3f6c4c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -112,6 +112,7 @@ public void registerProviders() { SlimeData.register(this.registrator); SpellcastingIllagerData.register(this.registrator); SpiderData.register(this.registrator); + TadpoleData.register(this.registrator); TameableData.register(this.registrator); ThrowableItemProjectileData.register(this.registrator); TNTData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TadpoleData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TadpoleData.java new file mode 100644 index 00000000000..0d9f64e0075 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TadpoleData.java @@ -0,0 +1,52 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.animal.frog.Tadpole; +import org.spongepowered.api.data.Keys; +import org.spongepowered.common.accessor.world.entity.animal.frog.TadpoleAccessor; +import org.spongepowered.common.data.provider.DataProviderRegistrator; +import org.spongepowered.common.util.SpongeTicks; + +public class TadpoleData { + + public static void register(final DataProviderRegistrator registrator) { + // @formatter:off + registrator + .asMutable(TadpoleAccessor.class) + .create(Keys.BABY_TICKS) + .get(h -> h.accessor$getAge() < 0 ? new SpongeTicks(Tadpole.ticksToBeFrog-h.accessor$getAge()) : null) + .setAnd((h, v) -> { + final int ticks = SpongeTicks.toSaturatedIntOrInfinite(v); + if (v.isInfinite() || ticks < 0) { + return false; + } + h.accessor$setAge(-ticks); + return true; + }) + ; + // @formatter:on + } +} From cdb317149b50a67ee5cf8dd6101c81c47d6f3625 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Mar 2025 00:52:56 -0800 Subject: [PATCH 212/586] fix(docs): remove reference to pale garden Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index a495efc5c62..45e646df4e0 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a495efc5c6214354941e81acab8b8905bb2b3600 +Subproject commit 45e646df4e09fd3e1e22c44abcea607670e38e35 From 46f542bb40bb4853575baf7f58c676e7759a74c6 Mon Sep 17 00:00:00 2001 From: Joni Aromaa Date: Sat, 8 Mar 2025 12:33:52 +0000 Subject: [PATCH 213/586] Registry rework (#4179) --- SpongeAPI | 2 +- .../spongepowered/forge/SpongeForgeMod.java | 1 - .../server/MinecraftServerMixin_Forge.java | 11 + .../world/level/LevelDataRegistries.java | 13 +- .../spongepowered/neoforge/SpongeNeoMod.java | 1 - .../core/server/MinecraftServerMixin_Neo.java | 11 + .../RegistryDataLoader_LoaderAccessor.java} | 14 +- .../resources/mixins.sponge.accessors.json | 1 + .../common/launch/Lifecycle.java | 16 +- .../spongepowered/common/SpongeLifecycle.java | 99 +++-- .../advancement/SpongeAdvancementBuilder.java | 40 +- .../SpongeAdvancementTemplate.java | 85 ---- .../adventure/SpongeChatTypeBuilder.java | 120 ++++++ .../adventure/SpongeChatTypeTemplate.java | 190 --------- .../common/bridge/core/RegistryBridge.java | 3 + .../bridge/core/WritableRegistryBridge.java | 20 + .../RegistryDataLoader_LoaderBridge.java} | 8 +- .../bridge/server/MinecraftServerBridge.java | 3 + .../level/dimension/LevelStemBridge.java | 5 +- .../command/SpongeParameterizedCommand.java | 11 +- .../brigadier/SpongeParameterTranslator.java | 29 +- .../argument/AbstractArgumentParser.java | 5 + .../brigadier/argument/ArgumentParser.java | 4 + .../argument/BindableValueParameter.java | 70 ++++ .../argument/StandardArgumentParser.java | 6 + .../command/manager/SpongeCommandManager.java | 16 +- .../registrar/BrigadierCommandRegistrar.java | 5 +- .../registrar/SpongeCommandRegistrarType.java | 13 +- .../SpongeParameterizedCommandRegistrar.java | 13 +- .../registrar/SpongeRawCommandRegistrar.java | 7 +- .../common/config/SpongeGameConfigs.java | 8 +- .../config/inheritable/WorldCategory.java | 23 + .../common/data/fixer/CombineMapsCodec.java | 9 +- .../data/provider/world/LevelStemData.java | 29 -- .../data/provider/world/biome/BiomeData.java | 2 +- .../data/type/SpongeArtTypeBuilder.java | 85 ++++ .../data/type/SpongeArtTypeTemplate.java | 137 ------ .../common/datapack/DataPackSerializer.java | 100 ----- .../datapack/JsonDataPackSerializer.java | 97 ----- .../datapack/NbtDataPackSerializer.java | 87 ---- .../common/datapack/SpongeDataPack.java | 32 -- .../datapack/SpongeDataPackManager.java | 277 ------------ .../common/datapack/SpongeDataPackType.java | 283 ------------- .../datapack/TagDataPackSerializer.java | 58 --- .../recipe/RecipeDataPackSerializer.java | 64 --- .../damage/SpongeDamageTypeBuilder.java | 99 +++++ .../damage/SpongeDamageTypeTemplate.java | 172 -------- .../AbstractRegisterRegistryEvent.java | 36 +- .../AbstractRegisterRegistryValueEvent.java | 80 ++-- .../lifecycle/RegisterCommandEventImpl.java | 10 +- .../item/recipe/SpongeRecipeRegistration.java | 135 +----- .../recipe/cooking/SpongeBlastingRecipe.java | 21 +- .../cooking/SpongeCampfireCookingRecipe.java | 21 +- .../cooking/SpongeCookingRecipeBuilder.java | 74 ++-- .../SpongeCookingRecipeRegistration.java | 156 ------- .../recipe/cooking/SpongeSmeltingRecipe.java | 21 +- .../recipe/cooking/SpongeSmokingRecipe.java | 21 +- .../SpongeSpecialCraftingRecipeBuilder.java | 23 +- ...ongeSpecialCraftingRecipeRegistration.java | 81 ---- .../crafting/custom/SpongeSpecialRecipe.java | 23 +- .../SpongeShapedCraftingRecipeBuilder.java | 22 +- ...pongeShapedCraftingRecipeRegistration.java | 94 ----- .../crafting/shaped/SpongeShapedRecipe.java | 73 +--- .../SpongeShapelessCraftingRecipeBuilder.java | 24 +- ...geShapelessCraftingRecipeRegistration.java | 96 ----- .../shapeless/SpongeShapelessRecipe.java | 65 +-- .../ingredient/IngredientResultUtil.java | 106 ----- .../recipe/ingredient/SpongeItemList.java | 12 - .../ingredient/SpongePredicateItemList.java | 9 - .../ingredient/SpongeStackItemList.java | 8 - .../recipe/smithing/SpongeSmithingRecipe.java | 45 +- .../smithing/SpongeSmithingRecipeBuilder.java | 24 +- .../SpongeSmithingRecipeRegistration.java | 83 ---- .../SpongeStoneCutterRecipeBuilder.java | 23 +- .../SpongeStonecuttingRecipe.java | 59 +-- .../SpongeStonecuttingRecipeRegistration.java | 76 ---- .../common/registry/InitialRegistryData.java | 6 +- .../common/registry/RegistryHolderLogic.java | 88 +++- .../registry/SpongeBuilderProvider.java | 100 +++-- .../registry/SpongeFactoryProvider.java | 11 +- .../common/registry/SpongeRegistries.java | 28 +- .../SpongeRegistryDependencyEntry.java} | 19 +- .../common/registry/SpongeRegistryHolder.java | 55 ++- .../SpongeRegistryRegistrationSet.java | 80 ++++ .../loader/CommandRegistryLoader.java | 10 +- .../registry/loader/SpongeRegistryLoader.java | 19 +- .../common/tag/SpongeTagTemplate.java | 91 ---- .../common/tag/SpongeTagTemplateBuilder.java | 128 ------ ...ackEntryBuilder.java => DataPackUtil.java} | 48 ++- .../world/biome/SpongeBiomeBuilder.java | 156 +++++++ .../world/biome/SpongeBiomeTemplate.java | 229 ---------- .../SpongeChunkGeneratorFactory.java | 12 - .../carver/SpongeCarverBuilder.java | 67 +++ .../carver/SpongeCarverTemplate.java | 139 ------- .../noise/SpongeDensityFunctionTemplate.java | 125 ------ .../config/noise/SpongeNoiseBuilder.java | 82 ++++ .../SpongeNoiseGeneratorConfigBuilder.java | 169 ++++++++ .../SpongeNoiseGeneratorConfigTemplate.java | 235 ----------- .../config/noise/SpongeNoiseTemplate.java | 150 ------- .../feature/SpongeFeatureBuilder.java | 69 +++ .../feature/SpongeFeatureTemplate.java | 139 ------- .../feature/SpongePlacedFeatureBuilder.java | 76 ++++ .../feature/SpongePlacedFeatureTemplate.java | 168 -------- .../structure/SpongeSchematicTemplate.java | 108 ----- .../structure/SpongeStructureSetBuilder.java | 80 ++++ .../structure/SpongeStructureSetTemplate.java | 158 ------- .../structure/SpongeStructureTemplate.java | 125 ------ .../jigsaw/SpongeJigsawPoolBuilder.java | 94 +++++ .../jigsaw/SpongeJigsawPoolTemplate.java | 160 ------- .../jigsaw/SpongeProcessorListBuilder.java} | 46 +- .../jigsaw/SpongeProcessorListTemplate.java | 136 ------ ...pongeServerWorldPropertiesLoadOptions.java | 139 +++++++ .../server/SpongeWorldArchetypeType.java | 66 +++ .../world/server/SpongeWorldManager.java | 393 +++++++++--------- .../world/server/SpongeWorldTemplate.java | 258 +----------- .../world/server/SpongeWorldTypeBuilder.java | 130 ++++++ .../world/server/SpongeWorldTypeTemplate.java | 214 ---------- src/main/resources/common.accesswidener | 1 + .../advancements/AdvancementMixin_API.java | 23 +- .../AdvancementNodeMixin_API.java | 21 +- .../core/MappedRegistryMixin_API.java | 14 +- .../api/minecraft/core/RegistryMixin.java | 88 ++++ .../network/chat/ChatTypeMixin_API.java | 8 + .../server/MinecraftServerMixin_API.java | 2 +- .../server/level/ServerPlayerMixin_API.java | 6 +- .../MultiPackResourceManagerMixin_API.java} | 19 +- .../damagesource/DamageTypeMixin_API.java | 9 + .../decoration/PaintingVariantMixin_API.java | 9 + .../world/item/crafting/RecipeMixin_API.java | 9 + .../world/level/biome/BiomeMixin_API.java | 9 + .../dimension/DimensionTypeMixin_API.java | 9 + .../level/dimension/LevelStemMixin_API.java | 64 +++ .../levelgen/DensityFunctionMixin_API.java | 10 + .../NoiseGeneratorSettingsMixin_API.java | 9 + .../NormalNoise_NoiseParametersMixin_API.java | 9 + .../ConfiguredWorldCarverMixin_API.java | 22 +- .../levelgen/carver/WorldCarverMixin_API.java | 27 -- .../feature/ConfiguredFeatureMixin_API.java | 10 + .../placement/PlacedFeatureMixin_API.java | 9 + .../structure/StructureMixin_API.java | 9 + .../structure/StructureSetMixin_API.java | 9 + .../pools/StructureTemplatePoolMixin_API.java | 9 + .../StructureProcessorListMixin_API.java | 10 + .../core/HolderLookup_ProviderMixin.java | 70 ++++ .../mixin/core/commands/CommandsMixin.java | 6 +- .../mixin/core/core/MappedRegistryMixin.java | 93 +++++ .../registries/BuiltInRegistriesMixin.java | 19 +- .../resources/RegistryDataLoaderMixin.java | 44 ++ .../RegistryDataLoader_LoaderMixin.java} | 33 +- .../core/server/MinecraftServerMixin.java | 18 +- .../ReloadableServerRegistriesMixin.java | 48 --- .../ReloadableServerResourcesMixin.java | 92 ++++ .../server/ServerAdvancementManagerMixin.java | 81 ++++ .../mixin/core/server/WorldLoaderMixin.java | 43 +- .../dedicated/DedicatedServerMixin.java | 3 - .../AbstractCookingRecipeSerializerMixin.java | 138 ------ .../crafting/CustomRecipeSerializerMixin.java | 58 --- .../item/crafting/RecipeManagerMixin.java | 30 ++ .../ShapedRecipe_SerializerMixin.java | 54 --- .../ShapelessRecipe_SerializerMixin.java | 57 --- .../SingleItemRecipe_SerializerMixin.java | 54 --- ...ithingTransformRecipe_SerializerMixin.java | 54 --- .../world/level/dimension/LevelStemMixin.java | 38 +- .../level/storage/PrimaryLevelDataMixin.java | 94 +++-- src/mixins/resources/mixins.sponge.api.json | 3 + src/mixins/resources/mixins.sponge.core.json | 12 +- .../stub/registry/StubRegistryHolder.java | 5 + .../test/advancement/AdvancementTest.java | 342 +++++++-------- .../org/spongepowered/test/chat/ChatTest.java | 37 +- .../raw/ClientSuggestionsRawCommand.java | 5 +- .../test/command/raw/RawCommand.java | 7 +- .../customregistry/CustomRegistryTest.java | 6 +- .../spongepowered/test/damage/DamageTest.java | 37 +- .../test/data/InfiniteTicksDataTest.java | 33 +- .../org/spongepowered/test/map/MapTest.java | 2 +- .../spongepowered/test/recipe/RecipeTest.java | 213 ++++------ .../org/spongepowered/test/tag/TagTest.java | 123 ++---- .../spongepowered/test/world/WorldTest.java | 68 ++- .../test/worldgen/BiomeTest.java | 48 +-- .../test/worldgen/CarverTest.java | 22 +- .../test/worldgen/FeatureTest.java | 70 ++-- .../test/worldgen/NoiseTest.java | 39 +- .../test/worldgen/StructureTest.java | 173 +++----- .../test/worldgen/WorldGenTest.java | 186 ++++----- .../server/IntegratedServerMixin_Vanilla.java | 1 - .../server/MinecraftServerMixin_Vanilla.java | 10 + .../DedicatedServerMixin_Vanilla.java | 1 - 187 files changed, 4039 insertions(+), 7466 deletions(-) rename src/{main/java/org/spongepowered/common/datapack/DataPackEncoder.java => accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java} (71%) delete mode 100644 src/main/java/org/spongepowered/common/advancement/SpongeAdvancementTemplate.java create mode 100644 src/main/java/org/spongepowered/common/adventure/SpongeChatTypeBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/adventure/SpongeChatTypeTemplate.java rename src/main/java/org/spongepowered/common/{item/recipe/ResultFunctionRecipe.java => bridge/resources/RegistryDataLoader_LoaderBridge.java} (86%) create mode 100644 src/main/java/org/spongepowered/common/command/brigadier/argument/BindableValueParameter.java create mode 100644 src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/DataPackSerializer.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/JsonDataPackSerializer.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/NbtDataPackSerializer.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/SpongeDataPack.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/SpongeDataPackType.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/TagDataPackSerializer.java delete mode 100644 src/main/java/org/spongepowered/common/datapack/recipe/RecipeDataPackSerializer.java create mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeRegistration.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeRegistration.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientResultUtil.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java delete mode 100644 src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipeRegistration.java rename src/main/java/org/spongepowered/common/{tag/SpongeTagTemplateFactory.java => registry/SpongeRegistryDependencyEntry.java} (68%) create mode 100644 src/main/java/org/spongepowered/common/registry/SpongeRegistryRegistrationSet.java delete mode 100644 src/main/java/org/spongepowered/common/tag/SpongeTagTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/tag/SpongeTagTemplateBuilder.java rename src/main/java/org/spongepowered/common/util/{AbstractDataPackEntryBuilder.java => DataPackUtil.java} (54%) create mode 100644 src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeDensityFunctionTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseBuilder.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/SpongeSchematicTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetTemplate.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolTemplate.java rename src/main/java/org/spongepowered/common/{event/lifecycle/RegisterDataPackValueEventImpl.java => world/generation/structure/jigsaw/SpongeProcessorListBuilder.java} (53%) delete mode 100644 src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListTemplate.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java delete mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java rename src/{main/java/org/spongepowered/common/datapack/DataPackDecoder.java => mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/MultiPackResourceManagerMixin_API.java} (63%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/LevelStemMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java rename src/mixins/java/org/spongepowered/common/mixin/core/{advancements/TreeNodePositionMixin.java => resources/RegistryDataLoader_LoaderMixin.java} (60%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerRegistriesMixin.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipe_SerializerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipe_SerializerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipe_SerializerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipe_SerializerMixin.java diff --git a/SpongeAPI b/SpongeAPI index f98dbbbc985..7dd5188d083 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit f98dbbbc985989385992ac648f3cda94ac26f3d2 +Subproject commit 7dd5188d0835a883697165867eb7aa051befac9b diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index 63aa5625ae2..f42d15a6647 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -114,7 +114,6 @@ public void onServerAboutToStart(final ServerAboutToStartEvent event) { lifecycle.establishServerFeatures(); - lifecycle.establishServerRegistries((Server) event.getServer()); lifecycle.callStartingEngineEvent((Server) event.getServer()); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java index d64d8c83bd5..40818502395 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java @@ -24,14 +24,19 @@ */ package org.spongepowered.forge.mixin.core.server; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.packs.resources.MultiPackResourceManager; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.forge.ForgeServer; @@ -50,4 +55,10 @@ public abstract class MinecraftServerMixin_Forge implements ForgeServer { public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } + + @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { + ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); + return original; + } } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java index 2116c2aee2c..0df1b2fe9bd 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java @@ -70,7 +70,9 @@ public static List levelDataRegistries(final Context context) { "Biomes", "BIOME", context.relativeClass("world.biome", "Biome"), - Registries.BIOME + Registries.BIOME, + a -> true, + RegistryScope.SERVER ), new RegistryEntriesGenerator<>( "world.generation.carver", @@ -219,6 +221,15 @@ public static List levelDataRegistries(final Context context) { "FLUID_TYPE", context.relativeClass("fluid", "FluidType"), Registries.FLUID + ), + new RegistryEntriesGenerator<>( + "world.server", + "WorldArchetypeTypes", + "WORLD_ARCHETYPE_TYPE", + context.relativeClass("world.server", "WorldArchetypeType"), + Registries.LEVEL_STEM, + $ -> true, + RegistryScope.SERVER ) ); } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java index a6500645e04..49d04dba88f 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java @@ -109,7 +109,6 @@ public void onServerAboutToStart(final ServerAboutToStartEvent event) { lifecycle.establishServerFeatures(); - lifecycle.establishServerRegistries((Server) event.getServer()); lifecycle.callStartingEngineEvent((Server) event.getServer()); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java index 13c42aa2305..f793f816f90 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java @@ -24,14 +24,19 @@ */ package org.spongepowered.neoforge.mixin.core.server; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.packs.resources.MultiPackResourceManager; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.neoforge.NeoServer; @@ -50,4 +55,10 @@ public abstract class MinecraftServerMixin_Neo implements NeoServer { public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } + + @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { + ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); + return original; + } } diff --git a/src/main/java/org/spongepowered/common/datapack/DataPackEncoder.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java similarity index 71% rename from src/main/java/org/spongepowered/common/datapack/DataPackEncoder.java rename to src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java index 2b74cd51dfb..151ea37279a 100644 --- a/src/main/java/org/spongepowered/common/datapack/DataPackEncoder.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java @@ -22,13 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.datapack; +package org.spongepowered.common.accessor.resources; -import net.minecraft.core.RegistryAccess; -import org.spongepowered.api.datapack.DataPackEntry; +import net.minecraft.core.WritableRegistry; +import net.minecraft.resources.RegistryDataLoader; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; -public interface DataPackEncoder> { +@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$Loader") +public interface RegistryDataLoader_LoaderAccessor { - E encode(T serializable, RegistryAccess registryAccess); + @Accessor("data") RegistryDataLoader.RegistryData accessor$data(); + @Accessor("registry") WritableRegistry accessor$registry(); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index c33965adab0..b8ab6c2177f 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -31,6 +31,7 @@ "network.protocol.game.ServerboundMovePlayerPacketAccessor", "network.protocol.game.ServerboundMoveVehiclePacketAccessor", "network.protocol.handshake.ClientIntentionPacketAccessor", + "resources.RegistryDataLoader_LoaderAccessor", "resources.ResourceKeyAccessor", "server.MinecraftServerAccessor", "server.level.ChunkMap_TrackedEntityAccessor", diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 8a0d4536500..868011ab5b2 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -25,13 +25,14 @@ package org.spongepowered.common.launch; import com.google.inject.Injector; -import net.minecraft.core.RegistryAccess; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.api.Client; import org.spongepowered.api.Engine; -import org.spongepowered.api.Server; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; + +import java.util.stream.Stream; /** @@ -50,9 +51,6 @@ public interface Lifecycle { void callRegisterBuilderEvent(); void establishEarlyGlobalRegistries(); - void finalizeEarlyGlobalRegistries(); - - void establishGlobalRegistries(RegistryAccess.Frozen registryAccess, final RegistryLayer layer); void establishDataProviders(); @@ -70,7 +68,11 @@ public interface Lifecycle { void callConstructEvent(); - void establishServerRegistries(Server server); + void beginEstablishServerRegistries(RegistryHolder server); + + void processServerRegistries(RegistryHolder server, Stream> registries); + + void endEstablishServerRegistries(RegistryHolder server); void establishClientRegistries(Client client); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index f89d0664c49..7ca2055c0ad 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -29,9 +29,7 @@ import com.google.inject.Singleton; import io.leangen.geantyref.TypeToken; import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.level.WorldDataConfiguration; @@ -39,13 +37,16 @@ import org.spongepowered.api.Client; import org.spongepowered.api.Engine; import org.spongepowered.api.Game; -import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; -import org.spongepowered.api.advancement.criteria.trigger.Trigger; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.EventContext; import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.applaunch.plugin.DummyPluginContainer; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.data.SpongeDataManager; @@ -71,7 +72,10 @@ import org.spongepowered.plugin.PluginContainer; import java.util.Collection; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; @Singleton public final class SpongeLifecycle implements Lifecycle { @@ -79,7 +83,6 @@ public final class SpongeLifecycle implements Lifecycle { private final Game game; private final Injector injector; private FeatureFlagSet featureFlags; - public boolean establishedPluginRegistries = false; @Inject public SpongeLifecycle(final Game game, final Injector injector) { @@ -113,50 +116,25 @@ public void callRegisterBuilderEvent() { this.game.eventManager().post(new RegisterBuilderEventImpl(Cause.of(EventContext.empty(), this.game), this.game)); } + @SuppressWarnings("unchecked") @Override public void establishEarlyGlobalRegistries() { final SpongeRegistryHolder holder = (SpongeRegistryHolder) this.game; holder.setRootMinecraftRegistry((Registry>) BuiltInRegistries.REGISTRY); SpongeRegistries.registerEarlyGlobalRegistries(holder); - } - @Override - public void finalizeEarlyGlobalRegistries() { + // Plugin registries + this.game.eventManager().post(new AbstractRegisterRegistryEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game)); - // Vanilla registries we want plugins to be able to modify: - // TODO marker for this in API? - this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.BuiltInImpl<>(Cause.of(EventContext.empty(), this.game), this.game, - (org.spongepowered.api.registry.Registry>) BuiltInRegistries.TRIGGER_TYPES)); - } + // Freeze Sponge Root - Registries are now available + holder.registryHolder().freezeSpongeRootRegistry(); - @Override - public void establishGlobalRegistries(final RegistryAccess.Frozen registryAccess, final RegistryLayer layer) { - final SpongeRegistryHolder holder = (SpongeRegistryHolder) this.game; - SpongeCommon.logger().info("Layer {}", layer); - switch (layer) - { - // WORLDGEN -> - case DIMENSIONS -> { - SpongeRegistries.registerGlobalRegistriesDimensionLayer((SpongeRegistryHolder) this.game, registryAccess, this.featureFlags); - - // Plugin registries - this.game.eventManager().post(new AbstractRegisterRegistryEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game)); - - // Freeze Sponge Root - Registries are now available - holder.registryHolder().freezeSpongeRootRegistry(); - } - case RELOADABLE -> { - if (!this.establishedPluginRegistries) { - // Plugin registry values - this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game)); - // Freeze Dynamic Registries - Values are now available - holder.registryHolder().freezeSpongeDynamicRegistries(); - - this.establishedPluginRegistries = true; - } - } - } + this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game, + holder.streamRegistries().collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())))); + + // Freeze Dynamic Registries - Values are now available + holder.registryHolder().freezeSpongeDynamicRegistries(true); } @Override @@ -209,31 +187,48 @@ public void callConstructEvent() { } @Override - public void establishServerRegistries(final Server server) { - SpongeRegistries.registerServerRegistries(server); + public void beginEstablishServerRegistries(final RegistryHolder server) { + SpongeRegistries.registerServerRegistries((SpongeRegistryHolder) server, this.featureFlags); + + ((SpongeRegistryHolder) server).registryHolder().featureFlagSet(this.featureFlags); - this.game.eventManager().post(new AbstractRegisterRegistryEvent.EngineScopedImpl<>(Cause.of(EventContext.empty(), this.game), this.game, - server)); + this.game.eventManager().post( + AbstractRegisterRegistryEvent.EngineScopedImpl.server(Cause.of(EventContext.empty(), this.game), this.game, server)); ((SpongeRegistryHolder) server).registryHolder().freezeSpongeRootRegistry(); - this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.EngineScopedImpl<>(Cause.of(EventContext.empty(), this.game), - this.game, server)); + this.processServerRegistries(server, server.streamRegistries(RegistryRoots.SPONGE) + .filter(r -> !r.type().equals(RegistryTypes.ADVANCEMENT) && !r.type().equals(RegistryTypes.RECIPE))); + } + + @Override + public void processServerRegistries(final RegistryHolder server, final Stream> registries) { + final Map, org.spongepowered.api.registry.Registry> map = + registries.collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())); + if (!map.isEmpty()) { + map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$setRegistryHolder(server)); + this.game.eventManager().post(AbstractRegisterRegistryValueEvent.EngineScopedImpl.server(Cause.of(EventContext.empty(), this.game), this.game, server, map)); + map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$markEventCalled()); + ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(false); + } + } - ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(); + @Override + public void endEstablishServerRegistries(final RegistryHolder server) { + ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(true); } @Override public void establishClientRegistries(final Client client) { - this.game.eventManager().post(new AbstractRegisterRegistryEvent.EngineScopedImpl<>(Cause.of(EventContext.empty(), this.game), this.game, - client)); + this.game.eventManager().post( + AbstractRegisterRegistryEvent.EngineScopedImpl.client(Cause.of(EventContext.empty(), this.game), this.game, client)); ((SpongeRegistryHolder) client).registryHolder().freezeSpongeRootRegistry(); - this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.EngineScopedImpl<>(Cause.of(EventContext.empty(), this.game), - this.game, client)); + this.game.eventManager().post(AbstractRegisterRegistryValueEvent.EngineScopedImpl.client(Cause.of(EventContext.empty(), this.game), + this.game, client, client.streamRegistries(RegistryRoots.SPONGE).collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())))); - ((SpongeRegistryHolder) client).registryHolder().freezeSpongeDynamicRegistries(); + ((SpongeRegistryHolder) client).registryHolder().freezeSpongeDynamicRegistries(true); } @Override diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index 79628a11ccd..8ece6efa10b 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -31,16 +31,13 @@ import net.minecraft.resources.ResourceLocation; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.advancement.AdvancementTemplate; +import org.spongepowered.api.advancement.Advancement; import org.spongepowered.api.advancement.DisplayInfo; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.util.Tuple; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.advancements.AdvancementBridge; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.common.util.SpongeCriterionUtil; import java.util.List; @@ -48,67 +45,70 @@ import java.util.Objects; import java.util.Optional; -public final class SpongeAdvancementBuilder extends AbstractResourceKeyedBuilder implements AdvancementTemplate.Builder.RootStep { +public final class SpongeAdvancementBuilder implements Advancement.Builder.RootStep { private @Nullable ResourceLocation parent; private AdvancementCriterion criterion; private @Nullable DisplayInfo displayInfo; private @Nullable ResourceLocation backgroundPath; - private DataPack pack = DataPacks.ADVANCEMENT; public SpongeAdvancementBuilder() { this.reset(); } @Override - public AdvancementTemplate.Builder parent(@Nullable AdvancementTemplate parent) { - return this.parent(parent.key()); - } - - @Override - public AdvancementTemplate.Builder parent(@Nullable ResourceKey parent) { + public Advancement.Builder parent(final ResourceKey parent) { this.parent = (ResourceLocation) (Object) parent; this.backgroundPath = null; return this; } @Override - public AdvancementTemplate.Builder.RootStep root() { + public Advancement.Builder.RootStep root() { this.parent = null; return this; } @Override - public AdvancementTemplate.Builder background(ResourceKey backgroundPath) { + public Advancement.Builder background(final ResourceKey backgroundPath) { this.backgroundPath = (ResourceLocation) (Object) backgroundPath; return this; } @Override - public AdvancementTemplate.Builder criterion(AdvancementCriterion criterion) { + public Advancement.Builder criterion(final AdvancementCriterion criterion) { Objects.requireNonNull(criterion, "criterion"); this.criterion = criterion; return this; } @Override - public AdvancementTemplate.Builder displayInfo(@Nullable DisplayInfo displayInfo) { + public Advancement.Builder displayInfo(final @Nullable DisplayInfo displayInfo) { this.displayInfo = displayInfo; return this; } @Override - public AdvancementTemplate.Builder reset() { + public Advancement.Builder from(final Advancement value) { + this.parent = (ResourceLocation) (Object) value.parent().orElse(null); + this.criterion = value.criterion(); + this.displayInfo = value.displayInfo().orElse(null); + this.backgroundPath = ((net.minecraft.advancements.Advancement) (Object) value).display() + .map(net.minecraft.advancements.DisplayInfo::getBackground).map(Optional::get).orElse(null); + return this; + } + + @Override + public Advancement.Builder reset() { this.criterion = AdvancementCriterion.empty(); this.displayInfo = null; this.parent = null; this.backgroundPath = null; - this.pack = DataPacks.ADVANCEMENT; return this; } @Override - public AdvancementTemplate build0() { + public Advancement build() { final Tuple>, List>> result = SpongeCriterionUtil.toVanillaCriteriaData(this.criterion); final AdvancementRewards rewards = AdvancementRewards.EMPTY; @@ -123,6 +123,6 @@ public AdvancementTemplate build0() { di.isHidden())); final var advancement = new net.minecraft.advancements.Advancement(Optional.ofNullable((this.parent)), displayInfo, rewards, result.first(), new AdvancementRequirements(result.second()), false); ((AdvancementBridge) (Object) advancement).bridge$setCriterion(this.criterion); - return new SpongeAdvancementTemplate(this.key, advancement, this.pack); + return (Advancement) (Object) advancement; } } diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementTemplate.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementTemplate.java deleted file mode 100644 index 51cc0aa2914..00000000000 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementTemplate.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.advancement; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.ResourceLocation; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.advancement.Advancement; -import org.spongepowered.api.advancement.AdvancementTemplate; -import org.spongepowered.api.advancement.AdvancementTree; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.common.SpongeCommon; - -import java.util.Optional; - -public record SpongeAdvancementTemplate(ResourceKey key, - net.minecraft.advancements.Advancement representedAdvancement, - DataPack pack - ) implements AdvancementTemplate { - - @Override - public Advancement advancement() { - return (Advancement) (Object) this.representedAdvancement; - } - - @Override - public Optional tree() { - if (this.representedAdvancement.parent().isEmpty()) { - var node = SpongeCommon.server().getAdvancements().tree().get((ResourceLocation) (Object) this.key); - return Optional.of((AdvancementTree) node); - } - return Optional.empty(); - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - return this.advancement().toContainer(); - } - - public static JsonElement encode(final net.minecraft.advancements.Advancement advancement) { - final DataResult encoded = net.minecraft.advancements.Advancement.CODEC.encodeStart(JsonOps.INSTANCE, advancement); - final JsonObject element = encoded.result().get().getAsJsonObject(); - if (element.get("rewards") != null && element.get("rewards").isJsonNull()) { - element.remove("rewards"); - } - return element; - } - - public static JsonElement encode(final AdvancementTemplate template, final RegistryAccess registryAccess) { - return SpongeAdvancementTemplate.encode((net.minecraft.advancements.Advancement) (Object) template.advancement()); - } - -} diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeBuilder.java b/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeBuilder.java new file mode 100644 index 00000000000..86a80a08da7 --- /dev/null +++ b/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeBuilder.java @@ -0,0 +1,120 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.adventure; + +import net.kyori.adventure.text.format.Style; +import net.minecraft.network.chat.ChatTypeDecoration; +import org.spongepowered.api.adventure.ChatType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public final class SpongeChatTypeBuilder implements ChatType.Builder { + + private String translationKey; + private net.minecraft.network.chat.Style style; + private List parameters; + + private ChatTypeDecoration narration; + + public SpongeChatTypeBuilder() { + this.reset(); + } + + @Override + public ChatType.Builder from(final ChatType value) { + net.minecraft.network.chat.ChatType chatType = (net.minecraft.network.chat.ChatType) (Object) value; + this.translationKey = chatType.chat().translationKey(); + this.parameters = chatType.chat().parameters(); + this.style = chatType.chat().style(); + this.narration = chatType.narration(); + return this; + } + + @Override + public ChatType.Builder translationKey(final String translationKey) { + this.translationKey = translationKey; + return this; + } + + @Override + public ChatType.Builder style(final Style style) { + this.style = SpongeAdventure.asVanilla(style); + return this; + } + + private void addParameter(final ChatTypeDecoration.Parameter parameter) { + if (this.parameters.contains(parameter)) { + // TODO check + // throw new IllegalStateException("Parameter already exists"); + } + this.parameters.add(parameter); + } + + @Override + public ChatType.Builder addSender() { + if (this.parameters == null) { + this.parameters = new ArrayList<>(); + } + this.addParameter(ChatTypeDecoration.Parameter.SENDER); + return this; + } + + @Override + public ChatType.Builder addContent() { + if (this.parameters == null) { + this.parameters = new ArrayList<>(); + } + this.addParameter(ChatTypeDecoration.Parameter.CONTENT); + return this; + } + + @Override + public ChatType.Builder addTarget() { + if (this.parameters == null) { + this.parameters = new ArrayList<>(); + } + this.addParameter(ChatTypeDecoration.Parameter.TARGET); + return this; + } + + @Override + public ChatType.Builder reset() { + this.translationKey = null; + this.style = net.minecraft.network.chat.Style.EMPTY; + this.parameters = null; + this.narration = ChatTypeDecoration.withSender("chat.type.text.narrate"); + return this; + } + + @Override + public ChatType build() { + Objects.requireNonNull(this.translationKey, "name"); + Objects.requireNonNull(this.parameters, "parameter"); + Objects.requireNonNull(this.style, "style"); + return (ChatType) (Object) new net.minecraft.network.chat.ChatType(new ChatTypeDecoration(this.translationKey, this.parameters, this.style), this.narration); + } +} diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeTemplate.java b/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeTemplate.java deleted file mode 100644 index bdc5636e3a6..00000000000 --- a/src/main/java/org/spongepowered/common/adventure/SpongeChatTypeTemplate.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.adventure; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.kyori.adventure.text.format.Style; -import net.minecraft.core.RegistryAccess; -import net.minecraft.network.chat.ChatType; -import net.minecraft.network.chat.ChatTypeDecoration; -import net.minecraft.resources.RegistryOps; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.adventure.ChatTypeTemplate; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeChatTypeTemplate(ResourceKey key, ChatType representedType, DataPack pack) implements ChatTypeTemplate { - - @Override - public org.spongepowered.api.adventure.ChatType type() { - return (org.spongepowered.api.adventure.ChatType) (Object) this.representedType; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeChatTypeTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized ChatType:\n" + serialized, e); - } - } - - public static JsonElement encode(final ChatTypeTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return ChatType.DIRECT_CODEC.encodeStart(ops, (ChatType) (Object) template.type()).getOrThrow(); - } - - public static ChatType decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return ChatType.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static ChatTypeTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final ChatType parsed = SpongeChatTypeTemplate.decode(packEntry, registryAccess); - return new SpongeChatTypeTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - private String translationKey; - private net.minecraft.network.chat.Style style; - private List parameters; - - private ChatTypeDecoration narration; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Builder fromValue(final org.spongepowered.api.adventure.ChatType value) { - ChatType chatType = (ChatType) (Object) value; - this.translationKey = chatType.chat().translationKey(); - this.parameters = chatType.chat().parameters(); - this.style = chatType.chat().style(); - this.narration = chatType.narration(); - return this; - } - - @Override - public Builder translationKey(final String translationKey) { - this.translationKey = translationKey; - return this; - } - - @Override - public Builder style(final Style style) { - this.style = SpongeAdventure.asVanilla(style); - return this; - } - - private void addParameter(final ChatTypeDecoration.Parameter parameter) { - if (this.parameters.contains(parameter)) { - // TODO check - // throw new IllegalStateException("Parameter already exists"); - } - this.parameters.add(parameter); - } - - @Override - public Builder addSender() { - if (this.parameters == null) { - this.parameters = new ArrayList<>(); - } - this.addParameter(ChatTypeDecoration.Parameter.SENDER); - return this; - } - - @Override - public Builder addContent() { - if (this.parameters == null) { - this.parameters = new ArrayList<>(); - } - this.addParameter(ChatTypeDecoration.Parameter.CONTENT); - return this; - } - - @Override - public Builder addTarget() { - if (this.parameters == null) { - this.parameters = new ArrayList<>(); - } - this.addParameter(ChatTypeDecoration.Parameter.TARGET); - return this; - } - - @Override - public Function valueExtractor() { - return ChatTypeTemplate::type; - } - - @Override - public Builder reset() { - this.key = null; - this.pack = DataPacks.CHAT_TYPE; - this.translationKey = null; - this.style = net.minecraft.network.chat.Style.EMPTY; - this.parameters = null; - this.narration = ChatTypeDecoration.withSender("chat.type.text.narrate");; - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final ChatType chatType = SpongeChatTypeTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((org.spongepowered.api.adventure.ChatType) (Object) chatType); - return this; - } - - @Override - protected ChatTypeTemplate build0() { - Objects.requireNonNull(this.translationKey, "name"); - Objects.requireNonNull(this.parameters, "parameter"); - Objects.requireNonNull(this.style, "style"); - final ChatType chatType = new ChatType(new ChatTypeDecoration(this.translationKey, this.parameters, this.style), this.narration); - return new SpongeChatTypeTemplate(this.key, chatType, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/bridge/core/RegistryBridge.java b/src/main/java/org/spongepowered/common/bridge/core/RegistryBridge.java index 0ffe903bea2..c58561d4cfc 100644 --- a/src/main/java/org/spongepowered/common/bridge/core/RegistryBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/core/RegistryBridge.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.bridge.core; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.RegistryEntry; import org.spongepowered.api.registry.RegistryType; @@ -39,6 +40,8 @@ public interface RegistryBridge { Optional> bridge$get(ResourceKey key); + @Nullable RegistryEntry bridge$getEntry(ResourceKey key); + Stream> bridge$streamEntries(); } diff --git a/src/main/java/org/spongepowered/common/bridge/core/WritableRegistryBridge.java b/src/main/java/org/spongepowered/common/bridge/core/WritableRegistryBridge.java index 3ea7241e75d..cab05649a50 100644 --- a/src/main/java/org/spongepowered/common/bridge/core/WritableRegistryBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/core/WritableRegistryBridge.java @@ -24,10 +24,30 @@ */ package org.spongepowered.common.bridge.core; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.registry.InitialRegistryData; + +import java.util.function.Supplier; +import java.util.stream.Stream; + public interface WritableRegistryBridge { boolean bridge$isDynamic(); void bridge$setDynamic(boolean isDynamic); + void bridge$setRegistryHolder(RegistryHolder registryHolder); + + void bridge$addDependencies(Supplier> supplier, RegistryType... dependencies); + + void bridge$addDependencies(Runnable runnable, RegistryType... dependencies); + + Stream> bridge$pendingDependencies(); + + void bridge$markEventCalled(); + + boolean bridge$eventCalled(); + + void bridge$unfreeze(); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/ResultFunctionRecipe.java b/src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java similarity index 86% rename from src/main/java/org/spongepowered/common/item/recipe/ResultFunctionRecipe.java rename to src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java index 18417201494..296187201d3 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ResultFunctionRecipe.java +++ b/src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.item.recipe; +package org.spongepowered.common.bridge.resources; -import java.util.Optional; +import org.spongepowered.api.registry.RegistryHolder; -public interface ResultFunctionRecipe { - Optional resultFunctionId(); +public interface RegistryDataLoader_LoaderBridge { + RegistryHolder bridge$registryHolder(); } diff --git a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java index 3c701b9513a..b6f7c9c4085 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java @@ -29,6 +29,7 @@ import net.minecraft.util.thread.BlockableEventLoop; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Game; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.user.SpongeUserManager; @@ -45,4 +46,6 @@ public interface MinecraftServerBridge { SpongeUserManager bridge$userManager(); BlockableEventLoop bridge$spongeMainThreadExecutor(); + + void bridge$reloadServerRegistries(RegistryHolder holder); } diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/dimension/LevelStemBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/dimension/LevelStemBridge.java index 087a0ed95ea..23eb8b0dc3c 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/dimension/LevelStemBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/dimension/LevelStemBridge.java @@ -29,7 +29,6 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.LevelStem; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.data.DataManipulator; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.common.world.server.SpongeWorldTemplate; import org.spongepowered.math.vector.Vector3i; @@ -62,7 +61,5 @@ public interface LevelStemBridge { LevelStem bridge$decorateData(SpongeWorldTemplate.SpongeDataSection data); - LevelStem bridge$decorateData(DataManipulator data); - - SpongeWorldTemplate.SpongeDataSection bridge$createData(); + boolean bridge$hasLegacyData(); } diff --git a/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java b/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java index 4fc69d8a08c..2d0ca14a3e8 100644 --- a/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java +++ b/src/main/java/org/spongepowered/common/command/SpongeParameterizedCommand.java @@ -40,6 +40,7 @@ import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.Flag; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.brigadier.SpongeParameterTranslator; import org.spongepowered.common.command.brigadier.SpongeStringReader; import org.spongepowered.common.command.brigadier.dispatcher.SpongeCommandDispatcher; @@ -66,6 +67,7 @@ public final class SpongeParameterizedCommand implements Command.Parameterized { private final @Nullable CommandExecutor executor; private final boolean isTerminal; private @Nullable SpongeCommandManager commandManager; + private @Nullable RegistryHolder registryHolder; private @Nullable SpongeCommandDispatcher cachedDispatcher; SpongeParameterizedCommand( @@ -87,9 +89,10 @@ public final class SpongeParameterizedCommand implements Command.Parameterized { this.isTerminal = isTerminal; } - public void setCommandManager(final SpongeCommandManager commandManager) { + public void setCommandManager(final SpongeCommandManager commandManager, final RegistryHolder registryHolder) { this.cachedDispatcher = null; this.commandManager = commandManager; + this.registryHolder = registryHolder; } @Override @@ -172,10 +175,10 @@ private SpongeCommandDispatcher getCachedDispatcher() { } public LiteralCommandNode buildWithAlias(final String primaryAlias) { - return this.buildWithAliases(Collections.singleton(primaryAlias)).iterator().next(); + return this.buildWithAliases(this.registryHolder, Collections.singleton(primaryAlias)).iterator().next(); } - public Collection> buildWithAliases(final Collection aliases) { - return SpongeParameterTranslator.INSTANCE.createCommandTree(this, aliases); + public Collection> buildWithAliases(final RegistryHolder registryHolder, final Collection aliases) { + return SpongeParameterTranslator.INSTANCE.createCommandTree(registryHolder, this, aliases); } } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/SpongeParameterTranslator.java b/src/main/java/org/spongepowered/common/command/brigadier/SpongeParameterTranslator.java index f2871715863..69229d9874a 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/SpongeParameterTranslator.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/SpongeParameterTranslator.java @@ -33,6 +33,7 @@ import org.spongepowered.api.command.Command; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.Flag; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.brigadier.argument.ArgumentParser; import org.spongepowered.common.command.brigadier.argument.CustomArgumentParser; import org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode; @@ -65,7 +66,8 @@ private SpongeParameterTranslator() { } @SuppressWarnings({"unchecked", "rawtypes"}) - public Collection> createCommandTree(final Command.Parameterized command, final Collection aliases) { + public Collection> createCommandTree(final RegistryHolder registryHolder, + final Command.Parameterized command, final Collection aliases) { if (aliases.isEmpty()) { throw new IllegalArgumentException("Aliases must not be empty."); } @@ -86,16 +88,16 @@ public Collection> createCommandTree(fina final SpongeLiteralCommandNode commandNode = new SpongeLiteralCommandNode(basicNode); if (executor != null) { - this.createAndAttachNode(Collections.singleton(commandNode), command.parameters(), executor, true, true); + this.createAndAttachNode(registryHolder, Collections.singleton(commandNode), command.parameters(), executor, true, true); } for (final Parameter.Subcommand subcommand : command.subcommands()) { final Collection> builtSubcommand = - this.createCommandTree(subcommand.command(), subcommand.aliases()); + this.createCommandTree(registryHolder, subcommand.command(), subcommand.aliases()); builtSubcommand.forEach(commandNode::addChild); } - this.createFlags(commandNode, command.flags(), executor); + this.createFlags(registryHolder, commandNode, command.flags(), executor); final List> allCommandNodes = new ArrayList<>(); allCommandNodes.add(commandNode); @@ -126,7 +128,7 @@ public Collection> createCommandTree(fina } @SuppressWarnings({"unchecked", "rawtypes"}) - private void createFlags(final LiteralCommandNode node, final List flags, + private void createFlags(final RegistryHolder registryHolder, final LiteralCommandNode node, final List flags, final @Nullable SpongeCommandExecutorWrapper wrapper) { final Collection> nodesToAddChildrenTo = new ArrayList<>(); for (final Flag flag : flags) { @@ -138,6 +140,7 @@ private void createFlags(final LiteralCommandNode node, fina final SpongeFlagLiteralCommandNode flagNode = new SpongeFlagLiteralCommandNode(flagLiteral, flag); if (flag.associatedParameter().isPresent()) { toBeRedirected = this.createAndAttachNode( + registryHolder, Collections.singleton(flagNode), Collections.singletonList(flag.associatedParameter().get()), wrapper, @@ -184,6 +187,7 @@ private void createFlags(final LiteralCommandNode node, fina } private Collection> createAndAttachNode( + final RegistryHolder registryHolder, final Collection> parents, final List children, final @Nullable SpongeCommandExecutorWrapper executorWrapper, @@ -210,6 +214,7 @@ private Collection> createAndAttachNod // If the child is a subcommand, get the subcommand and attach it. At this point, // we're done with the chain and we break out. final Collection> nodes = this.createCommandTree( + registryHolder, subcommands.command(), subcommands.aliases() ); @@ -231,6 +236,7 @@ private Collection> createAndAttachNod parametersToAttachTo = new ArrayList<>(); for (final Parameter p : ((SpongeFirstOfParameter) parameter).childParameters()) { final Collection> branchNodesToAttachTo = this.createAndAttachNode( + registryHolder, nodesToAttachTo, Collections.singletonList(p), executorWrapper, @@ -241,6 +247,7 @@ private Collection> createAndAttachNod } else { // not so fancy stuff, it's a sequence, returns the terminal nodes of the block parametersToAttachTo = new ArrayList<>(this.createAndAttachNode( + registryHolder, nodesToAttachTo, ((SpongeMultiParameter) parameter).childParameters(), executorWrapper, @@ -278,7 +285,7 @@ private Collection> createAndAttachNod key = key + suffix; } final SpongeArgumentCommandNodeBuilder thisNode = SpongeParameterTranslator - .createArgumentNodeBuilders(valueParameter, suffix == null ? null : suffix.toString()); + .createArgumentNodeBuilders(registryHolder, valueParameter, suffix == null ? null : suffix.toString()); if (isTerminal) { thisNode.executes(executorWrapper); @@ -334,20 +341,24 @@ private Collection> createAndAttachNod @SuppressWarnings({"unchecked", "rawtypes"}) private static @NonNull SpongeArgumentCommandNodeBuilder createArgumentNodeBuilders( + final RegistryHolder registryHolder, final SpongeParameterValue parameter, final @Nullable String suffix) { ArgumentParser type = parameter.argumentTypeIfStandard(); if (type == null) { - type = new CustomArgumentParser<>(parameter.parsers(), parameter.completer(), false); + type = new CustomArgumentParser<>( + (List) parameter.parsers().stream().map(p -> p.bind(registryHolder)).toList(), parameter.completer().bind(registryHolder), false); + } else { + type = type.bind(registryHolder); } final SpongeArgumentCommandNodeBuilder argumentBuilder = new SpongeArgumentCommandNodeBuilder<>( SpongeParameterKey.getSpongeKey(parameter.key()), type, - parameter.completer(), - parameter.modifier().orElse(null), + parameter.completer().bind(registryHolder), + parameter.modifier().map(m -> m.bind(registryHolder)).orElse(null), parameter.valueUsage().orElse(null), suffix, parameter.isOptional() diff --git a/src/main/java/org/spongepowered/common/command/brigadier/argument/AbstractArgumentParser.java b/src/main/java/org/spongepowered/common/command/brigadier/argument/AbstractArgumentParser.java index 5d78764b697..8885d70cedd 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/argument/AbstractArgumentParser.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/argument/AbstractArgumentParser.java @@ -36,6 +36,7 @@ import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.ValueParameter; import org.spongepowered.api.command.parameter.managed.ValueParameterModifier; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.brigadier.SpongeStringReader; import org.spongepowered.common.command.brigadier.context.SpongeCommandContext; import org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder; @@ -94,4 +95,8 @@ public boolean doesNotRead() { return false; } + @Override + public AbstractArgumentParser bind(final RegistryHolder registryHolder) { + return this; + } } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/argument/ArgumentParser.java b/src/main/java/org/spongepowered/common/command/brigadier/argument/ArgumentParser.java index 3dc705b38af..581e8684304 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/argument/ArgumentParser.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/argument/ArgumentParser.java @@ -33,6 +33,7 @@ import org.spongepowered.api.command.exception.ArgumentParseException; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.ValueParameterModifier; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.brigadier.SpongeStringReader; import org.spongepowered.common.command.brigadier.context.SpongeCommandContextBuilder; import org.spongepowered.common.util.Constants; @@ -90,4 +91,7 @@ default boolean hasClientNativeCompletions() { return false; } + default ArgumentParser bind(RegistryHolder registryHolder) { + return this; + } } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/argument/BindableValueParameter.java b/src/main/java/org/spongepowered/common/command/brigadier/argument/BindableValueParameter.java new file mode 100644 index 00000000000..b3f4fdf0dc1 --- /dev/null +++ b/src/main/java/org/spongepowered/common/command/brigadier/argument/BindableValueParameter.java @@ -0,0 +1,70 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.command.brigadier.argument; + +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.command.CommandCompletion; +import org.spongepowered.api.command.exception.ArgumentParseException; +import org.spongepowered.api.command.parameter.ArgumentReader; +import org.spongepowered.api.command.parameter.CommandContext; +import org.spongepowered.api.command.parameter.Parameter; +import org.spongepowered.api.command.parameter.managed.ValueParameter; +import org.spongepowered.api.command.parameter.managed.standard.ResourceKeyedValueParameter; +import org.spongepowered.api.registry.RegistryHolder; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public final class BindableValueParameter implements ResourceKeyedValueParameter { + + private final ResourceKey key; + private final Function> function; + + public BindableValueParameter(final ResourceKey key, final Function> function) { + this.key = key; + this.function = function; + } + + @Override + public ValueParameter bind(final RegistryHolder registryHolder) { + return this.function.apply(registryHolder); + } + + @Override + public List complete(final CommandContext context, final String currentInput) { + return List.of(); + } + + @Override + public Optional parseValue(final Parameter.Key parameterKey, final ArgumentReader.Mutable reader, final CommandContext.Builder context) throws ArgumentParseException { + return Optional.empty(); + } + + @Override + public ResourceKey key() { + return this.key; + } +} diff --git a/src/main/java/org/spongepowered/common/command/brigadier/argument/StandardArgumentParser.java b/src/main/java/org/spongepowered/common/command/brigadier/argument/StandardArgumentParser.java index 92affbb8265..45666543f62 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/argument/StandardArgumentParser.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/argument/StandardArgumentParser.java @@ -41,6 +41,7 @@ import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.ValueParameter; import org.spongepowered.api.command.parameter.managed.ValueParameterModifier; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.command.SpongeCommandCompletion; import org.spongepowered.common.command.brigadier.SpongeStringReader; @@ -144,6 +145,11 @@ public List complete(final @NonNull CommandCause context, fin } } + @Override + public StandardArgumentParser bind(final RegistryHolder registryHolder) { + return this; + } + @FunctionalInterface public interface Converter { Converter IDENTITY = (reader, cause, input) -> input; diff --git a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java index 4db64cbf0c0..78a21e7476d 100644 --- a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java +++ b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java @@ -62,13 +62,13 @@ import org.spongepowered.api.command.manager.CommandManager; import org.spongepowered.api.command.manager.CommandMapping; import org.spongepowered.api.command.registrar.CommandRegistrar; -import org.spongepowered.api.command.registrar.CommandRegistrarType; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.service.pagination.PaginationService; import org.spongepowered.api.service.permission.Subject; @@ -437,18 +437,17 @@ private void prettyPrintThrowableError(final Throwable thr, final String command } } - public void init() { + public void init(final RegistryHolder registryHolder) { final Cause cause = PhaseTracker.getInstance().currentCause(); final Set> usedTokens = new HashSet<>(); - Sponge.game().registry(RegistryTypes.COMMAND_REGISTRAR_TYPE).streamEntries().forEach(entry -> { - final CommandRegistrarType type = entry.value(); + registryHolder.registry(RegistryTypes.COMMAND_REGISTRAR_TYPE).stream().forEach(type -> { // someone's gonna do it, let's not let them take us down. final TypeToken handledType = type.handledType(); if (handledType == null) { SpongeCommon.logger().error("Registrar '{}' did not provide a handledType, skipping...", type.getClass()); } else if (usedTokens.add(handledType)) { // we haven't done it yet // Add the command registrar - final CommandRegistrar registrar = type.create(this); + final CommandRegistrar registrar = type.create(this, registryHolder); this.knownRegistrars.put(GenericTypeReflector.erase(type.handledType().getType()), registrar); if (registrar instanceof BrigadierCommandRegistrar) { this.brigadierRegistrar = (BrigadierCommandRegistrar) registrar; @@ -456,7 +455,7 @@ public void init() { this.registerInternalCommands((SpongeParameterizedCommandRegistrar) registrar); } - this.game.eventManager().post(this.createEvent(cause, this.game, registrar)); + this.game.eventManager().post(this.createEvent(cause, this.game, registrar, registryHolder)); } else { SpongeCommon.logger() .warn("Command type '{}' has already been collected, skipping request from {}", @@ -546,11 +545,12 @@ public Collection getAliasesForCause(final CommandCause cause) { return aliases; } - private > RegisterCommandEventImpl createEvent(final Cause cause, final Game game, final R registrar) { + private > RegisterCommandEventImpl createEvent(final Cause cause, final Game game, final R registrar, final RegistryHolder registryHolder) { return new RegisterCommandEventImpl<>( cause, game, - registrar + registrar, + registryHolder ); } diff --git a/src/main/java/org/spongepowered/common/command/registrar/BrigadierCommandRegistrar.java b/src/main/java/org/spongepowered/common/command/registrar/BrigadierCommandRegistrar.java index 2f9548993b1..88daffafa0b 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/BrigadierCommandRegistrar.java +++ b/src/main/java/org/spongepowered/common/command/registrar/BrigadierCommandRegistrar.java @@ -44,6 +44,7 @@ import org.spongepowered.api.command.manager.CommandMapping; import org.spongepowered.api.command.registrar.CommandRegistrar; import org.spongepowered.api.command.registrar.CommandRegistrarType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.util.Tuple; import org.spongepowered.common.command.SpongeCommandCompletion; import org.spongepowered.common.command.brigadier.dispatcher.SpongeCommandDispatcher; @@ -76,9 +77,9 @@ public final class BrigadierCommandRegistrar implements BrigadierBasedRegistrar< ); private final SpongeCommandManager manager; - private SpongeCommandDispatcher dispatcher; + private final SpongeCommandDispatcher dispatcher; - public BrigadierCommandRegistrar(final CommandManager.Mutable manager) { + public BrigadierCommandRegistrar(final CommandManager.Mutable manager, final RegistryHolder registryHolder) { this.manager = (SpongeCommandManager) manager; this.dispatcher = new SpongeCommandDispatcher(this.manager); } diff --git a/src/main/java/org/spongepowered/common/command/registrar/SpongeCommandRegistrarType.java b/src/main/java/org/spongepowered/common/command/registrar/SpongeCommandRegistrarType.java index e0ce31c54d1..3fc94920442 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/SpongeCommandRegistrarType.java +++ b/src/main/java/org/spongepowered/common/command/registrar/SpongeCommandRegistrarType.java @@ -29,16 +29,17 @@ import org.spongepowered.api.command.manager.CommandManager; import org.spongepowered.api.command.registrar.CommandRegistrar; import org.spongepowered.api.command.registrar.CommandRegistrarType; +import org.spongepowered.api.registry.RegistryHolder; -import java.util.function.Function; +import java.util.function.BiFunction; public final class SpongeCommandRegistrarType implements CommandRegistrarType { private final TypeToken handledType; - private final Function> supplier; + private final BiFunction> supplier; public SpongeCommandRegistrarType( final TypeToken handledType, - final Function> supplier + final BiFunction> supplier ) { this.handledType = handledType; this.supplier = supplier; @@ -46,7 +47,7 @@ public SpongeCommandRegistrarType( public SpongeCommandRegistrarType( final Class handledType, - final Function> supplier + final BiFunction> supplier ) { this(TypeToken.get(handledType), supplier); } @@ -57,7 +58,7 @@ public SpongeCommandRegistrarType( } @Override - public @NonNull CommandRegistrar create(final CommandManager.@NonNull Mutable manager) { - return this.supplier.apply(manager); + public @NonNull CommandRegistrar create(final CommandManager.@NonNull Mutable manager, final RegistryHolder registryHolder) { + return this.supplier.apply(manager, registryHolder); } } diff --git a/src/main/java/org/spongepowered/common/command/registrar/SpongeParameterizedCommandRegistrar.java b/src/main/java/org/spongepowered/common/command/registrar/SpongeParameterizedCommandRegistrar.java index dc02fbff51a..05b612d8f3d 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/SpongeParameterizedCommandRegistrar.java +++ b/src/main/java/org/spongepowered/common/command/registrar/SpongeParameterizedCommandRegistrar.java @@ -39,6 +39,7 @@ import org.spongepowered.api.command.manager.CommandManager; import org.spongepowered.api.command.manager.CommandMapping; import org.spongepowered.api.command.registrar.CommandRegistrarType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.SpongeCommandCompletion; import org.spongepowered.common.command.SpongeParameterizedCommand; import org.spongepowered.common.command.brigadier.dispatcher.SpongeCommandDispatcher; @@ -66,10 +67,12 @@ public final class SpongeParameterizedCommandRegistrar implements BrigadierBased ); private final CommandManager.Mutable commandManager; + private final RegistryHolder registryHolder; private final Map commandMap = new HashMap<>(); - public SpongeParameterizedCommandRegistrar(final CommandManager.Mutable commandManager) { + public SpongeParameterizedCommandRegistrar(final CommandManager.Mutable commandManager, final RegistryHolder registryHolder) { this.commandManager = commandManager; + this.registryHolder = registryHolder; } @Override @@ -102,8 +105,8 @@ private SpongeCommandManager commandManager() { null ); - this.createNode(mapping, command).forEach(this.commandManager().getDispatcher()::register); - ((SpongeParameterizedCommand) command).setCommandManager(this.commandManager()); + this.createNode(this.registryHolder, mapping, command).forEach(this.commandManager().getDispatcher()::register); + ((SpongeParameterizedCommand) command).setCommandManager(this.commandManager(), this.registryHolder); this.commandMap.put(mapping, command); return mapping; } @@ -194,11 +197,11 @@ private String createCommandString(final String command, final String argument) return command + " " + argument; } - private Collection> createNode(final CommandMapping mapping, final Command.Parameterized command) { + private Collection> createNode(final RegistryHolder registryHolder, final CommandMapping mapping, final Command.Parameterized command) { if (!(command instanceof SpongeParameterizedCommand)) { throw new IllegalArgumentException("Command must be a SpongeParameterizedCommand!"); } - return ((SpongeParameterizedCommand) command).buildWithAliases(mapping.allAliases()); + return ((SpongeParameterizedCommand) command).buildWithAliases(registryHolder, mapping.allAliases()); } } diff --git a/src/main/java/org/spongepowered/common/command/registrar/SpongeRawCommandRegistrar.java b/src/main/java/org/spongepowered/common/command/registrar/SpongeRawCommandRegistrar.java index 5102354ecc5..698a28c3b9b 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/SpongeRawCommandRegistrar.java +++ b/src/main/java/org/spongepowered/common/command/registrar/SpongeRawCommandRegistrar.java @@ -37,6 +37,7 @@ import org.spongepowered.api.command.manager.CommandMapping; import org.spongepowered.api.command.registrar.CommandRegistrar; import org.spongepowered.api.command.registrar.CommandRegistrarType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.command.brigadier.SpongeStringReader; import org.spongepowered.plugin.PluginContainer; @@ -55,9 +56,11 @@ public final class SpongeRawCommandRegistrar implements CommandRegistrar commands = new HashMap<>(); private final CommandManager.Mutable manager; + private final RegistryHolder registryHolder; - SpongeRawCommandRegistrar(final CommandManager.Mutable manager) { + SpongeRawCommandRegistrar(final CommandManager.Mutable manager, final RegistryHolder registryHolder) { this.manager = manager; + this.registryHolder = registryHolder; } @Override @@ -75,7 +78,7 @@ public CommandMapping register( final CommandMapping mapping = this.manager.registerAlias( this, container, - command.commandTree(), + command.commandTree(this.registryHolder), primaryAlias, secondaryAliases ); diff --git a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java index 984d916c6c0..0751816ece8 100644 --- a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java +++ b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java @@ -29,6 +29,7 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; +import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.applaunch.config.core.ConfigHandle; import org.spongepowered.common.applaunch.config.core.SpongeConfigs; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; @@ -37,6 +38,7 @@ import org.spongepowered.common.config.inheritable.InheritableConfigHandle; import org.spongepowered.common.config.inheritable.WorldConfig; import org.spongepowered.common.config.tracker.TrackerConfig; +import org.spongepowered.configurate.ConfigurationOptions; import java.io.IOException; import java.nio.file.DirectoryStream; @@ -58,6 +60,8 @@ public final class SpongeGameConfigs { private static ConfigHandle trackerConfigAdapter; private static volatile InheritableConfigHandle global; + private static ConfigurationOptions OPTIONS = SpongeConfigs.OPTIONS.serializers(c -> c.registerAll(SpongeAdventure.CONFIGURATE.serializers())); + private SpongeGameConfigs() { } @@ -107,7 +111,7 @@ public static InheritableConfigHandle createWorld(final @Nullable R } } try { - final InheritableConfigHandle config = new InheritableConfigHandle<>(WorldConfig.class, BaseConfig::transformation, SpongeConfigs.createLoader(configPath), + final InheritableConfigHandle config = new InheritableConfigHandle<>(WorldConfig.class, BaseConfig::transformation, SpongeConfigs.createLoader(configPath, SpongeGameConfigs.OPTIONS), SpongeGameConfigs.getGlobalInheritable()); config.load(); return config; @@ -147,7 +151,7 @@ public static InheritableConfigHandle getGlobalInheritable() { try { SpongeGameConfigs.global = new InheritableConfigHandle<>(GlobalConfig.class, BaseConfig::transformation, - SpongeConfigs.createLoader(SpongeConfigs.getDirectory().resolve(GlobalConfig.FILE_NAME)), null); + SpongeConfigs.createLoader(SpongeConfigs.getDirectory().resolve(GlobalConfig.FILE_NAME), SpongeGameConfigs.OPTIONS), null); SpongeGameConfigs.global.load(); } catch (final IOException e) { SpongeGameConfigs.LOGGER.error("Unable to load global world configuration in {}. Sponge will run with default settings", diff --git a/src/main/java/org/spongepowered/common/config/inheritable/WorldCategory.java b/src/main/java/org/spongepowered/common/config/inheritable/WorldCategory.java index 9f6b81913dd..0aa59383fe4 100644 --- a/src/main/java/org/spongepowered/common/config/inheritable/WorldCategory.java +++ b/src/main/java/org/spongepowered/common/config/inheritable/WorldCategory.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.config.inheritable; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; import org.spongepowered.configurate.objectmapping.meta.Setting; @@ -50,4 +52,25 @@ public final class WorldCategory { @Setting("log-auto-save") @Comment("Log when a world auto-saves its chunk data. Note: This may be spammy depending on the auto-save-interval configured for world.") public final boolean logAutoSave = false; + + @Setting(value = "load-on-startup") + @Comment("If 'true', this world will load on startup.") + public boolean loadOnStartup = true; + + @Setting(value = "keep-spawn-loaded") + @Comment("If 'true', this worlds spawn will remain loaded with no players.") + public boolean keepSpawnLoaded = true; + + @Setting(value = "pvp-enabled") + @Comment("If 'true', this world will allow PVP combat.") + public Boolean pvpEnabled; + + @Setting(value = "view-distance") + public Integer viewDistance; + + @Setting(value = "serialization-behavior") + public SerializationBehavior serializationBehavior; + + @Setting("display-name") + public Component displayName; } diff --git a/src/main/java/org/spongepowered/common/data/fixer/CombineMapsCodec.java b/src/main/java/org/spongepowered/common/data/fixer/CombineMapsCodec.java index 95f56113c5c..e6e13cdc5de 100644 --- a/src/main/java/org/spongepowered/common/data/fixer/CombineMapsCodec.java +++ b/src/main/java/org/spongepowered/common/data/fixer/CombineMapsCodec.java @@ -78,10 +78,13 @@ public DataResult decode(final DynamicOps ops, final MapLike input) public RecordBuilder encode(final A input, final DynamicOps ops, final RecordBuilder prefix) { final RecordBuilder firstResult = this.first.encode(input, ops, prefix); - final DataResult secondResult = this.second.encode(this.encodeAction.apply(input), ops, ops.createMap(Collections.emptyMap())); + final B rawSecondData = this.encodeAction.apply(input); + if (rawSecondData != null) { + final DataResult secondResult = this.second.encode(rawSecondData, ops, ops.createMap(Collections.emptyMap())); - // Need an actual result and not a builder: - firstResult.add(this.mergeKey(), secondResult); + // Need an actual result and not a builder: + firstResult.add(this.mergeKey(), secondResult); + } return firstResult; } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/LevelStemData.java b/src/main/java/org/spongepowered/common/data/provider/world/LevelStemData.java index b435651a4e0..70dc1e745e8 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/LevelStemData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/LevelStemData.java @@ -26,14 +26,10 @@ import net.minecraft.world.level.dimension.LevelStem; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.entity.living.player.gamemode.GameMode; import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.difficulty.Difficulty; import org.spongepowered.api.world.generation.ChunkGenerator; -import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; -// Used as delegate for WorldTemplate public final class LevelStemData { private LevelStemData() { @@ -47,31 +43,6 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (WorldType) (Object) h.type().value()) .create(Keys.CHUNK_GENERATOR) .get(h -> (ChunkGenerator) h.generator()) - .asImmutable(LevelStemBridge.class) - .create(Keys.DISPLAY_NAME) - .get(LevelStemBridge::bridge$displayName) - .create(Keys.GAME_MODE) - .get(h -> (GameMode) (Object) h.bridge$gameMode()) - .create(Keys.WORLD_DIFFICULTY) - .get(h -> (Difficulty) (Object) h.bridge$difficulty()) - .create(Keys.SERIALIZATION_BEHAVIOR) - .get(LevelStemBridge::bridge$serializationBehavior) - .create(Keys.IS_LOAD_ON_STARTUP) - .get(LevelStemBridge::bridge$loadOnStartup) - .create(Keys.PERFORM_SPAWN_LOGIC) - .get(LevelStemBridge::bridge$performsSpawnLogic) - .create(Keys.HARDCORE) - .get(LevelStemBridge::bridge$hardcore) - .create(Keys.COMMANDS) - .get(LevelStemBridge::bridge$allowCommands) - .create(Keys.PVP) - .get(LevelStemBridge::bridge$pvp) - .create(Keys.VIEW_DISTANCE) - .get(LevelStemBridge::bridge$viewDistance) - .create(Keys.SPAWN_POSITION) - .get(LevelStemBridge::bridge$spawnPosition) - .create(Keys.SEED) - .get(LevelStemBridge::bridge$seed) ; } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index e63a348dd9e..996efcd2768 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -98,7 +98,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.GRASS_COLOR) .get(h -> h.getSpecialEffects().getGrassColorOverride().map(Color::ofRgb).orElse(null)) .create(Keys.BACKGROUND_MUSIC) - .get(h -> h.getSpecialEffects().getBackgroundMusic().map(SoundConfig.BackgroundMusic.class::cast).orElse(null)) + .get(h -> h.getSpecialEffects().getBackgroundMusic().map(e -> e.unwrap().getFirst().data()).map(SoundConfig.BackgroundMusic.class::cast).orElse(null)) .create(Keys.AMBIENT_ADDITIONAL_SOUND) .get(h -> h.getSpecialEffects().getAmbientAdditionsSettings().map(SoundConfig.Additional.class::cast).orElse(null)) .create(Keys.AMBIENT_MOOD) diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java new file mode 100644 index 00000000000..154de888652 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java @@ -0,0 +1,85 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.type; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.decoration.PaintingVariant; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.data.type.ArtType; +import org.spongepowered.common.util.Preconditions; + +import java.util.Objects; +import java.util.Optional; + +public final class SpongeArtTypeBuilder implements ArtType.Builder { + + private int width; + private int height; + @Nullable private ResourceLocation assetId; + + public SpongeArtTypeBuilder() { + this.reset(); + } + + @Override + public ArtType.Builder dimensions(final int width, final int height) { + this.width = width; + this.height = height; + return this; + } + + @Override + public ArtType.Builder asset(final ResourceKey assetId) { + this.assetId = (ResourceLocation) (Object) assetId; + return this; + } + + @Override + public ArtType.Builder from(final ArtType value) { + if ((Object) value instanceof final PaintingVariant variant) { + this.width = variant.width(); + this.height = variant.height(); + this.assetId = variant.assetId(); + } + return this; + } + + @Override + public ArtType.Builder reset() { + this.width = 0; + this.height = 0; + this.assetId = null; + return this; + } + + @Override + public ArtType build() { + Preconditions.checkArgument(this.width >= 0, "width must set"); + Preconditions.checkArgument(this.height >= 0, "height must set"); + Objects.requireNonNull(this.assetId, "assetId"); + return (ArtType) (Object) new PaintingVariant(this.width, this.height, this.assetId, Optional.empty(), Optional.empty()); + } +} diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java deleted file mode 100644 index 1b184a83ef8..00000000000 --- a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeTemplate.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.type; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.decoration.PaintingVariant; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.type.ArtType; -import org.spongepowered.api.data.type.ArtTypeTemplate; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; -import org.spongepowered.common.util.Preconditions; - -import java.io.IOException; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Function; - -public record SpongeArtTypeTemplate(ResourceKey key, PaintingVariant representedType, DataPack pack) implements ArtTypeTemplate { - - @Override - public ArtType type() { - return (ArtType) (Object) this.representedType; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeArtTypeTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized DamageType:\n" + serialized, e); - } - } - - public static JsonElement encode(final ArtTypeTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return PaintingVariant.DIRECT_CODEC.encodeStart(ops, (PaintingVariant) (Object) template.type()).getOrThrow(); - } - - public static PaintingVariant decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return PaintingVariant.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeArtTypeTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final var parsed = SpongeArtTypeTemplate.decode(packEntry, registryAccess); - return new SpongeArtTypeTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - private int width; - private int height; - private ResourceLocation assetId; - - @Override - public Builder dimensions(final int width, final int height) { - this.width = width; - this.height = height; - return this; - } - - @Override - public Builder asset(final ResourceKey assetId) { - this.assetId = (ResourceLocation) (Object) assetId; - return this; - } - - @Override - public Builder fromValue(final ArtType value) { - if ((Object) value instanceof PaintingVariant variant) { - this.width = variant.width(); - this.height = variant.height(); - this.assetId = variant.assetId(); - } - return this; - } - - @Override - public Builder fromDataPack(final DataView dataView) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(dataView)); - final var damageType = SpongeArtTypeTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((ArtType) (Object) damageType); - return this; - } - - @Override - public Function valueExtractor() { - return ArtTypeTemplate::type; - } - - @Override - protected ArtTypeTemplate build0() { - Preconditions.checkArgument(this.width >= 0, "width must set"); - Preconditions.checkArgument(this.height >= 0, "height must set"); - Objects.requireNonNull(this.assetId, "assetId"); - return new SpongeArtTypeTemplate(this.key, new PaintingVariant(this.width, this.height, this.assetId, Optional.empty(), Optional.empty()), this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/datapack/DataPackSerializer.java b/src/main/java/org/spongepowered/common/datapack/DataPackSerializer.java deleted file mode 100644 index fa934269483..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/DataPackSerializer.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import com.google.gson.JsonObject; -import net.minecraft.SharedConstants; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.PackType; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPackEntry; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; - -public abstract class DataPackSerializer> { - - protected DataPackEncoder encoder; - protected DataPackDecoder decoder; - - public DataPackSerializer(final DataPackEncoder encoder, final DataPackDecoder decoder) { - this.encoder = encoder; - this.decoder = decoder; - } - - public boolean serialize(final SpongeDataPack pack, final Path packDir, final List packEntries) throws IOException { - if (packEntries.isEmpty()) { - return false; - } - - // Write our objects - for (final T packEntry : packEntries) { - this.serializeObject(pack, packDir, packEntry); - this.serializeAdditional(pack, packDir, packEntry); - } - return true; - } - - public Path packEntryFile(final SpongeDataPackType packType, final ResourceKey key, final Path packDir) { - final ResourceLocation loc = this.location(packType, key); - return packDir.resolve("data") - .resolve(loc.getNamespace()) - .resolve(loc.getPath()); - } - - public ResourceLocation location(final SpongeDataPackType packType, final ResourceKey key) { - return ResourceLocation.fromNamespaceAndPath(key.namespace(), packType.dir() + "/" + key.value() + this.fileEnding()); - } - - public abstract String fileEnding(); - - public abstract void serializeObject(final SpongeDataPack pack, final Path packDir, final T packEntry) throws IOException; - - protected abstract void serializeAdditional(final SpongeDataPack type, Path packDir, T entry) throws IOException; - - public abstract T deserialize(final SpongeDataPack pack, final Path file, final ResourceKey key) throws IOException; - - public abstract T deserialize(final SpongeDataPack pack, final InputStream is, final ResourceKey key) throws IOException; - - - - public static void writePackMetadata(final SpongeDataPack pack, final Path packDir, final boolean replace) throws IOException { - // Write our pack metadata - final Path packMeta = packDir.resolve("pack.mcmeta"); - if (replace || !Files.exists(packMeta)) { - final JsonObject packDataRoot = new JsonObject(); - final JsonObject packData = new JsonObject(); - packDataRoot.add("pack", packData); - packData.addProperty("pack_format", SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA)); - packData.addProperty("description", pack.description()); - - JsonDataPackSerializer.writeFile(packMeta, packDataRoot); - } - } - -} diff --git a/src/main/java/org/spongepowered/common/datapack/JsonDataPackSerializer.java b/src/main/java/org/spongepowered/common/datapack/JsonDataPackSerializer.java deleted file mode 100644 index 7ec99ec73dc..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/JsonDataPackSerializer.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.common.SpongeCommon; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Path; - -public class JsonDataPackSerializer> extends DataPackSerializer { - private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - - public JsonDataPackSerializer(final DataPackEncoder encoder, final DataPackDecoder decoder) { - super(encoder, decoder); - } - - @Override - public String fileEnding() { - return ".json"; - } - - @Override - public void serializeObject(final SpongeDataPack pack, final Path packDir, final T packEntry) throws IOException { - final JsonElement serialized = this.encoder.encode(packEntry, SpongeCommon.server().registryAccess()); - final Path file = this.packEntryFile(pack.type(), packEntry.key(), packDir); - final JsonElement finalJson = this.transformSerialized(file, packEntry, serialized); - Files.createDirectories(file.getParent()); - JsonDataPackSerializer.writeFile(file, finalJson); - } - - protected JsonElement transformSerialized(final Path file, final T entry, final JsonElement serialized) throws IOException { - return serialized; - } - - @Override - protected void serializeAdditional(final SpongeDataPack type, Path packDir, T entry) throws IOException { - } - - @Override - public T deserialize(final SpongeDataPack pack, final Path file, final ResourceKey key) throws IOException { - try (final InputStream stream = Files.newInputStream(file)) { - return this.deserialize(pack, stream, key); - } - } - - @Override - public T deserialize(final SpongeDataPack pack, final InputStream is, final ResourceKey key) throws IOException { - try (final InputStreamReader reader = new InputStreamReader(is)) { - final JsonElement element = JsonParser.parseReader(reader); - - if (this.decoder != null) { - // TODO this is actually blocking - return this.decoder.decode(pack, key, element, SpongeCommon.server().registryAccess()); - } - } - return null; - } - - public static void writeFile(final Path file, final JsonElement object) throws IOException { - try (BufferedWriter writer = Files.newBufferedWriter(file)) { - JsonDataPackSerializer.GSON.toJson(object, writer); - } - } - -} diff --git a/src/main/java/org/spongepowered/common/datapack/NbtDataPackSerializer.java b/src/main/java/org/spongepowered/common/datapack/NbtDataPackSerializer.java deleted file mode 100644 index 8ded4c9327f..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/NbtDataPackSerializer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.common.SpongeCommon; - -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; - -public class NbtDataPackSerializer> extends DataPackSerializer { - - public NbtDataPackSerializer(final DataPackEncoder encoder, final DataPackDecoder decoder) { - super(encoder, decoder); - } - - @Override - public String fileEnding() { - return ".nbt"; - } - - @Override - public void serializeObject(final SpongeDataPack pack, final Path packDir, final T packEntry) throws IOException { - final CompoundTag serialized = this.encoder.encode(packEntry, SpongeCommon.server().registryAccess()); - final Path file = this.packEntryFile(pack.type(), packEntry.key(), packDir); - Files.createDirectories(file.getParent()); - NbtDataPackSerializer.writeFile(file, serialized); - } - - @Override - protected void serializeAdditional(final SpongeDataPack type, Path packDir, T entry) throws IOException { - } - - @Override - public T deserialize(final SpongeDataPack pack, final Path file, final ResourceKey key) throws IOException { - try (final InputStream stream = Files.newInputStream(file)) { - return this.deserialize(pack, stream, key); - } - } - - @Override - public T deserialize(final SpongeDataPack pack, final InputStream is, final ResourceKey key) throws IOException { - try (final DataInputStream dis = new DataInputStream(is)) { - final CompoundTag element = NbtIo.readCompressed(dis, NbtAccounter.unlimitedHeap()); - if (this.decoder != null) { - // TODO this is actually blocking - return this.decoder.decode(pack, key, element, SpongeCommon.server().registryAccess()); - } - } - return null; - } - - public static void writeFile(final Path file, final CompoundTag object) throws IOException { - Files.deleteIfExists(file); - NbtIo.writeCompressed(object, file); - } - -} diff --git a/src/main/java/org/spongepowered/common/datapack/SpongeDataPack.java b/src/main/java/org/spongepowered/common/datapack/SpongeDataPack.java deleted file mode 100644 index a2000ec1e12..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/SpongeDataPack.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackEntry; - -public record SpongeDataPack>(String name, String description, SpongeDataPackType type) implements DataPack { - -} diff --git a/src/main/java/org/spongepowered/common/datapack/SpongeDataPackManager.java b/src/main/java/org/spongepowered/common/datapack/SpongeDataPackManager.java index 902c57407ee..635e24e6479 100644 --- a/src/main/java/org/spongepowered/common/datapack/SpongeDataPackManager.java +++ b/src/main/java/org/spongepowered/common/datapack/SpongeDataPackManager.java @@ -24,46 +24,14 @@ */ package org.spongepowered.common.datapack; -import com.google.gson.JsonElement; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.packs.PackResources; -import net.minecraft.server.packs.PackType; -import net.minecraft.server.packs.metadata.pack.PackMetadataSection; import net.minecraft.server.packs.repository.PackRepository; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceManager; -import org.apache.commons.io.FilenameUtils; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.api.datapack.DataPackType; -import org.spongepowered.api.datapack.DataPackTypes; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.EventContext; import org.spongepowered.api.world.server.DataPackManager; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.lifecycle.RegisterDataPackValueEventImpl; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; -import org.spongepowered.common.util.FutureUtil; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; -import java.util.stream.Stream; // TODO make IO non-blocking // TODO not all data-pack entries are on disk - this is currently not handled @@ -78,17 +46,6 @@ public SpongeDataPackManager(final MinecraftServer server, final Path packsDir) this.packsDir = packsDir; } - // TODO IntegratedServer call? - public void init() { - this.ignoreNext = false; - final List reloadablePacks = this.registerPacks(); - if (!reloadablePacks.isEmpty()) { - SpongeCommon.logger().info("Reloading for plugin data packs... " + reloadablePacks.size()); - this.ignoreNext = true; - this.server.reloadResources(this.discoverNewPacks()); - } - } - // see ReloadCommand#discoverNewPacks private List discoverNewPacks() { final PackRepository packRepo = this.server.getPackRepository(); @@ -108,238 +65,4 @@ public CompletableFuture reload() { this.ignoreNext = false; return this.server.reloadResources(this.discoverNewPacks()); } - - public List registerPacks() { - // Ignore reload immediately after first call - if (this.ignoreNext) { - this.ignoreNext = false; - return List.of(); - } - - SpongeIngredient.clearCache(); - IngredientResultUtil.clearCache(); - - final List reloadablePacks = new ArrayList<>(); - this.registerAndSerializePack(DataPackTypes.ADVANCEMENT, reloadablePacks); - this.registerAndSerializePack(DataPackTypes.RECIPE, reloadablePacks); - this.registerAndSerializePack(DataPackTypes.BLOCK_TAG, reloadablePacks); - this.registerAndSerializePack(DataPackTypes.DAMAGE_TYPE, reloadablePacks); - this.registerAndSerializePack(DataPackTypes.DAMAGE_TYPE_TAG, reloadablePacks); - return reloadablePacks; - } - - private > List callRegisterDataPackValueEvent(final SpongeDataPackType type) { - final RegisterDataPackValueEventImpl event = new RegisterDataPackValueEventImpl<>(Cause.of(EventContext.empty(), SpongeCommon.game()), SpongeCommon.game(), type); - SpongeCommon.post(event); - return event.serializables(); - } - - @SuppressWarnings("unchecked") - private > void registerAndSerializePack(final DataPackType type, final Collection reloadablePacks) { - final List packEntries = this.callRegisterDataPackValueEvent((SpongeDataPackType) type); - if (packEntries.isEmpty()) { - return; - } - this.serializePack(reloadablePacks, packEntries); - } - - private > void serializePack(final Collection reloadablePacks, final List packEntries) { - final Map, List> packEntryMap = packEntries.stream().collect(Collectors.groupingBy(DataPackEntry::pack)); - for (final Map.Entry, List> entry : packEntryMap.entrySet()) { - final SpongeDataPack implPack = (SpongeDataPack) entry.getKey(); - final String fullPackName = "file/" + implPack.name(); - try { - final boolean success = implPack.type().packSerializer().serialize(implPack, this.packDir(implPack), entry.getValue()); - DataPackSerializer.writePackMetadata(implPack, this.packDir(implPack), false); - if (success && implPack.type().reloadable()) { - if (!reloadablePacks.contains(fullPackName)) { - reloadablePacks.add(fullPackName); - } - } else { - reloadablePacks.remove(fullPackName); - } - } catch (final IOException e) { - reloadablePacks.remove(fullPackName); - SpongeCommon.logger().error(e); - } - } - } - - @Override - public > CompletableFuture save(final T entry) { - if (entry.pack().name().equals("Default")) { // cannot save into vanilla builtin pack - return CompletableFuture.completedFuture(false); - } - // TODO this is actually blocking - this.serializePack(new ArrayList<>(), List.of(entry)); - return CompletableFuture.completedFuture(((SpongeDataPackType)entry.pack().type()).reloadable()); - } - - @Override - public > CompletableFuture> load(final DataPack pack, final ResourceKey key) { - Objects.requireNonNull(key, "key"); - final SpongeDataPack implPack = (SpongeDataPack) pack; - final ResourceManager manager = this.server.getResourceManager(); - final DataPackSerializer packSerializer = implPack.type().packSerializer(); - final Optional resource = manager.getResource(packSerializer.location(implPack.type(), key)); - if (resource.isPresent()) { // loaded resource (includes vanilla builtin) - try (InputStream inputStream = resource.get().open()) { - final T deserialized = packSerializer.deserialize(implPack, inputStream, key); - return CompletableFuture.completedFuture(Optional.ofNullable(deserialized)); - } catch (final IOException ex) { - return FutureUtil.completedWithException(ex); - } - } - - // Next attempt to find file on disk - final Path file = this.packFile(implPack, key); - if (Files.exists(file)) { - try { - // TODO this is actually blocking - final T deserialized = packSerializer.deserialize(implPack, file, key); - return CompletableFuture.completedFuture(Optional.ofNullable(deserialized)); - } catch (final IOException ex) { - return FutureUtil.completedWithException(ex); - } - } - return CompletableFuture.completedFuture(Optional.empty()); - } - - @Override - public boolean exists(final DataPack pack, final ResourceKey key) { - final SpongeDataPack packImpl = (SpongeDataPack) pack; - final Path file = this.packFile(packImpl, Objects.requireNonNull(key, "key")); - return Files.exists(file); - } - - @Override - public boolean delete(final DataPack pack, final ResourceKey key) throws IOException { - final SpongeDataPack packImpl = (SpongeDataPack) pack; - final Path file = this.packFile(packImpl, Objects.requireNonNull(key, "key")); - return Files.deleteIfExists(file); - } - - @Override - public void copy(final DataPack pack, final ResourceKey from, final ResourceKey to) throws IOException { - this.copy(pack, from, pack, to); - } - - @Override - public void copy(final DataPack fromPack, final ResourceKey from, final DataPack toPack, final ResourceKey to) throws IOException { - final SpongeDataPack packImpl = (SpongeDataPack) fromPack; - final SpongeDataPack packImplTo = (SpongeDataPack) toPack; - final Path fileFrom = this.packFile(packImpl, Objects.requireNonNull(from, "from")); - final Path fileto = this.packFile(packImplTo, Objects.requireNonNull(to, "to")); - Files.createDirectories(fileto.getParent()); - Files.copy(fileFrom, fileto, StandardCopyOption.REPLACE_EXISTING); - } - - @Override - public void move(final DataPack pack, final ResourceKey from, final ResourceKey to) throws IOException { - this.move(pack, from, pack, to); - } - - - @Override - public void move(final DataPack fromPack, final ResourceKey from, final DataPack toPack, final ResourceKey to) throws IOException { - final SpongeDataPack packImpl = (SpongeDataPack) fromPack; - final SpongeDataPack packImplTo = (SpongeDataPack) toPack; - final Path fileFrom = this.packFile(packImpl, Objects.requireNonNull(from, "from")); - final Path fileto = this.packFile(packImplTo, Objects.requireNonNull(to, "to")); - Files.createDirectories(fileto.getParent()); - Files.copy(fileFrom, fileto, StandardCopyOption.REPLACE_EXISTING); - } - - - @Override - public List list(final DataPack pack) { - final List packEntries = new ArrayList<>(); - final Path packDir = this.packDir(pack); - if (!Files.isDirectory(packDir)) { - return packEntries; - } - try (final Stream namespaces = Files.walk(packDir.resolve("data"), 1)) { - namespaces.filter(Files::isDirectory).forEach(namespaceDir -> { - final Path typeDir = namespaceDir.resolve(((SpongeDataPack) pack).type().dir()); - if (Files.isDirectory(typeDir)) { - try (final Stream pluginTemplates = Files.walk(typeDir, 1)) { - pluginTemplates.filter(file -> file.toString().endsWith(".json")) - .map(file -> SpongeDataPackManager.keyFor(namespaceDir, file)) - .forEach(packEntries::add); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - }); - } catch (final IOException e) { - throw new RuntimeException(e); - } - return packEntries; - } - - @Override - public > Map, Collection> find(final DataPackType packType) { - final ResourceManager manager = this.server.getResourceManager(); - final Map> resources = new HashMap<>(); - final Map descriptions = new HashMap<>(); - final SpongeDataPackType typeImpl = (SpongeDataPackType) packType; - manager.listPacks().forEach(pack -> { - final String packName = pack.packId(); - descriptions.computeIfAbsent(packName, k -> this.packDescription(pack)); - for (final String namespace : pack.getNamespaces(PackType.SERVER_DATA)) { - final Collection locs = new HashSet<>(); - pack.listResources(PackType.SERVER_DATA, namespace, typeImpl.dir(), (loc, stream) -> locs.add(loc)); - if (!locs.isEmpty()) { - resources.computeIfAbsent(packName, k -> new ArrayList<>()).addAll(locs); - } - } - }); - - final Map, Collection> map = new HashMap<>(); - for (final Map.Entry> entry : resources.entrySet()) { - map.put(packType.pack(entry.getKey(), descriptions.get(entry.getKey())), entry.getValue().stream().map(loc -> { - final String path = loc.getPath(); - final String value = path.substring(typeImpl.dir().length() + 1, path.length() - typeImpl.packSerializer().fileEnding().length()); - return ResourceKey.of(loc.getNamespace(), value); - }).toList()); - } - return map; - } - - @Override - public > Optional> findPack(final DataPackType packType, final ResourceKey key) { - final SpongeDataPackType implType = (SpongeDataPackType) packType; - final ResourceLocation compareLoc = implType.packSerializer().location(implType, key); - for (final Resource resource : this.server.getResourceManager().listResources(((SpongeDataPackType) packType).dir(), loc -> loc.equals(compareLoc)).values()) { - String name = resource.sourcePackId(); - if (name.startsWith("file/")) { - name = name.substring(5); - } - return Optional.of(packType.pack(name, "N/A")); - } - return Optional.empty(); - } - - private String packDescription(final PackResources pack) { - try { - return pack.getMetadataSection(PackMetadataSection.TYPE).description().getString(); - } catch (final IOException e) { - return "N/A"; - } - } - - private static ResourceKey keyFor(final Path namespaceDir, final Path file) { - final String namespace = namespaceDir.getFileName().toString(); - final String value = FilenameUtils.removeExtension(file.getFileName().toString()); - return ResourceKey.of(namespace, value); - } - - private > Path packFile(final SpongeDataPack pack, final ResourceKey key) { - return pack.type().packSerializer().packEntryFile(pack.type(), key, this.packDir(pack)); - } - - private Path packDir(final DataPack pack) { - return this.packsDir.resolve(pack.name()); - } - } diff --git a/src/main/java/org/spongepowered/common/datapack/SpongeDataPackType.java b/src/main/java/org/spongepowered/common/datapack/SpongeDataPackType.java deleted file mode 100644 index 1b1b9aabe2e..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/SpongeDataPackType.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import com.google.gson.JsonElement; -import io.leangen.geantyref.TypeToken; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.advancement.AdvancementTemplate; -import org.spongepowered.api.adventure.ChatTypeTemplate; -import org.spongepowered.api.data.type.ArtTypeTemplate; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.api.datapack.DataPackType; -import org.spongepowered.api.event.cause.entity.damage.DamageTypeTemplate; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.registry.RegistryType; -import org.spongepowered.api.tag.TagTemplate; -import org.spongepowered.api.tag.Taggable; -import org.spongepowered.api.world.WorldTypeTemplate; -import org.spongepowered.api.world.biome.BiomeTemplate; -import org.spongepowered.api.world.generation.carver.CarverTemplate; -import org.spongepowered.api.world.generation.config.noise.DensityFunctionTemplate; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigTemplate; -import org.spongepowered.api.world.generation.config.noise.NoiseTemplate; -import org.spongepowered.api.world.generation.feature.FeatureTemplate; -import org.spongepowered.api.world.generation.feature.PlacedFeatureTemplate; -import org.spongepowered.api.world.generation.structure.SchematicTemplate; -import org.spongepowered.api.world.generation.structure.StructureSetTemplate; -import org.spongepowered.api.world.generation.structure.StructureTemplate; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolTemplate; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorListTemplate; -import org.spongepowered.api.world.server.WorldTemplate; -import org.spongepowered.common.advancement.SpongeAdvancementTemplate; -import org.spongepowered.common.adventure.SpongeChatTypeTemplate; -import org.spongepowered.common.data.type.SpongeArtTypeTemplate; -import org.spongepowered.common.datapack.recipe.RecipeDataPackSerializer; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTypeTemplate; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; -import org.spongepowered.common.tag.SpongeTagTemplate; -import org.spongepowered.common.world.biome.SpongeBiomeTemplate; -import org.spongepowered.common.world.generation.carver.SpongeCarverTemplate; -import org.spongepowered.common.world.generation.config.noise.SpongeDensityFunctionTemplate; -import org.spongepowered.common.world.generation.config.noise.SpongeNoiseGeneratorConfigTemplate; -import org.spongepowered.common.world.generation.config.noise.SpongeNoiseTemplate; -import org.spongepowered.common.world.generation.feature.SpongeFeatureTemplate; -import org.spongepowered.common.world.generation.feature.SpongePlacedFeatureTemplate; -import org.spongepowered.common.world.generation.structure.SpongeSchematicTemplate; -import org.spongepowered.common.world.generation.structure.SpongeStructureSetTemplate; -import org.spongepowered.common.world.generation.structure.SpongeStructureTemplate; -import org.spongepowered.common.world.generation.structure.jigsaw.SpongeJigsawPoolTemplate; -import org.spongepowered.common.world.generation.structure.jigsaw.SpongeProcessorListTemplate; -import org.spongepowered.common.world.server.SpongeWorldTemplate; -import org.spongepowered.common.world.server.SpongeWorldTypeTemplate; - -public record SpongeDataPackType>(String dir, boolean reloadable, TypeToken entryType, DataPackSerializer packSerializer) implements DataPackType { - - public static > SpongeDataPackType basic(final Class clazz, final String dir, final DataPackEncoder encoder, final DataPackDecoder decoder, final boolean reloadable) { - final TypeToken tt = TypeToken.get(clazz); - return new SpongeDataPackType<>(dir, reloadable, tt, new JsonDataPackSerializer<>(encoder, decoder)); - } - - public static > SpongeDataPackType custom(final Class clazz, final String dir, final DataPackSerializer serializer, final boolean reloadable) { - final TypeToken tt = TypeToken.get(clazz); - return new SpongeDataPackType<>(dir, reloadable, tt, serializer); - } - - public static > SpongeDataPackType custom(final TypeToken typeToken, final String dir, final DataPackSerializer serializer, final boolean reloadable) { - return new SpongeDataPackType<>(dir, reloadable, typeToken, serializer); - } - - public static final class FactoryImpl implements DataPackType.Factory { - - private final SpongeDataPackType advancement = SpongeDataPackType.basic(AdvancementTemplate.class, - "advancement", SpongeAdvancementTemplate::encode, null, // TODO decoder - true); - - private final SpongeDataPackType recipe = SpongeDataPackType.custom(RecipeRegistration.class, - "recipe", new RecipeDataPackSerializer(SpongeRecipeRegistration::encode, null), // TODO decoder - true); - - private final SpongeDataPackType worldType = SpongeDataPackType.basic(WorldTypeTemplate.class, - "dimension_type", SpongeWorldTypeTemplate::encode, SpongeWorldTypeTemplate::decode, - false); - - private final SpongeDataPackType world = SpongeDataPackType.basic(WorldTemplate.class, - "dimension", SpongeWorldTemplate::encode, SpongeWorldTemplate::decode, - false); - - private final SpongeDataPackType biome = SpongeDataPackType.basic(BiomeTemplate.class, - "worldgen/biome", SpongeBiomeTemplate::encode, SpongeBiomeTemplate::decode, - false); - - private final SpongeDataPackType carver = SpongeDataPackType.basic(CarverTemplate.class, - "worldgen/configured_carver", SpongeCarverTemplate::encode, SpongeCarverTemplate::decode, - false); - - private final SpongeDataPackType feature = SpongeDataPackType.basic(FeatureTemplate.class, - "worldgen/configured_feature", SpongeFeatureTemplate::encode, SpongeFeatureTemplate::decode, - false); - - private final SpongeDataPackType placedFeature = SpongeDataPackType.basic(PlacedFeatureTemplate.class, - "worldgen/placed_feature", SpongePlacedFeatureTemplate::encode, SpongePlacedFeatureTemplate::decode, - false); - - private final SpongeDataPackType noiseGeneratorConfig = SpongeDataPackType.basic(NoiseGeneratorConfigTemplate.class, - "worldgen/noise_settings", SpongeNoiseGeneratorConfigTemplate::encode, SpongeNoiseGeneratorConfigTemplate::decode, - false); - - private final SpongeDataPackType noise = SpongeDataPackType.basic(NoiseTemplate.class, - "worldgen/noise", SpongeNoiseTemplate::encode, SpongeNoiseTemplate::decode, - false); - - private final SpongeDataPackType densityFunction = SpongeDataPackType.basic(DensityFunctionTemplate.class, - "worldgen/density_function", SpongeDensityFunctionTemplate::encode, SpongeDensityFunctionTemplate::decode, - false); - - private final SpongeDataPackType structure = SpongeDataPackType.basic(StructureTemplate.class, - "worldgen/structure", SpongeStructureTemplate::encode, SpongeStructureTemplate::decode, - false); - - private final SpongeDataPackType schematic = SpongeDataPackType.custom(SchematicTemplate.class, - "structure", new NbtDataPackSerializer<>(SpongeSchematicTemplate::encode, SpongeSchematicTemplate::decode), - false); - - private final SpongeDataPackType processorList = SpongeDataPackType.basic(ProcessorListTemplate.class, - "worldgen/processor_list", SpongeProcessorListTemplate::encode, SpongeProcessorListTemplate::decode, - false); - - private final SpongeDataPackType structureSet = SpongeDataPackType.basic(StructureSetTemplate.class, - "worldgen/structure_set", SpongeStructureSetTemplate::encode, SpongeStructureSetTemplate::decode, - false); - - private final SpongeDataPackType jigsawPool = SpongeDataPackType.basic(JigsawPoolTemplate.class, - "worldgen/template_pool", SpongeJigsawPoolTemplate::encode, SpongeJigsawPoolTemplate::decode, - false); - - // TODO should be reloadable https://bugs.mojang.com/browse/MC-251318 - private final SpongeDataPackType chatType = SpongeDataPackType.basic(ChatTypeTemplate.class, - "chat_type", SpongeChatTypeTemplate::encode, SpongeChatTypeTemplate::decode, - false); - - private final SpongeDataPackType damageType = SpongeDataPackType.basic(DamageTypeTemplate.class, - "damage_type", SpongeDamageTypeTemplate::encode, SpongeDamageTypeTemplate::decode, - false); - - private final SpongeDataPackType artType = SpongeDataPackType.basic(ArtTypeTemplate.class, - "damage_type", SpongeArtTypeTemplate::encode, SpongeArtTypeTemplate::decode, - false); - - @Override - public DataPackType recipe() { - return this.recipe; - } - - @Override - public DataPackType advancement() { - return this.advancement; - } - - @Override - public DataPackType worldType() { - return this.worldType; - } - - @Override - public DataPackType world() { - return world; - } - - @Override - public DataPackType biome() { - return this.biome; - } - - @Override - public DataPackType carver() { - return this.carver; - } - - @Override - public DataPackType feature() { - return this.feature; - } - - @Override - public DataPackType placedFeature() { - return this.placedFeature; - } - - @Override - public DataPackType noiseGeneratorConfig() { - return this.noiseGeneratorConfig; - } - - @Override - public DataPackType noise() { - return this.noise; - } - - @Override - public DataPackType densityFunction() { - return this.densityFunction; - } - - @Override - public DataPackType structure() { - return this.structure; - } - - @Override - public DataPackType schematic() { - return this.schematic; - } - - @Override - public DataPackType processorList() { - return this.processorList; - } - - @Override - public DataPackType structureSet() { - return this.structureSet; - } - - @Override - public DataPackType jigsawPool() { - return this.jigsawPool; - } - - @Override - public DataPackType chatType() { - return this.chatType; - } - - @Override - public DataPackType damageType() { - return this.damageType; - } - - @Override - public > DataPackType> tag(RegistryType registry) { - final String tagDir = Registries.tagsDirPath(ResourceKey.createRegistryKey((ResourceLocation) (Object) registry.location())); - return SpongeDataPackType.custom(new TypeToken<>() {}, tagDir, - new TagDataPackSerializer<>(SpongeTagTemplate::encode, null), // TODO decoder - true); - } - - @Override - public DataPackType artType() { - return this.artType; - } - } - - public DataPack pack(final String name, final String description) { - return new SpongeDataPack<>(name, description, this); - } -} diff --git a/src/main/java/org/spongepowered/common/datapack/TagDataPackSerializer.java b/src/main/java/org/spongepowered/common/datapack/TagDataPackSerializer.java deleted file mode 100644 index 83402f25b70..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/TagDataPackSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack; - -import com.google.gson.JsonElement; -import org.spongepowered.api.tag.TagTemplate; -import org.spongepowered.api.tag.Taggable; - -import java.io.IOException; -import java.nio.file.Path; - -public final class TagDataPackSerializer> extends JsonDataPackSerializer> { - - public TagDataPackSerializer(final DataPackEncoder> encoder, final DataPackDecoder> decoder) { - super(encoder, decoder); - } - - @Override - protected JsonElement transformSerialized(final Path file, final TagTemplate entry, final JsonElement serialized) throws IOException{ - final JsonElement toWrite = serialized; - /* TODO support merging - if (Files.exists(file) && !((SpongeTagTemplate) entry).replace()) { - final JsonObject jsonObject; - try (BufferedReader bufferedReader = Files.newBufferedReader(file)) { - final JsonElement jsonElement = JsonParser.parseReader(bufferedReader); - jsonObject = jsonElement.getAsJsonObject(); - } - - toWrite = Tag.Builder.tag().addFromJson(jsonObject, filename).addFromJson(toWrite, filename).serializeToJson(); - // TagFile.CODEC.encodeStart(JsonOps.INSTANCE, new TagFile(builder.build(), this.replace)).getOrThrow(false, e -> {}).getAsJsonObject(); - } - //*/ - return toWrite; - } - -} diff --git a/src/main/java/org/spongepowered/common/datapack/recipe/RecipeDataPackSerializer.java b/src/main/java/org/spongepowered/common/datapack/recipe/RecipeDataPackSerializer.java deleted file mode 100644 index 27588abbdb6..00000000000 --- a/src/main/java/org/spongepowered/common/datapack/recipe/RecipeDataPackSerializer.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.datapack.recipe; - -import com.google.gson.JsonElement; -import com.mojang.serialization.JsonOps; -import net.minecraft.advancements.Advancement; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.common.datapack.DataPackDecoder; -import org.spongepowered.common.datapack.DataPackEncoder; -import org.spongepowered.common.datapack.JsonDataPackSerializer; -import org.spongepowered.common.datapack.SpongeDataPack; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -public final class RecipeDataPackSerializer extends JsonDataPackSerializer { - - public RecipeDataPackSerializer(final DataPackEncoder encoder, - final DataPackDecoder decoder) { - super(encoder, decoder); - } - - @Override - protected void serializeAdditional( - final SpongeDataPack type, final Path packDir, - final RecipeRegistration entry) throws IOException { - if (entry instanceof SpongeRecipeRegistration spongeReg) { - final var serialized = Advancement.CODEC.encodeStart(JsonOps.INSTANCE, spongeReg.advancement().value()); - - final Path file = packDir.resolve("data") - .resolve(entry.key().namespace()) - .resolve("advancement") - .resolve(entry.key().value() + ".json"); - Files.createDirectories(file.getParent()); - - JsonDataPackSerializer.writeFile(file, serialized.result().get()); - } - } -} diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeBuilder.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeBuilder.java new file mode 100644 index 00000000000..ac20dcf5d56 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeBuilder.java @@ -0,0 +1,99 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.cause.entity.damage; + +import net.minecraft.world.damagesource.DamageEffects; +import net.minecraft.world.damagesource.DeathMessageType; +import org.spongepowered.api.event.cause.entity.damage.DamageEffect; +import org.spongepowered.api.event.cause.entity.damage.DamageScaling; +import org.spongepowered.api.event.cause.entity.damage.DamageType; + +import java.util.Objects; + +public final class SpongeDamageTypeBuilder implements DamageType.Builder { + + private String msgId; + private net.minecraft.world.damagesource.DamageScaling scaling; + private float exhaustion; + private DamageEffects effects; + private DeathMessageType deathMessageType; + + public SpongeDamageTypeBuilder() { + this.reset(); + } + + @Override + public DamageType.Builder from(final DamageType value) { + var mcValue = (net.minecraft.world.damagesource.DamageType) (Object) value; + this.msgId = mcValue.msgId(); + this.exhaustion = mcValue.exhaustion(); + this.scaling = mcValue.scaling(); + this.effects = mcValue.effects(); + this.deathMessageType = mcValue.deathMessageType(); + return this; + } + + @Override + public DamageType.Builder name(final String name) { + this.msgId = name; + return this; + } + + @Override + public DamageType.Builder scaling(final DamageScaling scaling) { + this.scaling = (net.minecraft.world.damagesource.DamageScaling) (Object) scaling; + return this; + } + + @Override + public DamageType.Builder exhaustion(final double exhaustion) { + this.exhaustion = (float) exhaustion; + return this; + } + + @Override + public DamageType.Builder effect(final DamageEffect effect) { + this.effects = ((DamageEffects) (Object) effect); + return this; + } + + @Override + public DamageType.Builder reset() { + this.msgId = null; + this.scaling = net.minecraft.world.damagesource.DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER; + this.effects = DamageEffects.HURT; + this.deathMessageType = DeathMessageType.DEFAULT; + return this; + } + + @Override + public DamageType build() { + Objects.requireNonNull(this.msgId, "name"); + Objects.requireNonNull(this.scaling, "scaling"); + Objects.requireNonNull(this.effects, "effects"); + Objects.requireNonNull(this.deathMessageType, "deathMessageType"); + return (DamageType) (Object) new net.minecraft.world.damagesource.DamageType(this.msgId, this.scaling, this.exhaustion, this.effects, this.deathMessageType); + } +} diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeTemplate.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeTemplate.java deleted file mode 100644 index 32a6840a18d..00000000000 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTypeTemplate.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.cause.entity.damage; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.damagesource.DamageEffects; -import net.minecraft.world.damagesource.DamageType; -import net.minecraft.world.damagesource.DeathMessageType; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.event.cause.entity.damage.DamageEffect; -import org.spongepowered.api.event.cause.entity.damage.DamageScaling; -import org.spongepowered.api.event.cause.entity.damage.DamageTypeTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeDamageTypeTemplate(ResourceKey key, DamageType representedType, DataPack pack) implements DamageTypeTemplate { - - @Override - public org.spongepowered.api.event.cause.entity.damage.DamageType type() { - return (org.spongepowered.api.event.cause.entity.damage.DamageType) (Object) this.representedType; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeDamageTypeTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized DamageType:\n" + serialized, e); - } - } - - public static JsonElement encode(final DamageTypeTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return DamageType.DIRECT_CODEC.encodeStart(ops, (DamageType) (Object) template.type()).getOrThrow(); - } - - public static DamageType decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return DamageType.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static DamageTypeTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, - final RegistryAccess registryAccess) { - final DamageType parsed = SpongeDamageTypeTemplate.decode(packEntry, registryAccess); - return new SpongeDamageTypeTemplate(key, parsed, pack); - } - - public static final class BuilderImpl - extends AbstractDataPackEntryBuilder - implements Builder { - - private String msgId; - private net.minecraft.world.damagesource.DamageScaling scaling; - private float exhaustion; - private DamageEffects effects; - private DeathMessageType deathMessageType; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Builder fromValue(final org.spongepowered.api.event.cause.entity.damage.DamageType value) { - var mcValue = (DamageType) (Object) value; - this.msgId = mcValue.msgId(); - this.exhaustion = mcValue.exhaustion(); - this.scaling = mcValue.scaling(); - this.effects = mcValue.effects(); - this.deathMessageType = mcValue.deathMessageType(); - return this; - } - - @Override - public Builder name(final String name) { - this.msgId = name; - return this; - } - - @Override - public Builder scaling(final DamageScaling scaling) { - this.scaling = (net.minecraft.world.damagesource.DamageScaling) (Object) scaling; - return this; - } - - @Override - public Builder exhaustion(final double exhaustion) { - this.exhaustion = (float) exhaustion; - return this; - } - - @Override - public Builder effect(final DamageEffect effect) { - this.effects = ((DamageEffects) (Object) effect); - return this; - } - - @Override - public Function valueExtractor() { - return DamageTypeTemplate::type; - } - - @Override - public Builder reset() { - this.key = null; - this.pack = DataPacks.DAMAGE_TYPE; - this.msgId = null; - this.scaling = net.minecraft.world.damagesource.DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER; - this.effects = DamageEffects.HURT; - this.deathMessageType = DeathMessageType.DEFAULT; - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final DamageType damageType = SpongeDamageTypeTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((org.spongepowered.api.event.cause.entity.damage.DamageType) (Object) damageType); - return this; - } - - @Override - protected DamageTypeTemplate build0() { - Objects.requireNonNull(this.msgId, "name"); - Objects.requireNonNull(this.scaling, "scaling"); - Objects.requireNonNull(this.effects, "effects"); - Objects.requireNonNull(this.deathMessageType, "deathMessageType"); - final DamageType damageType = new DamageType(this.msgId, this.scaling, this.exhaustion, this.effects, this.deathMessageType); - return new SpongeDamageTypeTemplate(this.key, damageType, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java index 2bdae7ef9cc..9d8d3bb5c86 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java @@ -25,12 +25,15 @@ package org.spongepowered.common.event.lifecycle; import io.leangen.geantyref.TypeToken; +import org.spongepowered.api.Client; import org.spongepowered.api.Engine; import org.spongepowered.api.Game; import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Server; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.lifecycle.RegisterRegistryEvent; import org.spongepowered.api.registry.DuplicateRegistrationException; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.common.registry.RegistryLoader; @@ -38,6 +41,7 @@ import java.util.Map; import java.util.Objects; +import java.util.function.Function; import java.util.function.Supplier; public abstract class AbstractRegisterRegistryEvent extends AbstractLifecycleEvent implements RegisterRegistryEvent { @@ -68,6 +72,19 @@ public RegistryType register(final ResourceKey key, final boolean isDynam return type; } + @Override + public RegistryType register(final ResourceKey key, final boolean isDynamic, + final Function> defaultValues, final RegistryType... dependencies) throws DuplicateRegistrationException { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(defaultValues, "defaultValues"); + Objects.requireNonNull(dependencies, "dependencies"); + + final SpongeRegistryHolder holder = this.getHolder(); + final RegistryType type = RegistryType.of(RegistryRoots.SPONGE, key); + holder.createRegistry(type, defaultValues, isDynamic); + return null; + } + protected abstract SpongeRegistryHolder getHolder(); public static final class GameScopedImpl extends AbstractRegisterRegistryEvent implements RegisterRegistryEvent.GameScoped { @@ -85,13 +102,12 @@ protected SpongeRegistryHolder getHolder() { public static final class EngineScopedImpl extends AbstractRegisterRegistryEvent implements RegisterRegistryEvent.EngineScoped { private final TypeToken token; - private final E engine; + private final RegistryHolder registryHolder; - public EngineScopedImpl(final Cause cause, final Game game, final E engine) { + public EngineScopedImpl(final Cause cause, final Game game, final RegistryHolder registryHolder, final TypeToken token) { super(cause, game); - - this.token = TypeToken.get((Class) engine.getClass()); - this.engine = engine; + this.token = token; + this.registryHolder = registryHolder; } @Override @@ -101,7 +117,15 @@ public TypeToken paramType() { @Override protected SpongeRegistryHolder getHolder() { - return (SpongeRegistryHolder) this.engine; + return (SpongeRegistryHolder) this.registryHolder; + } + + public static EngineScopedImpl server(final Cause cause, final Game game, final RegistryHolder registryHolder) { + return new EngineScopedImpl<>(cause, game, registryHolder, TypeToken.get(Server.class)); + } + + public static EngineScopedImpl client(final Cause cause, final Game game, final RegistryHolder registryHolder) { + return new EngineScopedImpl<>(cause, game, registryHolder, TypeToken.get(Client.class)); } } diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryValueEvent.java b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryValueEvent.java index 901e6ce2650..114d9260697 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryValueEvent.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryValueEvent.java @@ -25,37 +25,48 @@ package org.spongepowered.common.event.lifecycle; import io.leangen.geantyref.TypeToken; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.Client; import org.spongepowered.api.Engine; import org.spongepowered.api.Game; import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; -import org.spongepowered.api.registry.DefaultedRegistryValue; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.registry.SpongeRegistryHolder; -import java.util.Objects; -import java.util.Optional; +import java.util.Map; +import java.util.function.BiConsumer; public abstract class AbstractRegisterRegistryValueEvent extends AbstractLifecycleEvent implements RegisterRegistryValueEvent { - public AbstractRegisterRegistryValueEvent(final Cause cause, final Game game) { + private final Map, Registry> registries; + + public AbstractRegisterRegistryValueEvent(final Cause cause, final Game game, final Map, Registry> registries) { super(cause, game); + this.registries = registries; } + @SuppressWarnings("unchecked") @Override - public RegistryStep registry(final RegistryType registryType) { - final Optional> optRegistry = this.getHolder().findRegistry(Objects.requireNonNull(registryType, "registryType")); - if (!optRegistry.isPresent()) { - throw new IllegalArgumentException(String.format("RegistryType '%s' has no registered registry!", registryType)); + public void registry(final RegistryType registryType, final BiConsumer> consumer) { + final @Nullable Registry registry = (Registry) this.registries.get(registryType); + if (registry != null) { + consumer.accept(this.getHolder(), new RegistryStepImpl<>(registry)); } - final Registry registry = optRegistry.get(); - if (!registry.isDynamic()) { - throw new IllegalStateException(String.format("RegistryType '%s' is read only and cannot accept new registry values!", registryType)); + } + + @Override + public void registry(final RegistryType registryType, final BiConsumer> consumer, final RegistryType... dependencies) { + final @Nullable Registry registry = (Registry) this.registries.get(registryType); + if (registry != null) { + ((WritableRegistryBridge) registry).bridge$addDependencies(() -> consumer.accept(this.getHolder(), new RegistryStepImpl<>(registry)), dependencies); } - return new RegistryStepImpl<>(registry); } protected abstract RegistryHolder getHolder(); @@ -75,24 +86,10 @@ public RegistryStep register(final ResourceKey key, final T value) { } } - public static final class BuiltInImpl extends AbstractLifecycleEvent implements RegisterRegistryValueEvent.BuiltIn { - - private Registry registry; - - public BuiltInImpl(final Cause cause, final Game game, Registry registry) { - super(cause, game); - this.registry = registry; - } - - @Override - public RegistryStep registry(final RegistryType registryType) { - return new RegistryStepImpl<>(registry); - } - } public static final class GameScopedImpl extends AbstractRegisterRegistryValueEvent implements RegisterRegistryValueEvent.GameScoped { - public GameScopedImpl(final Cause cause, final Game game) { - super(cause, game); + public GameScopedImpl(final Cause cause, final Game game, final Map, Registry> registries) { + super(cause, game, registries); } @Override @@ -104,12 +101,13 @@ protected RegistryHolder getHolder() { public static final class EngineScopedImpl extends AbstractRegisterRegistryValueEvent implements RegisterRegistryValueEvent.EngineScoped { private final TypeToken token; - private final E engine; + private final RegistryHolder registryHolder; - public EngineScopedImpl(final Cause cause, final Game game, final E engine) { - super(cause, game); - this.token = TypeToken.get((Class) engine.getClass()); - this.engine = engine; + public EngineScopedImpl(final Cause cause, final Game game, final RegistryHolder registryHolder, + final TypeToken token, final Map, Registry> registries) { + super(cause, game, registries); + this.token = token; + this.registryHolder = registryHolder; } @Override @@ -118,8 +116,16 @@ public TypeToken paramType() { } @Override - protected RegistryHolder getHolder() { - return this.engine; + protected SpongeRegistryHolder getHolder() { + return (SpongeRegistryHolder) this.registryHolder; + } + + public static EngineScopedImpl server(final Cause cause, final Game game, final RegistryHolder registryHolder, final Map, Registry> registries) { + return new EngineScopedImpl<>(cause, game, registryHolder, TypeToken.get(Server.class), registries); + } + + public static EngineScopedImpl client(final Cause cause, final Game game, final RegistryHolder registryHolder, final Map, Registry> registries) { + return new EngineScopedImpl<>(cause, game, registryHolder, TypeToken.get(Client.class), registries); } } @@ -127,8 +133,8 @@ public static final class WorldScopedImpl extends AbstractRegisterRegistryValueE private final ResourceKey worldKey; - public WorldScopedImpl(final Cause cause, final Game game, final ResourceKey worldKey) { - super(cause, game); + public WorldScopedImpl(final Cause cause, final Game game, final Map, Registry> registries, final ResourceKey worldKey) { + super(cause, game, registries); this.worldKey = worldKey; } diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterCommandEventImpl.java b/src/main/java/org/spongepowered/common/event/lifecycle/RegisterCommandEventImpl.java index 2a3a334fa98..cf47337122e 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterCommandEventImpl.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/RegisterCommandEventImpl.java @@ -31,6 +31,7 @@ import org.spongepowered.api.command.registrar.CommandRegistrar; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.plugin.PluginContainer; import java.util.Objects; @@ -38,10 +39,17 @@ public final class RegisterCommandEventImpl> extends AbstractLifecycleEvent.GenericImpl implements RegisterCommandEvent { private final R registrar; + private final RegistryHolder registryHolder; - public RegisterCommandEventImpl(final Cause cause, final Game game, final R registrar) { + public RegisterCommandEventImpl(final Cause cause, final Game game, final R registrar, final RegistryHolder registryHolder) { super(cause, game, registrar.type().handledType()); this.registrar = registrar; + this.registryHolder = registryHolder; + } + + @Override + public RegistryHolder registryHolder() { + return this.registryHolder; } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java index ceddabfb89a..6d07b8dacb6 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java @@ -24,151 +24,24 @@ */ package org.spongepowered.common.item.recipe; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.JsonOps; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.advancements.AdvancementRewards; -import net.minecraft.advancements.critereon.RecipeUnlockedTrigger; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeInput; -import net.minecraft.world.item.crafting.RecipeSerializer; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; -import java.io.IOException; import java.util.Collection; import java.util.function.Function; -public abstract class SpongeRecipeRegistration> implements RecipeRegistration { - - private static final Gson GSON = new Gson(); - - protected final ResourceLocation key; - protected final RecipeSerializer serializer; - protected final AdvancementHolder advancement; - protected final String group; - protected final DataPack pack; - - public SpongeRecipeRegistration(final ResourceLocation key, - final String group, final DataPack pack, final RecipeCategory recipeCategory, - final RecipeSerializer serializer) { - this.key = key; - this.serializer = serializer; - this.pack = pack; - var rKey = net.minecraft.resources.ResourceKey.create(Registries.RECIPE, key); - this.advancement = Advancement.Builder.advancement() - .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(rKey)) - .rewards(AdvancementRewards.Builder.recipe(rKey)) - .build(ResourceLocation.fromNamespaceAndPath(key.getNamespace(), "recipes/" + recipeCategory.getFolderName() + "/" + key.getPath())); - this.group = group == null ? "" : group; - } - - public static , I extends RecipeInput> RecipeSerializer determineSerializer(final ItemStack resultStack, - final Function resultFunction, - final Function> remainingItemsFunction, - final Collection ingredients, - final RecipeSerializer vanilla, final RecipeSerializer sponge) { - if (!resultStack.getComponents().isEmpty() || resultFunction != null || remainingItemsFunction != null) { - return sponge; - } - for (final Ingredient value : ingredients) { - if (value instanceof SpongeIngredient) { - return sponge; - } - } - return vanilla; - } +public final class SpongeRecipeRegistration { public static boolean isVanillaSerializer(final ItemStack resultStack, - final Function resultFunction, - final Function> remainingItemsFunction, - final Collection ingredients) { + final Function resultFunction, + final Function> remainingItemsFunction, + final Collection ingredients) { if (!resultStack.getComponents().isEmpty() || resultFunction != null || remainingItemsFunction != null) { return false; } return ingredients.stream().noneMatch(value -> value instanceof SpongeIngredient); } - - @Override - public ResourceKey key() { - return (ResourceKey) (Object) this.key; - } - - @Override - public int contentVersion() { - return 1; - } - - @Override - public DataContainer toContainer() { - var json = Recipe.CODEC.encodeStart(JsonOps.INSTANCE, (Recipe) this.recipe()).result().get(); - try { - return DataFormats.JSON.get().read(GSON.toJson(json)); // TODO serialize or get DataContainer without serializing - } catch (final IOException e) { - throw new IllegalStateException(e); - } - } - - @Override - public DataPack pack() { - return this.pack; - } - - @SuppressWarnings("unchecked") - protected void ensureCached() { - if (this instanceof SpongeRecipeRegistration.ResultFunctionRegistration rfr) { - IngredientResultUtil.cacheResultFunction(this.key, (Function) rfr.resultFunction()); - } - if (this instanceof SpongeRecipeRegistration.RemainingItemsFunctionRegistration rifr) { - IngredientResultUtil.cacheRemainingItemsFunction(this.key, (Function) rifr.remainingItems()); - } - } - - public AdvancementHolder advancement() { - return advancement; - } - - public static JsonObject encode(RecipeRegistration template, RegistryAccess access) { - try { - if (template instanceof SpongeRecipeRegistration srr) { - srr.ensureCached(); - } - final var ops = RegistryOps.create(JsonOps.INSTANCE, access); - final DataResult encoded = Recipe.CODEC.encodeStart(ops, (Recipe) template.recipe()); - if (encoded.result().isPresent()) { - return encoded.result().get().getAsJsonObject(); - } - final var error = encoded.error().get(); - throw new RuntimeException(error.message()); - } catch (Exception e) { - throw new RuntimeException("Could not encode recipe " + template.key(), e); - } - } - - public interface ResultFunctionRegistration { - - Function resultFunction(); - } - - public interface RemainingItemsFunctionRegistration { - - Function> remainingItems(); - } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java index 4d3223616b3..e86a6dee95f 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java @@ -30,29 +30,22 @@ import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import java.util.Optional; +import java.util.function.Function; -public class SpongeBlastingRecipe extends BlastingRecipe implements ResultFunctionRecipe { +public class SpongeBlastingRecipe extends BlastingRecipe { - private final String resultFunctionId; + private final Function function; - public SpongeBlastingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final String resultFunctionId) { + public SpongeBlastingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { super(group, category, ingredient, result, experience, cookingTime); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.function = function; } @Override public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - final ItemStack result = IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.function != null) { + final ItemStack result = this.function.apply($$0); result.setCount(1); return result; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java index 6fd30630776..27169173be6 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java @@ -30,29 +30,22 @@ import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import java.util.Optional; +import java.util.function.Function; -public class SpongeCampfireCookingRecipe extends CampfireCookingRecipe implements ResultFunctionRecipe { +public class SpongeCampfireCookingRecipe extends CampfireCookingRecipe { - private final String resultFunctionId; + private final Function function; - public SpongeCampfireCookingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final String resultFunctionId) { + public SpongeCampfireCookingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { super(group, category, ingredient, result, experience, cookingTime); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.function = function; } @Override public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - final ItemStack result = IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.function != null) { + final ItemStack result = this.function.apply($$0); result.setCount(1); return result; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java index d173ba4a708..b84cee4eb3e 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java @@ -25,31 +25,33 @@ package org.spongepowered.common.item.recipe.cooking; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.BlastingRecipe; +import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; +import net.minecraft.world.item.crafting.SmeltingRecipe; +import net.minecraft.world.item.crafting.SmokingRecipe; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.RecipeType; import org.spongepowered.api.item.recipe.cooking.CookingRecipe; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.util.Ticks; import org.spongepowered.common.inventory.util.InventoryUtil; +import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; +import org.spongepowered.common.util.SpongeTicks; +import java.util.Collections; import java.util.Objects; +import java.util.Optional; import java.util.function.Function; -public final class SpongeCookingRecipeBuilder extends AbstractResourceKeyedBuilder - implements CookingRecipe.Builder.ResultStep, CookingRecipe.Builder.IngredientStep, CookingRecipe.Builder.EndStep { +public final class SpongeCookingRecipeBuilder implements CookingRecipe.Builder.ResultStep, CookingRecipe.Builder.IngredientStep, CookingRecipe.Builder.EndStep { private net.minecraft.world.item.crafting.RecipeType type; private Ingredient ingredient; @@ -59,7 +61,6 @@ public final class SpongeCookingRecipeBuilder extends AbstractResourceKeyedBuild private @Nullable Float experience; private @Nullable Ticks cookingTime; private @Nullable String group; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category private CookingBookCategory cookingCategory = CookingBookCategory.MISC; // TODO support category @@ -72,7 +73,6 @@ public ResultStep ingredient(final org.spongepowered.api.item.recipe.crafting.In @Override public CookingRecipe.Builder reset() { - super.reset(); this.type = null; this.ingredient = null; this.result = null; @@ -80,7 +80,6 @@ public CookingRecipe.Builder reset() { this.experience = null; this.cookingTime = null; this.group = null; - this.pack = DataPacks.RECIPE; return this; } @@ -133,28 +132,45 @@ public EndStep group(final String group) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - protected RecipeRegistration build0() { + public CookingRecipe build() { Objects.requireNonNull(this.type, "type"); Objects.requireNonNull(this.ingredient, "ingredient"); Objects.requireNonNull(this.result, "result"); - return SpongeCookingRecipeRegistration.of((ResourceLocation) (Object) this.key, - this.type, - this.group, - this.ingredient, - this.experience, - this.cookingTime, - this.result, - this.resultFunction, - this.pack, - this.recipeCategory, - this.cookingCategory); - } + final var ingredientList = Collections.singletonList(this.ingredient); + final boolean isVanilla = SpongeRecipeRegistration.isVanillaSerializer(this.result, this.resultFunction, null, ingredientList); + + String group = this.group == null ? "" : this.group; + float experience = this.experience == null ? 0 : this.experience; + if (this.type == net.minecraft.world.item.crafting.RecipeType.BLASTING) { + final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(100); + if (!isVanilla) { + return (CookingRecipe) new SpongeBlastingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); + } + return (CookingRecipe) new BlastingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + } + if (this.type == net.minecraft.world.item.crafting.RecipeType.CAMPFIRE_COOKING) { + final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(600); + if (!isVanilla) { + return (CookingRecipe) new SpongeCampfireCookingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); + } + return (CookingRecipe) new CampfireCookingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + } + if (this.type == net.minecraft.world.item.crafting.RecipeType.SMOKING) { + final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(100); + if (!isVanilla) { + return (CookingRecipe) new SpongeSmokingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); + } + return (CookingRecipe) new SmokingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + } + if (this.type == net.minecraft.world.item.crafting.RecipeType.SMELTING) { + final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(200); + if (!isVanilla) { + return (CookingRecipe) new SpongeSmeltingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); + } + return (CookingRecipe) new SmeltingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + } + throw new IllegalArgumentException("Unknown RecipeType " + this.type); + } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java deleted file mode 100644 index 6a1b01b74e4..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeRegistration.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.cooking; - -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.AbstractCookingRecipe; -import net.minecraft.world.item.crafting.BlastingRecipe; -import net.minecraft.world.item.crafting.CampfireCookingRecipe; -import net.minecraft.world.item.crafting.CookingBookCategory; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.item.crafting.SmeltingRecipe; -import net.minecraft.world.item.crafting.SmokingRecipe; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.cooking.CookingRecipe; -import org.spongepowered.api.util.Ticks; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; -import org.spongepowered.common.util.SpongeTicks; - -import java.util.Collections; -import java.util.function.Function; - -public class SpongeCookingRecipeRegistration extends SpongeRecipeRegistration implements SpongeRecipeRegistration.ResultFunctionRegistration{ - - // Vanilla Recipe - private final Ingredient ingredient; - private final float experience; - private final Ticks cookingTime; - - // Sponge Recipe - private final ItemStack spongeResult; - private final Function resultFunction; - private final RecipeType type; - private final CookingBookCategory cookingCategory; - - public SpongeCookingRecipeRegistration(final ResourceLocation key, final RecipeType type, final RecipeSerializer serializer, - final String group, final Ingredient ingredient, final float experience, final Ticks cookingTime, - final ItemStack spongeResult, final Function resultFunction, - final DataPack pack, final RecipeCategory category, final CookingBookCategory cookingCategory) { - super(key, group, pack, category, serializer); - this.type = type; - this.ingredient = ingredient; - this.experience = experience; - this.cookingTime = cookingTime; - this.spongeResult = spongeResult; - this.resultFunction = resultFunction; - this.cookingCategory = cookingCategory; - } - - public static SpongeCookingRecipeRegistration of(final ResourceLocation key, final RecipeType type, final @Nullable String group, - final Ingredient ingredient, final Float experience, final @Nullable Ticks cookingTime, final ItemStack result, - final Function resultFunction, final DataPack pack, final RecipeCategory recipeCategory, final CookingBookCategory cookingCategory) - { - var finalCookingTime = cookingTime; - - final RecipeSerializer serializer; - if (type == RecipeType.BLASTING) { - if (finalCookingTime == null) { - finalCookingTime = Ticks.of(100); - } - serializer = RecipeSerializer.BLASTING_RECIPE; - } else if (type == RecipeType.CAMPFIRE_COOKING) { - if (finalCookingTime == null) { - finalCookingTime = Ticks.of(600); - } - serializer = RecipeSerializer.CAMPFIRE_COOKING_RECIPE; - } else if (type == RecipeType.SMOKING) { - if (finalCookingTime == null) { - finalCookingTime = Ticks.of(100); - } - serializer = RecipeSerializer.SMOKING_RECIPE; - } else if (type == RecipeType.SMELTING) { - if (finalCookingTime == null) { - finalCookingTime = Ticks.of(200); - } - serializer = RecipeSerializer.SMELTING_RECIPE; - } else { - throw new IllegalArgumentException("Unknown RecipeType " + type); - } - - return new SpongeCookingRecipeRegistration(key, type, serializer, group, - ingredient, experience == null ? 0 : experience, finalCookingTime, result, resultFunction, pack, recipeCategory, cookingCategory); - } - - @Override - public Recipe recipe() { - this.ensureCached(); - final int ticksCookingTime = SpongeTicks.toSaturatedIntOrInfinite(this.cookingTime); - final String resultFunctionId = this.resultFunction == null ? null : this.key.toString(); - - final var ingredientList = Collections.singletonList(ingredient); - final boolean isVanilla = SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, ingredientList); - - if (type == RecipeType.BLASTING) { - if (!isVanilla) { - return (CookingRecipe) new SpongeBlastingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime, resultFunctionId); - } - return (CookingRecipe) new BlastingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime); - } - if (type == RecipeType.CAMPFIRE_COOKING) { - if (!isVanilla) { - return (CookingRecipe) new SpongeCampfireCookingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime, resultFunctionId); - } - return (CookingRecipe) new CampfireCookingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime); - } - if (type == RecipeType.SMOKING) { - if (!isVanilla) { - return (CookingRecipe) new SpongeSmokingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime, resultFunctionId); - } - return (CookingRecipe) new SmokingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime); - } - if (type == RecipeType.SMELTING) { - if (!isVanilla) { - return (CookingRecipe) new SpongeSmeltingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime, resultFunctionId); - } - return (CookingRecipe) new SmeltingRecipe(this.group, this.cookingCategory, this.ingredient, this.spongeResult, this.experience, ticksCookingTime); - } - throw new IllegalArgumentException("Unknown RecipeType " + type); - - - } - - @Override - public Function resultFunction() { - return this.resultFunction; - } -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java index cdd5b5e9999..8fba2a264a2 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java @@ -30,29 +30,22 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.item.crafting.SmeltingRecipe; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import java.util.Optional; +import java.util.function.Function; -public class SpongeSmeltingRecipe extends SmeltingRecipe implements ResultFunctionRecipe { +public class SpongeSmeltingRecipe extends SmeltingRecipe { - private final String resultFunctionId; + private final Function function; - public SpongeSmeltingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final String resultFunctionId) { + public SpongeSmeltingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { super(group, category, ingredient, result, experience, cookingTime); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.function = function; } @Override public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - final ItemStack result = IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.function != null) { + final ItemStack result = this.function.apply($$0); result.setCount(1); return result; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java index e761bb39b93..8b0f4ae63e4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java @@ -30,29 +30,22 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.item.crafting.SmokingRecipe; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import java.util.Optional; +import java.util.function.Function; -public class SpongeSmokingRecipe extends SmokingRecipe implements ResultFunctionRecipe { +public class SpongeSmokingRecipe extends SmokingRecipe { - private final String resultFunctionId; + private final Function function; - public SpongeSmokingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final String resultFunctionId) { + public SpongeSmokingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { super(group, category, ingredient, result, experience, cookingTime); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.function = function; } @Override public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - final ItemStack result = IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.function != null) { + final ItemStack result = this.function.apply($$0); result.setCount(1); return result; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeBuilder.java index 358ecafd86e..fe77f6045b0 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeBuilder.java @@ -25,29 +25,22 @@ package org.spongepowered.common.item.recipe.crafting.custom; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.CraftingBookCategory; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.item.recipe.crafting.SpecialCraftingRecipe; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import java.util.List; import java.util.function.BiPredicate; import java.util.function.Function; -public final class SpongeSpecialCraftingRecipeBuilder extends AbstractResourceKeyedBuilder - implements SpecialCraftingRecipe.Builder, SpecialCraftingRecipe.Builder.ResultStep, SpecialCraftingRecipe.Builder.EndStep { +public final class SpongeSpecialCraftingRecipeBuilder implements SpecialCraftingRecipe.Builder, SpecialCraftingRecipe.Builder.ResultStep, SpecialCraftingRecipe.Builder.EndStep { private BiPredicate biPredicate; private Function> remainingItemsFunction; private Function resultFunction; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category @@ -77,25 +70,15 @@ public EndStep result(ItemStackLike result) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public RecipeRegistration build0() { - final ResourceLocation resourceLocation = (ResourceLocation) (Object) this.key; - // TODO: support categories - return new SpongeSpecialCraftingRecipeRegistration(resourceLocation, CraftingBookCategory.MISC, this.biPredicate, this.remainingItemsFunction, this.resultFunction, this.pack, this.recipeCategory); + public SpecialCraftingRecipe build() { + return (SpecialCraftingRecipe) (Object) new SpongeSpecialRecipe(CraftingBookCategory.MISC, this.biPredicate, this.remainingItemsFunction, this.resultFunction); } @Override public SpecialCraftingRecipe.Builder reset() { - super.reset(); this.biPredicate = null; this.remainingItemsFunction = null; this.resultFunction = null; - this.pack = DataPacks.RECIPE; return this; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeRegistration.java deleted file mode 100644 index 27a73748ed3..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialCraftingRecipeRegistration.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.crafting.custom; - -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.CraftingBookCategory; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.crafting.RecipeInput; -import org.spongepowered.api.item.recipe.crafting.SpecialCraftingRecipe; -import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiPredicate; -import java.util.function.Function; - -public class SpongeSpecialCraftingRecipeRegistration extends SpongeRecipeRegistration { - - public static final Map RECIPES = new HashMap<>(); - - private final BiPredicate biPredicate; - private final Function> remainingItemsFunction; - private final Function resultFunction; - - private final SpongeSpecialRecipe recipe; - - public SpongeSpecialCraftingRecipeRegistration(ResourceLocation key, - final CraftingBookCategory category, - BiPredicate biPredicate, - Function> remainingItemsFunction, - Function resultFunction, - DataPack pack, final RecipeCategory recipeCategory) { - super(key, "", pack, recipeCategory, null); - - this.biPredicate = biPredicate; - this.remainingItemsFunction = remainingItemsFunction; - this.resultFunction = resultFunction; - - this.recipe = new SpongeSpecialRecipe(key, category, this.biPredicate, this.remainingItemsFunction, this.resultFunction); - SpongeSpecialCraftingRecipeRegistration.RECIPES.put(this.recipe.id(), this.recipe); - } - - public static SpongeSpecialRecipe get(final String id, final CraftingBookCategory category) { - return SpongeSpecialCraftingRecipeRegistration.RECIPES.getOrDefault(id, - new SpongeSpecialRecipe(ResourceLocation.tryParse(id), category, (x, y) -> false, null, null)); - } - - @Override - public Recipe recipe() { - this.ensureCached(); - return (SpecialCraftingRecipe) (Object) this.recipe; - } -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index bc2ec36d749..1fe006055f1 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -24,12 +24,8 @@ */ package org.spongepowered.common.item.recipe.crafting.custom; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; @@ -40,7 +36,6 @@ import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.Constants; import java.util.List; import java.util.function.BiPredicate; @@ -48,36 +43,20 @@ public final class SpongeSpecialRecipe extends CustomRecipe { - public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( - $$0 -> $$0.group( - Codec.STRING.fieldOf(Constants.Recipe.SPONGE_TYPE).forGetter(SpongeSpecialRecipe::id), // important to fail early when decoding vanilla recipes - CraftingBookCategory.CODEC.fieldOf(Constants.Recipe.CATEGORY).orElse(CraftingBookCategory.MISC).forGetter(SpongeSpecialRecipe::category) - ) - .apply($$0, SpongeSpecialCraftingRecipeRegistration::get) - ); - - private final String id; private final BiPredicate biPredicate; private final Function> remainingItemsFunction; private final Function resultFunction; - public SpongeSpecialRecipe(ResourceLocation key, - CraftingBookCategory category, + public SpongeSpecialRecipe(CraftingBookCategory category, BiPredicate biPredicate, Function> remainingItemsFunction, Function resultFunction) { super(category); - this.id = key.toString(); this.biPredicate = biPredicate; this.remainingItemsFunction = remainingItemsFunction; this.resultFunction = resultFunction; } - public String id() { - return id; - } - - @Override public boolean matches(final CraftingInput input, final Level level) { return this.biPredicate.test(InventoryUtil.toSponge(input), (ServerWorld) level); diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java index 58022355737..c529193919f 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java @@ -29,23 +29,18 @@ import it.unimi.dsi.fastutil.chars.Char2ObjectArrayMap; import net.minecraft.core.NonNullList; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.ShapedRecipePattern; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.crafting.Ingredient; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.item.recipe.crafting.ShapedCraftingRecipe; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.common.util.Preconditions; import java.util.ArrayList; @@ -58,7 +53,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public final class SpongeShapedCraftingRecipeBuilder extends AbstractResourceKeyedBuilder implements +public final class SpongeShapedCraftingRecipeBuilder implements ShapedCraftingRecipe.Builder, ShapedCraftingRecipe.Builder.AisleStep.ResultStep, ShapedCraftingRecipe.Builder.RowsStep.ResultStep, ShapedCraftingRecipe.Builder.EndStep { @@ -71,7 +66,6 @@ public final class SpongeShapedCraftingRecipeBuilder extends AbstractResourceKey private Function resultFunction; private String group; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category private CraftingBookCategory craftingBookCategory = CraftingBookCategory.MISC; // TODO support category @@ -169,13 +163,7 @@ public EndStep group(final @Nullable String name) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public RecipeRegistration build0() { + public ShapedCraftingRecipe build() { Preconditions.checkState(!this.aisle.isEmpty(), "aisle has not been set"); Preconditions.checkState(!this.ingredientMap.isEmpty(), "no ingredients set"); Preconditions.checkState(!this.result.isEmpty(), "no result set"); @@ -197,20 +185,18 @@ public RecipeRegistration build0() { // Default space to Empty Ingredient // ingredientsMap.putIfAbsent(' ', net.minecraft.item.crafting.Ingredient.EMPTY); final ShapedRecipePattern pattern = ShapedRecipePattern.of(ingredientsMap, this.aisle); - return new SpongeShapedCraftingRecipeRegistration((ResourceLocation) (Object) key, this.group, pattern, - ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction, this.pack, this.recipeCategory, this.craftingBookCategory); + return (ShapedCraftingRecipe) new SpongeShapedRecipe(this.group == null ? "": this.group, this.craftingBookCategory, pattern, true, + ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction); } @Override public ShapedCraftingRecipe.Builder reset() { - super.reset(); this.aisle = new ArrayList<>(); this.ingredientMap.clear(); this.result = ItemStack.empty(); this.resultFunction = null; this.group = null; this.remainingItemsFunction = null; - this.pack = DataPacks.RECIPE; return this; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java deleted file mode 100644 index 8574bdcfaeb..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeRegistration.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.crafting.shaped; - -import net.minecraft.core.NonNullList; -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingBookCategory; -import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.ShapedRecipe; -import net.minecraft.world.item.crafting.ShapedRecipePattern; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.crafting.ShapedCraftingRecipe; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.util.Optional; -import java.util.function.Function; - -public class SpongeShapedCraftingRecipeRegistration extends SpongeRecipeRegistration implements - SpongeRecipeRegistration.ResultFunctionRegistration, - SpongeRecipeRegistration.RemainingItemsFunctionRegistration { - - // Vanilla Recipe - private final ShapedRecipePattern pattern; - - // Sponge Recipe - private final ItemStack spongeResult; - private final Function resultFunction; - private final Function> remainingItemsFunction; - private final CraftingBookCategory craftingBookCategory; - private final boolean showNotification = true; - - public SpongeShapedCraftingRecipeRegistration(final ResourceLocation key, final String group, final ShapedRecipePattern pattern, - final ItemStack spongeResult, final Function resultFunction, - final Function> remainingItemsFunction, - final DataPack pack, final RecipeCategory category, final CraftingBookCategory craftingBookCategory) { - super(key, group, pack, category, RecipeSerializer.SHAPED_RECIPE); - this.pattern = pattern; - this.spongeResult = spongeResult; - this.resultFunction = resultFunction; - this.remainingItemsFunction = remainingItemsFunction; - this.craftingBookCategory = craftingBookCategory; - } - - @Override - public Function resultFunction() { - return this.resultFunction; - } - - @Override - public Function> remainingItems() { - return this.remainingItemsFunction; - } - - @Override - public Recipe recipe() { - final var ingredients = this.pattern.ingredients().stream().filter(Optional::isPresent).map(Optional::get).toList(); - if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, this.remainingItemsFunction, ingredients)) { - return (ShapedCraftingRecipe) new ShapedRecipe(this.group, this.craftingBookCategory, this.pattern, this.spongeResult, this.showNotification); - } - this.ensureCached(); - return (ShapedCraftingRecipe) new SpongeShapedRecipe(this.group, this.craftingBookCategory, this.pattern, this.showNotification, - this.spongeResult, - this.resultFunction == null ? null : this.key.toString(), - this.remainingItemsFunction == null ? null : this.key.toString()); - } - -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java index 6ce7547a3f7..dad53506b17 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java @@ -25,9 +25,6 @@ package org.spongepowered.common.item.recipe.crafting.shaped; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; @@ -35,50 +32,13 @@ import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; -import org.spongepowered.common.bridge.world.item.crafting.ShapedRecipeBridge; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import org.spongepowered.common.util.Constants; -import java.util.Optional; +import java.util.function.Function; -public class SpongeShapedRecipe extends ShapedRecipe implements ResultFunctionRecipe { +public class SpongeShapedRecipe extends ShapedRecipe { - public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( - $$0 -> $$0.group( - Codec.STRING.fieldOf(Constants.Recipe.SPONGE_TYPE).forGetter(t -> "custom"), // important to fail early when decoding vanilla recipes - Codec.STRING.optionalFieldOf(Constants.Recipe.GROUP, "").forGetter(ShapedRecipe::group), - CraftingBookCategory.CODEC.fieldOf(Constants.Recipe.CATEGORY).orElse(CraftingBookCategory.MISC).forGetter(ShapedRecipe::category), - ShapedRecipePattern.MAP_CODEC.forGetter($$0x -> ((ShapedRecipeBridge) $$0x).bridge$pattern()), - ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), - Codec.BOOL.optionalFieldOf("show_notification", true).forGetter(ShapedRecipe::showNotification), - IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId), - IngredientResultUtil.CACHED_REMAINING_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_REMAINING_ITEMS).forGetter(SpongeShapedRecipe::remainingItemsFunctionId) - ) - .apply($$0, SpongeShapedRecipe::of) - ); - - private final String resultFunctionId; - private final String remainingItemsFunctionId; - - public static SpongeShapedRecipe of( - final String spongeType, - final String groupIn, final CraftingBookCategory category, - final ShapedRecipePattern pattern, - final ItemStack recipeOutputIn, - final boolean showNotification, - final Optional resultFunctionId, - final Optional remainingItemsFunctionId) { - return new SpongeShapedRecipe( - groupIn, - category, - pattern, - showNotification, - recipeOutputIn, - resultFunctionId.orElse(null), - remainingItemsFunctionId.orElse(null)); - } + private final Function resultFunction; + private final Function> remainingItemsFunction; public SpongeShapedRecipe( final String groupIn, @@ -86,34 +46,25 @@ public SpongeShapedRecipe( final ShapedRecipePattern pattern, final boolean showNotification, final ItemStack resultStack, - final String resultFunctionId, - final String remainingItemsFunctionId) { + final Function resultFunction, + final Function> remainingItemsFunction) { super(groupIn, category, pattern, resultStack, showNotification); - this.resultFunctionId = resultFunctionId; - this.remainingItemsFunctionId = remainingItemsFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(resultFunctionId); - } - - public Optional remainingItemsFunctionId() { - return Optional.ofNullable(remainingItemsFunctionId); + this.resultFunction = resultFunction; + this.remainingItemsFunction = remainingItemsFunction; } @Override public NonNullList getRemainingItems(final CraftingInput $$0) { - if (this.remainingItemsFunctionId != null) { - return IngredientResultUtil.cachedRemainingItemsFunction(this.remainingItemsFunctionId).apply($$0); + if (this.remainingItemsFunction != null) { + return this.remainingItemsFunction.apply($$0); } return super.getRemainingItems($$0); } @Override public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.resultFunction != null) { + return this.resultFunction.apply($$0); } return super.assemble($$0, $$1); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java index f048d2256e0..a84eb2c9dc7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java @@ -27,24 +27,19 @@ import net.minecraft.core.NonNullList; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.Ingredient; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.item.recipe.crafting.ShapelessCraftingRecipe; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.common.util.Preconditions; import java.util.List; @@ -52,15 +47,13 @@ import java.util.function.Function; import java.util.function.Supplier; -public class SpongeShapelessCraftingRecipeBuilder extends AbstractResourceKeyedBuilder - implements ShapelessCraftingRecipe.Builder.EndStep, ShapelessCraftingRecipe.Builder.ResultStep { +public class SpongeShapelessCraftingRecipeBuilder implements ShapelessCraftingRecipe.Builder.EndStep, ShapelessCraftingRecipe.Builder.ResultStep { private org.spongepowered.api.item.inventory.ItemStack result; private Function resultFunction; private Function> remainingItemsFunction; private final NonNullList ingredients = NonNullList.create(); private String group; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category private CraftingBookCategory craftingBookCategory = CraftingBookCategory.MISC; // TODO support category @@ -121,28 +114,19 @@ public EndStep group(final @Nullable String name) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public RecipeRegistration build0() { + public ShapelessCraftingRecipe build() { Preconditions.checkState(!this.ingredients.isEmpty(), "The ingredients are not set."); - return new SpongeShapelessCraftingRecipeRegistration((ResourceLocation) (Object) key, this.group, this.ingredients, - ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction, this.pack, - this.recipeCategory, this.craftingBookCategory); + return (ShapelessCraftingRecipe) new SpongeShapelessRecipe(this.group == null ? "": this.group, this.craftingBookCategory, this.ingredients, + ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction); } @Override public ShapelessCraftingRecipe.Builder reset() { - super.reset(); this.result = null; this.resultFunction = null; this.ingredients.clear(); this.group = null; this.remainingItemsFunction = null; - this.pack = DataPacks.RECIPE; return this; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeRegistration.java deleted file mode 100644 index c70e8658c1f..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeRegistration.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.crafting.shapeless; - -import net.minecraft.core.NonNullList; -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingBookCategory; -import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.ShapelessRecipe; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.crafting.ShapelessCraftingRecipe; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.util.List; -import java.util.function.Function; - -public class SpongeShapelessCraftingRecipeRegistration extends SpongeRecipeRegistration implements - SpongeRecipeRegistration.ResultFunctionRegistration, - SpongeRecipeRegistration.RemainingItemsFunctionRegistration -{ - // Vanilla Recipe - private final List ingredients; - - // Sponge Recipe - private final ItemStack spongeResult; - private final Function resultFunction; - private final Function> remainingItemsFunction; - private final CraftingBookCategory craftingBookCategory; - - public SpongeShapelessCraftingRecipeRegistration(final ResourceLocation key, final String group, - final List ingredients, final ItemStack spongeResult, final Function resultFunction, - final Function> remainingItemsFunction, - final DataPack pack, final RecipeCategory category, final CraftingBookCategory craftingBookCategory) { - super(key, group, pack, category, RecipeSerializer.SHAPELESS_RECIPE); - this.ingredients = ingredients; - this.spongeResult = spongeResult; - this.resultFunction = resultFunction; - this.remainingItemsFunction = remainingItemsFunction; - this.craftingBookCategory = craftingBookCategory; - } - - - @Override - public Function resultFunction() { - return this.resultFunction; - } - - @Override - public Function> remainingItems() { - return this.remainingItemsFunction; - } - - @Override - public Recipe recipe() { - this.ensureCached(); - final NonNullList ingredients = NonNullList.create(); - ingredients.addAll(this.ingredients); - - if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, this.remainingItemsFunction, ingredients)) { - return (ShapelessCraftingRecipe) new ShapelessRecipe(this.group, this.craftingBookCategory, this.spongeResult, ingredients); - } - - return (ShapelessCraftingRecipe) new SpongeShapelessRecipe(this.group, this.craftingBookCategory, ingredients, this.spongeResult, - this.resultFunction == null ? null : this.key.toString(), - this.remainingItemsFunction == null ? null : this.key.toString()); - - } -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index daed310a648..7981d28781e 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -24,9 +24,6 @@ */ package org.spongepowered.common.item.recipe.crafting.shapeless; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; @@ -36,10 +33,7 @@ import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.level.Level; import org.spongepowered.common.accessor.world.item.crafting.ShapelessRecipeAccessor; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; -import org.spongepowered.common.util.Constants; import java.util.ArrayList; import java.util.Collection; @@ -48,66 +42,29 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; +import java.util.function.Function; /** * Customized matching algorithm matching with ingredient predicate instead of packed item in vanilla */ public class SpongeShapelessRecipe extends ShapelessRecipe { - - public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( - $$0 -> $$0.group( - Codec.STRING.fieldOf(Constants.Recipe.SPONGE_TYPE).forGetter(t -> "custom"), // important to fail early when decoding vanilla recipes - Codec.STRING.optionalFieldOf("group", "").forGetter(ShapelessRecipe::group), - CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(ShapelessRecipe::category), - ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), - Ingredient.CODEC.listOf(1,9) - .fieldOf(Constants.Recipe.SHAPELESS_INGREDIENTS) - .forGetter(sr -> ((ShapelessRecipeAccessor) sr).accessor$ingredients()), - IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(SpongeShapelessRecipe::resultFunctionId), - IngredientResultUtil.CACHED_REMAINING_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_REMAINING_ITEMS).forGetter(SpongeShapelessRecipe::remainingItemsFunctionId) - ) - .apply($$0, SpongeShapelessRecipe::of) - ); private final boolean onlyVanillaIngredients; - private final String resultFunctionId; - private final String remainingItemsFunctionId; - - - public static SpongeShapelessRecipe of( - final String spongeType, - final String groupIn, - final CraftingBookCategory category, - final ItemStack recipeOutputIn, - final List recipeItemsIn, - final Optional resultFunctionId, - final Optional remainingItemsFunctionId) - { - return new SpongeShapelessRecipe(groupIn, category, recipeItemsIn, recipeOutputIn, - resultFunctionId.orElse(null), remainingItemsFunctionId.orElse(null)); - } + private final Function resultFunction; + private final Function> remainingItemsFunction; public SpongeShapelessRecipe(final String groupIn, final CraftingBookCategory category, final List recipeItemsIn, final ItemStack spongeResultStack, - final String resultFunctionId, - final String remainingItemsFunctionId) { + final Function resultFunction, + final Function> remainingItemsFunction) { super(groupIn, category, spongeResultStack, recipeItemsIn); this.onlyVanillaIngredients = recipeItemsIn.stream().noneMatch(i -> i instanceof SpongeIngredient); - this.resultFunctionId = resultFunctionId; - this.remainingItemsFunctionId = remainingItemsFunctionId; - } - - public Optional resultFunctionId() { - return Optional.ofNullable(resultFunctionId); - } - - public Optional remainingItemsFunctionId() { - return Optional.ofNullable(remainingItemsFunctionId); + this.resultFunction = resultFunction; + this.remainingItemsFunction = remainingItemsFunction; } @Override @@ -120,8 +77,8 @@ public boolean matches(final CraftingInput $$0, final Level $$1) { @Override public NonNullList getRemainingItems(final CraftingInput $$0) { - if (this.remainingItemsFunctionId != null) { - return IngredientResultUtil.cachedRemainingItemsFunction(this.remainingItemsFunctionId).apply($$0); + if (this.remainingItemsFunction != null) { + return this.remainingItemsFunction.apply($$0); } return super.getRemainingItems($$0); } @@ -129,8 +86,8 @@ public NonNullList getRemainingItems(final CraftingInput $$0) { @Override public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.resultFunction != null) { + return this.resultFunction.apply($$0); } return super.assemble($$0, $$1); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientResultUtil.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientResultUtil.java deleted file mode 100644 index 11d658bef51..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientResultUtil.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.ingredient; - -import com.google.gson.JsonElement; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.JsonOps; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.core.NonNullList; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.Container; -import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.RecipeInput; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.common.SpongeCommon; - -import java.text.MessageFormat; -import java.util.Map; -import java.util.function.Function; - -public final class IngredientResultUtil { - - private static final Map> cachedResultFunctions = new Object2ObjectOpenHashMap<>(); - private static final Map>> cachedRemainingItemsFunctions = new Object2ObjectOpenHashMap<>(); - - public static JsonElement serializeItemStack(final net.minecraft.world.item.ItemStack spongeResult) { - final DataResult encoded = net.minecraft.world.item.ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, spongeResult); - return encoded.result().get(); - - } - public static final Codec CACHED_RESULT_FUNC_CODEC = Codec.STRING.flatXmap( - id -> IngredientResultUtil.cachedResultFunction(id) != null ? DataResult.success(id) : - DataResult.error(() -> "Missing Result Function for id " + id), - DataResult::success - ); - - @Nullable - @SuppressWarnings("unchecked") - public static Function cachedResultFunction(String id) { - return (Function) IngredientResultUtil.cachedResultFunctions.get(id); - } - - - public static String cacheResultFunction(ResourceLocation id, - Function resultFunction) { - if (IngredientResultUtil.cachedResultFunctions.put(id.toString(), resultFunction) != null) { - SpongeCommon.logger().warn(MessageFormat.format( - "Duplicate cache result registration! " + id + " was replaced.", - new Object[]{} - )); - } - return id.toString(); - } - - public static final Codec CACHED_REMAINING_FUNC_CODEC = Codec.STRING.flatXmap( - id -> IngredientResultUtil.cachedRemainingItemsFunction(id) != null ? DataResult.success(id) : - DataResult.error(() -> "Missing Result Function for id " + id), - DataResult::success - ); - - @Nullable - @SuppressWarnings("unchecked") - public static Function> cachedRemainingItemsFunction(String id) { - return (Function>) IngredientResultUtil.cachedRemainingItemsFunctions.get(id); - } - - - public static String cacheRemainingItemsFunction(ResourceLocation id, - Function> resultFunction) { - if (IngredientResultUtil.cachedRemainingItemsFunctions.put(id.toString(), resultFunction) != null) { - SpongeCommon.logger().warn(MessageFormat.format( - "Duplicate cache result registration! " + id + " was replaced.", - new Object[]{} - )); - } - return id.toString(); - } - - public static void clearCache() { - IngredientResultUtil.cachedResultFunctions.clear(); - IngredientResultUtil.cachedRemainingItemsFunctions.clear(); - } -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java index 27a5e0a08b4..5ba2839a520 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java @@ -24,8 +24,6 @@ */ package org.spongepowered.common.item.recipe.ingredient; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import com.mojang.datafixers.util.Either; import net.minecraft.Util; import net.minecraft.core.Holder; @@ -116,16 +114,6 @@ public Collection getItems() { return Arrays.asList(this.stacks); } - public JsonObject serialize() { - final JsonObject jsonobject = new JsonObject(); - final JsonArray stackArray = new JsonArray(); - for (ItemStack stack : this.stacks) { - stackArray.add(IngredientResultUtil.serializeItemStack(stack)); - } - jsonobject.add(SpongeItemList.INGREDIENT_ITEM, stackArray); - return jsonobject; - } - public abstract boolean test(ItemStack stack); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongePredicateItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongePredicateItemList.java index 8c7a12fca86..f0d83b03ac4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongePredicateItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongePredicateItemList.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.item.recipe.ingredient; -import com.google.gson.JsonObject; import net.minecraft.world.item.ItemStack; import java.util.function.Predicate; @@ -43,14 +42,6 @@ public SpongePredicateItemList(String id, Predicate predicate, ItemSt this.predicate = predicate; } - @Override - public JsonObject serialize() { - final JsonObject jsonobject = super.serialize(); - jsonobject.addProperty(SpongeItemList.INGREDIENT_TYPE, SpongePredicateItemList.TYPE_PREDICATE); - jsonobject.addProperty(SpongePredicateItemList.INGREDIENT_PREDICATE, this.id); - return jsonobject; - } - @Override public boolean test(ItemStack stack) { return this.predicate.test(stack); diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeStackItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeStackItemList.java index 92aa5397364..bd230c3b71c 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeStackItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeStackItemList.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.item.recipe.ingredient; -import com.google.gson.JsonObject; import net.minecraft.world.item.ItemStack; public class SpongeStackItemList extends SpongeItemList { @@ -35,13 +34,6 @@ public SpongeStackItemList(ItemStack... stacks) { super(stacks); } - @Override - public JsonObject serialize() { - final JsonObject jsonobject = super.serialize(); - jsonobject.addProperty(SpongeItemList.INGREDIENT_TYPE, SpongeStackItemList.TYPE_STACK); - return jsonobject; - } - @Override public boolean test(ItemStack testStack) { if (this.stacks.length == 0) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index 42e3cf263b2..19b847892a3 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -24,61 +24,30 @@ */ package org.spongepowered.common.item.recipe.smithing; -import static org.spongepowered.common.util.Constants.Recipe.SPONGE_TYPE; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingRecipeInput; import net.minecraft.world.item.crafting.SmithingTransformRecipe; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; -import org.spongepowered.common.bridge.world.item.crafting.SmithingRecipeBridge; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import org.spongepowered.common.util.Constants; import java.util.Optional; +import java.util.function.Function; -public class SpongeSmithingRecipe extends SmithingTransformRecipe implements ResultFunctionRecipe { +public class SpongeSmithingRecipe extends SmithingTransformRecipe { - public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( - $$0 -> $$0.group( - Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_TEMPLATE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$template()), - Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_BASE_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$base()), - Ingredient.CODEC.optionalFieldOf(Constants.Recipe.SMITHING_ADDITION_INGREDIENT).forGetter($$0x -> ((SmithingRecipeBridge) $$0x).bridge$addition()), - ItemStack.CODEC.fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge) $$0x).bridge$result()), - IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) - ) - .apply($$0, SpongeSmithingRecipe::of) - ); - - private final String resultFunctionId; - - public static SpongeSmithingRecipe of(final String spongeType, final Optional template, final Optional base, - final Optional addition, final ItemStack resultIn, final Optional resultFunctionId) - { - return new SpongeSmithingRecipe(template, base, addition, resultIn, resultFunctionId.orElse(null)); - } + private Function resultFunction; public SpongeSmithingRecipe(final Optional template, final Optional base, - final Optional addition, final ItemStack spongeResult, final String resultFunctionId) { + final Optional addition, final ItemStack spongeResult, final Function resultFunction) { super(template, base, addition, spongeResult); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.resultFunction = resultFunction; } @Override public ItemStack assemble(final SmithingRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.resultFunction != null) { + return this.resultFunction.apply($$0); } return super.assemble($$0, $$1); diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java index d7eeb1bd5e7..1104b8c065c 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java @@ -26,29 +26,25 @@ import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingRecipeInput; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.item.recipe.smithing.SmithingRecipe; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.common.util.Preconditions; import java.util.Objects; +import java.util.Optional; import java.util.function.Function; -public final class SpongeSmithingRecipeBuilder extends AbstractResourceKeyedBuilder implements +public final class SpongeSmithingRecipeBuilder implements SmithingRecipe.Builder, SmithingRecipe.Builder.BaseStep, SmithingRecipe.Builder.AdditionStep, SmithingRecipe.Builder.ResultStep, SmithingRecipe.Builder.EndStep { private ItemStack result; @@ -57,7 +53,6 @@ public final class SpongeSmithingRecipeBuilder extends AbstractResourceKeyedBuil private Ingredient addition; private Function resultFunction; private @Nullable String group; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category @@ -122,15 +117,9 @@ public EndStep group(@Nullable String name) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public RecipeRegistration build0() { - return new SpongeSmithingRecipeRegistration((ResourceLocation) (Object) key, this.group, this.template, this.base, this.addition, - ItemStackUtil.toNative(this.result), this.resultFunction, this.pack, this.recipeCategory); + public SmithingRecipe build() { + return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), Optional.ofNullable(this.base), Optional.ofNullable(this.addition), + ItemStackUtil.toNative(this.result), this.resultFunction); } @Override @@ -140,7 +129,6 @@ public SmithingRecipe.Builder reset() { this.base = null; this.addition = null; this.group = null; - this.pack = DataPacks.RECIPE; - return super.reset(); + return this; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java deleted file mode 100644 index 26261ca7cc3..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeRegistration.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.smithing; - -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.SmithingRecipeInput; -import net.minecraft.world.item.crafting.SmithingTransformRecipe; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.smithing.SmithingRecipe; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.util.List; -import java.util.Optional; -import java.util.function.Function; - -public class SpongeSmithingRecipeRegistration extends SpongeRecipeRegistration implements - SpongeRecipeRegistration.ResultFunctionRegistration { - - // Vanilla Recipe - private final Ingredient template; - - private final Ingredient base; - private final Ingredient addition; - - // Sponge Recipe - private final ItemStack spongeResult; - private final Function resultFunction; - - public SpongeSmithingRecipeRegistration(ResourceLocation key, String group, final Ingredient template, Ingredient base, - Ingredient addition, ItemStack spongeResult, Function resultFunction, - DataPack pack, final RecipeCategory category) { - super(key, group, pack, category, RecipeSerializer.SMITHING_TRANSFORM); - this.template = template; - this.base = base; - this.addition = addition; - this.spongeResult = spongeResult; - this.resultFunction = resultFunction; - } - - @Override - public Recipe recipe() { - this.ensureCached(); - if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, List.of(this.template, this.base, this.addition))) { - return (SmithingRecipe) new SmithingTransformRecipe(Optional.of(this.template), Optional.of(this.base), Optional.of(this.addition), this.spongeResult); - - } - return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), Optional.ofNullable(this.base), Optional.ofNullable(this.addition), - this.spongeResult, this.resultFunction == null ? null : this.key.toString()); - } - - @Override - public Function resultFunction() { - return this.resultFunction; - } -} diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java index 0c00ca927f2..57a78fc0a74 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java @@ -26,36 +26,30 @@ import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.crafting.RecipeInput; import org.spongepowered.api.item.recipe.single.StoneCutterRecipe; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.ingredient.IngredientUtil; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.common.util.Preconditions; import java.util.Objects; import java.util.function.Function; -public final class SpongeStoneCutterRecipeBuilder extends AbstractResourceKeyedBuilder implements +public final class SpongeStoneCutterRecipeBuilder implements StoneCutterRecipe.Builder, StoneCutterRecipe.Builder.ResultStep, StoneCutterRecipe.Builder.EndStep { private ItemStack result; private Ingredient ingredient; private Function resultFunction; private @Nullable String group; - private DataPack pack = DataPacks.RECIPE; private RecipeCategory recipeCategory = RecipeCategory.MISC; // TODO support category @@ -96,15 +90,9 @@ public EndStep group(@Nullable String name) { } @Override - public EndStep pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public RecipeRegistration build0() { - return new SpongeStonecuttingRecipeRegistration((ResourceLocation) (Object) key, this.group, this.ingredient, - ItemStackUtil.toNative(this.result), this.resultFunction, this.pack, this.recipeCategory); + public StoneCutterRecipe build() { + return (StoneCutterRecipe) new SpongeStonecuttingRecipe(this.group == null ? "": this.group, this.ingredient, + ItemStackUtil.toNative(this.result), this.resultFunction); } @Override @@ -113,7 +101,6 @@ public StoneCutterRecipe.Builder reset() { this.resultFunction = null; this.ingredient = null; this.group = null; - this.pack = DataPacks.RECIPE; - return super.reset(); + return this; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index 7cc74df448e..b3f5b62ad75 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -24,73 +24,28 @@ */ package org.spongepowered.common.item.recipe.stonecutting; -import static org.spongepowered.common.util.Constants.Recipe.SPONGE_TYPE; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.HolderLookup; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.SingleItemRecipe; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.item.crafting.StonecutterRecipe; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.ingredient.IngredientResultUtil; -import org.spongepowered.common.util.Constants; - -import java.util.Optional; - - -public class SpongeStonecuttingRecipe extends StonecutterRecipe implements ResultFunctionRecipe { - private static final MapCodec RESULT_CODEC = RecordCodecBuilder.mapCodec( - $$0 -> $$0.group( - BuiltInRegistries.ITEM.byNameCodec().fieldOf(Constants.Recipe.RESULT).forGetter(ItemStack::getItem), - Codec.INT.fieldOf(Constants.Recipe.COUNT).forGetter(ItemStack::getCount) - ) - .apply($$0, ItemStack::new) - ); +import java.util.function.Function; - public static final MapCodec SPONGE_CODEC = RecordCodecBuilder.mapCodec( - $$1 -> $$1.group( - Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Codec.STRING.optionalFieldOf("group", "").forGetter(SingleItemRecipe::group), - Ingredient.CODEC.fieldOf(Constants.Recipe.STONECUTTING_INGREDIENT).forGetter(SingleItemRecipe::input), - RESULT_CODEC.forGetter($$0x -> $$0x.result()), - ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), - IngredientResultUtil.CACHED_RESULT_FUNC_CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) - ) - .apply($$1, SpongeStonecuttingRecipe::of) - ); - private final String resultFunctionId; +public class SpongeStonecuttingRecipe extends StonecutterRecipe { - public static SpongeStonecuttingRecipe of(final String spongeType, - final String groupIn, - final Ingredient ingredientIn, - final ItemStack resultIn, - final ItemStack spongeResult, - final Optional resultFunctionId) { - return new SpongeStonecuttingRecipe(groupIn, ingredientIn, spongeResult.isEmpty() ? resultIn : spongeResult, resultFunctionId.orElse(null)); - } + private Function resultFunction; - public SpongeStonecuttingRecipe(final String groupIn, final Ingredient ingredientIn, final ItemStack spongeResult, final String resultFunctionId) { + public SpongeStonecuttingRecipe(final String groupIn, final Ingredient ingredientIn, final ItemStack spongeResult, final Function resultFunction) { super(groupIn, ingredientIn, spongeResult); - this.resultFunctionId = resultFunctionId; - } - - @Override - public Optional resultFunctionId() { - return Optional.ofNullable(this.resultFunctionId); + this.resultFunction = resultFunction; } @Override public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { - if (this.resultFunctionId != null) { - return IngredientResultUtil.cachedResultFunction(this.resultFunctionId).apply($$0); + if (this.resultFunction != null) { + return this.resultFunction.apply($$0); } return super.assemble($$0, $$1); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipeRegistration.java deleted file mode 100644 index bb101b4c0b4..00000000000 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipeRegistration.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.item.recipe.stonecutting; - -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.item.crafting.StonecutterRecipe; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.item.recipe.Recipe; -import org.spongepowered.api.item.recipe.RecipeRegistration; -import org.spongepowered.api.item.recipe.single.StoneCutterRecipe; -import org.spongepowered.common.item.recipe.SpongeRecipeRegistration; - -import java.util.Collections; -import java.util.function.Function; - -public class SpongeStonecuttingRecipeRegistration extends SpongeRecipeRegistration implements - SpongeRecipeRegistration.ResultFunctionRegistration { - - // Vanilla Recipe - private final Ingredient ingredient; - - // Sponge Recipe - private final ItemStack spongeResult; - private Function resultFunction; - - public SpongeStonecuttingRecipeRegistration(ResourceLocation key, String group, Ingredient ingredient, - ItemStack spongeResult, Function resultFunction, - DataPack pack, final RecipeCategory category) { - super(key, group, pack, category, RecipeSerializer.STONECUTTER); - this.ingredient = ingredient; - this.spongeResult = spongeResult; - this.resultFunction = resultFunction; - } - - @Override - public Recipe recipe() { - this.ensureCached(); - if (SpongeRecipeRegistration.isVanillaSerializer(this.spongeResult, this.resultFunction, null, Collections.singleton(this.ingredient))) { - return (StoneCutterRecipe) new StonecutterRecipe(this.group, this.ingredient, this.spongeResult); - } - return (StoneCutterRecipe) new SpongeStonecuttingRecipe( - this.group, this.ingredient, this.spongeResult, this.resultFunction == null ? null : this.key.toString()); - } - - @Override - public Function resultFunction() { - return this.resultFunction; - } -} diff --git a/src/main/java/org/spongepowered/common/registry/InitialRegistryData.java b/src/main/java/org/spongepowered/common/registry/InitialRegistryData.java index 2774ffb923a..9f8bbe1a04d 100644 --- a/src/main/java/org/spongepowered/common/registry/InitialRegistryData.java +++ b/src/main/java/org/spongepowered/common/registry/InitialRegistryData.java @@ -36,7 +36,7 @@ public abstract class InitialRegistryData { abstract @Nullable Map keyToId(); - void forEach(final LoaderConsumer consumer) { + public void forEach(final LoaderConsumer consumer) { final Map kv = this.keyToValue(); final Map ki = this.keyToId(); @@ -56,7 +56,7 @@ void forEach(final LoaderConsumer consumer) { } } - static @Nullable InitialRegistryData noIds(final @Nullable Supplier> values) { + public static @Nullable InitialRegistryData noIds(final @Nullable Supplier> values) { if (values == null) { return null; } @@ -73,7 +73,7 @@ Map keyToValue() { }; } - interface LoaderConsumer { + public interface LoaderConsumer { void accept(final ResourceKey key, final OptionalInt id, final T value); } } diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 6aa0912b050..05aaa04ae42 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -26,12 +26,16 @@ import com.mojang.serialization.Lifecycle; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.core.HolderLookup; import net.minecraft.core.MappedRegistry; import net.minecraft.core.RegistrationInfo; import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.DependencySorter; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.flag.FeatureFlags; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.DuplicateRegistrationException; @@ -42,7 +46,6 @@ import org.spongepowered.api.registry.ValueNotFoundException; import org.spongepowered.common.accessor.core.MappedRegistryAccessor; import org.spongepowered.common.accessor.resources.ResourceKeyAccessor; -import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.core.WritableRegistryBridge; import java.util.Map; @@ -53,19 +56,21 @@ import java.util.function.Supplier; import java.util.stream.Stream; -public final class RegistryHolderLogic implements RegistryHolder { +public final class RegistryHolderLogic implements RegistryHolder, HolderLookup.Provider { private final Map>> roots = new Object2ObjectOpenHashMap<>(); + private @Nullable FeatureFlagSet featureFlagSet; + public RegistryHolderLogic() { this.roots.put( - (ResourceKey) (Object) ResourceLocation.withDefaultNamespace("root"), + RegistryRoots.MINECRAFT, new MappedRegistry<>( net.minecraft.resources.ResourceKey.createRegistryKey((ResourceLocation) (Object) RegistryRoots.MINECRAFT), Lifecycle.experimental() ) ); - final ResourceLocation sponge = ResourceLocation.fromNamespaceAndPath("sponge", "root"); + final ResourceLocation sponge = (ResourceLocation) (Object) RegistryRoots.SPONGE; this.roots.put( (ResourceKey) (Object) sponge, new MappedRegistry<>( @@ -81,17 +86,34 @@ public RegistryHolderLogic() { public RegistryHolderLogic(final RegistryAccess dynamicAccess) { this(); - final WritableRegistry root = (WritableRegistry) this.roots.get(ResourceLocation.withDefaultNamespace("root")); + final WritableRegistry root = (WritableRegistry) this.roots.get(RegistryRoots.MINECRAFT); // Add the dynamic registries. These are server-scoped in Vanilla dynamicAccess.registries().forEach(entry -> root.register(entry.key(), entry.value(), RegistrationInfo.BUILT_IN)); root.freeze(); } + public RegistryHolderLogic(final RegistryAccess dynamicAccess, final @Nullable FeatureFlagSet featureFlagSet) { + this(dynamicAccess); + + this.featureFlagSet = featureFlagSet; + } + public void setRootMinecraftRegistry(final net.minecraft.core.Registry> rootRegistry) { this.roots.put(RegistryRoots.MINECRAFT, rootRegistry); } + @SuppressWarnings({"unchecked", "rawtypes"}) + public void setRootMinecraftRegistry(final RegistryAccess registryAccess) { + final MappedRegistry rootRegistry = new MappedRegistry<>( + net.minecraft.resources.ResourceKey.createRegistryKey((ResourceLocation) (Object) RegistryRoots.MINECRAFT), + Lifecycle.experimental() + ); + registryAccess.registries().forEach(r -> rootRegistry.register(r.key(), r.value(), RegistrationInfo.BUILT_IN)); + rootRegistry.freeze(); + this.roots.put(RegistryRoots.MINECRAFT, rootRegistry); + } + @Override public Registry registry(final RegistryType type) { final var root = this.roots.get(Objects.requireNonNull(type, "type").root()); @@ -112,6 +134,11 @@ public Optional> findRegistry(final RegistryType type) { return (Optional>) (Object) root.getOptional((ResourceLocation) (Object) type.location()); } + @Override + public Stream> streamRegistries() { + return this.roots.values().stream().flatMap(r -> (Stream>) (Object) r.stream()); + } + @Override public Stream> streamRegistries(final ResourceKey root) { final net.minecraft.core.Registry> rootRegistry = this.roots.get(Objects.requireNonNull(root, "root")); @@ -131,7 +158,7 @@ public Registry createRegistry(final RegistryType type, final @Nullabl public Registry createRegistry(final RegistryType type, final @Nullable Supplier> defaultValues, final boolean isDynamic) { - return this.createRegistry(type, InitialRegistryData.noIds(defaultValues), this.registrySupplier(isDynamic, null), false); + return this.createRegistry(type, InitialRegistryData.noIds(defaultValues), this.registrySupplier(isDynamic, null)); } @SuppressWarnings("unchecked") @@ -141,27 +168,29 @@ public Function { final MappedRegistry reg = new MappedRegistry<>(key, Lifecycle.stable()); - ((WritableRegistryBridge)reg).bridge$setDynamic(isDynamic); + ((WritableRegistryBridge) reg).bridge$setDynamic(isDynamic); + ((WritableRegistryBridge) reg).bridge$setRegistryHolder(this); return reg; }; } else { return (key) -> { final CallbackRegistry reg = new CallbackRegistry<>(key, Lifecycle.stable(), callback); ((WritableRegistryBridge) (Object) reg).bridge$setDynamic(isDynamic); + ((WritableRegistryBridge) (Object) reg).bridge$setRegistryHolder(this); return reg; }; } } public Registry createRegistry(final RegistryType type, final @Nullable InitialRegistryData defaultValues, - final Function>, net.minecraft.core.Registry> registrySupplier, final boolean replace) { + final Function>, net.minecraft.core.Registry> registrySupplier) { final net.minecraft.core.Registry> root = this.roots.get(Objects.requireNonNull(type, "type").root()); if (root == null) { throw new ValueNotFoundException(String.format("No '%s' root registry has been defined", type.root())); } var registry = root.getValue((ResourceLocation) (Object) type.location()); final boolean exists = registry != null; - if (!replace && exists) { + if (exists) { throw new DuplicateRegistrationException(String.format("Registry '%s' in root '%s' has already been defined", type.location(), type.root())); } final net.minecraft.resources.ResourceKey> key; @@ -191,19 +220,10 @@ public Registry createRegistry(final RegistryType type, final @Nullabl }); } - // This is so wrong and dirty and only because we don't have layered registries... - final boolean frozen = ((MappedRegistryAccessor>) root).accessor$frozen(); - - if (replace && exists) { - ((MappedRegistryAccessor>) root).accessor$frozen(false); - ((MappedRegistryBridge>) root).bridge$forceRemoveValue(key); - } - ((WritableRegistry) root).register(key, registry, RegistrationInfo.BUILT_IN); if (registry instanceof CallbackRegistry) { ((CallbackRegistry) registry).setCallbackEnabled(true); } - ((MappedRegistryAccessor>) root).accessor$frozen(frozen); return (Registry) registry; } @@ -212,7 +232,35 @@ public void freezeSpongeRootRegistry() { this.roots.get(RegistryRoots.SPONGE).freeze(); } - public void freezeSpongeDynamicRegistries() { - this.roots.get(RegistryRoots.SPONGE).forEach(net.minecraft.core.Registry::freeze); + public void freezeSpongeDynamicRegistries(final boolean force) { + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final net.minecraft.core.Registry> registry = this.roots.get(RegistryRoots.SPONGE); + registry.stream() + .filter(r -> force || (((WritableRegistryBridge) r).bridge$eventCalled() && ((WritableRegistryBridge) r).bridge$pendingDependencies() + .allMatch(t -> this.findRegistry(t).map(v -> ((MappedRegistryAccessor) v).accessor$frozen() || ((WritableRegistryBridge) v).bridge$eventCalled()).orElse(false)))) + .forEach(r -> dependencies.addEntry( + ((Registry) r).type(), new SpongeRegistryDependencyEntry<>(r, ((WritableRegistryBridge) r).bridge$pendingDependencies().toList()))); + dependencies.orderByDependencies(($, v) -> v.cookie().freeze()); + } + + public FeatureFlagSet featureFlagSet() { + return this.featureFlagSet == null ? FeatureFlags.VANILLA_SET : this.featureFlagSet; + } + + public void featureFlagSet(final FeatureFlagSet featureFlagSet) { + this.featureFlagSet = featureFlagSet; + } + + @Override + public Stream>> listRegistryKeys() { + return this.streamRegistries().map(k -> + ResourceKeyAccessor.invoker$create((ResourceLocation) (Object) k.type().root(), (ResourceLocation) (Object) k.type().location())); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Optional> lookup( + final net.minecraft.resources.ResourceKey> resourceKey) { + return (Optional) this.findRegistry(RegistryType.of((ResourceKey) (Object) resourceKey.registry(), (ResourceKey) (Object) resourceKey.location())); } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java index 726bb27bf8b..e6e08443838 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java @@ -27,13 +27,13 @@ import com.google.inject.Singleton; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.advancement.AdvancementTemplate; +import org.spongepowered.api.advancement.Advancement; import org.spongepowered.api.advancement.DisplayInfo; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.api.advancement.criteria.ScoreAdvancementCriterion; import org.spongepowered.api.advancement.criteria.trigger.FilteredTrigger; import org.spongepowered.api.advancement.criteria.trigger.Trigger; -import org.spongepowered.api.adventure.ChatTypeTemplate; +import org.spongepowered.api.adventure.ChatType; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.block.entity.BlockEntityArchetype; @@ -50,7 +50,7 @@ import org.spongepowered.api.data.MutableDataProviderBuilder; import org.spongepowered.api.data.meta.BannerPatternLayer; import org.spongepowered.api.data.persistence.DataStore; -import org.spongepowered.api.data.type.ArtTypeTemplate; +import org.spongepowered.api.data.type.ArtType; import org.spongepowered.api.effect.particle.ParticleEffect; import org.spongepowered.api.effect.potion.PotionEffect; import org.spongepowered.api.effect.sound.SoundType; @@ -68,7 +68,7 @@ import org.spongepowered.api.entity.attribute.AttributeModifier; import org.spongepowered.api.entity.living.player.tab.TabListEntry; import org.spongepowered.api.event.EventContextKey; -import org.spongepowered.api.event.cause.entity.damage.DamageTypeTemplate; +import org.spongepowered.api.event.cause.entity.damage.DamageType; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.fluid.FluidStack; import org.spongepowered.api.fluid.FluidStackSnapshot; @@ -107,34 +107,32 @@ import org.spongepowered.api.util.ResettableBuilder; import org.spongepowered.api.util.transformation.Transformation; import org.spongepowered.api.world.LocatableBlock; +import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.WorldTypeEffect; -import org.spongepowered.api.world.WorldTypeTemplate; -import org.spongepowered.api.world.biome.BiomeTemplate; +import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.biome.provider.CheckerboardBiomeConfig; import org.spongepowered.api.world.biome.provider.EndStyleBiomeConfig; import org.spongepowered.api.world.biome.provider.MultiNoiseBiomeConfig; import org.spongepowered.api.world.border.WorldBorder; import org.spongepowered.api.world.explosion.Explosion; -import org.spongepowered.api.world.generation.carver.CarverTemplate; +import org.spongepowered.api.world.generation.carver.Carver; import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.generation.config.flat.FlatGeneratorConfig; -import org.spongepowered.api.world.generation.config.noise.DensityFunctionTemplate; +import org.spongepowered.api.world.generation.config.noise.Noise; import org.spongepowered.api.world.generation.config.noise.NoiseConfig; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigTemplate; -import org.spongepowered.api.world.generation.config.noise.NoiseTemplate; -import org.spongepowered.api.world.generation.feature.FeatureTemplate; -import org.spongepowered.api.world.generation.feature.PlacedFeatureTemplate; -import org.spongepowered.api.world.generation.structure.SchematicTemplate; +import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; +import org.spongepowered.api.world.generation.feature.Feature; +import org.spongepowered.api.world.generation.feature.PlacedFeature; import org.spongepowered.api.world.generation.structure.StructurePlacement; -import org.spongepowered.api.world.generation.structure.StructureSetTemplate; -import org.spongepowered.api.world.generation.structure.StructureTemplate; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolTemplate; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorListTemplate; +import org.spongepowered.api.world.generation.structure.StructureSet; +import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPool; +import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; import org.spongepowered.api.world.portal.PortalLogic; import org.spongepowered.api.world.schematic.PaletteType; import org.spongepowered.api.world.schematic.Schematic; import org.spongepowered.api.world.server.TicketType; -import org.spongepowered.api.world.server.WorldTemplate; +import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.api.world.volume.stream.StreamOptions; import org.spongepowered.common.advancement.SpongeAdvancementBuilder; import org.spongepowered.common.advancement.SpongeDisplayInfoBuilder; @@ -142,7 +140,7 @@ import org.spongepowered.common.advancement.SpongeTriggerBuilder; import org.spongepowered.common.advancement.criterion.SpongeCriterionBuilder; import org.spongepowered.common.advancement.criterion.SpongeScoreCriterionBuilder; -import org.spongepowered.common.adventure.SpongeChatTypeTemplate; +import org.spongepowered.common.adventure.SpongeChatTypeBuilder; import org.spongepowered.common.ban.SpongeBanBuilder; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.block.SpongeBlockStateBuilder; @@ -162,7 +160,7 @@ import org.spongepowered.common.data.key.SpongeKeyBuilder; import org.spongepowered.common.data.persistence.datastore.SpongeDataStoreBuilder; import org.spongepowered.common.data.provider.DataProviderRegistrator; -import org.spongepowered.common.data.type.SpongeArtTypeTemplate; +import org.spongepowered.common.data.type.SpongeArtTypeBuilder; import org.spongepowered.common.effect.particle.SpongeParticleEffectBuilder; import org.spongepowered.common.effect.potion.SpongePotionBuilder; import org.spongepowered.common.effect.sound.SpongeSoundBuilder; @@ -181,7 +179,7 @@ import org.spongepowered.common.entity.player.tab.TabListEntryBuilder; import org.spongepowered.common.event.SpongeEventContextKeyBuilder; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSourceBuilder; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTypeTemplate; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTypeBuilder; import org.spongepowered.common.fluid.SpongeFluidStackBuilder; import org.spongepowered.common.fluid.SpongeFluidStackSnapshotBuilder; import org.spongepowered.common.fluid.SpongeFluidStateBuilder; @@ -216,33 +214,31 @@ import org.spongepowered.common.util.transformation.SpongeTransformationBuilder; import org.spongepowered.common.world.SpongeExplosionBuilder; import org.spongepowered.common.world.SpongeWorldTypeEffect; -import org.spongepowered.common.world.biome.SpongeBiomeTemplate; +import org.spongepowered.common.world.biome.SpongeBiomeBuilder; import org.spongepowered.common.world.biome.provider.SpongeCheckerboardBiomeConfig; import org.spongepowered.common.world.biome.provider.SpongeEndStyleBiomeConfig; import org.spongepowered.common.world.biome.provider.SpongeMultiNoiseBiomeConfig; import org.spongepowered.common.world.border.SpongeWorldBorderBuilder; import org.spongepowered.common.world.generation.SpongeWorldGenerationConfigBuilder; -import org.spongepowered.common.world.generation.carver.SpongeCarverTemplate; +import org.spongepowered.common.world.generation.carver.SpongeCarverBuilder; import org.spongepowered.common.world.generation.config.flat.SpongeFlatGeneratorConfig; -import org.spongepowered.common.world.generation.config.noise.SpongeDensityFunctionTemplate; +import org.spongepowered.common.world.generation.config.noise.SpongeNoiseBuilder; import org.spongepowered.common.world.generation.config.noise.SpongeNoiseConfig; -import org.spongepowered.common.world.generation.config.noise.SpongeNoiseGeneratorConfigTemplate; -import org.spongepowered.common.world.generation.config.noise.SpongeNoiseTemplate; -import org.spongepowered.common.world.generation.feature.SpongeFeatureTemplate; -import org.spongepowered.common.world.generation.feature.SpongePlacedFeatureTemplate; -import org.spongepowered.common.world.generation.structure.SpongeSchematicTemplate; +import org.spongepowered.common.world.generation.config.noise.SpongeNoiseGeneratorConfigBuilder; +import org.spongepowered.common.world.generation.feature.SpongeFeatureBuilder; +import org.spongepowered.common.world.generation.feature.SpongePlacedFeatureBuilder; import org.spongepowered.common.world.generation.structure.SpongeStructurePlacementBuilder; -import org.spongepowered.common.world.generation.structure.SpongeStructureSetTemplate; -import org.spongepowered.common.world.generation.structure.SpongeStructureTemplate; -import org.spongepowered.common.world.generation.structure.jigsaw.SpongeJigsawPoolTemplate; -import org.spongepowered.common.world.generation.structure.jigsaw.SpongeProcessorListTemplate; +import org.spongepowered.common.world.generation.structure.SpongeStructureSetBuilder; +import org.spongepowered.common.world.generation.structure.jigsaw.SpongeJigsawPoolBuilder; +import org.spongepowered.common.world.generation.structure.jigsaw.SpongeProcessorListBuilder; import org.spongepowered.common.world.portal.SpongePortalLogicBuilder; import org.spongepowered.common.world.schematic.SpongePaletteTypeBuilder; import org.spongepowered.common.world.schematic.SpongeSchematicBuilder; import org.spongepowered.common.world.server.SpongeLocatableBlockBuilder; +import org.spongepowered.common.world.server.SpongeServerWorldPropertiesLoadOptions; import org.spongepowered.common.world.server.SpongeTicketTypeBuilder; -import org.spongepowered.common.world.server.SpongeWorldTemplate; -import org.spongepowered.common.world.server.SpongeWorldTypeTemplate; +import org.spongepowered.common.world.server.SpongeWorldArchetypeType; +import org.spongepowered.common.world.server.SpongeWorldTypeBuilder; import org.spongepowered.common.world.volume.stream.SpongeStreamOptionsBuilder; import java.util.Map; @@ -337,7 +333,7 @@ public void registerDefaultBuilders() { .register(Enchantment.Builder.class, SpongeEnchantmentBuilder::new) .register(Enchantment.RandomListBuilder.class, SpongeRandomEnchantmentListBuilder::new) .register(Key.Builder.class, SpongeKeyBuilder::new) - .register(AdvancementTemplate.Builder.class, SpongeAdvancementBuilder::new) + .register(Advancement.Builder.class, SpongeAdvancementBuilder::new) .register(DisplayInfo.Builder.class, SpongeDisplayInfoBuilder::new) .register(AdvancementCriterion.Builder.class, SpongeCriterionBuilder::new) .register(ScoreAdvancementCriterion.Builder.class, SpongeScoreCriterionBuilder::new) @@ -366,13 +362,12 @@ public void registerDefaultBuilders() { .register(FluidState.Builder.class, SpongeFluidStateBuilder::new) .register(WorldGenerationConfig.Builder.class, SpongeWorldGenerationConfigBuilder::new) .register(WorldTypeEffect.Builder.class, SpongeWorldTypeEffect.BuilderImpl::new) - .register(WorldTypeTemplate.Builder.class, SpongeWorldTypeTemplate.BuilderImpl::new) - .register(WorldTemplate.Builder.class, SpongeWorldTemplate.BuilderImpl::new) + .register(WorldType.Builder.class, SpongeWorldTypeBuilder::new) + .register(WorldArchetypeType.Builder.class, SpongeWorldArchetypeType::new) .register(NoiseConfig.Builder.class, SpongeNoiseConfig.BuilderImpl::new) .register(FlatGeneratorConfig.Builder.class, SpongeFlatGeneratorConfig.BuilderImpl::new) - .register(NoiseGeneratorConfigTemplate.Builder.class, SpongeNoiseGeneratorConfigTemplate.BuilderImpl::new) - .register(NoiseTemplate.Builder.class, SpongeNoiseTemplate.BuilderImpl::new) - .register(DensityFunctionTemplate.Builder.class, SpongeDensityFunctionTemplate.BuilderImpl::new) + .register(NoiseGeneratorConfig.Builder.class, SpongeNoiseGeneratorConfigBuilder::new) + .register(Noise.Builder.class, SpongeNoiseBuilder::new) .register(CheckerboardBiomeConfig.Builder.class, SpongeCheckerboardBiomeConfig.BuilderImpl::new) .register(EndStyleBiomeConfig.Builder.class, SpongeEndStyleBiomeConfig.BuilderImpl::new) .register(MultiNoiseBiomeConfig.Builder.class, SpongeMultiNoiseBiomeConfig.BuilderImpl::new) @@ -380,21 +375,20 @@ public void registerDefaultBuilders() { .register(MapDecoration.Builder.class, SpongeMapDecorationBuilder::new) .register(MapCanvas.Builder.class, SpongeMapCanvasBuilder::new) .register(Transformation.Builder.class, SpongeTransformationBuilder::new) - .register(BiomeTemplate.Builder.class, SpongeBiomeTemplate.BuilderImpl::new) - .register(CarverTemplate.Builder.class, SpongeCarverTemplate.BuilderImpl::new) - .register(FeatureTemplate.Builder.class, SpongeFeatureTemplate.BuilderImpl::new) - .register(PlacedFeatureTemplate.Builder.class, SpongePlacedFeatureTemplate.BuilderImpl::new) - .register(StructureTemplate.Builder.class, SpongeStructureTemplate.BuilderImpl::new) - .register(SchematicTemplate.Builder.class, SpongeSchematicTemplate.BuilderImpl::new) - .register(ProcessorListTemplate.Builder.class, SpongeProcessorListTemplate.BuilderImpl::new) + .register(Biome.Builder.class, SpongeBiomeBuilder::new) + .register(Carver.Builder.class, SpongeCarverBuilder::new) + .register(Feature.Builder.class, SpongeFeatureBuilder::new) + .register(PlacedFeature.Builder.class, SpongePlacedFeatureBuilder::new) + .register(ProcessorList.Builder.class, SpongeProcessorListBuilder::new) .register(StructurePlacement.Builder.class, SpongeStructurePlacementBuilder::new) - .register(StructureSetTemplate.Builder.class, SpongeStructureSetTemplate.BuilderImpl::new) - .register(JigsawPoolTemplate.Builder.class, SpongeJigsawPoolTemplate.BuilderImpl::new) - .register(ChatTypeTemplate.Builder.class, SpongeChatTypeTemplate.BuilderImpl::new) - .register(DamageTypeTemplate.Builder.class, SpongeDamageTypeTemplate.BuilderImpl::new) - .register(ArtTypeTemplate.Builder.class, SpongeArtTypeTemplate.BuilderImpl::new) + .register(StructureSet.Builder.class, SpongeStructureSetBuilder::new) + .register(JigsawPool.Builder.class, SpongeJigsawPoolBuilder::new) + .register(ChatType.Builder.class, SpongeChatTypeBuilder::new) + .register(DamageType.Builder.class, SpongeDamageTypeBuilder::new) + .register(ArtType.Builder.class, SpongeArtTypeBuilder::new) .register(TicketType.Builder.class, SpongeTicketTypeBuilder::new) .register(PortalLogic.Builder.class, SpongePortalLogicBuilder::new) + .register(ServerWorldProperties.LoadOptions.Builder.class, SpongeServerWorldPropertiesLoadOptions.BuilderImpl::new) ; } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index a6802500de8..8891c2041ad 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -43,7 +43,6 @@ import org.spongepowered.api.data.DataManipulator; import org.spongepowered.api.data.type.ToolRule; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.datapack.DataPackType; import org.spongepowered.api.effect.ForwardingViewer; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.event.EventListenerRegistration; @@ -61,6 +60,7 @@ import org.spongepowered.api.registry.FactoryProvider; import org.spongepowered.api.registry.RegistryKey; import org.spongepowered.api.registry.RegistryReference; +import org.spongepowered.api.registry.RegistryRegistrationSet; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.registry.TypeNotFoundException; import org.spongepowered.api.resource.ResourcePath; @@ -74,7 +74,6 @@ import org.spongepowered.api.state.IntegerStateProperty; import org.spongepowered.api.state.StateMatcher; import org.spongepowered.api.tag.Tag; -import org.spongepowered.api.tag.TagTemplate; import org.spongepowered.api.util.AABB; import org.spongepowered.api.util.MinecraftDayTime; import org.spongepowered.api.util.Range; @@ -101,7 +100,6 @@ import org.spongepowered.api.world.schematic.PaletteReference; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerLocationCreator; -import org.spongepowered.api.world.server.WorldTemplate; import org.spongepowered.api.world.volume.archetype.entity.EntityArchetypeEntry; import org.spongepowered.api.world.volume.block.BlockVolumeFactory; import org.spongepowered.api.world.weather.Weather; @@ -122,7 +120,6 @@ import org.spongepowered.common.data.manipulator.ImmutableDataManipulatorFactory; import org.spongepowered.common.data.manipulator.MutableDataManipulatorFactory; import org.spongepowered.common.data.value.SpongeValueFactory; -import org.spongepowered.common.datapack.SpongeDataPackType; import org.spongepowered.common.effect.SpongeCustomForwardingViewer; import org.spongepowered.common.entity.effect.SpongeVanishState; import org.spongepowered.common.event.SpongeEventListenerRegistration; @@ -145,7 +142,6 @@ import org.spongepowered.common.service.server.permission.SpongeNodeTree; import org.spongepowered.common.state.SpongeStateMatcherFactory; import org.spongepowered.common.tag.SpongeTagFactory; -import org.spongepowered.common.tag.SpongeTagTemplateFactory; import org.spongepowered.common.util.SpongeAABB; import org.spongepowered.common.util.SpongeDamageSourceFactory; import org.spongepowered.common.util.SpongeMinecraftDayTime; @@ -172,7 +168,6 @@ import org.spongepowered.common.world.schematic.SpongePaletteReferenceFactory; import org.spongepowered.common.world.server.SpongeServerLocation; import org.spongepowered.common.world.server.SpongeServerLocationCreatorFactory; -import org.spongepowered.common.world.server.SpongeWorldTemplate; import org.spongepowered.common.world.volume.archetype.entity.SpongeEntityArchetypeEntryFactory; import org.spongepowered.common.world.volume.block.SpongeBlockVolumeFactory; import org.spongepowered.common.world.weather.SpongeWeather; @@ -247,7 +242,6 @@ public void registerDefaultFactories() { .registerFactory(RegistryKey.Factory.class, new SpongeRegistryKey.FactoryImpl()) .registerFactory(RegistryType.Factory.class, new SpongeRegistryType.FactoryImpl()) .registerFactory(RegistryReference.Factory.class, new SpongeRegistryReference.FactoryImpl()) - .registerFactory(DataPackType.Factory.class, new SpongeDataPackType.FactoryImpl()) .registerFactory(BlockVolumeFactory.class, new SpongeBlockVolumeFactory()) .registerFactory(DamageSource.Factory.class, new SpongeDamageSourceFactory()) .registerFactory(PaletteReference.Factory.class, new SpongePaletteReferenceFactory()) @@ -258,7 +252,6 @@ public void registerDefaultFactories() { .registerFactory(BiomeAttributes.Factory.class, new SpongeBiomeAttributesFactory()) .registerFactory(BiomeProvider.Factory.class, new SpongeBiomeProviderFactory()) .registerFactory(WorldTypeEffect.Factory.class, new SpongeWorldTypeEffect.FactoryImpl()) - .registerFactory(WorldTemplate.Factory.class, new SpongeWorldTemplate.FactoryImpl()) .registerFactory(LayerConfig.Factory.class, new SpongeLayerConfigFactory()) .registerFactory(SurfaceRule.Factory.class, new SpongeSurfaceRulesFactory()) .registerFactory(ChunkGenerator.Factory.class, new SpongeChunkGeneratorFactory()) @@ -268,7 +261,6 @@ public void registerDefaultFactories() { .registerFactory(DisplaySlot.Factory.class, new SpongeDisplaySlotFactory()) .registerFactory(Weather.Factory.class, new SpongeWeather.FactoryImpl()) .registerFactory(NodeTree.Factory.class, new SpongeNodeTree.FactoryImpl()) - .registerFactory(TagTemplate.Factory.class, new SpongeTagTemplateFactory()) .registerFactory(Tag.Factory.class, new SpongeTagFactory()) .registerFactory(EventListenerRegistration.Factory.class, new SpongeEventListenerRegistration.FactoryImpl()) .registerFactory(CommandResult.Factory.class, new SpongeCommandResultFactory()) @@ -293,6 +285,7 @@ public void registerDefaultFactories() { .registerFactory(PortalLogic.Factory.class, new SpongePortalLogicFactory()) .registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory()) .registerFactory(ArmorTrim.Factory.class, new SpongeArmorTrimFactory()) + .registerFactory(RegistryRegistrationSet.Factory.class, new SpongeRegistryRegistrationSet.FactoryImpl()) ; } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java index fcde5c162f6..a377af375e3 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java @@ -26,9 +26,9 @@ import net.minecraft.commands.CommandBuildContext; import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.flag.FeatureFlagSet; -import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.advancement.Advancement; +import org.spongepowered.api.item.recipe.Recipe; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.service.economy.Currency; import org.spongepowered.common.registry.loader.CommandRegistryLoader; @@ -37,6 +37,8 @@ import org.spongepowered.common.registry.loader.SpongeRegistryLoader; import org.spongepowered.common.registry.loader.VanillaRegistryLoader; +import java.util.List; + public final class SpongeRegistries { // During Bootstrap @@ -83,6 +85,7 @@ public static void registerEarlyGlobalRegistries(final SpongeRegistryHolder hold holder.createFrozenRegistry(RegistryTypes.MAP_DECORATION_ORIENTATION, SpongeRegistryLoader.mapDecorationOrientation()); holder.createFrozenRegistry(RegistryTypes.MAP_SHADE, SpongeRegistryLoader.mapShade()); holder.createFrozenRegistry(RegistryTypes.NOISE_CONFIG, SpongeRegistryLoader.noiseConfig()); + holder.createFrozenRegistry(RegistryTypes.REGISTRY_KEYED_VALUE_PARAMETER, CommandRegistryLoader.valueParameter()); SpongeRegistries.registerEarlyDynamicRegistries(holder); } @@ -94,20 +97,19 @@ private static void registerEarlyDynamicRegistries(final SpongeRegistryHolder ho holder.createRegistry(RegistryTypes.TELEPORT_HELPER_FILTER, DynamicSpongeRegistryLoader.teleportHelperFilter(), true); } + @SuppressWarnings({"unchecked", "rawtypes"}) + public static void registerServerRegistries(final SpongeRegistryHolder holder, final FeatureFlagSet featureFlags) { + holder.createFrozenRegistry(RegistryTypes.COMMAND_TREE_NODE_TYPE, (h) -> + CommandRegistryLoader.clientCompletionKey(CommandBuildContext.simple( + new RegistryAccess.ImmutableRegistryAccess((List) h.streamRegistries().toList()), featureFlags)), RegistryTypes.WORLD_ARCHETYPE_TYPE); - public static void registerGlobalRegistriesDimensionLayer(final SpongeRegistryHolder holder, final RegistryAccess.Frozen registryAccess, final FeatureFlagSet featureFlags) { - if (holder.findRegistry(RegistryTypes.COMMAND_TREE_NODE_TYPE).isPresent()) { - return; // Already done - } - final RegistryAccess.ImmutableRegistryAccess builtInRegistryAccess = new RegistryAccess.ImmutableRegistryAccess(BuiltInRegistries.REGISTRY.stream().toList()); - final CommandBuildContext cbCtx = CommandBuildContext.simple(builtInRegistryAccess, featureFlags); - holder.createOrReplaceFrozenRegistry(RegistryTypes.COMMAND_TREE_NODE_TYPE, CommandRegistryLoader.clientCompletionKey(cbCtx)); - holder.createOrReplaceFrozenRegistry(RegistryTypes.REGISTRY_KEYED_VALUE_PARAMETER, CommandRegistryLoader.valueParameter(cbCtx)); + holder.createFrozenRegistry(RegistryTypes.FLAT_GENERATOR_CONFIG, SpongeRegistryLoader::flatGeneratorConfig, RegistryTypes.WORLD_ARCHETYPE_TYPE); - holder.createOrReplaceFrozenRegistry(RegistryTypes.FLAT_GENERATOR_CONFIG, SpongeRegistryLoader.flatGeneratorConfig(registryAccess)); + SpongeRegistries.registerDynamicServerRegistries(holder); } - public static void registerServerRegistries(final RegistryHolder holder) { + private static void registerDynamicServerRegistries(final SpongeRegistryHolder holder) { + holder.createRegistry(RegistryTypes.ADVANCEMENT, (RegistryLoader) null, true); + holder.createRegistry(RegistryTypes.RECIPE, (RegistryLoader>) null, true); } - } diff --git a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplateFactory.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistryDependencyEntry.java similarity index 68% rename from src/main/java/org/spongepowered/common/tag/SpongeTagTemplateFactory.java rename to src/main/java/org/spongepowered/common/registry/SpongeRegistryDependencyEntry.java index a50a9f943c0..fb5b1bc3692 100644 --- a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplateFactory.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistryDependencyEntry.java @@ -22,19 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.tag; +package org.spongepowered.common.registry; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.tag.TagTemplate; -import org.spongepowered.api.tag.Taggable; +import net.minecraft.util.DependencySorter; +import org.spongepowered.api.registry.RegistryType; -import java.util.Objects; +import java.util.Collection; +import java.util.function.Consumer; -public final class SpongeTagTemplateFactory implements TagTemplate.Factory { +public record SpongeRegistryDependencyEntry(T cookie, Collection> dependencies) implements DependencySorter.Entry> { @Override - public > TagTemplate.Builder builder(final DataPack> pack) { - return new SpongeTagTemplateBuilder<>(Objects.requireNonNull(pack, "tagType")); + public void visitRequiredDependencies(final Consumer> consumer) { + this.dependencies.forEach(consumer); } + @Override + public void visitOptionalDependencies(final Consumer> consumer) { + } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistryHolder.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistryHolder.java index 903455675ac..3aa0ddf4dbb 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeRegistryHolder.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistryHolder.java @@ -24,21 +24,26 @@ */ package org.spongepowered.common.registry; +import net.minecraft.core.HolderLookup; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.world.flag.FeatureFlagSet; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; -public interface SpongeRegistryHolder extends RegistryHolder { +public interface SpongeRegistryHolder extends RegistryHolder, HolderLookup.Provider { RegistryHolderLogic registryHolder(); @@ -46,14 +51,25 @@ default void setRootMinecraftRegistry(Registry> registry) { this.registryHolder().setRootMinecraftRegistry(registry); } + default void setRootMinecraftRegistry(RegistryAccess registryAccess) { + this.registryHolder().setRootMinecraftRegistry(registryAccess); + } + default org.spongepowered.api.registry.Registry createRegistry(final RegistryType type, final @Nullable InitialRegistryData defaultValues, - final boolean isDynamic, final @Nullable BiConsumer, T> callback, final boolean replace) { - return this.registryHolder().createRegistry(type, defaultValues, this.registryHolder().registrySupplier(isDynamic, callback), replace); + final boolean isDynamic, final @Nullable BiConsumer, T> callback) { + return this.registryHolder().createRegistry(type, defaultValues, this.registryHolder().registrySupplier(isDynamic, callback)); } default org.spongepowered.api.registry.Registry createRegistry(final RegistryType type, final @Nullable Supplier> defaultValues, final boolean isDynamic) { - return this.createRegistry(type, InitialRegistryData.noIds(defaultValues), isDynamic, null, false); + return this.createRegistry(type, InitialRegistryData.noIds(defaultValues), isDynamic, null); + } + + default org.spongepowered.api.registry.Registry createRegistry(final RegistryType type, final @Nullable Function> defaultValues, + final boolean isDynamic, final RegistryType... dependencies) { + final org.spongepowered.api.registry.Registry registry = this.createRegistry(type, (RegistryLoader) null, isDynamic, null); + ((WritableRegistryBridge) registry).bridge$addDependencies(() -> InitialRegistryData.noIds(() -> defaultValues.apply(this.registryHolder())), dependencies); + return registry; } default org.spongepowered.api.registry.Registry createRegistry(final RegistryType type, final RegistryLoader loader) { @@ -68,17 +84,21 @@ default org.spongepowered.api.registry.Registry createFrozenRegistry(fina return registry; } - default org.spongepowered.api.registry.Registry createOrReplaceFrozenRegistry(final RegistryType type, final RegistryLoader loader) { - final org.spongepowered.api.registry.Registry registry = this.createRegistry(type, loader, false, null, true); - if (registry instanceof MappedRegistry toFreeze) { - toFreeze.freeze(); - } + default org.spongepowered.api.registry.Registry createFrozenRegistry(final RegistryType type, + final Function> loader, final RegistryType... dependencies) { + final org.spongepowered.api.registry.Registry registry = this.createRegistry(type, (RegistryLoader) null, false); + ((WritableRegistryBridge) registry).bridge$addDependencies(() -> loader.apply(this.registryHolder()), dependencies); return registry; } default org.spongepowered.api.registry.Registry createRegistry(final RegistryType type, final RegistryLoader loader, final boolean isDynamic) { - return this.createRegistry(type, loader, isDynamic, null, false); + return this.createRegistry(type, loader, isDynamic, null); + } + + @Override + default Stream> streamRegistries() { + return this.registryHolder().streamRegistries(); } @Override @@ -95,4 +115,19 @@ default Optional> findRegistry(fi default org.spongepowered.api.registry.Registry registry(final RegistryType type) { return this.registryHolder().registry(Objects.requireNonNull(type, "type")); } + + default FeatureFlagSet featureFlagSet() { + return this.registryHolder().featureFlagSet(); + } + + @Override + default Stream>> listRegistryKeys() { + return this.registryHolder().listRegistryKeys(); + } + + @Override + default Optional> lookup( + final net.minecraft.resources.ResourceKey> resourceKey) { + return this.registryHolder().lookup(resourceKey); + } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistryRegistrationSet.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistryRegistrationSet.java new file mode 100644 index 00000000000..03aa2ca963c --- /dev/null +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistryRegistrationSet.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.registry; + +import com.google.common.collect.ImmutableMap; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryRegistrationSet; +import org.spongepowered.api.registry.RegistryType; + +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +public record SpongeRegistryRegistrationSet(RegistryType registryType, Map> values) implements RegistryRegistrationSet { + + public static final class BuilderImpl implements RegistryRegistrationSet.Builder { + + private final RegistryType registryType; + private final Supplier defaultHolder; + + private ImmutableMap.Builder> builder = ImmutableMap.builder(); + + BuilderImpl(final RegistryType registryType, final Supplier defaultHolder) { + this.registryType = registryType; + this.defaultHolder = defaultHolder; + } + + @SuppressWarnings("unchecked") + @Override + public DefaultedRegistryReference register(final ResourceKey key, final Function value) { + this.builder.put(key, (Function) value); + return new SpongeDefaultedRegistryReference<>(new SpongeRegistryKey<>((RegistryType) this.registryType, key), this.defaultHolder); + } + + @Override + public Builder reset() { + this.builder = ImmutableMap.builder(); + return this; + } + + @NotNull + @Override + public RegistryRegistrationSet build() { + return new SpongeRegistryRegistrationSet<>(this.registryType, this.builder.build()); + } + } + + public static final class FactoryImpl implements RegistryRegistrationSet.Factory { + + @Override + public Builder builder(final RegistryType registryType, final Supplier defaultHolder) { + return new BuilderImpl<>(registryType, defaultHolder); + } + } +} diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index f0c4ab3d9c8..f256e6c9a5f 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -58,6 +58,7 @@ import net.minecraft.commands.synchronization.brigadier.FloatArgumentInfo; import net.minecraft.commands.synchronization.brigadier.IntegerArgumentInfo; import net.minecraft.commands.synchronization.brigadier.LongArgumentInfo; +import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.Vec2; @@ -84,6 +85,7 @@ import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.common.accessor.commands.arguments.DimensionArgumentAccessor; import org.spongepowered.common.adventure.SpongeAdventure; +import org.spongepowered.common.command.brigadier.argument.BindableValueParameter; import org.spongepowered.common.command.brigadier.argument.ClientNativeArgumentParser; import org.spongepowered.common.command.parameter.managed.clientcompletion.SpongeClientCompletionType; import org.spongepowered.common.command.parameter.managed.operator.SpongeAdditionOperator; @@ -134,11 +136,11 @@ public final class CommandRegistryLoader { @SuppressWarnings("ConstantConditions") - public static RegistryLoader> valueParameter(final CommandBuildContext cbCtx) { + public static RegistryLoader> valueParameter() { return RegistryLoader.of(l -> { l.add(ResourceKeyedValueParameters.BIG_DECIMAL, SpongeBigDecimalValueParameter::new); l.add(ResourceKeyedValueParameters.BIG_INTEGER, SpongeBigIntegerValueParameter::new); - l.add(ResourceKeyedValueParameters.BLOCK_STATE, k -> ClientNativeArgumentParser.createConverter(k, BlockStateArgument.block(cbCtx), (reader, cause, state) -> (BlockState) state.getState())); + l.add(ResourceKeyedValueParameters.BLOCK_STATE, k -> new BindableValueParameter<>(k, h -> ClientNativeArgumentParser.createConverter(k, BlockStateArgument.block(CommandBuildContext.simple((HolderLookup.Provider) h, ((CommandBuildContext) h).enabledFeatures())), (reader, cause, state) -> (BlockState) state.getState()))); l.add(ResourceKeyedValueParameters.BOOLEAN, k -> ClientNativeArgumentParser.createIdentity(k, BoolArgumentType.bool())); l.add(ResourceKeyedValueParameters.COLOR, SpongeColorValueParameter::new); l.add(ResourceKeyedValueParameters.DATA_CONTAINER, SpongeDataContainerValueParameter::new); @@ -149,7 +151,7 @@ public static RegistryLoader> valueParameter(final CommandBuil l.add(ResourceKeyedValueParameters.GAME_PROFILE, SpongeGameProfileValueParameter::new); l.add(ResourceKeyedValueParameters.INTEGER, k -> ClientNativeArgumentParser.createIdentity(k, IntegerArgumentType.integer())); l.add(ResourceKeyedValueParameters.IP, SpongeIPAddressValueParameter::new); - l.add(ResourceKeyedValueParameters.ITEM_STACK_SNAPSHOT, k -> ClientNativeArgumentParser.createConverter(k, ItemArgument.item(cbCtx), (reader, cause, converter) -> new SpongeItemStackSnapshot((ItemStack) (Object) converter.createItemStack(1, true)))); + l.add(ResourceKeyedValueParameters.ITEM_STACK_SNAPSHOT, k -> new BindableValueParameter<>(k, h -> ClientNativeArgumentParser.createConverter(k, ItemArgument.item(CommandBuildContext.simple((HolderLookup.Provider) h, ((CommandBuildContext) h).enabledFeatures())), (reader, cause, converter) -> new SpongeItemStackSnapshot((ItemStack) (Object) converter.createItemStack(1, true))))); l.add(ResourceKeyedValueParameters.LOCATION, SpongeServerLocationValueParameter::new); l.add(ResourceKeyedValueParameters.LONG, k -> ClientNativeArgumentParser.createIdentity(k, LongArgumentType.longArg())); l.add(ResourceKeyedValueParameters.MANY_ENTITIES, k -> ClientNativeArgumentParser.createConverter(k, EntityArgument.entities(), (reader, cause, selector) -> selector.findEntities((CommandSourceStack) cause).stream().map(x -> (Entity) x).collect( @@ -172,7 +174,7 @@ public static RegistryLoader> valueParameter(final CommandBuil l.add(ResourceKeyedValueParameters.TARGET_PLAYER, k -> new SpongeTargetEntityValueParameter(k, true)); l.add(ResourceKeyedValueParameters.TEXT_FORMATTING_CODE, k -> ClientNativeArgumentParser.createConverter(k, StringArgumentType.string(), (reader, cause, result) -> LegacyComponentSerializer.legacyAmpersand().deserialize(result))); l.add(ResourceKeyedValueParameters.TEXT_FORMATTING_CODE_ALL, k -> ClientNativeArgumentParser.createConverter(k, StringArgumentType.greedyString(), (reader, cause, result) -> LegacyComponentSerializer.legacyAmpersand().deserialize(result))); - l.add(ResourceKeyedValueParameters.TEXT_JSON, k -> ClientNativeArgumentParser.createConverter(k, ComponentArgument.textComponent(cbCtx), (reader, cause, result) -> SpongeAdventure.asAdventure(result))); + l.add(ResourceKeyedValueParameters.TEXT_JSON, k -> new BindableValueParameter<>(k, h -> ClientNativeArgumentParser.createConverter(k, ComponentArgument.textComponent(CommandBuildContext.simple((HolderLookup.Provider) h, ((CommandBuildContext) h).enabledFeatures())), (reader, cause, result) -> SpongeAdventure.asAdventure(result)))); l.add(ResourceKeyedValueParameters.TEXT_JSON_ALL, k -> ClientNativeArgumentParser.createConverter(k, StringArgumentType.greedyString(), (reader, cause, result) -> GsonComponentSerializer.gson().deserialize(result))); l.add(ResourceKeyedValueParameters.URL, k -> ClientNativeArgumentParser.createConverter(k, StringArgumentType.string(), (reader, cause, input) -> { diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index 54cc7107c21..5f48b0b3477 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -24,8 +24,6 @@ */ package org.spongepowered.common.registry.loader; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorPreset; import net.minecraft.world.level.material.MapColor; @@ -80,7 +78,10 @@ import org.spongepowered.api.map.color.MapShades; import org.spongepowered.api.map.decoration.orientation.MapDecorationOrientation; import org.spongepowered.api.map.decoration.orientation.MapDecorationOrientations; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryKey; +import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.service.ban.Ban; import org.spongepowered.api.service.ban.BanType; @@ -580,13 +581,13 @@ public static RegistryLoader noiseConfig() { }); } - public static RegistryLoader flatGeneratorConfig(RegistryAccess registryAccess) { - final Registry registry = registryAccess.lookupOrThrow(Registries.FLAT_LEVEL_GENERATOR_PRESET); - return RegistryLoader.of(l -> { - for (final var entry : registry.entrySet()) { - l.add(RegistryKey.of(RegistryTypes.FLAT_GENERATOR_CONFIG, (ResourceKey) (Object) entry.getKey().location()), () -> (FlatGeneratorConfig) entry.getValue().settings()); - } - }); + public static RegistryLoader flatGeneratorConfig(RegistryHolder registryAccess) { + final RegistryType registryType = RegistryType.of( + (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.registry(), (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.location()); + final Registry registry = registryAccess.registry(registryType); + return RegistryLoader.of(l -> + registry.streamEntries().forEach(e -> + l.add(RegistryKey.of(RegistryTypes.FLAT_GENERATOR_CONFIG, e.key()), () -> (FlatGeneratorConfig) e.value().settings()))); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplate.java b/src/main/java/org/spongepowered/common/tag/SpongeTagTemplate.java deleted file mode 100644 index 7f7d0c84d03..00000000000 --- a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplate.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.tag; - -import com.google.gson.JsonObject; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagBuilder; -import net.minecraft.tags.TagFile; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataQuery; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.tag.TagTemplate; -import org.spongepowered.api.tag.Taggable; -import org.spongepowered.common.SpongeCommon; - -import java.io.IOException; -import java.util.Map; - -public record SpongeTagTemplate>( - ResourceKey key, boolean replace, Map elements, - Map subTags, - DataPack> pack) implements TagTemplate { - - @Override - public int contentVersion() { - return 1; - } - - @Override - public DataContainer toContainer() { - final JsonObject jsonObject = SpongeTagTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - final DataContainer container = DataFormats.JSON.get().read(jsonObject.getAsString()); - container.set(DataQuery.of("replace"), this.replace); - return container; - } catch (IOException e) { - SpongeCommon.logger().error("Error reading json serialized by minecraft", e); - return DataContainer.createNew(); - } - } - - public static > JsonObject encode(TagTemplate template, RegistryAccess registryAccess) { - final TagBuilder builder = TagBuilder.create(); - final SpongeTagTemplate spongeTemplate = (SpongeTagTemplate) template; - spongeTemplate.elements.forEach((k, v) -> { - final ResourceLocation location = (ResourceLocation) (Object) k; - // "N/A" is supposed to be the source, but we don't know it, and we're serializing it so it isn't used anyway. (Gone when we serializeToJson) - if (v) { - builder.addElement(location); - } else { - builder.addOptionalElement(location); - } - }); - spongeTemplate.subTags.forEach((k, v) -> { - final ResourceLocation location = (ResourceLocation) (Object) k; - if (v) { - builder.addTag(location); - } else { - builder.addOptionalTag(location); - } - }); - return TagFile.CODEC.encodeStart(JsonOps.INSTANCE, new TagFile(builder.build(), spongeTemplate.replace)).getOrThrow().getAsJsonObject(); - } - -} diff --git a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplateBuilder.java b/src/main/java/org/spongepowered/common/tag/SpongeTagTemplateBuilder.java deleted file mode 100644 index becd5815af9..00000000000 --- a/src/main/java/org/spongepowered/common/tag/SpongeTagTemplateBuilder.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.tag; - -import com.google.common.collect.ImmutableMap; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.registry.RegistryKey; -import org.spongepowered.api.tag.Tag; -import org.spongepowered.api.tag.TagTemplate; -import org.spongepowered.api.tag.Taggable; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public final class SpongeTagTemplateBuilder> implements TagTemplate.Builder { - - private @Nullable ResourceKey key; - private boolean replace = false; - private final Map values = new HashMap<>(); - private final Map children = new HashMap<>(); - private final DataPack> pack; - - public SpongeTagTemplateBuilder(final DataPack> pack) { - this.pack = pack; - } - - @Override - public TagTemplate.Builder key(final ResourceKey key) { - this.key = key; - return this; - } - - @Override - public TagTemplate.Builder replace(final boolean replace) { - this.replace = replace; - return this; - } - - @Override - public TagTemplate.Builder addChild(final Tag childTag, final boolean required) { - this.children.put(childTag.key(), required); - return this; - } - - @Override - public TagTemplate.Builder addChild(final TagTemplate childTag) throws IllegalArgumentException { - final SpongeTagTemplate spongeTagTemplate = ((SpongeTagTemplate) childTag); - // Circular references aren't allow - causes loading failure. So do a basic sanity check, - // we can't ensure theres no circular references until everything is resolved, but we can check - // 1 level down if we're given a tagtemplate. - if (spongeTagTemplate.subTags().containsKey(this.key)) { - throw new IllegalArgumentException("Recursive tag reference detected! Cannot add a child tag with parent as child! Key: " + this.key); - } - this.children.put(childTag.key(), true); - return this; - } - - @Override - public TagTemplate.Builder addChildren(final Collection> children, final boolean required) { - children.stream().map(Tag::key).forEach(key -> this.children.put(key, required)); - return this; - } - - @Override - public TagTemplate.Builder addChildren(final Map, Boolean> childrenMap) { - childrenMap.forEach((k, v) -> this.children.put(k.key(), v)); - return this; - } - - @Override - public TagTemplate.Builder addValue(final RegistryKey value, final boolean required) throws IllegalArgumentException { - this.values.put(value.location(), required); - return this; - } - - @Override - public TagTemplate.Builder addValues(final Collection> values, final boolean required) throws IllegalArgumentException { - values.forEach(v -> this.values.put(v.location(), required)); - return this; - } - - @Override - public @NonNull SpongeTagTemplate build() { - if (this.key == null) { - throw new IllegalStateException("Key has not been provided yet!"); - } - return new SpongeTagTemplate<>(this.key, - this.replace, - ImmutableMap.copyOf(this.values), - ImmutableMap.copyOf(this.children), - this.pack); - } - - @Override - public TagTemplate.Builder reset() { - this.replace = false; - this.values.clear(); - this.children.clear(); - return this; - } - -} diff --git a/src/main/java/org/spongepowered/common/util/AbstractDataPackEntryBuilder.java b/src/main/java/org/spongepowered/common/util/DataPackUtil.java similarity index 54% rename from src/main/java/org/spongepowered/common/util/AbstractDataPackEntryBuilder.java rename to src/main/java/org/spongepowered/common/util/DataPackUtil.java index 747d4610344..d00194f0ee5 100644 --- a/src/main/java/org/spongepowered/common/util/AbstractDataPackEntryBuilder.java +++ b/src/main/java/org/spongepowered/common/util/DataPackUtil.java @@ -24,30 +24,32 @@ */ package org.spongepowered.common.util; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.api.util.DataPackEntryBuilder; - -import java.util.function.Function; - -public abstract class AbstractDataPackEntryBuilder, B extends DataPackEntryBuilder> - extends AbstractResourceKeyedBuilder implements DataPackEntryBuilder { - - protected DataPack pack; - - @Override - public B pack(final DataPack pack) { - this.pack = pack; - return (B) this; +import com.google.gson.JsonElement; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.data.persistence.DataFormats; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.io.IOException; +import java.util.Optional; + +public final class DataPackUtil { + + public static Optional toDataContainer(final RegistryHolder registryHolder, final Codec codec, final T value) { + final DataResult result = codec.encodeStart( + ((SpongeRegistryHolder) registryHolder).createSerializationContext(JsonOps.INSTANCE), value); + if (result.isSuccess()) { + try { + return Optional.of(DataFormats.JSON.get().read(result.getOrThrow().toString())); + } catch (final IOException ignored) { + } + } + return Optional.empty(); } - public abstract Function valueExtractor(); - - @Override - public B from(final TT value) { - this.fromValue(valueExtractor().apply(value)).pack(value.pack()).key(value.key()); - return (B) this; + private DataPackUtil() { } - - } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java new file mode 100644 index 00000000000..8c56f801a87 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java @@ -0,0 +1,156 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.biome; + +import net.minecraft.core.Holder; +import net.minecraft.sounds.Music; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.biome.AmbientAdditionsSettings; +import net.minecraft.world.level.biome.AmbientParticleSettings; +import net.minecraft.world.level.biome.BiomeGenerationSettings; +import net.minecraft.world.level.biome.BiomeSpecialEffects; +import net.minecraft.world.level.biome.MobSpawnSettings; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import org.spongepowered.api.data.DataManipulator; +import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.api.entity.EntityCategory; +import org.spongepowered.api.entity.EntityType; +import org.spongepowered.api.world.biome.Biome; +import org.spongepowered.api.world.biome.ambient.SoundConfig; +import org.spongepowered.api.world.biome.climate.GrassColorModifiers; +import org.spongepowered.api.world.biome.climate.TemperatureModifiers; +import org.spongepowered.api.world.biome.spawner.NaturalSpawnCost; +import org.spongepowered.api.world.biome.spawner.NaturalSpawner; +import org.spongepowered.api.world.generation.carver.Carver; +import org.spongepowered.api.world.generation.feature.DecorationStep; +import org.spongepowered.api.world.generation.feature.PlacedFeature; +import org.spongepowered.common.data.SpongeDataManager; +import org.spongepowered.common.data.provider.DataProviderLookup; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public final class SpongeBiomeBuilder implements Biome.Builder { + + private static DataProviderLookup PROVIDER_LOOKUP = SpongeDataManager.getProviderRegistry().getProviderLookup(net.minecraft.world.level.biome.Biome.class); + + private DataManipulator.Mutable manipulator = DataManipulator.mutableOf(); + + public SpongeBiomeBuilder() { + this.reset(); + } + + @Override + public Biome.Builder add(final Key> key, final V value) { + if (!PROVIDER_LOOKUP.getProvider(key).isSupported(net.minecraft.world.level.biome.Biome.class)) { + throw new IllegalArgumentException(key + " is not supported for biomes"); + } + this.manipulator.set(key, value); + return this; + } + + @Override + public Biome.Builder reset() { + this.manipulator = DataManipulator.mutableOf(); + return this; + } + + @Override + public Biome.Builder from(final org.spongepowered.api.world.biome.Biome biome) { + this.manipulator.set(biome.getValues()); + return this; + } + + @Override + public Biome build() { + final var precipitation = this.manipulator.require(Keys.HAS_PRECIPITATION); + final Double temperature = this.manipulator.require(Keys.BIOME_TEMPERATURE); + final Double downfall = this.manipulator.require(Keys.HUMIDITY); + final var temperatureModifier = this.manipulator.getOrElse(Keys.TEMPERATURE_MODIFIER, TemperatureModifiers.NONE.get()); + + final var fogColor = this.manipulator.require(Keys.FOG_COLOR); + final var waterColor = this.manipulator.require(Keys.WATER_COLOR); + final var waterFogColor = this.manipulator.require(Keys.WATER_FOG_COLOR); + final var skyColor = this.manipulator.require(Keys.SKY_COLOR); + final var foliageColor = this.manipulator.get(Keys.FOLIAGE_COLOR); + final var grassColor = this.manipulator.get(Keys.GRASS_COLOR); + final var grassColorModifier = this.manipulator.getOrElse(Keys.GRASS_COLOR_MODIFIER, GrassColorModifiers.NONE.get()); + final var particleSettings = this.manipulator.get(Keys.AMBIENT_PARTICLE); + final Optional ambientSound = this.manipulator.get(Keys.AMBIENT_SOUND); + final Optional ambientMood = this.manipulator.get(Keys.AMBIENT_MOOD); + final Optional additionalSound = this.manipulator.get(Keys.AMBIENT_ADDITIONAL_SOUND); + final Optional backgroundMusic = this.manipulator.get(Keys.BACKGROUND_MUSIC); + + final Double spawnChance = this.manipulator.require(Keys.SPAWN_CHANCE); + final Map> spawners = this.manipulator.getOrElse(Keys.NATURAL_SPAWNERS, Map.of()); + final Map, NaturalSpawnCost> spawnerCosts = this.manipulator.getOrElse(Keys.NATURAL_SPAWNER_COST, Map.of()); + + final Map> features = this.manipulator.getOrElse(Keys.FEATURES, Map.of()); + final List carvers = this.manipulator.getOrElse(Keys.CARVERS, List.of()); + + final BiomeSpecialEffects.Builder effectsBuilder = new BiomeSpecialEffects.Builder() + .fogColor(fogColor.rgb()) + .waterColor(waterColor.rgb()) + .waterFogColor(waterFogColor.rgb()) + .skyColor(skyColor.rgb()) + .grassColorModifier((BiomeSpecialEffects.GrassColorModifier) (Object) grassColorModifier); + foliageColor.ifPresent(c -> effectsBuilder.foliageColorOverride(c.rgb())); + grassColor.ifPresent(c -> effectsBuilder.grassColorOverride(c.rgb())); + particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) ps)); + ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); + ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) m)); + additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) s)); + backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) m)); + + final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() + .creatureGenerationProbability(spawnChance.floatValue()); + spawners.forEach((cat, spawner) -> spawner.forEach(sp -> { + spawnerBuilder.addSpawn((MobCategory) (Object) cat, (MobSpawnSettings.SpawnerData) sp); + })); + spawnerCosts.forEach((type, cost) -> spawnerBuilder.addMobCharge((net.minecraft.world.entity.EntityType) (Object) type, cost.budget(), + cost.charge())); + + final BiomeGenerationSettings.PlainBuilder generationBuilder = new BiomeGenerationSettings.PlainBuilder(); + features.forEach((step, list) -> list.forEach(feature -> generationBuilder.addFeature((GenerationStep.Decoration) (Object) step, + Holder.direct((net.minecraft.world.level.levelgen.placement.PlacedFeature) (Object) feature)))); + carvers.forEach((carver) -> generationBuilder.addCarver(Holder.direct((ConfiguredWorldCarver) (Object) carver))); + + final net.minecraft.world.level.biome.Biome.BiomeBuilder vanillaBuilder = new net.minecraft.world.level.biome.Biome.BiomeBuilder() + .hasPrecipitation(precipitation) + .temperature(temperature.floatValue()) + .downfall(downfall.floatValue()) + .temperatureAdjustment((net.minecraft.world.level.biome.Biome.TemperatureModifier) (Object) temperatureModifier) + .specialEffects(effectsBuilder.build()) + .mobSpawnSettings(spawnerBuilder.build()) + .generationSettings(generationBuilder.build()); + return (Biome) (Object) vanillaBuilder.build(); + } +} diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java deleted file mode 100644 index 481ed65a69c..00000000000 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeTemplate.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.biome; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; -import net.minecraft.sounds.Music; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.level.biome.AmbientAdditionsSettings; -import net.minecraft.world.level.biome.AmbientParticleSettings; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeGenerationSettings; -import net.minecraft.world.level.biome.BiomeSpecialEffects; -import net.minecraft.world.level.biome.MobSpawnSettings; -import net.minecraft.world.level.levelgen.GenerationStep; -import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.DataManipulator; -import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.effect.sound.SoundType; -import org.spongepowered.api.entity.EntityCategory; -import org.spongepowered.api.entity.EntityType; -import org.spongepowered.api.world.biome.BiomeTemplate; -import org.spongepowered.api.world.biome.ambient.SoundConfig; -import org.spongepowered.api.world.biome.climate.GrassColorModifiers; -import org.spongepowered.api.world.biome.climate.TemperatureModifiers; -import org.spongepowered.api.world.biome.spawner.NaturalSpawnCost; -import org.spongepowered.api.world.biome.spawner.NaturalSpawner; -import org.spongepowered.api.world.generation.carver.Carver; -import org.spongepowered.api.world.generation.feature.DecorationStep; -import org.spongepowered.api.world.generation.feature.PlacedFeature; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.data.SpongeDataManager; -import org.spongepowered.common.data.provider.DataProviderLookup; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - -public record SpongeBiomeTemplate(ResourceKey key, Biome representedBiome, DataPack pack) implements BiomeTemplate { - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeBiomeTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Biome:\n" + serialized, e); - } - } - - @Override - public org.spongepowered.api.world.biome.Biome biome() { - return (org.spongepowered.api.world.biome.Biome) (Object) this.representedBiome; - } - - public static JsonElement encode(final BiomeTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return Biome.DIRECT_CODEC.encodeStart(ops, (Biome) (Object) template.biome()).getOrThrow(); - } - - public static Biome decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return Biome.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static BiomeTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final Biome parsed = SpongeBiomeTemplate.decode(packEntry, registryAccess); - return new SpongeBiomeTemplate(key, parsed, pack); - } - - public static class BuilderImpl extends AbstractDataPackEntryBuilder implements BiomeTemplate.Builder { - - private static DataProviderLookup PROVIDER_LOOKUP = SpongeDataManager.getProviderRegistry().getProviderLookup(Biome.class); - - private DataManipulator.Mutable manipulator = DataManipulator.mutableOf(); - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return BiomeTemplate::biome; - } - - @Override - public Builder add(final Key> key, final V value) { - if (!PROVIDER_LOOKUP.getProvider(key).isSupported(Biome.class)) { - throw new IllegalArgumentException(key + " is not supported for biomes"); - } - this.manipulator.set(key, value); - return this; - } - - @Override - public Builder reset() { - this.manipulator = DataManipulator.mutableOf(); - this.key = null; - this.pack = DataPacks.BIOME; - return this; - } - - @Override - public Builder fromValue(final org.spongepowered.api.world.biome.Biome biome) { - this.manipulator.set(biome.getValues()); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final Biome biome = SpongeBiomeTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((org.spongepowered.api.world.biome.Biome) (Object) biome); - return this; - } - - @Override - protected BiomeTemplate build0() { - final var precipitation = this.manipulator.require(Keys.HAS_PRECIPITATION); - final Double temperature = this.manipulator.require(Keys.BIOME_TEMPERATURE); - final Double downfall = this.manipulator.require(Keys.HUMIDITY); - final var temperatureModifier = this.manipulator.getOrElse(Keys.TEMPERATURE_MODIFIER, TemperatureModifiers.NONE.get()); - - final var fogColor = this.manipulator.require(Keys.FOG_COLOR); - final var waterColor = this.manipulator.require(Keys.WATER_COLOR); - final var waterFogColor = this.manipulator.require(Keys.WATER_FOG_COLOR); - final var skyColor = this.manipulator.require(Keys.SKY_COLOR); - final var foliageColor = this.manipulator.get(Keys.FOLIAGE_COLOR); - final var grassColor = this.manipulator.get(Keys.GRASS_COLOR); - final var grassColorModifier = this.manipulator.getOrElse(Keys.GRASS_COLOR_MODIFIER, GrassColorModifiers.NONE.get()); - final var particleSettings = this.manipulator.get(Keys.AMBIENT_PARTICLE); - final Optional ambientSound = this.manipulator.get(Keys.AMBIENT_SOUND); - final Optional ambientMood = this.manipulator.get(Keys.AMBIENT_MOOD); - final Optional additionalSound = this.manipulator.get(Keys.AMBIENT_ADDITIONAL_SOUND); - final Optional backgroundMusic = this.manipulator.get(Keys.BACKGROUND_MUSIC); - - final Double spawnChance = this.manipulator.require(Keys.SPAWN_CHANCE); - final Map> spawners = this.manipulator.getOrElse(Keys.NATURAL_SPAWNERS, Map.of()); - final Map, NaturalSpawnCost> spawnerCosts = this.manipulator.getOrElse(Keys.NATURAL_SPAWNER_COST, Map.of()); - - final Map> features = this.manipulator.getOrElse(Keys.FEATURES, Map.of()); - final List carvers = this.manipulator.getOrElse(Keys.CARVERS, List.of()); - - final BiomeSpecialEffects.Builder effectsBuilder = new BiomeSpecialEffects.Builder() - .fogColor(fogColor.rgb()) - .waterColor(waterColor.rgb()) - .waterFogColor(waterFogColor.rgb()) - .skyColor(skyColor.rgb()) - .grassColorModifier((BiomeSpecialEffects.GrassColorModifier) (Object) grassColorModifier); - foliageColor.ifPresent(c -> effectsBuilder.foliageColorOverride(c.rgb())); - grassColor.ifPresent(c -> effectsBuilder.grassColorOverride(c.rgb())); - particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) ps)); - ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); - ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) m)); - additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) s)); - backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) m)); - - final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() - .creatureGenerationProbability(spawnChance.floatValue()); - spawners.forEach((cat, spawner) -> spawner.forEach(sp -> { - spawnerBuilder.addSpawn((MobCategory) (Object) cat, (MobSpawnSettings.SpawnerData) sp); - })); - spawnerCosts.forEach((type, cost) -> spawnerBuilder.addMobCharge((net.minecraft.world.entity.EntityType) (Object) type, cost.budget(), - cost.charge())); - - final Registry placedFeatureRegistry = SpongeCommon.vanillaRegistry(Registries.PLACED_FEATURE); - final Registry> configuredWorldCarverRegistry = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_CARVER); - final BiomeGenerationSettings.Builder generationBuilder = new BiomeGenerationSettings.Builder(placedFeatureRegistry, configuredWorldCarverRegistry); - features.forEach((step, list) -> list.forEach(feature -> generationBuilder.addFeature((GenerationStep.Decoration) (Object) step, - Holder.direct((net.minecraft.world.level.levelgen.placement.PlacedFeature) (Object) feature)))); - carvers.forEach((carver) -> generationBuilder.addCarver(Holder.direct((ConfiguredWorldCarver) (Object) carver))); - - final Biome.BiomeBuilder vanillaBuilder = new Biome.BiomeBuilder() - .hasPrecipitation(precipitation) - .temperature(temperature.floatValue()) - .downfall(downfall.floatValue()) - .temperatureAdjustment((Biome.TemperatureModifier) (Object) temperatureModifier) - .specialEffects(effectsBuilder.build()) - .mobSpawnSettings(spawnerBuilder.build()) - .generationSettings(generationBuilder.build()); - return new SpongeBiomeTemplate(this.key, vanillaBuilder.build(), this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java b/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java index 9c52d42e4b0..59634ec1fa3 100644 --- a/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/SpongeChunkGeneratorFactory.java @@ -24,8 +24,6 @@ */ package org.spongepowered.common.world.generation; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.level.biome.BiomeSource; @@ -36,17 +34,13 @@ import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.world.biome.provider.BiomeProvider; import org.spongepowered.api.world.generation.ChunkGenerator; import org.spongepowered.api.world.generation.ConfigurableChunkGenerator; import org.spongepowered.api.world.generation.config.flat.FlatGeneratorConfig; import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.world.server.SpongeWorldTemplate; -import java.io.IOException; import java.util.Objects; @SuppressWarnings("unchecked") @@ -93,10 +87,4 @@ public ConfigurableChunkGenerator theEnd() { var biomeSource = TheEndBiomeSource.create(biomeRegistry); return this.noiseBasedChunkGenerator(biomeSource, noiseGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)); } - - @Override - public ChunkGenerator fromDataPack(DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - return (ChunkGenerator) SpongeWorldTemplate.decodeStem(json, SpongeCommon.server().registryAccess()).generator(); - } } diff --git a/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverBuilder.java b/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverBuilder.java new file mode 100644 index 00000000000..8bdc6956d0f --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverBuilder.java @@ -0,0 +1,67 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.carver; + +import net.minecraft.world.level.levelgen.carver.CarverConfiguration; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.carver.WorldCarver; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.world.generation.carver.Carver; +import org.spongepowered.api.world.generation.carver.CarverType; + +public final class SpongeCarverBuilder implements Carver.Builder { + + @Nullable private WorldCarver type; + @Nullable private CarverConfiguration config; + + public SpongeCarverBuilder() { + this.reset(); + } + + @Override + public Carver.Builder reset() { + this.type = null; + this.config = null; + return this; + } + + @Override + public Carver.Builder type(final CarverType type) { + this.type = (WorldCarver) type; + return this; + } + + @Override + public Carver.Builder from(final Carver carver) { + this.type(carver.type()); + this.config = ((ConfiguredWorldCarver) (Object) carver).config(); + return this; + } + + @Override + public Carver build() { + return (Carver) (Object) new ConfiguredWorldCarver<>((WorldCarver) this.type, this.config); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverTemplate.java b/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverTemplate.java deleted file mode 100644 index cefbb919521..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/carver/SpongeCarverTemplate.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.carver; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.Codec; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.carver.CarverConfiguration; -import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; -import net.minecraft.world.level.levelgen.carver.WorldCarver; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.carver.Carver; -import org.spongepowered.api.world.generation.carver.CarverTemplate; -import org.spongepowered.api.world.generation.carver.CarverType; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.function.Function; - -public record SpongeCarverTemplate(ResourceKey key, ConfiguredWorldCarver representedCarver, DataPack pack) implements CarverTemplate { - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeCarverTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Carver:\n" + serialized, e); - } - } - - @Override - public Carver carver() { - return (Carver) (Object) this.representedCarver; - } - - public static JsonElement encode(final Codec> codec, final ConfiguredWorldCarver carver, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return codec.encodeStart(ops, carver).getOrThrow(); - } - - public static JsonElement encode(final CarverTemplate template, final RegistryAccess registryAccess) { - return SpongeCarverTemplate.encode(ConfiguredWorldCarver.DIRECT_CODEC, (ConfiguredWorldCarver) (Object) template.carver(), registryAccess); - } - - public static ConfiguredWorldCarver decode(final Codec> codec, final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return codec.parse(ops, json).getOrThrow(); - } - - public static CarverTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final ConfiguredWorldCarver parsed = SpongeCarverTemplate.decode(ConfiguredWorldCarver.DIRECT_CODEC, packEntry, registryAccess); - return new SpongeCarverTemplate(key, parsed, pack); - } - - public static class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private WorldCarver type; - @Nullable private CarverConfiguration config; - - @Override - public Function valueExtractor() { - return CarverTemplate::carver; - } - - @Override - public Builder reset() { - this.type = null; - this.config = null; - this.key = null; - this.pack = DataPacks.CARVER; - return this; - } - - @Override - public Builder type(final CarverType type) { - this.type = (WorldCarver) type; - return this; - } - - @Override - public Builder fromValue(final Carver carver) { - this.type(carver.type()); - this.config = ((ConfiguredWorldCarver) (Object) carver).config(); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final ConfiguredWorldCarver carver = SpongeCarverTemplate.decode(ConfiguredWorldCarver.DIRECT_CODEC, json, SpongeCommon.server().registryAccess()); - this.fromValue((Carver) (Object) carver); - return this; - } - - @Override - protected CarverTemplate build0() { - ConfiguredWorldCarver carver = new ConfiguredWorldCarver<>((WorldCarver) this.type, this.config); - return new SpongeCarverTemplate(this.key, carver, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeDensityFunctionTemplate.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeDensityFunctionTemplate.java deleted file mode 100644 index 7d52ebff2c2..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeDensityFunctionTemplate.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.config.noise; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.DensityFunction; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.config.noise.DensityFunctionTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeDensityFunctionTemplate(ResourceKey key, DensityFunction representedFunction, DataPack pack) implements DensityFunctionTemplate { - - @Override - public org.spongepowered.api.world.generation.config.noise.DensityFunction densityFunction() { - return (org.spongepowered.api.world.generation.config.noise.DensityFunction) this.representedFunction; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeDensityFunctionTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Density Function:\n" + serialized, e); - } - } - - public static JsonElement encode(final DensityFunctionTemplate template, final RegistryAccess registryAccess) { - return DensityFunction.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, (DensityFunction) template.densityFunction()).getOrThrow(); - } - - public static DensityFunction decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return DensityFunction.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeDensityFunctionTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final DensityFunction parsed = SpongeDensityFunctionTemplate.decode(packEntry, registryAccess); - return new SpongeDensityFunctionTemplate(key, parsed, pack); - } - - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private DensityFunction densityFunction; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return DensityFunctionTemplate::densityFunction; - } - - @Override - public Builder fromValue(final org.spongepowered.api.world.generation.config.noise.DensityFunction densityFunction) { - this.densityFunction = (DensityFunction) densityFunction; - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - this.densityFunction = SpongeDensityFunctionTemplate.decode(json, SpongeCommon.server().registryAccess()); - return this; - } - - @Override - public Builder reset() { - this.pack = DataPacks.DENSITY_FUNCTION; - this.key = null; - this.densityFunction = null; - return this; - } - - @Override - protected SpongeDensityFunctionTemplate build0() { - Objects.requireNonNull(this.densityFunction, "densityFunction"); - return new SpongeDensityFunctionTemplate(this.key, this.densityFunction, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseBuilder.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseBuilder.java new file mode 100644 index 00000000000..c622ace73e5 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseBuilder.java @@ -0,0 +1,82 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.config.noise; + +import net.minecraft.world.level.levelgen.synth.NormalNoise; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.world.generation.config.noise.Noise; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.DoubleStream; + +public final class SpongeNoiseBuilder implements Noise.Builder { + + @Nullable private Integer octave; + @Nullable private List amplitudes; + + public SpongeNoiseBuilder() { + this.reset(); + } + + @Override + public Noise.Builder from(final Noise noise) { + this.octave(noise.octave()).amplitudes(noise.amplitudes()); + return this; + } + + @Override + public Noise.Builder octave(final int octave) { + this.octave = octave; + return this; + } + + @Override + public Noise.Builder amplitudes(final double... amplitudes) { + this.amplitudes = DoubleStream.of(amplitudes).boxed().toList(); + return this; + } + + @Override + public Noise.Builder amplitudes(final List amplitudes) { + this.amplitudes = amplitudes; + return this; + } + + @Override + public Noise.Builder reset() { + this.octave = null; + this.amplitudes = null; + return this; + } + + @Override + public Noise build() { + Objects.requireNonNull(this.octave, "octave"); + Objects.requireNonNull(this.amplitudes, "amplitudes"); + return (Noise) (Object) new NormalNoise.NoiseParameters(this.octave, new ArrayList<>(this.amplitudes)); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigBuilder.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigBuilder.java new file mode 100644 index 00000000000..9d209c1707e --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigBuilder.java @@ -0,0 +1,169 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.config.noise; + +import net.minecraft.world.level.biome.OverworldBiomeBuilder; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.world.biome.BiomeAttributes; +import org.spongepowered.api.world.generation.config.SurfaceRule; +import org.spongepowered.api.world.generation.config.noise.NoiseConfig; +import org.spongepowered.api.world.generation.config.noise.NoiseConfigs; +import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; +import org.spongepowered.api.world.generation.config.noise.NoiseRouter; + +import java.util.List; +import java.util.Objects; + +public final class SpongeNoiseGeneratorConfigBuilder implements NoiseGeneratorConfig.Builder { + + public NoiseConfig noiseConfig; + public BlockState defaultBlock, defaultFluid; + public int seaLevel; + public boolean aquifers, oreVeins, legacyRandomSource, disableMobGeneration; + public SurfaceRule surfaceRule; + private NoiseRouter router; + private List spawnTargets; + + public SpongeNoiseGeneratorConfigBuilder() { + this.reset(); + } + + @Override + public NoiseGeneratorConfig.Builder noiseConfig(final NoiseConfig config) { + this.noiseConfig = Objects.requireNonNull(config, "config"); + return this; + } + + @Override + public NoiseGeneratorConfig.Builder defaultBlock(final BlockState block) { + this.defaultBlock = Objects.requireNonNull(block, "block"); + return this; + } + + @Override + public NoiseGeneratorConfig.Builder defaultFluid(final BlockState fluid) { + this.defaultFluid = Objects.requireNonNull(fluid, "fluid"); + return this; + } + + @Override + public NoiseGeneratorConfig.Builder surfaceRule(SurfaceRule rule) { + this.surfaceRule = rule; + return this; + } + + + @Override + public NoiseGeneratorConfig.Builder seaLevel(final int y) { + this.seaLevel = y; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder mobGeneration(boolean mobGeneration) { + this.disableMobGeneration = !mobGeneration; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder aquifers(final boolean enableAquifers) { + this.aquifers = enableAquifers; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder oreVeins(final boolean enableOreVeins) { + this.oreVeins = enableOreVeins; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder randomSource(boolean useLegacyRandomSource) { + this.legacyRandomSource = useLegacyRandomSource; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder noiseRouter(final NoiseRouter router) { + this.router = router; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder spawnTargets(final List spawnTargets) { + this.spawnTargets = spawnTargets; + return this; + } + + @Override + public NoiseGeneratorConfig.Builder reset() { + this.noiseConfig = NoiseConfigs.OVERWORLD.get(); + this.defaultBlock = BlockTypes.STONE.get().defaultState(); + this.defaultFluid = BlockTypes.WATER.get().defaultState(); + this.surfaceRule = SurfaceRule.overworld(); + this.seaLevel = 63; + this.aquifers = false; + this.oreVeins = false; + this.legacyRandomSource = false; + this.router = null; + this.spawnTargets = (List) new OverworldBiomeBuilder().spawnTarget(); + return this; + } + + @Override + public NoiseGeneratorConfig.Builder from(final NoiseGeneratorConfig value) { + this.noiseConfig = value.noiseConfig(); + this.defaultBlock = value.defaultBlock(); + this.defaultFluid = value.defaultFluid(); + this.surfaceRule = value.surfaceRule(); + this.seaLevel = value.seaLevel(); + this.aquifers = value.aquifers(); + this.oreVeins = value.oreVeins(); + this.legacyRandomSource = value.legacyRandomSource(); + this.router = value.noiseRouter(); + this.spawnTargets = value.spawnTargets(); + return this; + } + + @Override + public NoiseGeneratorConfig build() { + final NoiseGeneratorSettings settings = new NoiseGeneratorSettings( + (net.minecraft.world.level.levelgen.NoiseSettings) (Object) this.noiseConfig, + (net.minecraft.world.level.block.state.BlockState) this.defaultBlock, + (net.minecraft.world.level.block.state.BlockState) this.defaultFluid, + (net.minecraft.world.level.levelgen.NoiseRouter) (Object) Objects.requireNonNull(this.router, "router"), + (net.minecraft.world.level.levelgen.SurfaceRules.RuleSource) this.surfaceRule, + (List) this.spawnTargets, + this.seaLevel, + this.disableMobGeneration, + this.aquifers, + this.oreVeins, + this.legacyRandomSource + ); + return (NoiseGeneratorConfig) (Object) settings; + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigTemplate.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigTemplate.java deleted file mode 100644 index cb7707232b1..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseGeneratorConfigTemplate.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.config.noise; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.biome.OverworldBiomeBuilder; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockTypes; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.biome.BiomeAttributes; -import org.spongepowered.api.world.generation.config.SurfaceRule; -import org.spongepowered.api.world.generation.config.noise.NoiseConfig; -import org.spongepowered.api.world.generation.config.noise.NoiseConfigs; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigTemplate; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigs; -import org.spongepowered.api.world.generation.config.noise.NoiseRouter; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeNoiseGeneratorConfigTemplate(ResourceKey key, NoiseGeneratorSettings representedSettings, DataPack pack) implements NoiseGeneratorConfigTemplate { - - @Override - public NoiseGeneratorConfig config() { - return (NoiseGeneratorConfig) (Object) this.representedSettings; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeNoiseGeneratorConfigTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized NoiseGeneratorConfig:\n" + serialized, e); - } - } - - public static JsonElement encode(final NoiseGeneratorConfigTemplate template, final RegistryAccess registryAccess) { - return NoiseGeneratorSettings.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, (NoiseGeneratorSettings) (Object) template.config()).getOrThrow(); - } - - public static NoiseGeneratorSettings decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return NoiseGeneratorSettings.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static NoiseGeneratorConfigTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final NoiseGeneratorSettings parsed = SpongeNoiseGeneratorConfigTemplate.decode(packEntry, registryAccess); - return new SpongeNoiseGeneratorConfigTemplate(key, parsed, pack); - } - - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - public NoiseConfig noiseConfig; - public BlockState defaultBlock, defaultFluid; - public int seaLevel; - public boolean aquifers, oreVeins, legacyRandomSource, disableMobGeneration; - public SurfaceRule surfaceRule; - private NoiseRouter router; - private List spawnTargets; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return NoiseGeneratorConfigTemplate::config; - } - - @Override - public Builder noiseConfig(final NoiseConfig config) { - this.noiseConfig = Objects.requireNonNull(config, "config"); - return this; - } - - @Override - public Builder defaultBlock(final BlockState block) { - this.defaultBlock = Objects.requireNonNull(block, "block"); - return this; - } - - @Override - public Builder defaultFluid(final BlockState fluid) { - this.defaultFluid = Objects.requireNonNull(fluid, "fluid"); - return this; - } - - @Override - public Builder surfaceRule(SurfaceRule rule) { - this.surfaceRule = rule; - return this; - } - - - @Override - public Builder seaLevel(final int y) { - this.seaLevel = y; - return this; - } - - @Override - public Builder mobGeneration(boolean mobGeneration) { - this.disableMobGeneration = !mobGeneration; - return this; - } - - @Override - public Builder aquifers(final boolean enableAquifers) { - this.aquifers = enableAquifers; - return this; - } - - @Override - public Builder oreVeins(final boolean enableOreVeins) { - this.oreVeins = enableOreVeins; - return this; - } - - @Override - public Builder randomSource(boolean useLegacyRandomSource) { - this.legacyRandomSource = useLegacyRandomSource; - return this; - } - - @Override - public Builder noiseRouter(final NoiseRouter router) { - this.router = router; - return this; - } - - @Override - public Builder spawnTargets(final List spawnTargets) { - this.spawnTargets = spawnTargets; - return this; - } - - @Override - public Builder reset() { - this.noiseConfig = NoiseConfigs.OVERWORLD.get(); - this.defaultBlock = BlockTypes.STONE.get().defaultState(); - this.defaultFluid = BlockTypes.WATER.get().defaultState(); - this.surfaceRule = SurfaceRule.overworld(); - this.seaLevel = 63; - this.aquifers = false; - this.oreVeins = false; - this.legacyRandomSource = false; - this.router = NoiseGeneratorConfigs.OVERWORLD.get().noiseRouter(); - this.spawnTargets = (List) new OverworldBiomeBuilder().spawnTarget();; - this.pack = DataPacks.NOISE_GENERATOR_CONFIG; - this.key = null; - return this; - } - - @Override - public Builder fromValue(final NoiseGeneratorConfig value) { - this.noiseConfig = value.noiseConfig(); - this.defaultBlock = value.defaultBlock(); - this.defaultFluid = value.defaultFluid(); - this.surfaceRule = value.surfaceRule(); - this.seaLevel = value.seaLevel(); - this.aquifers = value.aquifers(); - this.legacyRandomSource = value.legacyRandomSource(); - return this; - } - - @Override - public Builder fromDataPack(final DataView datapack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(datapack)); - final NoiseGeneratorSettings decoded = SpongeNoiseGeneratorConfigTemplate.decode(json, SpongeCommon.server().registryAccess()); - return this.fromValue((NoiseGeneratorConfig) (Object) decoded); - } - - @Override - protected NoiseGeneratorConfigTemplate build0() { - final NoiseGeneratorSettings settings = new NoiseGeneratorSettings( - (net.minecraft.world.level.levelgen.NoiseSettings) (Object) this.noiseConfig, - (net.minecraft.world.level.block.state.BlockState) this.defaultBlock, - (net.minecraft.world.level.block.state.BlockState) this.defaultFluid, - (net.minecraft.world.level.levelgen.NoiseRouter) (Object) this.router, - (net.minecraft.world.level.levelgen.SurfaceRules.RuleSource) this.surfaceRule, - (List) this.spawnTargets, - this.seaLevel, - this.disableMobGeneration, - this.aquifers, - this.oreVeins, - this.legacyRandomSource - ); - return new SpongeNoiseGeneratorConfigTemplate(this.key, settings, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseTemplate.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseTemplate.java deleted file mode 100644 index 57e4ab827cd..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeNoiseTemplate.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.config.noise; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.synth.NormalNoise; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.config.noise.Noise; -import org.spongepowered.api.world.generation.config.noise.NoiseTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.DoubleStream; - -public record SpongeNoiseTemplate(ResourceKey key, NormalNoise.NoiseParameters noiseParameters, DataPack pack) implements NoiseTemplate { - - @Override - public Noise noise() { - return (Noise) (Object) this.noiseParameters; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeNoiseTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Noise:\n" + serialized, e); - } - } - - public static JsonElement encode(final NoiseTemplate template, final RegistryAccess registryAccess) { - return NormalNoise.NoiseParameters.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, (NormalNoise.NoiseParameters) (Object) template.noise()).getOrThrow(); - } - - public static NormalNoise.NoiseParameters decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return NormalNoise.NoiseParameters.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeNoiseTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final NormalNoise.NoiseParameters parsed = SpongeNoiseTemplate.decode(packEntry, registryAccess); - return new SpongeNoiseTemplate(key, parsed, pack); - } - - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private Integer octave; - @Nullable private List amplitudes; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Builder fromValue(final Noise noise) { - this.octave(noise.octave()).amplitudes(noise.amplitudes()); - return this; - } - - @Override - public Builder octave(final int octave) { - this.octave = octave; - return this; - } - - @Override - public Builder amplitudes(final double... amplitudes) { - this.amplitudes = DoubleStream.of(amplitudes).boxed().toList(); - return this; - } - - @Override - public Builder amplitudes(final List amplitudes) { - this.amplitudes = amplitudes; - return this; - } - - @Override - public Builder reset() { - this.octave = null; - this.amplitudes = null; - this.pack = DataPacks.NOISE; - this.key = null; - return this; - } - - @Override - public Builder fromDataPack(final DataView datapack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(datapack)); - return this.fromValue((Noise) (Object) SpongeNoiseTemplate.decode(json, SpongeCommon.server().registryAccess())); - } - - @Override - public Function valueExtractor() { - return NoiseTemplate::noise; - } - - @Override - protected SpongeNoiseTemplate build0() { - Objects.requireNonNull(this.octave, "octave"); - Objects.requireNonNull(this.amplitudes, "amplitudes"); - final NormalNoise.NoiseParameters params = new NormalNoise.NoiseParameters(this.octave, new ArrayList<>(this.amplitudes)); - return new SpongeNoiseTemplate(this.key, params, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureBuilder.java b/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureBuilder.java new file mode 100644 index 00000000000..316ffd292a8 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureBuilder.java @@ -0,0 +1,69 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.feature; + +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; +import org.spongepowered.api.world.generation.feature.Feature; +import org.spongepowered.api.world.generation.feature.FeatureType; + +import java.util.Objects; + +public final class SpongeFeatureBuilder implements Feature.Builder { + + private net.minecraft.world.level.levelgen.feature.Feature type; + private FeatureConfiguration config; + + public SpongeFeatureBuilder() { + this.reset(); + } + + @Override + public Feature.Builder type(final FeatureType type) { + this.type = (net.minecraft.world.level.levelgen.feature.Feature) type; + return this; + } + + @Override + public Feature.Builder reset() { + this.type = null; + this.config = null; + return this; + } + + @Override + public Feature.Builder from(final org.spongepowered.api.world.generation.feature.Feature feature) { + this.type(feature.type()); + this.config = ((ConfiguredFeature) (Object) feature).config(); + return this; + } + + @Override + public Feature build() { + Objects.requireNonNull(this.type, "config"); + Objects.requireNonNull(this.config, "config"); + return (Feature) (Object) new ConfiguredFeature<>((net.minecraft.world.level.levelgen.feature.Feature) this.type, this.config); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureTemplate.java b/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureTemplate.java deleted file mode 100644 index 514c33a6f2b..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/feature/SpongeFeatureTemplate.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.feature; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.feature.Feature; -import org.spongepowered.api.world.generation.feature.FeatureTemplate; -import org.spongepowered.api.world.generation.feature.FeatureType; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeFeatureTemplate(ResourceKey key, ConfiguredFeature representedFeature, DataPack pack) implements FeatureTemplate { - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeFeatureTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Feature:\n" + serialized, e); - } - } - - @Override - public org.spongepowered.api.world.generation.feature.Feature feature() { - return (org.spongepowered.api.world.generation.feature.Feature) (Object) this.representedFeature; - } - - public static JsonElement encode(final FeatureTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return ConfiguredFeature.DIRECT_CODEC.encodeStart(ops, (ConfiguredFeature) (Object) template.feature()).getOrThrow(); - } - - public static ConfiguredFeature decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return ConfiguredFeature.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeFeatureTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final ConfiguredFeature parsed = SpongeFeatureTemplate.decode(packEntry, registryAccess); - return new SpongeFeatureTemplate(key, parsed, pack); - } - - public static class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - private net.minecraft.world.level.levelgen.feature.Feature type; - private FeatureConfiguration config; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return FeatureTemplate::feature; - } - - @Override - public Builder type(final FeatureType type) { - this.type = (net.minecraft.world.level.levelgen.feature.Feature) type; - return this; - } - - @Override - public Builder reset() { - this.key = null; - this.type = null; - this.config = null; - this.pack = DataPacks.FEATURE; - return this; - } - - @Override - public Builder fromValue(final org.spongepowered.api.world.generation.feature.Feature feature) { - this.type(feature.type()); - this.config = ((ConfiguredFeature) (Object) feature).config(); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final ConfiguredFeature feature = SpongeFeatureTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((Feature) (Object) feature); - return this; - } - - @Override - protected FeatureTemplate build0() { - Objects.requireNonNull(this.type, "config"); - Objects.requireNonNull(this.config, "config"); - final ConfiguredFeature feature = new ConfiguredFeature<>((net.minecraft.world.level.levelgen.feature.Feature) this.type, this.config); - return new SpongeFeatureTemplate(this.key, feature, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureBuilder.java b/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureBuilder.java new file mode 100644 index 00000000000..e5d6861a7cd --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureBuilder.java @@ -0,0 +1,76 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.feature; + +import net.minecraft.core.Holder; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.placement.PlacementModifier; +import org.spongepowered.api.world.generation.feature.Feature; +import org.spongepowered.api.world.generation.feature.PlacedFeature; + +import java.util.ArrayList; +import java.util.List; + +public final class SpongePlacedFeatureBuilder implements PlacedFeature.Builder { + + private Holder> feature; + private List modifiers = new ArrayList<>(); + + public SpongePlacedFeatureBuilder() { + this.reset(); + } + + @Override + public PlacedFeature.Builder reset() { + this.feature = null; + this.modifiers.clear(); + return this; + } + + @Override + public PlacedFeature.Builder from(final PlacedFeature feature) { + this.feature(feature.feature()); + this.modifiers.clear(); + this.modifiers.addAll((List) feature.placementModifiers()); + return this; + } + + @Override + public PlacedFeature.Builder feature(final Feature feature) { + this.feature = Holder.direct((ConfiguredFeature) (Object) feature); + return this; + } + + @Override + public PlacedFeature.Builder addModifier(final org.spongepowered.api.world.generation.feature.PlacementModifier modifier) { + this.modifiers.add((net.minecraft.world.level.levelgen.placement.PlacementModifier) modifier); + return this; + } + + @Override + public PlacedFeature build() { + return (PlacedFeature) (Object) new net.minecraft.world.level.levelgen.placement.PlacedFeature(this.feature, this.modifiers); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java b/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java deleted file mode 100644 index 77a0b06ab0c..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/feature/SpongePlacedFeatureTemplate.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.feature; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.persistence.Queries; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.feature.Feature; -import org.spongepowered.api.world.generation.feature.FeatureTemplate; -import org.spongepowered.api.world.generation.feature.PlacedFeature; -import org.spongepowered.api.world.generation.feature.PlacedFeatureTemplate; -import org.spongepowered.api.world.generation.feature.PlacementModifier; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public record SpongePlacedFeatureTemplate(ResourceKey key, net.minecraft.world.level.levelgen.placement.PlacedFeature represented, DataPack pack) implements PlacedFeatureTemplate { - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongePlacedFeatureTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - final DataContainer container = DataFormats.JSON.get().read(serialized.toString()); - container.set(Queries.CONTENT_VERSION, this.contentVersion()); - return container; - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Placed Feature:\n" + serialized, e); - } - } - - @Override - public PlacedFeature feature() { - return (PlacedFeature) (Object) this.represented; - } - - public static JsonElement encode(final PlacedFeatureTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return net.minecraft.world.level.levelgen.placement.PlacedFeature.DIRECT_CODEC.encodeStart(ops, (net.minecraft.world.level.levelgen.placement.PlacedFeature) (Object) template.feature()).getOrThrow(); - } - - public static net.minecraft.world.level.levelgen.placement.PlacedFeature decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return net.minecraft.world.level.levelgen.placement.PlacedFeature.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static PlacedFeatureTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final net.minecraft.world.level.levelgen.placement.PlacedFeature parsed = SpongePlacedFeatureTemplate.decode(packEntry, registryAccess); - return new SpongePlacedFeatureTemplate(key, parsed, pack); - } - - public static class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - private Holder> feature; - private List modifiers = new ArrayList<>(); - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return PlacedFeatureTemplate::feature; - } - - @Override - public Builder reset() { - this.key = null; - this.feature = null; - this.modifiers.clear(); - this.pack = DataPacks.PLACED_FEATURE; - return this; - } - - @Override - public Builder fromValue(final PlacedFeature feature) { - this.feature(feature.feature()); - this.modifiers.clear(); - this.modifiers.addAll((List) feature.placementModifiers()); - return this; - } - - @Override - public Builder feature(final Feature feature) { - final Registry> registry = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE); - final ResourceLocation key = registry.getKey((ConfiguredFeature) (Object) feature); - if (key == null) { - this.feature = Holder.direct((ConfiguredFeature) (Object) feature); - } else { - this.feature = registry.getOrThrow(net.minecraft.resources.ResourceKey.create(Registries.CONFIGURED_FEATURE, key)); - } - return this; - } - - @Override - public Builder feature(final FeatureTemplate feature) { - final Registry> registry = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE); - final net.minecraft.resources.ResourceKey> key = - net.minecraft.resources.ResourceKey.create(Registries.CONFIGURED_FEATURE, ((ResourceLocation) (Object) feature.key())); - this.feature = Holder.Reference.createStandAlone(registry, key); - return this; - } - - @Override - public Builder addModifier(final PlacementModifier modifier) { - this.modifiers.add((net.minecraft.world.level.levelgen.placement.PlacementModifier) modifier); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final net.minecraft.world.level.levelgen.placement.PlacedFeature feature = SpongePlacedFeatureTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((PlacedFeature) (Object) feature); - return this; - } - - @Override - protected PlacedFeatureTemplate build0() { - var feature = new net.minecraft.world.level.levelgen.placement.PlacedFeature(this.feature, this.modifiers); - return new SpongePlacedFeatureTemplate(this.key, feature, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeSchematicTemplate.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeSchematicTemplate.java deleted file mode 100644 index 924ef197561..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeSchematicTemplate.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.structure; - -import net.minecraft.core.RegistryAccess; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.structure.SchematicTemplate; -import org.spongepowered.api.world.schematic.Schematic; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.data.persistence.NBTTranslator; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; - -import java.util.Objects; - -public record SpongeSchematicTemplate(ResourceKey key, StructureTemplate nbtStructure, DataPack pack) implements SchematicTemplate { - - @Override - public Schematic schematic() { - return (Schematic) this.nbtStructure; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final CompoundTag serialized = SpongeSchematicTemplate.encode(this, SpongeCommon.server().registryAccess()); - return NBTTranslator.INSTANCE.translateFrom(serialized); - } - - public static CompoundTag encode(final SchematicTemplate template, final RegistryAccess registryAccess) { - return ((SpongeSchematicTemplate) template).nbtStructure.save(new CompoundTag()); - } - - public static StructureTemplate decode(final CompoundTag nbt, final RegistryAccess registryAccess) { - return SpongeCommon.server().getStructureManager().readStructure(nbt); - } - - public static SpongeSchematicTemplate decode(final DataPack pack, final ResourceKey key, final CompoundTag packEntry, final RegistryAccess registryAccess) { - final StructureTemplate parsed = SpongeSchematicTemplate.decode(packEntry, registryAccess); - return new SpongeSchematicTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractResourceKeyedBuilder implements Builder { - - private DataPack pack = DataPacks.SCHEMATIC; - @Nullable private StructureTemplate nbtStructure; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Builder from(final SchematicTemplate value) { - this.nbtStructure = ((SpongeSchematicTemplate) value).nbtStructure; - return this; - } - - @Override - public Builder reset() { - this.pack = DataPacks.SCHEMATIC; - this.nbtStructure = null; - return this; - } - - @Override - public Builder pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - protected SpongeSchematicTemplate build0() { - Objects.requireNonNull(this.nbtStructure, "structure"); - return new SpongeSchematicTemplate(this.key, this.nbtStructure, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetBuilder.java new file mode 100644 index 00000000000..8991ae7add7 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetBuilder.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.structure; + +import net.minecraft.core.Holder; +import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.world.generation.structure.Structure; +import org.spongepowered.api.world.generation.structure.StructureSet; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public final class SpongeStructureSetBuilder implements StructureSet.Builder { + + @Nullable + private StructurePlacement placement; + private List structureSelectionEntries = new ArrayList<>(); + + public SpongeStructureSetBuilder() { + this.reset(); + } + + @Override + public StructureSet.Builder from(final org.spongepowered.api.world.generation.structure.StructureSet structureSet) { + var mcSet = (net.minecraft.world.level.levelgen.structure.StructureSet) (Object) structureSet; + this.structureSelectionEntries = mcSet.structures(); + this.placement = mcSet.placement(); + return this; + } + + @Override + public StructureSet.Builder placement(final org.spongepowered.api.world.generation.structure.StructurePlacement placement) { + this.placement = (StructurePlacement) placement; + return this; + } + + @Override + public StructureSet.Builder add(final Structure structure, final int weight) { + final var mcStructure = (net.minecraft.world.level.levelgen.structure.Structure) structure; + this.structureSelectionEntries.add(new net.minecraft.world.level.levelgen.structure.StructureSet.StructureSelectionEntry(Holder.direct(mcStructure), weight)); + return this; + } + + @Override + public StructureSet.Builder reset() { + this.placement = null; + this.structureSelectionEntries = new ArrayList<>(); + return this; + } + + @Override + public StructureSet build() { + Objects.requireNonNull(this.placement, "placement"); + return (StructureSet) (Object) new net.minecraft.world.level.levelgen.structure.StructureSet(this.structureSelectionEntries, this.placement); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetTemplate.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetTemplate.java deleted file mode 100644 index e2b13b26b98..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureSetTemplate.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.structure; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.structure.StructureSet; -import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.structure.Structure; -import org.spongepowered.api.world.generation.structure.StructureSetTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeStructureSetTemplate(ResourceKey key, StructureSet representedStructureSet, DataPack pack) implements StructureSetTemplate { - - @Override - public org.spongepowered.api.world.generation.structure.StructureSet structureSet() { - return (org.spongepowered.api.world.generation.structure.StructureSet) (Object) this.representedStructureSet; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeStructureSetTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Structure:\n" + serialized, e); - } - } - - public static JsonElement encode(final StructureSetTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureSet.DIRECT_CODEC.encodeStart(ops, (StructureSet) (Object) template.structureSet()).getOrThrow(); - } - - public static StructureSet decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureSet.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeStructureSetTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final StructureSet parsed = SpongeStructureSetTemplate.decode(packEntry, registryAccess); - return new SpongeStructureSetTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private StructurePlacement placement; - private List structureSelectionEntries = new ArrayList<>(); - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return StructureSetTemplate::structureSet; - } - - @Override - public Builder fromValue(final org.spongepowered.api.world.generation.structure.StructureSet structureSet) { - var mcSet = (StructureSet) (Object) structureSet; - this.structureSelectionEntries = mcSet.structures(); - this.placement = mcSet.placement(); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final StructureSet decoded = SpongeStructureSetTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.structureSelectionEntries = decoded.structures(); - this.placement = decoded.placement(); - return this; - } - - @Override - public Builder placement(final org.spongepowered.api.world.generation.structure.StructurePlacement placement) { - this.placement = (StructurePlacement) placement; - return this; - } - - @Override - public Builder add(final Structure structure, final int weight) { - final Registry registry = SpongeCommon.vanillaRegistry(Registries.STRUCTURE); - final var mcStructure = (net.minecraft.world.level.levelgen.structure.Structure) structure; - Holder holder; - try { - holder = registry.createIntrusiveHolder(mcStructure); - } catch (Exception e) { - holder = Holder.direct(mcStructure); - } - this.structureSelectionEntries.add(new StructureSet.StructureSelectionEntry(holder, weight)); - return this; - } - - @Override - public Builder reset() { - super.reset(); - this.pack = DataPacks.STRUCTURE_SET; - this.placement = null; - this.structureSelectionEntries = new ArrayList<>(); - return this; - } - - @Override - protected SpongeStructureSetTemplate build0() { - Objects.requireNonNull(this.placement, "placement"); - return new SpongeStructureSetTemplate(this.key, new StructureSet(this.structureSelectionEntries, this.placement), this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureTemplate.java b/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureTemplate.java deleted file mode 100644 index 61894fca865..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/structure/SpongeStructureTemplate.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.structure; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.structure.Structure; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.structure.StructureTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeStructureTemplate(ResourceKey key, Structure representedStructure, DataPack pack) implements StructureTemplate { - - @Override - public org.spongepowered.api.world.generation.structure.Structure structure() { - return (org.spongepowered.api.world.generation.structure.Structure) this.representedStructure; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeStructureTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Structure:\n" + serialized, e); - } - } - - public static JsonElement encode(final StructureTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return Structure.DIRECT_CODEC.encodeStart(ops, (Structure) template.structure()).getOrThrow(); - } - - public static net.minecraft.world.level.levelgen.structure.Structure decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return Structure.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeStructureTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final Structure parsed = SpongeStructureTemplate.decode(packEntry, registryAccess); - return new SpongeStructureTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private Structure structure; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return StructureTemplate::structure; - } - - @Override - public Builder fromValue(final org.spongepowered.api.world.generation.structure.Structure structure) { - this.structure = (Structure) structure; - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - this.structure = SpongeStructureTemplate.decode(json, SpongeCommon.server().registryAccess()); - return this; - } - - @Override - public Builder reset() { - this.key = null; - this.pack = DataPacks.STRUCTURE; - this.structure = null; - return this; - } - - @Override - protected SpongeStructureTemplate build0() { - Objects.requireNonNull(this.structure, "Structure"); - return new SpongeStructureTemplate(this.key, this.structure, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java new file mode 100644 index 00000000000..a94ab0b917c --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java @@ -0,0 +1,94 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.generation.structure.jigsaw; + +import com.mojang.datafixers.util.Pair; +import net.minecraft.core.Holder; +import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement; +import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.registry.RegistryReference; +import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPool; +import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolElement; +import org.spongepowered.common.accessor.world.level.levelgen.structure.pools.StructureTemplatePoolAccessor; + +import java.util.ArrayList; +import java.util.List; + +public final class SpongeJigsawPoolBuilder implements JigsawPool.Builder { + + private Holder fallback; + private List> templates; + + public SpongeJigsawPoolBuilder() { + this.reset(); + } + + @Override + public JigsawPool.Builder from(final JigsawPool StructureTemplatePool) { + var mcPool = (StructureTemplatePool) StructureTemplatePool; + this.fallback = mcPool.getFallback(); + this.templates = new ArrayList<>(((StructureTemplatePoolAccessor) mcPool).accessor$rawTemplates()); + return this; + } + + @Override + public JigsawPool.Builder add(final JigsawPoolElement element, final int weight) { + this.templates.add(Pair.of((StructurePoolElement) element, weight)); + return this; + } + + @Override + public JigsawPool.Builder name(final ResourceKey name) { +// TODO this.name = (ResourceLocation) (Object) name; + return this; + } + + @Override + public JigsawPool.Builder fallback(final RegistryReference fallback) { +// TODO this.fallback = (ResourceLocation) (Object) fallback.location(); + return this; + } + + @Override + public JigsawPool.Builder fallback(final JigsawPool fallback) { +// TODO this.fallback = (ResourceLocation) (Object) fallback.key(); + return this; + } + + @Override + public JigsawPool.Builder reset() { + // TODO this.name = null; + // TODO this.fallback = new ResourceLocation("empty"); + this.templates = new ArrayList<>(); + return this; + } + + @Override + public JigsawPool build() { + // TODO Objects.requireNonNull(this.name, "name"); + return (JigsawPool) new StructureTemplatePool(this.fallback, this.templates); + } +} diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolTemplate.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolTemplate.java deleted file mode 100644 index a6011f2a6cd..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolTemplate.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.structure.jigsaw; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement; -import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.registry.RegistryReference; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPool; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolElement; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.world.level.levelgen.structure.pools.StructureTemplatePoolAccessor; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public record SpongeJigsawPoolTemplate(ResourceKey key, StructureTemplatePool representedJigsawPool, DataPack pack) implements JigsawPoolTemplate { - - @Override - public JigsawPool jigsawPool() { - return (JigsawPool) this.representedJigsawPool; - } - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeJigsawPoolTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Structure:\n" + serialized, e); - } - } - - public static JsonElement encode(final JigsawPoolTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureTemplatePool.DIRECT_CODEC.encodeStart(ops, (StructureTemplatePool) template.jigsawPool()).getOrThrow(); - } - - public static StructureTemplatePool decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureTemplatePool.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeJigsawPoolTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final StructureTemplatePool parsed = SpongeJigsawPoolTemplate.decode(packEntry, registryAccess); - return new SpongeJigsawPoolTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - private Holder fallback; - private List> templates; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return JigsawPoolTemplate::jigsawPool; - } - - @Override - public Builder fromValue(final JigsawPool StructureTemplatePool) { - var mcPool = (StructureTemplatePool) StructureTemplatePool; - this.fallback = mcPool.getFallback(); - this.templates = new ArrayList<>(((StructureTemplatePoolAccessor) mcPool).accessor$rawTemplates()); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final StructureTemplatePool decoded = SpongeJigsawPoolTemplate.decode(json, SpongeCommon.server().registryAccess()); - return this.fromValue((JigsawPool) decoded); - } - - @Override - public Builder add(final JigsawPoolElement element, final int weight) { - this.templates.add(Pair.of((StructurePoolElement) element, weight)); - return this; - } - - @Override - public Builder name(final ResourceKey name) { -// TODO this.name = (ResourceLocation) (Object) name; - return this; - } - - @Override - public Builder fallback(final RegistryReference fallback) { -// TODO this.fallback = (ResourceLocation) (Object) fallback.location(); - return this; - } - - @Override - public Builder fallback(final JigsawPoolTemplate fallback) { -// TODO this.fallback = (ResourceLocation) (Object) fallback.key(); - return this; - } - - @Override - public Builder reset() { - super.reset(); - this.pack = DataPacks.JIGSAW_POOL; - // TODO this.name = null; - // TODO this.fallback = new ResourceLocation("empty"); - this.templates = new ArrayList<>(); - return this; - } - - @Override - protected SpongeJigsawPoolTemplate build0() { - // TODO Objects.requireNonNull(this.name, "name"); - return new SpongeJigsawPoolTemplate(this.key, new StructureTemplatePool(this.fallback, this.templates), this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterDataPackValueEventImpl.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListBuilder.java similarity index 53% rename from src/main/java/org/spongepowered/common/event/lifecycle/RegisterDataPackValueEventImpl.java rename to src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListBuilder.java index 467c20abb3e..0afee0aebd5 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterDataPackValueEventImpl.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListBuilder.java @@ -22,43 +22,45 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.event.lifecycle; +package org.spongepowered.common.world.generation.structure.jigsaw; -import com.google.gson.JsonElement; -import org.spongepowered.api.Game; -import org.spongepowered.api.datapack.DataPackEntry; -import org.spongepowered.api.datapack.DataPackType; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; -import org.spongepowered.common.datapack.SpongeDataPackType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.world.generation.structure.jigsaw.Processor; +import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; -import java.util.ArrayList; import java.util.List; import java.util.Objects; -public final class RegisterDataPackValueEventImpl> extends AbstractLifecycleEvent.GenericImpl implements RegisterDataPackValueEvent { +public final class SpongeProcessorListBuilder implements ProcessorList.Builder { - private final DataPackType type; - private final List serializables; + @Nullable private StructureProcessorList processorList; - public RegisterDataPackValueEventImpl(final Cause cause, final Game game, final SpongeDataPackType type) { - super(cause, game, type.entryType()); - this.type = type; - this.serializables = new ArrayList<>(); + public SpongeProcessorListBuilder() { + this.reset(); } @Override - public DataPackType type() { - return this.type; + public ProcessorList.Builder fromValues(final List processorList) { + this.processorList = new StructureProcessorList((List) processorList); + return this; + } + + @Override + public ProcessorList.Builder from(final ProcessorList processorList) { + this.processorList = new StructureProcessorList((List) processorList.processors()); + return this; } @Override - public RegisterDataPackValueEvent register(final T serializable) { - this.serializables.add(Objects.requireNonNull(serializable, "serializable")); + public ProcessorList.Builder reset() { + this.processorList = null; return this; } - public List serializables() { - return this.serializables; + @Override + public ProcessorList build() { + Objects.requireNonNull(this.processorList, "processorList"); + return (ProcessorList) this.processorList; } } diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListTemplate.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListTemplate.java deleted file mode 100644 index 03abb6d758c..00000000000 --- a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorListTemplate.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.generation.structure.jigsaw; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.world.generation.structure.jigsaw.Processor; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorListTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -public record SpongeProcessorListTemplate(ResourceKey key, StructureProcessorList representedProcessors, DataPack pack) implements ProcessorListTemplate { - - @Override - public ProcessorList processorList() { - return (ProcessorList) this.representedProcessors; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeProcessorListTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized ProcessorList:\n" + serialized, e); - } - } - - public static JsonElement encode(final ProcessorListTemplate template, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureProcessorType.LIST_OBJECT_CODEC.encodeStart(ops, ((StructureProcessorList) template.processorList())).getOrThrow(); - } - - public static StructureProcessorList decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return StructureProcessorType.LIST_OBJECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static SpongeProcessorListTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement json, final RegistryAccess registryAccess) { - final StructureProcessorList parsed = SpongeProcessorListTemplate.decode(json, registryAccess); - return new SpongeProcessorListTemplate(key, parsed, pack); - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements Builder { - - @Nullable private StructureProcessorList processorList; - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return value -> (ProcessorList) ((SpongeProcessorListTemplate) value).representedProcessors; - } - - @Override - public Builder fromValues(final List processorList) { - this.processorList = new StructureProcessorList((List) processorList); - return this; - } - - @Override - public Builder fromValue(final ProcessorList processorList) { - this.processorList = (StructureProcessorList) processorList; - return this; - } - - @Override - public Builder reset() { - this.pack = DataPacks.PROCESSOR_LIST; - this.key = null; - this.processorList = null; - return this; - } - - @Override - public Builder fromDataPack(final DataView datapack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(datapack)); - final StructureProcessorList decoded = SpongeProcessorListTemplate.decode(json, SpongeCommon.server().registryAccess()); - this.fromValue((ProcessorList) decoded); - return this; - } - - @Override - protected SpongeProcessorListTemplate build0() { - Objects.requireNonNull(this.processorList, "processorList"); - return new SpongeProcessorListTemplate(this.key, this.processorList, this.pack); - } - } -} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java new file mode 100644 index 00000000000..608cf6d9629 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java @@ -0,0 +1,139 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.api.world.server.storage.ServerWorldProperties; + +import java.util.Optional; +import java.util.function.Consumer; + +public record SpongeServerWorldPropertiesLoadOptions( + @Nullable GetOperation getOperationValue, + @Nullable LoadOperation loadOperationValue, + @Nullable CreateOperation createOperationValue) implements ServerWorldProperties.LoadOptions { + + @Override + public Optional getOperation() { + return Optional.ofNullable(this.getOperationValue); + } + + @Override + public Optional loadOperation() { + return Optional.ofNullable(this.loadOperationValue); + } + + @Override + public Optional createOperation() { + return Optional.ofNullable(this.createOperationValue); + } + + public record GetOperationImpl(@Nullable Consumer callback) implements GetOperation { + + @Override + public Optional> getCallback() { + return Optional.ofNullable(this.callback); + } + } + + public record LoadOperationImpl(@Nullable Consumer callback) implements LoadOperation { + + @Override + public Optional> loadCallback() { + return Optional.ofNullable(this.callback); + } + } + + public record CreateOperationImpl(WorldArchetypeType worldArchetype, @Nullable Consumer callback) implements CreateOperation { + + @Override + public WorldArchetypeType worldArchetype() { + return this.worldArchetype; + } + + @Override + public Optional> createCallback() { + return Optional.ofNullable(this.callback); + } + } + + public static final class BuilderImpl implements ServerWorldProperties.LoadOptions.Builder.GetStep, + ServerWorldProperties.LoadOptions.Builder.LoadStep, ServerWorldProperties.LoadOptions.Builder.CreateStep { + + private @Nullable GetOperation getOperation; + private @Nullable LoadOperation loadOperation; + private @Nullable CreateOperation createOperation; + + @Override + public GetStep get() { + this.getOperation = new GetOperationImpl(null); + return this; + } + + @Override + public LoadStep load() { + this.loadOperation = new LoadOperationImpl(null); + return this; + } + + @Override + public CreateStep create(final WorldArchetypeType worldArchetype) { + this.createOperation = new CreateOperationImpl(worldArchetype, null); + return this; + } + + @Override + public GetStep getCallback(final Consumer getCallback) { + this.getOperation = new GetOperationImpl(getCallback); + return this; + } + + @Override + public LoadStep loadCallback(final Consumer loadCallback) { + this.loadOperation = new LoadOperationImpl(loadCallback); + return this; + } + + @Override + public CreateStep createCallback(final Consumer initializeCallback) { + this.createOperation = new CreateOperationImpl(this.createOperation.worldArchetype(), initializeCallback); + return this; + } + + @Override + public Builder reset() { + this.getOperation = null; + this.loadOperation = null; + this.createOperation = null; + return this; + } + + @Override + public ServerWorldProperties.LoadOptions build() { + return new SpongeServerWorldPropertiesLoadOptions(this.getOperation, this.loadOperation, this.createOperation); + } + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java new file mode 100644 index 00000000000..7146348657a --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java @@ -0,0 +1,66 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import net.minecraft.core.Holder; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.dimension.LevelStem; +import org.spongepowered.api.world.WorldType; +import org.spongepowered.api.world.generation.ChunkGenerator; +import org.spongepowered.api.world.server.WorldArchetypeType; + +public final class SpongeWorldArchetypeType implements WorldArchetypeType.Builder { + + private WorldType worldType; + private ChunkGenerator chunkGenerator; + + public SpongeWorldArchetypeType() { + this.reset(); + } + + @Override + public WorldArchetypeType.Builder worldType(final WorldType worldType) { + this.worldType = worldType; + return this; + } + + @Override + public WorldArchetypeType.Builder chunkGenerator(final ChunkGenerator chunkGenerator) { + this.chunkGenerator = chunkGenerator; + return this; + } + + @Override + public WorldArchetypeType.Builder reset() { + this.worldType = null; + this.chunkGenerator = null; + return this; + } + + @Override + public WorldArchetypeType build() { + return (WorldArchetypeType) (Object) new LevelStem(Holder.direct((DimensionType) (Object) this.worldType), (net.minecraft.world.level.chunk.ChunkGenerator) this.chunkGenerator); + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index ec79096c28b..247262f26b5 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -33,7 +33,6 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.MiscOverworldFeatures; import net.minecraft.resources.ResourceLocation; @@ -45,7 +44,6 @@ import net.minecraft.util.Mth; import net.minecraft.util.TimeUtil; import net.minecraft.util.Unit; -import net.minecraft.world.Difficulty; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; import net.minecraft.world.entity.npc.WanderingTraderSpawner; @@ -53,19 +51,17 @@ import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.ForcedChunksSavedData; import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.WorldDataConfiguration; import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.DebugLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner; -import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.storage.LevelDataAndDimensions; import net.minecraft.world.level.storage.LevelStorageSource; @@ -76,9 +72,6 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackTypes; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.world.LoadWorldEvent; import org.spongepowered.api.event.world.UnloadWorldEvent; @@ -88,7 +81,6 @@ import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.api.world.server.WorldManager; -import org.spongepowered.api.world.server.WorldTemplate; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.MinecraftServerAccessor; @@ -100,6 +92,7 @@ import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; +import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.launch.Launch; @@ -122,13 +115,13 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.OptionalLong; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; public class SpongeWorldManager implements WorldManager { @@ -244,70 +237,77 @@ public Collection worldsOfType(final WorldType type) { } @Override - public CompletableFuture loadWorld(final WorldTemplate template) { - final ResourceKey key = Objects.requireNonNull(template, "template").key(); - final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(key); - if (Level.OVERWORLD.equals(registryKey)) { - return FutureUtil.completedWithException(new IllegalArgumentException("The default world cannot be told to load!")); - } + public CompletableFuture> loadWorld(final ResourceKey key, ServerWorldProperties.LoadOptions propertiesLoadOption) { + final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); - final ServerLevel serverWorld = this.worlds.get(registryKey); - if (serverWorld != null) { - return CompletableFuture.completedFuture((ServerWorld) serverWorld); + final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOption.getOperation().orElse(null); + if (getOperation != null) { + final ServerLevel world = this.worlds.get(registryKey); + if (world != null) { + getOperation.getCallback().ifPresent(c -> c.accept((ServerWorldProperties) world.getLevelData())); + return CompletableFuture.completedFuture(Optional.of((ServerWorld) world)); + } } - this.saveTemplate(template); - - return this.loadWorld0(registryKey, ((SpongeWorldTemplate) template).levelStem()); - } - - @Override - public CompletableFuture loadWorld(final ResourceKey key) { - if (DefaultWorldKeys.DEFAULT.equals(key)) { + if (Level.OVERWORLD.equals(registryKey) && (propertiesLoadOption.loadOperation().isPresent() || propertiesLoadOption.createOperation().isPresent())) { return FutureUtil.completedWithException(new IllegalArgumentException("The default world cannot be told to load!")); } - final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); - final ServerLevel world = this.worlds.get(registryKey); - if (world != null) { - return CompletableFuture.completedFuture((ServerWorld) world); + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOption.loadOperation().orElse(null); + if (loadOperation != null && this.worldExists(key)) { + try { + final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(key); + try { + final Optional result = this.loadLevelData(storageSource, registryKey); + if (result.isPresent()) { + loadOperation.loadCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.get().data())); + return this.loadWorld0(registryKey, result.get(), storageSource); + } else { + storageSource.close(); + } + } catch (final Exception e) { + storageSource.close(); + return CompletableFuture.failedFuture(e); + } + } catch (final IOException e) { + return CompletableFuture.failedFuture(e); + } } - // First find a loaded level-stem / To load based on a datapack load using the WorldTemplate instead - - final net.minecraft.resources.ResourceKey stemKey = net.minecraft.resources.ResourceKey.create(Registries.LEVEL_STEM, (ResourceLocation) (Object) key); - final @Nullable LevelStem levelStem = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).getValue(stemKey); - if (levelStem != null) { - return this.loadWorld0(registryKey, levelStem); + final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOption.createOperation().orElse(null); + if (createOperation != null && !this.worldExists(key)) { + try { + final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(key); + try { + final LevelDataLoadResult result = this.loadLevelData(key, () -> this.createLevelData(registryKey, (LevelStem) (Object) createOperation.worldArchetype())); + createOperation.createCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.data())); + return this.loadWorld0(registryKey, result, storageSource); + } catch (final Exception e) { + storageSource.close(); + return CompletableFuture.failedFuture(e); + } + } catch (final IOException e) { + return CompletableFuture.failedFuture(e); + } } - // Then attempt to load from data pack - final DataPack pack = this.findPack(key); - return this.loadTemplate(pack, key).thenCompose(template -> { - if (template.isEmpty()) { - return FutureUtil.completedWithException(new IOException(String.format("Failed to load a template for '%s'!", key))); - } - return this.loadWorld0(registryKey, ((SpongeWorldTemplate) template.get()).levelStem()); - }); + return CompletableFuture.completedFuture(Optional.empty()); } - private CompletableFuture loadWorld0(final net.minecraft.resources.ResourceKey registryKey, final LevelStem levelStem) { - final ResourceKey worldKey = (ResourceKey) (Object) registryKey.location(); - - MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); - - final ServerLevel level; + private CompletableFuture> loadWorld0(final net.minecraft.resources.ResourceKey registryKey, + final LevelDataLoadResult levelData, final LevelStorageSource.LevelStorageAccess storageSource) { + final ServerLevel world; try { - level = this.createNonDefaultLevel(registryKey, levelStem, worldKey); - } catch (final IOException e) { - return FutureUtil.completedWithException(new RuntimeException(String.format("Failed to create level data for world '%s'!", worldKey), e)); + world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); + } catch (final Exception e) { + return FutureUtil.completedWithException(new RuntimeException(String.format("Failed to create level data for world '%s'!", registryKey.location()), e)); } - return SpongeCommon.asyncScheduler().submit(() -> this.prepareLevel(level)).thenApply(w -> { - ((MinecraftServerAccessor) this.server).invoker$forceDifficulty(); - return w; - }).thenCompose(w -> this.loadSpawnChunksAsync(level)) - .thenApply(w -> (ServerWorld) w); + return SpongeCommon.asyncScheduler().submit(() -> this.prepareLevel(world)).thenApply(w -> { + ((MinecraftServerAccessor) this.server).invoker$forceDifficulty(); + return w; + }).thenCompose(w -> this.loadSpawnChunksAsync(world)) + .thenApply(w -> Optional.of((ServerWorld) w)); } private LevelStorageSource.LevelStorageAccess getLevelStorageAccess(final ResourceKey worldKey) throws IOException { @@ -319,22 +319,6 @@ private LevelStorageSource.LevelStorageAccess getLevelStorageAccess(final Resour return LevelStorageSource.createDefault(this.customWorldsDirectory).createAccess(name); } - private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelData, final LevelStem levelStem, final String directoryName) { - final LevelStemBridge levelStemBridge = (LevelStemBridge) (Object) levelStem; - final GameType gameType = levelStemBridge.bridge$gameMode(); - final Boolean hardcore = levelStemBridge.bridge$hardcore(); - final Difficulty difficulty = levelStemBridge.bridge$difficulty(); - final Boolean allowCommands = levelStemBridge.bridge$allowCommands(); - return new LevelSettings( - directoryName, - gameType == null ? defaultLevelData.getGameType() : gameType, - hardcore == null ? defaultLevelData.isHardcore() : hardcore, - difficulty == null ? defaultLevelData.getDifficulty() : difficulty, - allowCommands == null ? defaultLevelData.isAllowCommands() : allowCommands, - defaultLevelData.getGameRules().copy(defaultLevelData.enabledFeatures()), - defaultLevelData.getDataConfiguration()); - } - @Override public CompletableFuture unloadWorld(final ResourceKey key) { final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); @@ -372,35 +356,42 @@ public CompletableFuture unloadWorld(final ServerWorld world) { } @Override - public CompletableFuture> loadProperties(final ResourceKey key) { + public CompletableFuture> loadProperties(final ResourceKey key, ServerWorldProperties.LoadOptions propertiesLoadOptions) { final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); - if (this.worlds.get(registryKey) != null) { - return CompletableFuture.completedFuture(Optional.empty()); + final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOptions.getOperation().orElse(null); + if (getOperation != null) { + final @Nullable ServerLevel level = this.worlds.get(registryKey); + if (level != null) { + final ServerWorldProperties properties = (ServerWorldProperties) level.getLevelData(); + getOperation.getCallback().ifPresent(c -> c.accept(properties)); + return CompletableFuture.completedFuture(Optional.of(properties)); + } } - if (!this.worldExists(key)) { - return CompletableFuture.completedFuture(Optional.empty()); + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOptions.loadOperation().orElse(null); + if (loadOperation != null && this.worldExists(key)) { + try { + final Optional result = this.loadLevelData(registryKey); + if (result.isPresent()) { + final ServerWorldProperties properties = (ServerWorldProperties) result.get().data(); + loadOperation.loadCallback().ifPresent(c -> c.accept(properties)); + return CompletableFuture.completedFuture(Optional.of(properties)); + } + } catch (final IOException e) { + return FutureUtil.completedWithException(e); + } } - final PrimaryLevelData levelData; - try (var storageSource = this.getLevelStorageAccess(key)) { - final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - levelData = this.loadLevelData(defaultLevelData.getDataConfiguration(), storageSource.getDataTag()); - } catch (final Exception e) { - return FutureUtil.completedWithException(e); + final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOptions.createOperation().orElse(null); + if (createOperation != null && !this.worldExists(key)) { + final ServerWorldProperties properties = (ServerWorldProperties) this.loadLevelData(key, () -> this.createLevelData( + registryKey, (LevelStem) (Object) createOperation.worldArchetype())).data(); + createOperation.createCallback().ifPresent(c -> c.accept(properties)); + return CompletableFuture.completedFuture(Optional.of(properties)); } - final DataPack pack = this.findPack(key); - return this.loadTemplate(pack, key).thenCompose(template -> { - if (template.isPresent()) { - final LevelStem scratch = ((SpongeWorldTemplate) template.get()).levelStem(); - ((PrimaryLevelDataBridge) levelData).bridge$populateFromLevelStem(scratch); - } - - ((PrimaryLevelDataBridge) levelData).bridge$spongeData().setKey(key); - return CompletableFuture.completedFuture(Optional.of((ServerWorldProperties) levelData)); - }); + return CompletableFuture.completedFuture(Optional.empty()); } @Override @@ -421,15 +412,7 @@ public CompletableFuture saveProperties(final ServerWorldProperties pro // TODO else: what about DerivedDataLevel? // Properties doesn't have everything we need...namely the generator, load the template and set values we actually got - final DataPack pack = this.findPack(properties.key()); - return this.loadTemplate(pack, properties.key()).thenCompose(r -> { - final WorldTemplate template = r.orElse(null); - if (template != null) { - return this.saveTemplate(WorldTemplate.builder().from(template).from(properties).build()); - } - - return CompletableFuture.completedFuture(true); - }); + return FutureUtil.completedWithException(new IllegalArgumentException("TODO!")); } @@ -534,12 +517,6 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr throw new CompletionException(e); } }).thenApplyAsync($ -> { - try { - this.server().dataPackManager().copy(this.findPack(key), key, copyKey); - } catch (final IOException e) { - throw new CompletionException(e); - } - return true; }, SpongeCommon.server()); } @@ -590,12 +567,6 @@ public CompletableFuture moveWorld(final ResourceKey key, final Resourc throw new CompletionException(e); } }).thenApplyAsync($ -> { - try { - this.server().dataPackManager().move(this.findPack(key), key, movedKey); - } catch (final IOException e) { - throw new CompletionException(e); - } - return true; }, SpongeCommon.server()); } @@ -642,12 +613,6 @@ public CompletableFuture deleteWorld(final ResourceKey key) { throw new CompletionException(e); } }).thenApplyAsync($ -> { - try { - this.server().dataPackManager().delete(this.findPack(key), key); - } catch (final IOException e) { - throw new CompletionException(e); - } - //After vanilla has detected a new dimension from a data pack it "promotes" it //to the overworld's level data where the level persist even when the data pack is removed. //This forcible removes it from there too. @@ -665,10 +630,6 @@ public CompletableFuture deleteWorld(final ResourceKey key) { }, SpongeCommon.server()); } - private DataPack findPack(ResourceKey key) { - return this.server().dataPackManager().findPack(DataPackTypes.WORLD, key).orElse(DataPacks.WORLD); - } - private void unloadWorld0(final ServerLevel level) throws IOException { final net.minecraft.resources.ResourceKey registryKey = level.dimension(); @@ -705,26 +666,39 @@ private void unloadWorld0(final ServerLevel level) throws IOException { public void createNonDefaultLevels() { final Registry registry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM); - for (LevelStem levelStem : registry) { + for (final LevelStem levelStem : registry) { final ResourceKey worldKey = (ResourceKey) (Object) registry.getKey(levelStem); if (DefaultWorldKeys.DEFAULT.equals(worldKey)) { continue; } - final LevelStemBridge bridge = (LevelStemBridge) (Object) levelStem; - if (!bridge.bridge$loadOnStartup()) { - SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey); + final LevelStemBridge templateBridge = (LevelStemBridge) (Object) levelStem; + if (templateBridge.bridge$hasLegacyData()) { + ((MappedRegistryBridge) registry).bridge$forceRemoveValue(Registries.levelToLevelStem(SpongeWorldManager.createRegistryKey(worldKey))); continue; } - MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(worldKey); try { - final ServerLevel level = this.createNonDefaultLevel(registryKey, levelStem, worldKey); - this.prepareLevel(level); - } catch (final Exception e) { + final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(worldKey); + try { + final LevelDataLoadResult levelData = this.loadLevelData(storageSource, registryKey, () -> this.createLevelData(registryKey, levelStem)); + if (!((PrimaryLevelDataBridge) levelData.data()).bridge$loadOnStartup()) { + SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey); + continue; + } + + final ServerLevel world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); + this.prepareLevel(world); + } catch (final Exception e) { + storageSource.close(); + throw e; + } + } catch (final IOException e) { throw new RuntimeException(String.format("Failed to create level data for world '%s'!", worldKey), e); + } catch (final Exception e) { + throw new IllegalStateException(String.format("Failed to create level data for world '%s'!", worldKey), e); } } } @@ -737,55 +711,94 @@ public void prepareLevels() { ((SpongeUserManager) Sponge.server().userManager()).init(); } - private PrimaryLevelData getOrCreateLevelData(@Nullable final Dynamic dynamicLevelData, final LevelStem levelStem, final String directoryName) { - final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - if (dynamicLevelData != null) { - try { - return this.loadLevelData(defaultLevelData.getDataConfiguration(), dynamicLevelData); - } catch (Exception e) { - throw new RuntimeException("Failed to load level data from " + directoryName, e); - } - } + private LevelDataLoadResult loadLevelData(final ResourceKey key, final Supplier loader) { + return this.loadLevelData(key, loader, Optional::of); + } - if (this.server.isDemo()) { - return new PrimaryLevelData(MinecraftServer.DEMO_SETTINGS, WorldOptions.DEMO_OPTIONS, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()); - } + private T loadLevelData(final ResourceKey key, final Supplier loader, final Function> mapper) { + final T result = loader.get(); + mapper.apply(result).ifPresent(r -> { + final DimensionType dimensionType = r.stem().type().value(); + final ResourceKey worldTypeKey = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getKey(dimensionType); + ((PrimaryLevelDataBridge) r.data()).bridge$spongeData().setKey(key); + ((PrimaryLevelDataBridge) r.data()).bridge$spongeData().setConfigAdapter(SpongeGameConfigs.createWorld(worldTypeKey, key)); + ((PrimaryLevelDataBridge) r.data()).bridge$populateFromLevelStem(r.stem()); + }); + return result; + } - final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, levelStem, directoryName); - WorldOptions worldGenOptions = defaultLevelData.worldGenOptions(); - final Long customSeed = ((LevelStemBridge) (Object) levelStem).bridge$seed(); - if (customSeed != null) { - worldGenOptions = worldGenOptions.withSeed(OptionalLong.of(customSeed)); + private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey) throws IOException { + try (final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess((ResourceKey) (Object) registryKey.location())) { + return this.loadLevelData(storageSource, registryKey); } - return new PrimaryLevelData(levelSettings, worldGenOptions, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()); } - private PrimaryLevelData loadLevelData(final WorldDataConfiguration datapackConfig, final Dynamic dataTag) { - final RegistryAccess.Frozen access = this.server.registryAccess(); - final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions(dataTag, datapackConfig, access.lookupOrThrow(Registries.LEVEL_STEM), access); - return (PrimaryLevelData) levelData.worldData(); + private Optional loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, + final net.minecraft.resources.ResourceKey registryKey) { + return this.loadLevelData((ResourceKey) (Object) registryKey.location(), () -> + Optional.ofNullable(this.loadLevelTag(storageSource)) + .map(t -> this.readLevelData(registryKey, t)), Function.identity()); } - private ServerLevel createNonDefaultLevel(final net.minecraft.resources.ResourceKey registryKey, final LevelStem levelStem, final ResourceKey worldKey) throws IOException { - if (DefaultWorldKeys.DEFAULT.equals(worldKey)) { - throw new IllegalArgumentException(); - } - - final String directoryName = this.getDirectoryName(worldKey); - final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(worldKey); + private LevelDataLoadResult loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, + final net.minecraft.resources.ResourceKey registryKey, final Supplier defaultSupplier) { + return this.loadLevelData((ResourceKey) (Object) registryKey.location(), () -> + Optional.ofNullable(this.loadLevelTag(storageSource)) + .map(t -> this.readLevelData(registryKey, t)) + .orElseGet(defaultSupplier)); + } - @Nullable Dynamic dataTag; + private @Nullable Dynamic loadLevelTag(final LevelStorageSource.LevelStorageAccess storageSource) { try { - dataTag = storageSource.getDataTag(); - } catch (IOException e) { - dataTag = null; + return storageSource.getDataTag(); + } catch (final IOException e) { + try { + final Dynamic dataTag = storageSource.getDataTagFallback(); + storageSource.restoreLevelDataFromOld(); + return dataTag; + } catch (final IOException ex) { + return null; + } } + } - final PrimaryLevelData levelData = this.getOrCreateLevelData(dataTag, levelStem, directoryName); - levelData.setModdedInfo(this.server.getServerModName(), this.server.getModdedStatus().shouldReportAsModified()); + private LevelDataLoadResult readLevelData(final net.minecraft.resources.ResourceKey registryKey, final Dynamic dataTag) { + final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); + final net.minecraft.core. RegistryAccess.Frozen access = this.server.registryAccess(); + final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions( + dataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); + return new LevelDataLoadResult((PrimaryLevelData) levelData.worldData(), levelData.dimensions().dimensions().getValueOrThrow(Registries.levelToLevelStem(registryKey))); + } + + + private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, + final LevelStem levelStem) { + final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); + final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.location())); + return new LevelDataLoadResult( + new PrimaryLevelData(levelSettings, defaultLevelData.worldGenOptions(), SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem); + } + + private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelData, final String directoryName) { + return new LevelSettings( + directoryName, + defaultLevelData.getGameType(), + defaultLevelData.isHardcore(), + defaultLevelData.getDifficulty(), + defaultLevelData.isAllowCommands(), + defaultLevelData.getGameRules().copy(defaultLevelData.enabledFeatures()), + defaultLevelData.getDataConfiguration()); + } + + private ServerLevel createLevel( + final net.minecraft.resources.ResourceKey registryKey, + final LevelStem levelStem, + final LevelStorageSource.LevelStorageAccess storageSource, + final PrimaryLevelData levelData) { + + final ResourceKey worldKey = (ResourceKey) (Object) registryKey.location(); - ((PrimaryLevelDataBridge) levelData).bridge$populateFromLevelStem(levelStem); - ((PrimaryLevelDataBridge) levelData).bridge$spongeData().setKey(worldKey); + MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); final List spawners; if (levelStem.type().is(BuiltinDimensionTypes.OVERWORLD) || levelStem.type().is(BuiltinDimensionTypes.OVERWORLD_CAVES)) { @@ -794,14 +807,20 @@ private ServerLevel createNonDefaultLevel(final net.minecraft.resources.Resource spawners = ImmutableList.of(); } + levelData.setModdedInfo(this.server.getServerModName(), this.server.getModdedStatus().shouldReportAsModified()); + final long seed = BiomeManager.obfuscateSeed(levelData.worldGenOptions().seed()); final Executor executor = ((MinecraftServerAccessor) this.server).accessor$executor(); final ChunkProgressListener progressListener = ((MinecraftServerAccessor) this.server).accessor$progressListenerFactory().create(SpongeWorldManager.getSpawnRadius(levelData)); - final ServerLevel level = new ServerLevel(this.server, executor, storageSource, levelData, registryKey, levelStem, progressListener, levelData.isDebugWorld(), seed, spawners, true, null); - this.worlds.put(registryKey, level); - PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(level); - return level; + final ServerLevel world = new ServerLevel(this.server, executor, storageSource, levelData, + registryKey, levelStem, progressListener, levelData.isDebugWorld(), seed, spawners, true, null); + this.worlds.put(registryKey, world); + + // Ensure that the world border is registered. + world.getWorldBorder().applySettings(levelData.getWorldBorder()); + PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); + return world; } private ServerLevel prepareLevel(final ServerLevel level) { @@ -818,8 +837,6 @@ private ServerLevel prepareLevel(final ServerLevel level) { levelDataBridge.bridge$triggerViewDistanceLogic(); - level.getWorldBorder().applySettings(levelData.getWorldBorder()); - if (!initialized) { if (levelData instanceof WorldData worldData) { try { @@ -943,20 +960,6 @@ private static void updateForcedChunks(final ServerLevel level, final ServerChun } } - private CompletionStage saveTemplate(final WorldTemplate template) { - return this.server().dataPackManager().save(template).thenApply(b -> true); - } - - private CompletableFuture> loadTemplate(final DataPack pack, final ResourceKey key) { - if (this.server().dataPackManager().exists(pack, key)) { - return this.server().dataPackManager().load(pack, key).exceptionally(e -> { - e.printStackTrace(); - return Optional.empty(); - }); - } - return CompletableFuture.completedFuture(Optional.empty()); - } - public static net.minecraft.resources.ResourceKey createRegistryKey(final ResourceKey key) { return net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (ResourceLocation) (Object) key); } @@ -1009,4 +1012,8 @@ private static PrimaryLevelData.SpecialWorldProperty specialWorldProperty(final return generator instanceof FlatLevelSource ? PrimaryLevelData.SpecialWorldProperty.FLAT : PrimaryLevelData.SpecialWorldProperty.NONE; } } + + private record LevelDataLoadResult(PrimaryLevelData data, LevelStem stem) + { + } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java index 52874b97ba7..a04501c75b5 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java @@ -24,71 +24,27 @@ */ package org.spongepowered.common.world.server; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import com.mojang.serialization.Codec; -import com.mojang.serialization.JsonOps; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.kyori.adventure.text.Component; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Difficulty; import net.minecraft.world.level.GameType; -import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.DataHolder; -import org.spongepowered.api.data.DataManipulator; -import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.persistence.Queries; -import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.world.SerializationBehavior; -import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.WorldTypes; -import org.spongepowered.api.world.biome.provider.BiomeProvider; -import org.spongepowered.api.world.generation.ChunkGenerator; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigs; -import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.api.world.server.WorldTemplate; -import org.spongepowered.api.world.server.storage.ServerWorldProperties; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; -import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; -import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.fixer.SpongeDataCodec; -import org.spongepowered.common.data.holder.SpongeDataHolder; -import org.spongepowered.common.data.provider.DataProviderLookup; import org.spongepowered.common.serialization.EnumCodec; import org.spongepowered.common.serialization.MathCodecs; -import org.spongepowered.common.util.AbstractResourceKeyedBuilder; import org.spongepowered.math.vector.Vector3i; -import java.io.IOException; -import java.util.List; -import java.util.Objects; import java.util.Optional; -public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem, DataPack pack) implements WorldTemplate, SpongeDataHolder { - - public static final Codec CODEC = RecordCodecBuilder.create( - ($$0) -> $$0.group(DimensionType.CODEC.fieldOf("type").forGetter(LevelStem::type), - net.minecraft.world.level.chunk.ChunkGenerator.CODEC.fieldOf("generator").forGetter(LevelStem::generator)) - .apply($$0, $$0.stable(LevelStem::new))); +public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem) { private static final Codec SPONGE_CODEC = RecordCodecBuilder .create(r -> r @@ -120,61 +76,7 @@ public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem, DataPack public static final Codec DIRECT_CODEC = new MapCodec.MapCodecCodec(new SpongeDataCodec<>(LevelStem.CODEC, SpongeWorldTemplate.SPONGE_CODEC, (type, data) -> ((LevelStemBridge) (Object) type).bridge$decorateData(data), - type -> ((LevelStemBridge) (Object) type).bridge$createData())); - - @Override - public List impl$delegateDataHolder() { - return List.of((DataHolder) (Object) this.levelStem, this); - } - - public static LevelStem decodeStem(final JsonElement pack, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - SpongeWorldTemplate.fixDimensionDatapack(pack); - return LevelStem.CODEC.parse(ops, pack).getOrThrow(); - } - - public static WorldTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final LevelStem stem = SpongeWorldTemplate.decodeStem(packEntry, registryAccess); - return new SpongeWorldTemplate(key, stem, pack); - } - - public static JsonElement encode(final WorldTemplate s, final RegistryAccess registryAccess) { - if (s instanceof final SpongeWorldTemplate t) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return SpongeWorldTemplate.DIRECT_CODEC.encodeStart(ops, t.levelStem).getOrThrow(); - } - throw new IllegalArgumentException("WorldTemplate is not a SpongeWorldTemplate"); - } - - // TODO datafixer? - // TODO make it automatically work when loading API8 created worlds - private static void fixDimensionDatapack(final JsonElement element) { - try { - final JsonObject biomeSource = element.getAsJsonObject().getAsJsonObject("generator").getAsJsonObject("biome_source"); - if ("minecraft:vanilla_layered".equals(biomeSource.get("type").getAsString())) { - biomeSource.addProperty("type", "minecraft:multi_noise"); - biomeSource.addProperty("preset", "minecraft:overworld"); - } - } catch (final Exception ignored) { - } - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeWorldTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - final DataContainer container = DataFormats.JSON.get().read(serialized.toString()); - container.set(Queries.CONTENT_VERSION, this.contentVersion()); - return container; - } catch (final IOException e) { - throw new IllegalStateException("Could not read deserialized LevelStem:\n" + serialized, e); - } - } + type -> null)); public record SpongeDataSection(@Nullable Component displayName, @Nullable GameType gameMode, @@ -189,160 +91,4 @@ public record SpongeDataSection(@Nullable Component displayName, @Nullable Boolean pvp, @Nullable Long seed) { } - - - public static final class BuilderImpl extends AbstractResourceKeyedBuilder - implements WorldTemplate.Builder { - - private static final DataProviderLookup PROVIDER_LOOKUP = SpongeDataManager.getProviderRegistry().getProviderLookup(LevelStem.class); - - private DataManipulator.Mutable data = DataManipulator.mutableOf(); - private DataPack pack = DataPacks.WORLD; - - @Override - public Builder add(final Key> key, final V value) { - if (!PROVIDER_LOOKUP.getProvider(key).isSupported(LevelStem.class)) { - throw new IllegalArgumentException(key + " is not supported for world templates"); - } - this.data.set(key, value); - return this; - } - - @Override - public Builder reset() { - super.reset(); - this.key = null; - this.data = DataManipulator.mutableOf(); - this.data.set(Keys.WORLD_TYPE, WorldTypes.OVERWORLD.get()); - this.data.set(Keys.CHUNK_GENERATOR, ChunkGenerator.overworld()); - this.pack = DataPacks.WORLD; - return this; - } - - @Override - public Builder from(final WorldTemplate template) { - this.key = Objects.requireNonNull(template, "template").key(); - this.data = DataManipulator.mutableOf(template.getValues()); - this.pack = template.pack(); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final LevelStem levelStem = SpongeWorldTemplate.decodeStem(json, SpongeCommon.server().registryAccess()); - return this.from(levelStem); - - } - - @Override - public Builder from(final ServerWorld world) { - this.from(world.properties()); - this.data.set(Keys.CHUNK_GENERATOR, world.generator()); - return this; - } - - @Override - public Builder pack(final DataPack pack) { - this.pack = pack; - return this; - } - - @Override - public Builder from(final ServerWorldProperties properties) { - final ServerLevelDataBridge bridge = (ServerLevelDataBridge) properties; - this.key = properties.key(); - properties.displayName().ifPresent(name -> this.data.set(Keys.DISPLAY_NAME, name)); - this.data.set(Keys.WORLD_TYPE, properties.worldType()); - if (bridge.bridge$customGameType()) { - this.data.set(Keys.GAME_MODE, properties.gameMode()); - } - if (bridge.bridge$customDifficulty()) { - this.data.set(Keys.WORLD_DIFFICULTY, properties.difficulty()); - } - bridge.bridge$serializationBehavior().ifPresent(s -> this.data.set(Keys.SERIALIZATION_BEHAVIOR, s)); - bridge.bridge$viewDistance().ifPresent(v -> this.data.set(Keys.VIEW_DISTANCE, v)); - if (bridge.bridge$customSpawnPosition()) { - this.data.set(Keys.SPAWN_POSITION, properties.spawnPosition()); - } - this.data.set(Keys.IS_LOAD_ON_STARTUP, properties.loadOnStartup()); - this.data.set(Keys.PERFORM_SPAWN_LOGIC, properties.performsSpawnLogic()); - this.data.set(Keys.HARDCORE, properties.hardcore()); - this.data.set(Keys.COMMANDS, properties.commands()); - this.data.set(Keys.PVP, properties.pvp()); - return this; - } - - private Builder from(final LevelStem levelStem) { - this.data.set(((DataHolder) (Object) levelStem).getValues()); - return this; - } - - @Override - protected WorldTemplate build0() { - final ChunkGenerator chunkGenerator = this.data.require(Keys.CHUNK_GENERATOR); - final Holder dimensionType = BuilderImpl.dimensionTypeHolder(this.data.require(Keys.WORLD_TYPE)); - final LevelStem levelStem = new LevelStem(dimensionType, (net.minecraft.world.level.chunk.ChunkGenerator) chunkGenerator); - ((LevelStemBridge) (Object) levelStem).bridge$decorateData(this.data); - return new SpongeWorldTemplate(this.key, levelStem, this.pack); - } - - @NonNull - private static Holder dimensionTypeHolder(final WorldType worldType) { - final Registry dimensionTypeRegistry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); - final ResourceLocation key = dimensionTypeRegistry.getKey((DimensionType) (Object) worldType); - if (key == null) { - return Holder.direct((DimensionType) (Object) worldType); - } - return dimensionTypeRegistry.getOrThrow(net.minecraft.resources.ResourceKey.create(Registries.DIMENSION_TYPE, key)); - } - - } - - public static final class FactoryImpl implements WorldTemplate.Factory { - - @Override - public WorldTemplate overworld() { - return new BuilderImpl() - .reset() - .key(ResourceKey.minecraft("overworld")) - .add(Keys.WORLD_TYPE, WorldTypes.OVERWORLD.get()) - .add(Keys.CHUNK_GENERATOR, ChunkGenerator.overworld()) - .add(Keys.PERFORM_SPAWN_LOGIC, true) - .build(); - } - - @Override - public WorldTemplate overworldCaves() { - return new BuilderImpl() - .reset() - .key(ResourceKey.minecraft("overworld_caves")) - .add(Keys.WORLD_TYPE, WorldTypes.OVERWORLD.get()) - .add(Keys.CHUNK_GENERATOR, ChunkGenerator.noise(BiomeProvider.overworld(), NoiseGeneratorConfigs.CAVES.get())) - .add(Keys.PERFORM_SPAWN_LOGIC, true) - .build(); - } - - @Override - public WorldTemplate theNether() { - return new BuilderImpl() - .reset() - .key(ResourceKey.minecraft("the_nether")) - .add(Keys.WORLD_TYPE, WorldTypes.THE_NETHER.get()) - .add(Keys.CHUNK_GENERATOR, ChunkGenerator.theNether()) - .build(); - } - - @Override - public WorldTemplate theEnd() { - return new BuilderImpl() - .reset() - .key(ResourceKey.minecraft("the_end")) - .add(Keys.WORLD_TYPE, WorldTypes.THE_END.get()) - .add(Keys.CHUNK_GENERATOR, ChunkGenerator.theEnd()) - .build(); - } - - } - } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java new file mode 100644 index 00000000000..2c02abb62c8 --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -0,0 +1,130 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.valueproviders.UniformInt; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.dimension.DimensionType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.block.BlockType; +import org.spongepowered.api.data.DataManipulator; +import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.tag.Tag; +import org.spongepowered.api.util.MinecraftDayTime; +import org.spongepowered.api.util.Range; +import org.spongepowered.api.world.WorldType; +import org.spongepowered.api.world.WorldTypeEffect; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; +import org.spongepowered.common.data.SpongeDataManager; +import org.spongepowered.common.data.provider.DataProviderLookup; + +import java.util.OptionalLong; + +public final class SpongeWorldTypeBuilder implements WorldType.Builder { + + private static final DataProviderLookup PROVIDER_LOOKUP = SpongeDataManager.getProviderRegistry().getProviderLookup(DimensionType.class); + + private DataManipulator.Mutable data = DataManipulator.mutableOf(); + + public SpongeWorldTypeBuilder() { + this.reset(); + } + + @Override + public WorldType.Builder add(final Key> key, final V value) { + if (!PROVIDER_LOOKUP.getProvider(key).isSupported(DimensionType.class)) { + throw new IllegalArgumentException(key + " is not supported for world types"); + } + this.data.set(key, value); + return this; + } + + @Override + public WorldType.Builder reset() { + this.data = DataManipulator.mutableOf(); + final DimensionType defaultOverworld = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(BuiltinDimensionTypes.OVERWORLD); + this.from((WorldType) (Object) defaultOverworld); + return this; + } + + @Override + public WorldType.Builder from(final WorldType type) { + this.data.set(type.getValues()); + return this; + } + + @Override + public @NonNull WorldType build() { + @Nullable final WorldTypeEffect effect = this.data.getOrNull(Keys.WORLD_TYPE_EFFECT); + final boolean scorching = this.data.require(Keys.SCORCHING); + final boolean natural = this.data.require(Keys.NATURAL_WORLD_TYPE); + final double coordinateMultiplier = this.data.require(Keys.COORDINATE_MULTIPLIER); + final boolean hasSkylight = this.data.require(Keys.HAS_SKYLIGHT); + final boolean hasCeiling = this.data.require(Keys.HAS_CEILING); + final float ambientLighting = this.data.require(Keys.AMBIENT_LIGHTING); + @Nullable final MinecraftDayTime fixedTime = this.data.getOrNull(Keys.FIXED_TIME); + final boolean bedsUsable = this.data.require(Keys.BEDS_USABLE); + final boolean respawnAnchorsUsable = this.data.require(Keys.RESPAWN_ANCHOR_USABLE); + final int floor = this.data.require(Keys.WORLD_FLOOR); + final int height = this.data.require(Keys.WORLD_HEIGHT); + final int logicalHeight = this.data.require(Keys.WORLD_LOGICAL_HEIGHT); + @Nullable final Tag infiniburn = this.data.getOrNull(Keys.INFINIBURN); + + final boolean piglinSafe = this.data.require(Keys.PIGLIN_SAFE); + final boolean hasRaids = this.data.require(Keys.HAS_RAIDS); + final int monsterSpawnBlockLightLimit = this.data.getOrElse(Keys.SPAWN_LIGHT_LIMIT, 0); + final Range lightRange = this.data.getOrElse(Keys.SPAWN_LIGHT_RANGE, Range.intRange(0, 7)); + final boolean createDragonFight = this.data.getOrElse(Keys.CREATE_DRAGON_FIGHT, false); + final UniformInt monsterSpawnLightTest = UniformInt.of(lightRange.min(), lightRange.max()); + + final SpongeDimensionTypes.SpongeDataSection spongeData = new SpongeDimensionTypes.SpongeDataSection(createDragonFight); + try { + + final DimensionType dimensionType = + new DimensionType(fixedTime == null ? OptionalLong.empty() : OptionalLong.of(fixedTime.asTicks().ticks()), + hasSkylight, hasCeiling, scorching, natural, coordinateMultiplier, + bedsUsable, respawnAnchorsUsable, + floor, height, logicalHeight, + (TagKey) (Object) infiniburn, + (ResourceLocation) (Object) effect.key(), + ambientLighting, + new DimensionType.MonsterSettings(piglinSafe, hasRaids, monsterSpawnLightTest, monsterSpawnBlockLightLimit)); + if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { + bridge.bridge$decorateData(spongeData); + } + return (WorldType) (Object) dimensionType; + } catch (IllegalStateException e) { // catch and rethrow minecraft internal exception + throw new IllegalStateException("World type was not valid!", e); + } + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java deleted file mode 100644 index 586e9d4380d..00000000000 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeTemplate.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.server; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.JsonOps; -import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.util.valueproviders.UniformInt; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; -import net.minecraft.world.level.dimension.DimensionType; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.data.DataManipulator; -import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.persistence.Queries; -import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPacks; -import org.spongepowered.api.tag.Tag; -import org.spongepowered.api.util.MinecraftDayTime; -import org.spongepowered.api.util.Range; -import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.WorldTypeEffect; -import org.spongepowered.api.world.WorldTypeTemplate; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; -import org.spongepowered.common.data.SpongeDataManager; -import org.spongepowered.common.data.holder.SpongeDataHolder; -import org.spongepowered.common.data.provider.DataProviderLookup; -import org.spongepowered.common.util.AbstractDataPackEntryBuilder; - -import java.io.IOException; -import java.util.OptionalLong; -import java.util.function.Function; - -public record SpongeWorldTypeTemplate( - ResourceKey key, - DimensionType dimensionType, - DataPack pack -) implements WorldTypeTemplate, SpongeDataHolder { - - public static DimensionType decode(final JsonElement json, final RegistryAccess registryAccess) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return SpongeDimensionTypes.DIRECT_CODEC.parse(ops, json).getOrThrow(); - } - - public static WorldTypeTemplate decode(final DataPack pack, final ResourceKey key, final JsonElement packEntry, final RegistryAccess registryAccess) { - final DimensionType parsed = SpongeWorldTypeTemplate.decode(packEntry, registryAccess); - return new SpongeWorldTypeTemplate(key, parsed, pack); - } - - public static JsonElement encode(final WorldTypeTemplate template, final RegistryAccess registryAccess) { - if (template instanceof final SpongeWorldTypeTemplate t) { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); - return SpongeDimensionTypes.DIRECT_CODEC.encodeStart(ops, t.dimensionType).getOrThrow(); - } - throw new IllegalArgumentException("WorldTypeTemplate is not a SpongeWorldTypeTemplate"); - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement serialized = SpongeWorldTypeTemplate.encode(this, SpongeCommon.server().registryAccess()); - try { - final DataContainer container = DataFormats.JSON.get().read(serialized.toString()); - container.set(Queries.CONTENT_VERSION, this.contentVersion()); - return container; - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized DimensionType:\n" + serialized, e); - } - } - - public static final class BuilderImpl extends AbstractDataPackEntryBuilder implements WorldTypeTemplate.Builder { - - private static final DataProviderLookup PROVIDER_LOOKUP = SpongeDataManager.getProviderRegistry().getProviderLookup(DimensionType.class); - - private DataManipulator.Mutable data = DataManipulator.mutableOf(); - - public BuilderImpl() { - this.reset(); - } - - @Override - public Function valueExtractor() { - return (w) -> (WorldType) (Object) ((SpongeWorldTypeTemplate) w).dimensionType; - } - - @Override - public WorldTypeTemplate.Builder add(final Key> key, final V value) { - if (!PROVIDER_LOOKUP.getProvider(key).isSupported(DimensionType.class)) { - throw new IllegalArgumentException(key + " is not supported for world types"); - } - this.data.set(key, value); - return this; - } - - @Override - public Builder reset() { - this.data = DataManipulator.mutableOf(); - this.key = null; - this.pack = DataPacks.WORLD_TYPE; - final DimensionType defaultOverworld = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(BuiltinDimensionTypes.OVERWORLD); - this.fromValue((WorldType) (Object) defaultOverworld); - return this; - } - - @Override - public Builder fromValue(final WorldType type) { - this.data.set(type.getValues()); - return this; - } - - @Override - public Builder fromDataPack(final DataView pack) throws IOException { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(pack)); - final DataResult> parsed = DimensionType.CODEC.parse(JsonOps.INSTANCE, json); - final DimensionType dimensionType = parsed.getOrThrow().value(); - - this.fromValue((WorldType) (Object) dimensionType); - return this; - } - - @Override - public Builder from(WorldType type) { - this.data.set(type.getValues()); - return this; - } - - @Override - public @NonNull WorldTypeTemplate build0() { - @Nullable final WorldTypeEffect effect = this.data.getOrNull(Keys.WORLD_TYPE_EFFECT); - final boolean scorching = this.data.require(Keys.SCORCHING); - final boolean natural = this.data.require(Keys.NATURAL_WORLD_TYPE); - final double coordinateMultiplier = this.data.require(Keys.COORDINATE_MULTIPLIER); - final boolean hasSkylight = this.data.require(Keys.HAS_SKYLIGHT); - final boolean hasCeiling = this.data.require(Keys.HAS_CEILING); - final float ambientLighting = this.data.require(Keys.AMBIENT_LIGHTING); - @Nullable final MinecraftDayTime fixedTime = this.data.getOrNull(Keys.FIXED_TIME); - final boolean bedsUsable = this.data.require(Keys.BEDS_USABLE); - final boolean respawnAnchorsUsable = this.data.require(Keys.RESPAWN_ANCHOR_USABLE); - final int floor = this.data.require(Keys.WORLD_FLOOR); - final int height = this.data.require(Keys.WORLD_HEIGHT); - final int logicalHeight = this.data.require(Keys.WORLD_LOGICAL_HEIGHT); - @Nullable final Tag infiniburn = this.data.getOrNull(Keys.INFINIBURN); - - final boolean piglinSafe = this.data.require(Keys.PIGLIN_SAFE); - final boolean hasRaids = this.data.require(Keys.HAS_RAIDS); - final int monsterSpawnBlockLightLimit = this.data.getOrElse(Keys.SPAWN_LIGHT_LIMIT, 0); - final Range lightRange = this.data.getOrElse(Keys.SPAWN_LIGHT_RANGE, Range.intRange(0, 7)); - final boolean createDragonFight = this.data.getOrElse(Keys.CREATE_DRAGON_FIGHT, false); - final UniformInt monsterSpawnLightTest = UniformInt.of(lightRange.min(), lightRange.max()); - - final SpongeDimensionTypes.SpongeDataSection spongeData = new SpongeDimensionTypes.SpongeDataSection(createDragonFight); - try { - - final DimensionType dimensionType = - new DimensionType(fixedTime == null ? OptionalLong.empty() : OptionalLong.of(fixedTime.asTicks().ticks()), - hasSkylight, hasCeiling, scorching, natural, coordinateMultiplier, - bedsUsable, respawnAnchorsUsable, - floor, height, logicalHeight, - (TagKey) (Object) infiniburn, - (ResourceLocation) (Object) effect.key(), - ambientLighting, - new DimensionType.MonsterSettings(piglinSafe, hasRaids, monsterSpawnLightTest, monsterSpawnBlockLightLimit)); - if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { - bridge.bridge$decorateData(spongeData); - } - return new SpongeWorldTypeTemplate(this.key, dimensionType, this.pack); - } catch (IllegalStateException e) { // catch and rethrow minecraft internal exception - throw new IllegalStateException(String.format("Template '%s' was not valid!", this.key), e); - } - } - } -} diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index 216dbb883d7..3ea9701b26f 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -19,3 +19,4 @@ accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$A accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$ActionType accessible class net/minecraft/world/entity/monster/SpellcasterIllager$IllagerSpell accessible class net/minecraft/world/level/biome/Biome$ClimateSettings +accessible class net/minecraft/core/MappedRegistry$TagSet diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java index 79d4e5c2ac3..cc5d46c9762 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.api.minecraft.advancements; -import com.google.gson.JsonElement; import net.kyori.adventure.text.Component; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementRequirements; @@ -35,16 +34,14 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.Queries; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.advancement.SpongeAdvancementTemplate; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.advancements.AdvancementBridge; +import org.spongepowered.common.util.DataPackUtil; -import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Optional; @@ -87,19 +84,7 @@ public Component asComponent() { } @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - final JsonElement json = SpongeAdvancementTemplate.encode((Advancement) (Object) this); - try { - final DataContainer container = DataFormats.JSON.get().read(json.toString()); - container.set(Queries.CONTENT_VERSION, this.contentVersion()); - return container; - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Advancement:\n" + json, e); - } + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, Advancement.CODEC, (Advancement) (Object) this); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java index c6322958f92..328ea086457 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java @@ -31,7 +31,6 @@ import net.minecraft.resources.ResourceLocation; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.Advancement; -import org.spongepowered.api.advancement.AdvancementTemplate; import org.spongepowered.api.advancement.AdvancementTree; import org.spongepowered.api.advancement.TreeLayoutElement; import org.spongepowered.asm.mixin.Final; @@ -92,11 +91,12 @@ public Collection layoutElements() { } @Override - public Optional layoutElement(final AdvancementTemplate advancement) { - if (advancement.advancement().displayInfo().isEmpty()) { + public Optional layoutElement(final Advancement advancement) { + if (advancement.displayInfo().isEmpty()) { return Optional.empty(); } - return this.layoutElement(advancement.key()); + return this.impl$findElementInfo((AdvancementNode) (Object) this, (net.minecraft.advancements.Advancement) (Object) advancement) + .map(TreeLayoutElement.class::cast); } @Override @@ -120,4 +120,17 @@ public Optional layoutElement(final ResourceKey advancementKe } return Optional.empty(); } + + private Optional impl$findElementInfo(AdvancementNode node, net.minecraft.advancements.Advancement advancement) { + if (node.holder().value() == advancement) { + return node.advancement().display(); + } + for (final AdvancementNode child : node.children()) { + final var info = this.impl$findElementInfo(child, advancement); + if (info.isPresent()) { + return info; + } + } + return Optional.empty(); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java index b1ff4f5c63e..82f095dcec1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java @@ -30,7 +30,6 @@ import net.minecraft.core.RegistrationInfo; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryEntry; @@ -58,16 +57,11 @@ public abstract class MappedRegistryMixin_API implements Registry { @Shadow public abstract Holder.Reference shadow$register(final net.minecraft.resources.ResourceKey $$0, final T $$1, final RegistrationInfo $$2); @Shadow public abstract net.minecraft.resources.ResourceKey> shadow$key(); - @Shadow @Nullable public abstract T shadow$getValue(@Nullable ResourceLocation var1); private ResourceLocation impl$getKey(final T value) { return ((net.minecraft.core.Registry) this).getKey(value); } - private Optional impl$getOptional(@Nullable ResourceLocation param0) { - return ((net.minecraft.core.Registry) this).getOptional(param0); - } - private Optional> impl$getTag(TagKey var1) { return ((net.minecraft.core.Registry) this).get(var1); } @@ -107,16 +101,18 @@ public Optional> findEntry(final ResourceKey key) return ((RegistryBridge) this).bridge$get(Objects.requireNonNull(key, "key")); } + @SuppressWarnings("unchecked") @Override public Optional findValue(final ResourceKey key) { - return (Optional) this.impl$getOptional((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + return ((RegistryBridge) this).bridge$get(Objects.requireNonNull(key, "key")).map(RegistryEntry::value); } + @SuppressWarnings("unchecked") @Override public V value(final ResourceKey key) { - final V value = (V) this.shadow$getValue((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + final RegistryEntry value = ((RegistryBridge) this).bridge$getEntry(Objects.requireNonNull(key, "key")); if (value != null) { - return value; + return value.value(); } throw new ValueNotFoundException(String.format("No value was found for key '%s'!", key)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java new file mode 100644 index 00000000000..58a3621b0e6 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java @@ -0,0 +1,88 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.core; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.api.registry.RegistryEntry; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.registry.ValueNotFoundException; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.registry.SpongeRegistryEntry; + +import java.util.Objects; +import java.util.Optional; + +import javax.annotation.Nullable; + +@Mixin(Registry.class) +public interface RegistryMixin extends org.spongepowered.api.registry.Registry { + + @Shadow ResourceKey> shadow$key(); + + @Shadow @Nullable ResourceLocation shadow$getKey(T object); + + @Shadow Optional shadow$getOptional(@org.jetbrains.annotations.Nullable ResourceLocation arg); + + @Shadow @Nullable T shadow$getValue(@org.jetbrains.annotations.Nullable ResourceLocation arg); + + @Override + default RegistryType type() { + return RegistryType.of((org.spongepowered.api.ResourceKey) (Object) this.shadow$key().registry(), (org.spongepowered.api.ResourceKey) (Object) this.shadow$key().location()); + } + + @Override + default org.spongepowered.api.ResourceKey valueKey(final T value) { + return (org.spongepowered.api.ResourceKey) (Object) this.shadow$getKey(Objects.requireNonNull(value, "value")); + } + + @Override + default Optional findValueKey(final T value) { + return Optional.ofNullable(this.valueKey(Objects.requireNonNull(value, "value"))); + } + + @Override + default Optional> findEntry(final org.spongepowered.api.ResourceKey key) { + return this.shadow$getOptional((ResourceLocation) (Object) Objects.requireNonNull(key, "key")).map(e -> + new SpongeRegistryEntry<>((RegistryType) this.type(), key, (V) e)); + } + + @Override + default Optional findValue(final org.spongepowered.api.ResourceKey key) { + return (Optional) this.shadow$getOptional((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + } + + @Override + default V value(final org.spongepowered.api.ResourceKey key) { + final V value = (V) this.shadow$getValue((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + if (value != null) { + return value; + } + + throw new ValueNotFoundException(String.format("No value was found for key '%s'!", key)); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/network/chat/ChatTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/network/chat/ChatTypeMixin_API.java index 46d50d5e73f..73933748089 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/network/chat/ChatTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/network/chat/ChatTypeMixin_API.java @@ -32,10 +32,13 @@ import net.minecraft.network.chat.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.adventure.SpongeAdventure; +import org.spongepowered.common.util.DataPackUtil; import java.util.Optional; @@ -91,4 +94,9 @@ public static abstract class BoundMixin_API implements net.kyori.adventure.chat. } } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, ChatType.DIRECT_CODEC, (ChatType) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index 623c29a2f01..d4d9abc6887 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -167,7 +167,7 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe this.api$playerDataHandler = new SpongePlayerDataManager(this); this.api$teleportHelper = new SpongeTeleportHelper(); this.api$mapStorage = new SpongeMapStorage(); - this.api$registryHolder = new RegistryHolderLogic(levelStem.registries().compositeAccess()); + this.api$registryHolder = ((SpongeRegistryHolder) levelStem.resourceManager()).registryHolder(); this.api$userManager = new SpongeUserManager((MinecraftServer) (Object) this); this.api$dataPackManager = new SpongeDataPackManager((MinecraftServer) (Object) this, this.storageSource.getLevelPath(LevelResource.DATAPACK_DIR)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java index 0afada62855..a441053c05c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java @@ -50,7 +50,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.advancement.AdvancementProgress; -import org.spongepowered.api.advancement.AdvancementTemplate; import org.spongepowered.api.advancement.AdvancementTree; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -64,6 +63,7 @@ import org.spongepowered.api.event.world.ChangeWorldBorderEvent; import org.spongepowered.api.network.ServerSideConnection; import org.spongepowered.api.profile.GameProfile; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.scoreboard.Scoreboard; import org.spongepowered.api.world.border.WorldBorder; import org.spongepowered.api.world.server.ServerWorld; @@ -236,9 +236,9 @@ public CooldownTracker cooldownTracker() { } @Override - public AdvancementProgress progress(final AdvancementTemplate advancement) { + public AdvancementProgress progress(final org.spongepowered.api.advancement.Advancement advancement) { Objects.requireNonNull(advancement, "advancement"); - final AdvancementHolder holder = new AdvancementHolder((ResourceLocation) (Object) advancement.key(), (Advancement) (Object) advancement.advancement()); + final AdvancementHolder holder = new AdvancementHolder((ResourceLocation) (Object) advancement.key(RegistryTypes.ADVANCEMENT), (Advancement) (Object) advancement); return (AdvancementProgress) this.advancements.getOrStartProgress(holder); } diff --git a/src/main/java/org/spongepowered/common/datapack/DataPackDecoder.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/MultiPackResourceManagerMixin_API.java similarity index 63% rename from src/main/java/org/spongepowered/common/datapack/DataPackDecoder.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/MultiPackResourceManagerMixin_API.java index 85a9b41d0ec..82eba978b20 100644 --- a/src/main/java/org/spongepowered/common/datapack/DataPackDecoder.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/MultiPackResourceManagerMixin_API.java @@ -22,15 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.datapack; +package org.spongepowered.common.mixin.api.minecraft.server.packs.resources; import net.minecraft.core.RegistryAccess; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackEntry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.registry.RegistryHolderLogic; +import org.spongepowered.common.registry.SpongeRegistryHolder; -public interface DataPackDecoder> { +@Mixin(MultiPackResourceManager.class) +public abstract class MultiPackResourceManagerMixin_API implements SpongeRegistryHolder { - T decode(DataPack pack, ResourceKey key, E from, RegistryAccess registryAccess); + private RegistryHolderLogic api$registryHolder = new RegistryHolderLogic(RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY)); + @Override + public RegistryHolderLogic registryHolder() { + return this.api$registryHolder; + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java index 01af5bb9ca2..2d1e88833ec 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java @@ -25,17 +25,21 @@ package org.spongepowered.common.mixin.api.minecraft.world.damagesource; import net.minecraft.world.damagesource.DamageEffects; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.event.cause.entity.damage.DamageEffect; import org.spongepowered.api.event.cause.entity.damage.DamageScaling; import org.spongepowered.api.event.cause.entity.damage.DamageType; import org.spongepowered.api.registry.DefaultedRegistryType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.Collection; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -86,4 +90,9 @@ public DefaultedRegistryType registryType() { public Collection> tags() { return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.damagesource.DamageType.DIRECT_CODEC, (net.minecraft.world.damagesource.DamageType) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java index e8d4d2f761b..fcad5395cb3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java @@ -24,10 +24,19 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.decoration; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.type.ArtType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.util.DataPackUtil; + +import java.util.Optional; @Mixin(net.minecraft.world.entity.decoration.PaintingVariant.class) public abstract class PaintingVariantMixin_API implements ArtType { + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.entity.decoration.PaintingVariant.DIRECT_CODEC, (net.minecraft.world.entity.decoration.PaintingVariant) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java index 8b19f11b424..99c6a0396bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java @@ -30,9 +30,11 @@ import net.minecraft.world.item.crafting.display.RecipeDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay; import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.recipe.Recipe; import org.spongepowered.api.item.recipe.RecipeType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -40,8 +42,10 @@ import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.crafting.RecipeUtil; import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; import java.util.function.Predicate; @Mixin(net.minecraft.world.item.crafting.Recipe.class) @@ -101,4 +105,9 @@ default boolean isDynamic() { default RecipeType type() { return (RecipeType) this.shadow$getType(); } + + @Override + default Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.item.crafting.Recipe.CODEC, (net.minecraft.world.item.crafting.Recipe) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java index dc0b59e52f7..b1583a8f400 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java @@ -28,15 +28,19 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.tags.TagKey; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.registry.DefaultedRegistryType; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.tag.Tag; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeDataHolder; +import org.spongepowered.common.util.DataPackUtil; import java.util.Collection; +import java.util.Optional; @Mixin(net.minecraft.world.level.biome.Biome.class) public abstract class BiomeMixin_API implements Biome, SpongeDataHolder { @@ -57,4 +61,9 @@ public boolean is(final Tag tag) { final Holder.Reference holder = registry.createIntrusiveHolder((net.minecraft.world.level.biome.Biome) (Object) this); return holder.is(((TagKey) (Object) tag)); } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.level.biome.Biome.DIRECT_CODEC, (net.minecraft.world.level.biome.Biome) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java index 31356c536b5..f1cba73ef1e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java @@ -29,13 +29,17 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.world.WorldType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeDataHolder; +import org.spongepowered.common.util.DataPackUtil; import java.util.Objects; +import java.util.Optional; @Mixin(DimensionType.class) public abstract class DimensionTypeMixin_API implements WorldType, SpongeDataHolder { @@ -58,4 +62,9 @@ public Context context() { return registry.getKey((DimensionType) (Object) this); } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, DimensionType.DIRECT_CODEC, (DimensionType) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/LevelStemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/LevelStemMixin_API.java new file mode 100644 index 00000000000..e8b0d2a19de --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/LevelStemMixin_API.java @@ -0,0 +1,64 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.level.dimension; + +import net.minecraft.core.Holder; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.dimension.LevelStem; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.world.WorldType; +import org.spongepowered.api.world.generation.ChunkGenerator; +import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; + +import java.util.Optional; + +@Mixin(LevelStem.class) +public abstract class LevelStemMixin_API implements WorldArchetypeType { + + // @formatter:off + @Shadow @Final private Holder type; + @Shadow @Final private net.minecraft.world.level.chunk.ChunkGenerator generator; + // @formatter:on + + @Override + public WorldType worldType() { + return (WorldType) (Object) this.type.value(); + } + + @Override + public ChunkGenerator chunkGenerator() { + return (ChunkGenerator) this.generator; + } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, LevelStem.CODEC, (LevelStem) (Object) this); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java index 2e4cd9244f8..7962c30de34 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java @@ -25,10 +25,15 @@ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen; import net.minecraft.world.level.levelgen.DensityFunction; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import org.spongepowered.math.vector.Vector3i; +import java.util.Optional; + @Mixin(DensityFunction.class) public interface DensityFunctionMixin_API extends org.spongepowered.api.world.generation.config.noise.DensityFunction { @@ -57,4 +62,9 @@ default double compute(final Vector3i pos) { default double compute(final int x, final int y, final int z) { return this.shadow$compute(new DensityFunction.SinglePointContext(x, y, z)); } + + @Override + default Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, DensityFunction.DIRECT_CODEC, (DensityFunction) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseGeneratorSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseGeneratorSettingsMixin_API.java index baee3cb40a7..d8f11aad61b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseGeneratorSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseGeneratorSettingsMixin_API.java @@ -30,6 +30,8 @@ import net.minecraft.world.level.levelgen.NoiseSettings; import net.minecraft.world.level.levelgen.SurfaceRules; import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.biome.BiomeAttributes; import org.spongepowered.api.world.generation.config.SurfaceRule; import org.spongepowered.api.world.generation.config.noise.NoiseConfig; @@ -41,8 +43,10 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; @Mixin(NoiseGeneratorSettings.class) @Implements(@Interface(iface = NoiseGeneratorConfig.class, prefix = "noiseGeneratorConfig$", remap = Remap.NONE)) @@ -116,4 +120,9 @@ public boolean mobGeneration() { public SurfaceRule surfaceRule() { return (SurfaceRule) this.surfaceRule; } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, NoiseGeneratorSettings.DIRECT_CODEC, (NoiseGeneratorSettings) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NormalNoise_NoiseParametersMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NormalNoise_NoiseParametersMixin_API.java index 73e92ecb3d8..b9405ddf57a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NormalNoise_NoiseParametersMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NormalNoise_NoiseParametersMixin_API.java @@ -26,12 +26,16 @@ import it.unimi.dsi.fastutil.doubles.DoubleList; import net.minecraft.world.level.levelgen.synth.NormalNoise; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.config.noise.Noise; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; @Mixin(NormalNoise.NoiseParameters.class) public abstract class NormalNoise_NoiseParametersMixin_API implements Noise { @@ -50,4 +54,9 @@ public int octave() { public List amplitudes() { return this.amplitudes; } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, NormalNoise.NoiseParameters.DIRECT_CODEC, (NormalNoise.NoiseParameters) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/ConfiguredWorldCarverMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/ConfiguredWorldCarverMixin_API.java index b8deff29e63..c3012dc7ca8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/ConfiguredWorldCarverMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/ConfiguredWorldCarverMixin_API.java @@ -24,22 +24,20 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen.carver; -import com.google.gson.JsonElement; -import com.mojang.serialization.Codec; import net.minecraft.world.level.levelgen.carver.CarverConfiguration; import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.carver.WorldCarver; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.carver.Carver; import org.spongepowered.api.world.generation.carver.CarverType; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.world.generation.carver.SpongeCarverTemplate; +import org.spongepowered.common.util.DataPackUtil; + +import java.util.Optional; -import java.io.IOException; @Mixin(ConfiguredWorldCarver.class) public abstract class ConfiguredWorldCarverMixin_API implements Carver { @@ -54,13 +52,9 @@ public CarverType type() { return (CarverType) this.worldCarver; } + @SuppressWarnings("unchecked") @Override - public DataView toContainer() { - final JsonElement serialized = SpongeCarverTemplate.encode((Codec>) (Object) this.worldCarver.configuredCodec(), (ConfiguredWorldCarver) (Object) this, SpongeCommon.server().registryAccess()); - try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Carver: " + serialized, e); - } + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, ConfiguredWorldCarver.DIRECT_CODEC, (ConfiguredWorldCarver) (Object) this); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/WorldCarverMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/WorldCarverMixin_API.java index e0105288e0e..99201607945 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/WorldCarverMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/carver/WorldCarverMixin_API.java @@ -24,39 +24,12 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen.carver; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; import net.minecraft.world.level.levelgen.carver.CarverConfiguration; -import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; import net.minecraft.world.level.levelgen.carver.WorldCarver; -import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.world.generation.carver.Carver; import org.spongepowered.api.world.generation.carver.CarverType; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.world.generation.carver.SpongeCarverTemplate; - -import java.io.IOException; @Mixin(WorldCarver.class) public abstract class WorldCarverMixin_API implements CarverType { - //@formatter:off - @Shadow @Final private MapCodec> configuredCodec; - //@formatter:on - - @Override - public Carver configure(final DataView config) throws IllegalArgumentException { - try { - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(config)); - return (Carver) (Object) SpongeCarverTemplate.decode((Codec>) (Object) this.configuredCodec.codec(), json, SpongeCommon.server().registryAccess()); - } catch (IOException e) { - throw new IllegalStateException("Could not read configuration: " + config, e); - } - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/feature/ConfiguredFeatureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/feature/ConfiguredFeatureMixin_API.java index 3226480c026..8aa1a19924f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/feature/ConfiguredFeatureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/feature/ConfiguredFeatureMixin_API.java @@ -33,8 +33,10 @@ import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataFormats; import org.spongepowered.api.data.persistence.DataView; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.feature.Feature; import org.spongepowered.api.world.generation.feature.FeatureType; import org.spongepowered.api.world.server.ServerLocation; @@ -43,10 +45,12 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.util.DataPackUtil; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3i; import java.io.IOException; +import java.util.Optional; @Mixin(ConfiguredFeature.class) public abstract class ConfiguredFeatureMixin_API< @@ -86,4 +90,10 @@ public boolean place(ServerWorld world, Vector3i pos) { public boolean place(final ServerLocation location) { return this.place(location.world(), location.blockPosition()); } + + @SuppressWarnings("unchecked") + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, ConfiguredFeature.DIRECT_CODEC, (ConfiguredFeature) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/placement/PlacedFeatureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/placement/PlacedFeatureMixin_API.java index 57948bd01be..eff1e4bb02e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/placement/PlacedFeatureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/placement/PlacedFeatureMixin_API.java @@ -30,6 +30,8 @@ import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.feature.Feature; import org.spongepowered.api.world.generation.feature.FeatureType; import org.spongepowered.api.world.generation.feature.PlacementModifier; @@ -38,10 +40,12 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3i; import java.util.List; +import java.util.Optional; @Mixin(PlacedFeature.class) public abstract class PlacedFeatureMixin_API implements org.spongepowered.api.world.generation.feature.PlacedFeature { @@ -71,4 +75,9 @@ public boolean place(final ServerWorld world, final Vector3i pos) { public boolean place(final ServerLocation location) { return this.place(location.world(), location.blockPosition()); } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, PlacedFeature.DIRECT_CODEC, (PlacedFeature) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java index 8a3c6acabed..14e1d805aed 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java @@ -42,9 +42,11 @@ import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; import net.minecraft.world.level.levelgen.structure.StructureStart; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataFormats; import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.entity.EntityCategory; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.feature.DecorationStep; import org.spongepowered.api.world.generation.structure.StructureType; import org.spongepowered.api.world.server.ServerLocation; @@ -52,12 +54,14 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.util.DataPackUtil; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3i; import java.io.IOException; import java.util.Collection; import java.util.Map; +import java.util.Optional; @Mixin(Structure.class) public abstract class StructureMixin_API implements org.spongepowered.api.world.generation.structure.Structure { @@ -144,4 +148,9 @@ public DataView toContainer() { final var type = (net.minecraft.world.level.levelgen.structure.StructureType) this.shadow$type(); return type.codec().codec(); } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, Structure.DIRECT_CODEC, (Structure) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSetMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSetMixin_API.java index 8b3ada0c98f..4ac59ca1519 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSetMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureSetMixin_API.java @@ -25,14 +25,18 @@ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen.structure; import net.minecraft.world.level.levelgen.structure.StructureSet; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.util.weighted.WeightedTable; import org.spongepowered.api.world.generation.structure.Structure; import org.spongepowered.api.world.generation.structure.StructurePlacement; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; @Mixin(StructureSet.class) public abstract class StructureSetMixin_API implements org.spongepowered.api.world.generation.structure.StructureSet { @@ -55,4 +59,9 @@ public WeightedTable structures() { public StructurePlacement placement() { return (StructurePlacement) this.placement; } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, StructureSet.DIRECT_CODEC, (StructureSet) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/pools/StructureTemplatePoolMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/pools/StructureTemplatePoolMixin_API.java index fe1eb34bdb1..3ec26a852e0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/pools/StructureTemplatePoolMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/pools/StructureTemplatePoolMixin_API.java @@ -28,14 +28,18 @@ import net.minecraft.core.Holder; import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement; import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.util.weighted.WeightedTable; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPool; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolElement; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; @Mixin(StructureTemplatePool.class) public abstract class StructureTemplatePoolMixin_API implements JigsawPool { @@ -58,4 +62,9 @@ public WeightedTable elements() { } return weightedTable; } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, StructureTemplatePool.DIRECT_CODEC, (StructureTemplatePool) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorListMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorListMixin_API.java index b7a829a3658..658bb9d26b7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorListMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorListMixin_API.java @@ -26,13 +26,18 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.structure.jigsaw.Processor; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.DataPackUtil; import java.util.List; +import java.util.Optional; @Mixin(StructureProcessorList.class) public abstract class StructureProcessorListMixin_API implements ProcessorList { @@ -45,4 +50,9 @@ public abstract class StructureProcessorListMixin_API implements ProcessorList { public List processors() { return (List) this.list; } + + @Override + public Optional toDataPack(final RegistryHolder registryHolder) { + return DataPackUtil.toDataContainer(registryHolder, StructureProcessorType.LIST_OBJECT_CODEC, (StructureProcessorList) (Object) this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java new file mode 100644 index 00000000000..6fa56d0aac3 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java @@ -0,0 +1,70 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core; + +import net.minecraft.core.HolderLookup; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.registry.ValueNotFoundException; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.resources.ResourceKeyAccessor; + +import java.util.Optional; +import java.util.stream.Stream; + +@Mixin(value = HolderLookup.Provider.class, priority = 999) +public interface HolderLookup_ProviderMixin extends RegistryHolder { + + @Shadow Optional> shadow$lookup(net.minecraft.resources.ResourceKey> arg); + + @Shadow Stream> shadow$listRegistries(); + + @Override + default Registry registry(final RegistryType type) { + return this.findRegistry(type) + .orElseThrow(() -> new ValueNotFoundException(String.format("No '%s' registry has been defined in root '%s'", type.location(), type.root()))); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + default Optional> findRegistry(final RegistryType type) { + return (Optional) this.shadow$lookup(ResourceKeyAccessor.invoker$create((ResourceLocation) (Object) type.root(), (ResourceLocation) (Object) type.location())); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + default Stream> streamRegistries() { + return (Stream) this.shadow$listRegistries(); + } + + @Override + default Stream> streamRegistries(final ResourceKey root) { + return this.streamRegistries().filter(r -> r.type().root().equals(root)); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 7160e683861..49ef9cb8abf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -31,6 +31,7 @@ import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.RootCommandNode; +import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.SharedSuggestionProvider; @@ -39,6 +40,7 @@ import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -88,12 +90,12 @@ public abstract class CommandsMixin implements CommandsBridge { args = "class=com/mojang/brigadier/CommandDispatcher", remap = false )) - private CommandDispatcher impl$useSpongeDispatcher() { + private CommandDispatcher impl$useSpongeDispatcher(final Commands.CommandSelection $$0, final CommandBuildContext $$1) { if (!Launch.instance().pluginManager().isReady()) { return new CommandDispatcher<>(); } final SpongeCommandManager manager = Launch.instance().lifecycle().platformInjector().getInstance(SpongeCommandManager.class); - manager.init(); + manager.init((RegistryHolder) $$1); this.impl$commandManager = manager; return new DelegatingCommandDispatcher(manager.getBrigadierRegistrar()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java index 61d5d664916..12730ddf63d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java @@ -32,9 +32,13 @@ import net.minecraft.core.RegistrationInfo; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.RegistryEntry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.registry.ValueNotFoundException; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -46,28 +50,47 @@ import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.core.RegistryBridge; import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.registry.InitialRegistryData; import org.spongepowered.common.registry.SpongeRegistryEntry; import org.spongepowered.common.registry.SpongeRegistryType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Stream; @Mixin(MappedRegistry.class) public abstract class MappedRegistryMixin implements RegistryBridge, WritableRegistryBridge, MappedRegistryBridge { + // @formatter:off + @Shadow private boolean frozen; @Shadow @Final private ObjectList> byId; @Shadow @Final private Reference2IntMap toId; @Shadow @Final private Map> byLocation; @Shadow @Final private Map, Holder.Reference> byKey; @Shadow @Final private Map> byValue; @Shadow @Final private Map, RegistrationInfo> registrationInfos; + @Shadow @Final private net.minecraft.resources.ResourceKey> key; + @Shadow MappedRegistry.TagSet allTags; + @Shadow public abstract Holder.Reference shadow$register(net.minecraft.resources.ResourceKey arg, T object, RegistrationInfo arg2); + // @formatter:on + + private RegistryHolder impl$registryHolder; private RegistryType impl$type; private final Map> impl$entries = new LinkedHashMap<>(); + private final Set> impl$dependencies = new HashSet<>(); + private final List impl$preFreezeTasks = new ArrayList<>(); + private boolean impl$isDynamic = true; + private boolean impl$eventCalled = false; @Override public boolean bridge$isDynamic() { @@ -114,6 +137,11 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa return Optional.ofNullable(this.impl$entries.get(resourceKey)); } + @Override + public @Nullable RegistryEntry bridge$getEntry(final ResourceKey resourceKey) { + return this.impl$entries.get(resourceKey); + } + @Override public Stream> bridge$streamEntries() { return this.impl$entries.values().stream(); @@ -133,4 +161,69 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa this.registrationInfos.remove(key); this.impl$entries.remove((ResourceKey) (Object) key.location()); } + + @Inject(method = "freeze", at = @At(value = "FIELD", target = "Lnet/minecraft/core/MappedRegistry;frozen:Z", opcode = Opcodes.PUTFIELD)) + private void impl$onFreeze(final CallbackInfoReturnable> cir) { + this.impl$dependencies.forEach(t -> { + if (!this.impl$registryHolder.findRegistry(t) + .map(r -> ((MappedRegistryMixin) r).frozen) + .orElse(false)) { + throw new ValueNotFoundException(String.format("Dependency %s was not found!", t)); + } + }); + this.impl$preFreezeTasks.forEach(Runnable::run); + this.impl$preFreezeTasks.clear(); + } + + @Override + public void bridge$setRegistryHolder(final RegistryHolder registryHolder) { + this.impl$registryHolder = registryHolder; + } + + @Override + public void bridge$addDependencies(final Supplier> supplier, final RegistryType... dependencies) { + if (Arrays.stream(dependencies).allMatch(d -> this.impl$registryHolder.findRegistry(d) + .map(r -> ((MappedRegistryMixin) r).frozen) + .orElse(false))) { + this.impl$appendRegister(supplier); + return; + } + this.bridge$addDependencies(() -> this.impl$appendRegister(supplier), dependencies); + } + + private void impl$appendRegister(final Supplier> supplier) { + supplier.get().forEach((vk, vi, vv) -> + this.shadow$register( + net.minecraft.resources.ResourceKey.create(this.key, (ResourceLocation) (Object) vk), + vv, + RegistrationInfo.BUILT_IN + )); + } + + @Override + public void bridge$addDependencies(final Runnable runnable, final RegistryType... dependencies) { + this.impl$dependencies.addAll(List.of(dependencies)); + this.impl$preFreezeTasks.add(runnable); + } + + @Override + public Stream> bridge$pendingDependencies() { + return this.impl$dependencies.stream(); + } + + @Override + public void bridge$markEventCalled() { + this.impl$eventCalled = true; + } + + @Override + public boolean bridge$eventCalled() { + return this.impl$eventCalled; + } + + @Override + public void bridge$unfreeze() { + this.frozen = false; + this.allTags = MappedRegistry.TagSet.unbound(); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java index 01b7d782789..872a14e721c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java @@ -26,17 +26,12 @@ import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.launch.Launch; -import java.util.Map; -import java.util.function.Supplier; @Mixin(BuiltInRegistries.class) public abstract class BuiltInRegistriesMixin { @@ -44,18 +39,8 @@ public abstract class BuiltInRegistriesMixin { // We hook in here if we extend existing vanilla BuiltInRegistries with our own // This methods should then be called during bootstrap - @Shadow @Final private static Map> LOADERS; - - @Inject(method = "bootStrap", at = @At(value = "HEAD")) - private static void impl$beforeCreateContents(CallbackInfo ci) - { + @Inject(method = "freeze", at = @At(value = "HEAD")) + private static void impl$onFreeze(final CallbackInfo ci) { Launch.instance().lifecycle().establishEarlyGlobalRegistries(); } - - @Inject(method = "bootStrap", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/registries/BuiltInRegistries;freeze()V")) - private static void impl$beforeFreeze(CallbackInfo ci) - { - Launch.instance().lifecycle().finalizeEarlyGlobalRegistries(); - } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index dec6168190e..fd22bfbd74d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -24,8 +24,11 @@ */ package org.spongepowered.common.mixin.core.resources; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.serialization.Decoder; import net.minecraft.core.RegistrationInfo; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.ChatType; @@ -35,13 +38,30 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.DependencySorter; import org.spongepowered.api.adventure.ChatTypes; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; +import org.spongepowered.common.registry.SpongeRegistryHolder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; @Mixin(RegistryDataLoader.class) public class RegistryDataLoaderMixin { @@ -62,4 +82,28 @@ public class RegistryDataLoaderMixin { $$2.register(ResourceKey.create($$2.key(), (ResourceLocation) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); } } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", + at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) + private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + instance.stream() + .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + .forEach((k, v) -> { + ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + lifecycle.processServerRegistries(k, v.stream() + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); + }); + + List> loaders = new ArrayList<>(instance.size()); + dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); + + original.call(Collections.unmodifiableList(loaders), consumer); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/TreeNodePositionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java similarity index 60% rename from src/mixins/java/org/spongepowered/common/mixin/core/advancements/TreeNodePositionMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java index 0e2157c6685..0eb5e8828c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/TreeNodePositionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java @@ -22,28 +22,29 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.advancements; +package org.spongepowered.common.mixin.core.resources; -import net.minecraft.advancements.AdvancementNode; -import net.minecraft.advancements.TreeNodePosition; -import org.spongepowered.api.advancement.AdvancementTree; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.advancement.AdvancementTreeEvent; +import net.minecraft.resources.RegistryOps; +import net.minecraft.server.packs.resources.ResourceManager; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; -@Mixin(TreeNodePosition.class) -public abstract class TreeNodePositionMixin { +@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$Loader") +public abstract class RegistryDataLoader_LoaderMixin implements RegistryDataLoader_LoaderBridge { - @Inject(method = "run", at = @At("RETURN")) - private static void impl$onLayout(AdvancementNode node, CallbackInfo ci) { - final Cause cause = PhaseTracker.getInstance().currentCause(); - final AdvancementTreeEvent.GenerateLayout event = SpongeEventFactory.createAdvancementTreeEventGenerateLayout(cause, (AdvancementTree) node); - SpongeCommon.post(event); + private RegistryHolder impl$registryHolder; + + @Inject(method = "loadFromResources", at = @At("HEAD")) + private void impl$onLoadFromResources(final ResourceManager $$0, final RegistryOps.RegistryInfoLookup $$1, final CallbackInfo ci) { + this.impl$registryHolder = (RegistryHolder) $$0; + } + + @Override + public RegistryHolder bridge$registryHolder() { + return this.impl$registryHolder; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index b3e62b821f8..29504b2c2be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -60,6 +60,7 @@ import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.world.LoadWorldEvent; import org.spongepowered.api.event.world.UnloadWorldEvent; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.SubjectProxy; import org.spongepowered.api.world.DefaultWorldKeys; @@ -93,14 +94,14 @@ import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.config.inheritable.InheritableConfigHandle; import org.spongepowered.common.config.inheritable.WorldConfig; -import org.spongepowered.common.datapack.SpongeDataPackManager; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.generation.GenerationPhase; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import java.io.IOException; import java.util.Collection; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -427,13 +428,6 @@ public void setDifficulty(final Difficulty difficulty, final boolean force) { return this.impl$serviceProvider; } - @Inject(method = "reloadResources", at = @At(value = "HEAD")) - public void impl$reloadResources(final Collection datapacksToLoad, final CallbackInfoReturnable> cir) { - final List reloadablePacks = ((SpongeDataPackManager) this.dataPackManager()).registerPacks(); - datapacksToLoad.addAll(reloadablePacks); - this.shadow$getPackRepository().reload(); - } - @Override public String toString() { return this.getClass().getSimpleName(); @@ -458,4 +452,10 @@ public String toString() { cir.setReturnValue(true); } } + + @Override + public void bridge$reloadServerRegistries(final RegistryHolder holder) { + ((SpongeRegistryHolder) holder).setRootMinecraftRegistry(this.shadow$registryAccess()); + Launch.instance().lifecycle().beginEstablishServerRegistries(holder); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerRegistriesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerRegistriesMixin.java deleted file mode 100644 index 4671fc49048..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerRegistriesMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.core.LayeredRegistryAccess; -import net.minecraft.core.RegistryAccess; -import net.minecraft.server.RegistryLayer; -import net.minecraft.server.ReloadableServerRegistries; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.launch.Launch; - -@Mixin(ReloadableServerRegistries.class) -public abstract class ReloadableServerRegistriesMixin { - - @WrapOperation(method = "reload", at = @At(value = "INVOKE", - target = "Lnet/minecraft/core/LayeredRegistryAccess;getAccessForLoading(Ljava/lang/Object;)Lnet/minecraft/core/RegistryAccess$Frozen;")) - private static RegistryAccess.Frozen impl$onGetRegistryAccess(final LayeredRegistryAccess instance, final Object layer, final Operation original) { - final RegistryAccess.Frozen registryAccess = original.call(instance, layer); - final var lifecycle = Launch.instance().lifecycle(); - lifecycle.establishGlobalRegistries(registryAccess, (RegistryLayer) layer); - return registryAccess; - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java new file mode 100644 index 00000000000..189bba4c36f --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java @@ -0,0 +1,92 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.server; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import net.minecraft.commands.Commands; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.ReloadableServerRegistries; +import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.flag.FeatureFlagSet; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.accessor.core.MappedRegistryAccessor; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.stream.Stream; + +@Mixin(ReloadableServerResources.class) +public abstract class ReloadableServerResourcesMixin { + + @SuppressWarnings({"unchecked", "rawtypes"}) + @ModifyExpressionValue(method = "loadResources", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerRegistries;reload(Lnet/minecraft/core/LayeredRegistryAccess;Ljava/util/List;Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private static CompletableFuture impl$onLoadResources(final CompletableFuture original, + final ResourceManager $$0, final LayeredRegistryAccess $$1, final List> $$2, + final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final int $$5, final Executor $$6, final Executor $$7) { + return original.thenApply(r -> { + final SpongeRegistryHolder spongeRegistryHolder = (SpongeRegistryHolder) $$0; + spongeRegistryHolder.setRootMinecraftRegistry(r.layers().compositeAccess()); + spongeRegistryHolder.registryHolder().freezeSpongeDynamicRegistries(false); + + final List spongeRegistries = (List) Stream.concat( + spongeRegistryHolder.streamRegistries(RegistryRoots.SPONGE), + Sponge.game().streamRegistries(RegistryRoots.SPONGE)).toList(); + + final RegistryAccess.Frozen reloadable = r.layers().getLayer(RegistryLayer.RELOADABLE); + final RegistryAccess.Frozen combined = new RegistryAccess.ImmutableRegistryAccess((Stream) Stream.concat( + reloadable.registries(), + spongeRegistries.stream().filter(v -> ((MappedRegistryAccessor) v).accessor$frozen()).map(v -> new RegistryAccess.RegistryEntry<>(v.key(), v)) + )).freeze(); + + return new ReloadableServerRegistries.LoadResult( + r.layers().replaceFrom(RegistryLayer.RELOADABLE, combined), + HolderLookup.Provider.create((Stream) Stream.concat(r.lookupWithUpdatedTags().listRegistries(), spongeRegistries.stream())) + ); + }); + } + + @ModifyReturnValue(method = "loadResources", at = @At(value = "RETURN")) + private static CompletableFuture impl$onLoaded(final CompletableFuture original, + final ResourceManager $$0, final LayeredRegistryAccess $$1, final List> $$2, + final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final int $$5, final Executor $$6, final Executor $$7) { + return original.thenApply(r -> { + Launch.instance().lifecycle().endEstablishServerRegistries((RegistryHolder) $$0); + return r; + }); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java new file mode 100644 index 00000000000..bb1e1a3c9f2 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java @@ -0,0 +1,81 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.server; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementNode; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.ServerAdvancementManager; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.advancement.AdvancementTree; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.advancement.AdvancementTreeEvent; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryEntry; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.RegistryHolderLogic; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Mixin(ServerAdvancementManager.class) +public abstract class ServerAdvancementManagerMixin { + + @SuppressWarnings({"unchecked"}) + @WrapMethod(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V") + private void impl$onApply(final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2, final Operation original) { + final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$1).registryHolder(); + final Registry registry = (Registry) (Object) registryHolder.registry(RegistryTypes.ADVANCEMENT); + $$0.forEach((k, v) -> registry.register((ResourceKey) (Object) k, v)); + Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$1, Stream.of(registry)); + original.call(registry.streamEntries().collect(Collectors.toMap(RegistryEntry::key, RegistryEntry::value)), $$1, $$2); + } + + @WrapOperation(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/TreeNodePosition;run(Lnet/minecraft/advancements/AdvancementNode;)V")) + private void impl$onLayout(final AdvancementNode instance, final Operation original, + final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2) { + original.call(instance); + + final Cause cause = PhaseTracker.getInstance().currentCause(); + final AdvancementTreeEvent.GenerateLayout event = SpongeEventFactory.createAdvancementTreeEventGenerateLayout( + cause, ((SpongeRegistryHolder) $$1).registryHolder(), (AdvancementTree) instance); + SpongeCommon.post(event); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index d14acc9b3df..371555bd1ab 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -27,41 +27,42 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import com.mojang.datafixers.util.Pair; -import net.minecraft.core.LayeredRegistryAccess; -import net.minecraft.core.RegistryAccess; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.WorldLoader; import net.minecraft.server.packs.resources.CloseableResourceManager; import net.minecraft.world.level.WorldDataConfiguration; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; + + @Mixin(WorldLoader.class) public abstract class WorldLoaderMixin { - @ModifyExpressionValue(method = "load", at = @At(value = "INVOKE", + @WrapOperation(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$PackConfig;createResourceManager()Lcom/mojang/datafixers/util/Pair;")) - private static Pair impl$onCreateResourceManager(final Pair pair) { - Launch.instance().lifecycle().setWorldDataConfiguration(pair.getFirst()); + private static Pair impl$onCreateResourceManager(final WorldLoader.PackConfig instance, + final Operation> original) { + final Pair pair = original.call(instance); + final CloseableResourceManager resourceManager = pair.getSecond(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.setWorldDataConfiguration(pair.getFirst()); + lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); return pair; } - @WrapOperation(method = "load", at = @At(value = "INVOKE", - target = "Lnet/minecraft/core/LayeredRegistryAccess;getAccessForLoading(Ljava/lang/Object;)Lnet/minecraft/core/RegistryAccess$Frozen;")) - private static RegistryAccess.Frozen impl$onGetRegistryAccess(final LayeredRegistryAccess instance, final Object layer, final Operation original) { - final RegistryAccess.Frozen registryAccess = original.call(instance, layer); - final var lifecycle = Launch.instance().lifecycle(); - lifecycle.establishGlobalRegistries(registryAccess, (RegistryLayer) layer); - return registryAccess; - } - - @WrapOperation(method = "load", at = @At(value = "INVOKE", - target = "Lnet/minecraft/core/LayeredRegistryAccess;replaceFrom(Ljava/lang/Object;[Lnet/minecraft/core/RegistryAccess$Frozen;)Lnet/minecraft/core/LayeredRegistryAccess;")) - private static LayeredRegistryAccess impl$afterLoadDimensionRegistries(final LayeredRegistryAccess instance, final Object worldGenLayer, final RegistryAccess.Frozen[] registries, final Operation> original) { - final var lifecycle = Launch.instance().lifecycle(); - lifecycle.establishGlobalRegistries(registries[0], RegistryLayer.DIMENSIONS); - return original.call(instance, worldGenLayer, registries); + @ModifyExpressionValue(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$WorldDataSupplier;get(Lnet/minecraft/server/WorldLoader$DataLoadContext;)Lnet/minecraft/server/WorldLoader$DataLoadOutput;")) + private static WorldLoader.DataLoadOutput impl$onBakedDimensionRegistries(final WorldLoader.DataLoadOutput original, + final @Local CloseableResourceManager resourceManager) { + original.finalDimensions().registries().forEach(r -> ((WritableRegistryBridge) r.value()).bridge$unfreeze()); + Launch.instance().lifecycle().processServerRegistries((RegistryHolder) resourceManager, original.finalDimensions().registries().map(e -> (Registry) e.value())); + original.finalDimensions().registries().forEach(r -> r.value().freeze()); + return original; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java index 758ddb4846b..3539859ecd7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java @@ -44,7 +44,6 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.server.players.GameProfileCacheBridge; -import org.spongepowered.common.datapack.SpongeDataPackManager; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.mixin.core.server.MinecraftServerMixin; @@ -71,8 +70,6 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin { }); SpongeCommon.game().setServer(this); $$6.profileCache().load(); - - ((SpongeDataPackManager) this.dataPackManager()).init(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java deleted file mode 100644 index 99fbd9f1af7..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/AbstractCookingRecipeSerializerMixin.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import static org.spongepowered.common.util.Constants.Recipe.SPONGE_TYPE; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.AbstractCookingRecipe; -import net.minecraft.world.item.crafting.BlastingRecipe; -import net.minecraft.world.item.crafting.CampfireCookingRecipe; -import net.minecraft.world.item.crafting.CookingBookCategory; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.SmeltingRecipe; -import net.minecraft.world.item.crafting.SmokingRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.item.crafting.CookingRecipeBridge; -import org.spongepowered.common.bridge.world.item.crafting.RecipeResultBridge; -import org.spongepowered.common.item.recipe.ResultFunctionRecipe; -import org.spongepowered.common.item.recipe.cooking.CookingRecipeFactory; -import org.spongepowered.common.item.recipe.cooking.SpongeBlastingRecipe; -import org.spongepowered.common.item.recipe.cooking.SpongeCampfireCookingRecipe; -import org.spongepowered.common.item.recipe.cooking.SpongeSmeltingRecipe; -import org.spongepowered.common.item.recipe.cooking.SpongeSmokingRecipe; -import org.spongepowered.common.util.Constants; - -import java.util.function.Function; - -@Mixin(AbstractCookingRecipe.Serializer.class) -public abstract class AbstractCookingRecipeSerializerMixin { - - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private MapCodec impl$onCreateCodec( - final Function, ? extends App, T>> builder, - final AbstractCookingRecipe.Factory $$0, - final int defaultCookingTime) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - - final T constructed = $$0.create(null, null, null, null, 0, 0); - if (constructed instanceof BlastingRecipe) { - var spongeCodec = AbstractCookingRecipeSerializerMixin.impl$buildCodec(SpongeBlastingRecipe::new, defaultCookingTime); - return Codec.mapEither(spongeCodec, mcMapCodec).xmap(to -> to.map(si -> (T) si, i -> i), - fr -> { - if (fr instanceof SpongeBlastingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } - - if (constructed instanceof CampfireCookingRecipe) { - var spongeCodec = AbstractCookingRecipeSerializerMixin.impl$buildCodec(SpongeCampfireCookingRecipe::new, defaultCookingTime); - return Codec.mapEither(spongeCodec, mcMapCodec).xmap(to -> to.map(si -> (T) si, i -> i), - fr -> { - if (fr instanceof SpongeCampfireCookingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } - - - if (constructed instanceof SmeltingRecipe) { - var spongeCodec = AbstractCookingRecipeSerializerMixin.impl$buildCodec(SpongeSmeltingRecipe::new, defaultCookingTime); - return Codec.mapEither(spongeCodec, mcMapCodec).xmap(to -> to.map(si -> (T) si, i -> i), - fr -> { - if (fr instanceof SpongeSmeltingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } - - - - if (constructed instanceof SmokingRecipe) { - var spongeCodec = AbstractCookingRecipeSerializerMixin.impl$buildCodec(SpongeSmokingRecipe::new, defaultCookingTime); - return Codec.mapEither(spongeCodec, mcMapCodec).xmap(to -> to.map(si -> (T) si, i -> i), - fr -> { - if (fr instanceof SpongeSmokingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } - - // TODO no sponge handling? - return mcMapCodec; - } - - private static MapCodec impl$buildCodec(CookingRecipeFactory factory, int defaultCookingTime) - { - return RecordCodecBuilder.mapCodec( - $$2 -> $$2.group( - Codec.STRING.fieldOf(SPONGE_TYPE).forGetter(a -> "custom"), - Codec.STRING.optionalFieldOf("group", "").forGetter(AbstractCookingRecipe::group), - CookingBookCategory.CODEC.fieldOf("category").orElse(CookingBookCategory.MISC).forGetter(AbstractCookingRecipe::category), - Ingredient.CODEC.fieldOf(Constants.Recipe.COOKING_INGREDIENT).forGetter($$0x -> ((CookingRecipeBridge) $$0x).bridge$ingredient()), - BuiltInRegistries.ITEM.byNameCodec().xmap(ItemStack::new, ItemStack::getItem).fieldOf(Constants.Recipe.RESULT).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$result()), - Codec.FLOAT.fieldOf(Constants.Recipe.COOKING_EXP).orElse(0.0F).forGetter(AbstractCookingRecipe::experience), - Codec.INT.fieldOf(Constants.Recipe.COOKING_TIME).orElse(defaultCookingTime).forGetter(AbstractCookingRecipe::cookingTime), - ItemStack.CODEC.optionalFieldOf(Constants.Recipe.SPONGE_RESULT, ItemStack.EMPTY).forGetter($$0x -> ((RecipeResultBridge)$$0x).bridge$spongeResult()), - Codec.STRING.optionalFieldOf(Constants.Recipe.SPONGE_RESULTFUNCTION).forGetter(ResultFunctionRecipe::resultFunctionId) - ) - .apply($$2, factory::create) - ); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java deleted file mode 100644 index c29e4b941b4..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/CustomRecipeSerializerMixin.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.CustomRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.item.recipe.crafting.custom.SpongeSpecialRecipe; - -import java.util.function.Function; - -@Mixin(CustomRecipe.Serializer.class) -public abstract class CustomRecipeSerializerMixin { - - - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private MapCodec impl$onCreateCodec(final Function, ? extends App, T>> builder) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - final var eitherMapCodec = Codec.mapEither((MapCodec) SpongeSpecialRecipe.SPONGE_CODEC, mcMapCodec); - return eitherMapCodec.xmap(to -> to.map(si -> si, i -> i), fr -> { - if (fr instanceof SpongeSpecialRecipe) { - return Either.left(fr); - } - return Either.right(fr); - }); - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java index 6a88a92d0e8..99704db7bef 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java @@ -24,18 +24,35 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import net.minecraft.core.HolderLookup; +import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.RegistryHolderLogic; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.stream.Stream; @Mixin(RecipeManager.class) public abstract class RecipeManagerMixin { @@ -60,4 +77,17 @@ public abstract class RecipeManagerMixin { return parsed; } + @SuppressWarnings("unchecked") + @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/world/item/crafting/RecipeMap;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V")) + private void impl$onPrepare(final ResourceManager $$0, final FileToIdConverter $$1, final DynamicOps $$2, final Codec> $$3, + final Map> $$4, final Operation original) { + SortedMap> result = new TreeMap<>(); + original.call($$0, $$1, $$2, $$3, result); + final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$0).registryHolder(); + final Registry> registry = (Registry>) (Object) registryHolder.registry(RegistryTypes.RECIPE); + result.forEach((k, v) -> registry.register((org.spongepowered.api.ResourceKey) (Object) k, v)); + Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$0, Stream.of(registry)); + registry.streamEntries().forEach(e -> $$4.put((ResourceLocation) (Object) e.key(), e.value())); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipe_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipe_SerializerMixin.java deleted file mode 100644 index 10af39bc8f3..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipe_SerializerMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.world.item.crafting.ShapedRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.item.recipe.crafting.shaped.SpongeShapedRecipe; - -import java.util.function.Function; - -@Mixin(ShapedRecipe.Serializer.class) -public abstract class ShapedRecipe_SerializerMixin { - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private static MapCodec impl$onCreateCodec(final Function, ? extends App, ShapedRecipe>> builder) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - return Codec.mapEither(SpongeShapedRecipe.SPONGE_CODEC, mcMapCodec).xmap(to -> to.map(si -> si, i -> i), - fr -> { - if (fr instanceof SpongeShapedRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipe_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipe_SerializerMixin.java deleted file mode 100644 index a8bf6cacf16..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipe_SerializerMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.world.item.crafting.ShapelessRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.item.recipe.crafting.shapeless.SpongeShapelessRecipe; - -import java.util.function.Function; - -@Mixin(ShapelessRecipe.Serializer.class) -public abstract class ShapelessRecipe_SerializerMixin { - - - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private static MapCodec impl$onCreateCodec( - final Function, ? extends App, ShapelessRecipe>> builder) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - return Codec.mapEither(SpongeShapelessRecipe.SPONGE_CODEC, mcMapCodec).xmap(to -> to.map(si -> si, i -> i), - fr -> { - if (fr instanceof SpongeShapelessRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipe_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipe_SerializerMixin.java deleted file mode 100644 index 251b5bb9d9d..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipe_SerializerMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.world.item.crafting.SingleItemRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.item.recipe.stonecutting.SpongeStonecuttingRecipe; - -import java.util.function.Function; - -@Mixin(SingleItemRecipe.Serializer.class) -public abstract class SingleItemRecipe_SerializerMixin { - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private MapCodec impl$onCreateCodec(final Function, ? extends App, SingleItemRecipe>> builder) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - return Codec.mapEither(SpongeStonecuttingRecipe.SPONGE_CODEC, mcMapCodec).xmap(to -> to.map(si -> si, i -> i), - fr -> { - if (fr instanceof SpongeStonecuttingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipe_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipe_SerializerMixin.java deleted file mode 100644 index fd37c712862..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipe_SerializerMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.item.crafting; - -import com.mojang.datafixers.kinds.App; -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.world.item.crafting.SmithingTransformRecipe; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.item.recipe.smithing.SpongeSmithingRecipe; - -import java.util.function.Function; - -@Mixin(SmithingTransformRecipe.Serializer.class) -public abstract class SmithingTransformRecipe_SerializerMixin { - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;mapCodec(Ljava/util/function/Function;)Lcom/mojang/serialization/MapCodec;")) - private static MapCodec impl$onCreateCodec(final Function, ? extends App, SmithingTransformRecipe>> builder) { - final var mcMapCodec = RecordCodecBuilder.mapCodec(builder); - return Codec.mapEither(SpongeSmithingRecipe.SPONGE_CODEC, mcMapCodec).xmap(to -> to.map(si -> si, i -> i), - fr -> { - if (fr instanceof SpongeSmithingRecipe si) { - return Either.left(si); - } - return Either.right(fr); - }); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/LevelStemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/LevelStemMixin.java index d2b159b0593..12845f1430a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/LevelStemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/LevelStemMixin.java @@ -30,8 +30,6 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.LevelStem; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.data.DataManipulator; -import org.spongepowered.api.data.Keys; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -145,37 +143,9 @@ public abstract class LevelStemMixin implements LevelStemBridge, SpongeDataHolde } @Override - public LevelStem bridge$decorateData(final DataManipulator data) { - this.impl$displayName = data.getOrNull(Keys.DISPLAY_NAME); - this.impl$gameMode = (GameType) (Object) data.get(Keys.GAME_MODE).orElse(null); - this.impl$difficulty = (Difficulty) (Object) data.get(Keys.WORLD_DIFFICULTY).orElse(null); - this.impl$serializationBehavior = data.getOrElse(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.AUTOMATIC); - this.impl$viewDistance = data.getOrNull(Keys.VIEW_DISTANCE); - this.impl$spawnPosition = data.getOrNull(Keys.SPAWN_POSITION); - this.impl$loadOnStartup = data.getOrElse(Keys.IS_LOAD_ON_STARTUP, true); - this.impl$performsSpawnLogic = data.getOrElse(Keys.PERFORM_SPAWN_LOGIC, false); - this.impl$hardcore = data.getOrNull(Keys.HARDCORE); - this.impl$allowCommands = data.getOrNull(Keys.COMMANDS); - this.impl$pvp = data.getOrNull(Keys.PVP); - this.impl$seed = data.getOrNull(Keys.SEED); - return (LevelStem) (Object) this; - } - - @Override - public SpongeWorldTemplate.SpongeDataSection bridge$createData() { - return new SpongeWorldTemplate.SpongeDataSection( - this.impl$displayName, - this.impl$gameMode, - this.impl$difficulty, - this.impl$serializationBehavior, - this.impl$viewDistance, - this.impl$spawnPosition, - this.impl$loadOnStartup, - this.impl$performsSpawnLogic, - this.impl$hardcore, - this.impl$allowCommands, - this.impl$pvp, - this.impl$seed - ); + public boolean bridge$hasLegacyData() { + return this.impl$displayName != null || this.impl$gameMode != null || this.impl$difficulty != null || this.impl$serializationBehavior != null + || this.impl$viewDistance != null || this.impl$spawnPosition != null || this.impl$hardcore != null || this.impl$allowCommands != null + || this.impl$pvp != null || this.impl$seed != null; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 3721accbe50..8b79a84e067 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -28,22 +28,33 @@ import com.google.common.collect.HashBiMap; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; +import com.mojang.serialization.DynamicOps; import net.kyori.adventure.text.Component; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntArrayTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.WorldDimensions; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WorldData; @@ -53,6 +64,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.accessor.server.MinecraftServerAccessor; import org.spongepowered.common.accessor.world.level.LevelSettingsAccessor; @@ -68,9 +80,11 @@ import org.spongepowered.math.vector.Vector3i; import java.util.Collections; +import java.util.Map; import java.util.Optional; import java.util.StringJoiner; import java.util.UUID; +import java.util.stream.Collectors; @Mixin(PrimaryLevelData.class) public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldData, PrimaryLevelDataBridge, DataCompoundHolder { @@ -84,17 +98,16 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Shadow public abstract void shadow$setSpawn(BlockPos p_176143_1_, float p_176143_2_); // @formatter:on + @Shadow + private boolean difficultyLocked; private final SpongeServerLevelData impl$spongeData = new SpongeServerLevelData(); private DimensionType impl$dimensionType; - @Nullable private SerializationBehavior impl$serializationBehavior; - @Nullable private Component impl$displayName; - @Nullable private Integer impl$viewDistance; - private Boolean impl$pvp; + private ChunkGenerator impl$chunkGenerator; private final BiMap impl$playerUniqueIdMap = HashBiMap.create(); - private boolean impl$customDifficulty = false, impl$customGameType = false, impl$customSpawnPosition = false, impl$loadOnStartup, impl$performsSpawnLogic; + private boolean impl$customDifficulty = false, impl$customGameType = false, impl$customSpawnPosition = false; private BiMap impl$mapUUIDIndex = HashBiMap.create(); private @Nullable CompoundTag impl$compound; @@ -141,70 +154,75 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Override public Optional bridge$pvp() { - return Optional.ofNullable(this.impl$pvp); + return Optional.ofNullable(this.impl$spongeData.configAdapter().get().world.pvpEnabled); } @Override public void bridge$setPvp(@Nullable final Boolean pvp) { - this.impl$pvp = pvp; + this.impl$spongeData.configAdapter().get().world.pvpEnabled = pvp; } @Override public boolean bridge$performsSpawnLogic() { - return this.impl$performsSpawnLogic; + return this.impl$spongeData.configAdapter().get().world.keepSpawnLoaded; } @Override public void bridge$setPerformsSpawnLogic(final boolean performsSpawnLogic) { - this.impl$performsSpawnLogic = performsSpawnLogic; + this.impl$spongeData.configAdapter().get().world.keepSpawnLoaded = performsSpawnLogic; } @Override public boolean bridge$loadOnStartup() { - return this.impl$loadOnStartup; + return this.impl$spongeData.configAdapter().get().world.loadOnStartup; } @Override public void bridge$setLoadOnStartup(final boolean loadOnStartup) { - this.impl$loadOnStartup = loadOnStartup; + this.impl$spongeData.configAdapter().get().world.loadOnStartup = loadOnStartup; } @Override public Optional bridge$serializationBehavior() { - return Optional.ofNullable(this.impl$serializationBehavior); + return Optional.ofNullable(this.impl$spongeData.configAdapter().get().world.serializationBehavior); } @Override public void bridge$setSerializationBehavior(@Nullable final SerializationBehavior behavior) { - this.impl$serializationBehavior = behavior; + this.impl$spongeData.configAdapter().get().world.serializationBehavior = behavior; } @Override public Optional bridge$displayName() { - return Optional.ofNullable(this.impl$displayName); + return Optional.ofNullable(this.impl$spongeData.configAdapter().get().world.displayName); } @Override public void bridge$setDisplayName(@Nullable final Component displayName) { - this.impl$displayName = displayName; + this.impl$spongeData.configAdapter().get().world.displayName = displayName; } @Override public Optional bridge$viewDistance() { - return Optional.ofNullable(this.impl$viewDistance); + return Optional.ofNullable(this.impl$spongeData.configAdapter().get().world.viewDistance); } @Override public void bridge$setViewDistance(@Nullable final Integer viewDistance) { - this.impl$viewDistance = viewDistance; + this.impl$spongeData.configAdapter().get().world.viewDistance = viewDistance; this.bridge$triggerViewDistanceLogic(); } - @Override public void bridge$populateFromLevelStem(final LevelStem dimension) { - final LevelStemBridge bridge = (LevelStemBridge) (Object) dimension; this.impl$dimensionType = dimension.type().value(); - this.impl$displayName = bridge.bridge$displayName(); + this.impl$chunkGenerator = dimension.generator(); + + // Legacy back compat + final LevelStemBridge bridge = (LevelStemBridge) (Object) dimension; + if (!bridge.bridge$hasLegacyData()) { + return; + } + Optional.ofNullable(bridge.bridge$displayName()).ifPresent(this::bridge$setDisplayName); final Difficulty difficulty = bridge.bridge$difficulty(); final GameType gameType = bridge.bridge$gameMode(); final Boolean isHardcore = bridge.bridge$hardcore(); @@ -216,13 +234,13 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat this.impl$customGameType = true; } this.settings = new LevelSettings( - this.settings.levelName(), - gameType == null ? this.settings.gameType() : gameType, - isHardcore == null ? this.settings.hardcore() : isHardcore, - difficulty == null ? this.settings.difficulty() : difficulty, - allowCommands == null ? this.settings.allowCommands() : allowCommands, - this.settings.gameRules(), - this.settings.getDataConfiguration()); + this.settings.levelName(), + gameType == null ? this.settings.gameType() : gameType, + isHardcore == null ? this.settings.hardcore() : isHardcore, + difficulty == null ? this.settings.difficulty() : difficulty, + allowCommands == null ? this.settings.allowCommands() : allowCommands, + this.settings.gameRules(), + this.settings.getDataConfiguration()); final Vector3i spawnPos = bridge.bridge$spawnPosition(); if (spawnPos != null) { @@ -230,11 +248,11 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat this.impl$customSpawnPosition = true; } - this.impl$serializationBehavior = bridge.bridge$serializationBehavior(); - this.impl$pvp = bridge.bridge$pvp(); - this.impl$loadOnStartup = bridge.bridge$loadOnStartup(); - this.impl$performsSpawnLogic = bridge.bridge$performsSpawnLogic(); - this.impl$viewDistance = bridge.bridge$viewDistance(); + Optional.ofNullable(bridge.bridge$serializationBehavior()).ifPresent(this::bridge$setSerializationBehavior); + Optional.ofNullable(bridge.bridge$pvp()).ifPresent(this::bridge$setPvp); + this.bridge$setLoadOnStartup(bridge.bridge$loadOnStartup()); + this.bridge$setPerformsSpawnLogic(bridge.bridge$performsSpawnLogic()); + this.bridge$setViewDistance(bridge.bridge$viewDistance()); } @Override @@ -363,4 +381,16 @@ public String toString() { public void data$setCompound(final CompoundTag nbt) { this.impl$compound = nbt; } + + @Redirect(method = "setTagData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldGenSettings;encode(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/world/level/levelgen/WorldOptions;Lnet/minecraft/core/RegistryAccess;)Lcom/mojang/serialization/DataResult;")) + private DataResult impl$onEncodeWorldGenSettings(final DynamicOps $$0, final WorldOptions $$1, final RegistryAccess $$2) { + final Map, LevelStem> dimensions = $$2.lookupOrThrow(Registries.LEVEL_STEM) + .listElements() + .collect(Collectors.toMap(Holder.Reference::key, Holder.Reference::value)); + if (this.impl$dimensionType != null && this.impl$chunkGenerator != null) { + dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (ResourceLocation) (Object) this.impl$spongeData.key()), + $ -> new LevelStem($$2.lookupOrThrow(Registries.DIMENSION_TYPE).wrapAsHolder(this.impl$dimensionType), this.impl$chunkGenerator)); + } + return WorldGenSettings.encode($$0, $$1, new WorldDimensions(dimensions)); + } } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 0dfaca38272..639210f4640 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -26,6 +26,7 @@ "minecraft.commands.arguments.selector.EntitySelectorParserMixin_API", "minecraft.commands.synchronization.SuggestionProviders_WrapperMixin_API", "minecraft.core.MappedRegistryMixin_API", + "minecraft.core.RegistryMixin", "minecraft.core.particles.ParticleTypeMixin_API", "minecraft.entity.boss.WitherEntityMixin_API", "minecraft.item.BlockItemMixin_API", @@ -61,6 +62,7 @@ "minecraft.server.packs.repository.PackCompatibilityMixin_API", "minecraft.server.packs.repository.PackMixin_API", "minecraft.server.packs.repository.PackRepositoryMixin_API", + "minecraft.server.packs.resources.MultiPackResourceManagerMixin_API", "minecraft.server.packs.resources.ResourceManagerMixin_API", "minecraft.server.players.BanListEntryMixin_API", "minecraft.server.players.GameProfileCacheMixin_API", @@ -452,6 +454,7 @@ "minecraft.world.level.chunk.LevelChunkMixin_API", "minecraft.world.level.chunk.ProtoChunkMixin_API", "minecraft.world.level.dimension.DimensionTypeMixin_API", + "minecraft.world.level.dimension.LevelStemMixin_API", "minecraft.world.level.gameevent.PositionSourceMixin_API", "minecraft.world.level.levelgen.DensityFunctionMixin_API", "minecraft.world.level.levelgen.FlatLevelSourceMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 39767176fcc..e7f533139a3 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -4,6 +4,7 @@ "package": "org.spongepowered.common.mixin.core", "mixinPriority": 1101, "mixins": [ + "HolderLookup_ProviderMixin", "advancements.AdvancementMixin", "advancements.AdvancementProgressMixin", "advancements.CriteriaTriggersMixin", @@ -11,7 +12,6 @@ "advancements.CriterionProgressMixin", "advancements.CriterionTrigger_ListenerMixin", "advancements.DisplayInfoMixin", - "advancements.TreeNodePositionMixin", "adventure.KeyMixin", "adventure.bossbar.HackyBossBarPlatformBridgeMixin", "adventure.chat.SignedMessageMixin", @@ -53,11 +53,13 @@ "network.syncher.SynchedEntityData_BuilderMixin", "network.syncher.SynchedEntityDataMixin", "registries.BuiltInRegistriesMixin", + "resources.RegistryDataLoader_LoaderMixin", "resources.RegistryDataLoaderMixin", "server.MainMixin", "server.MinecraftServerMixin", "server.PlayerAdvancementsMixin", - "server.ReloadableServerRegistriesMixin", + "server.ReloadableServerResourcesMixin", + "server.ServerAdvancementManagerMixin", "server.ServerFunctionManagerMixin", "server.ServerScoreboardMixin", "server.WorldLoaderMixin", @@ -209,17 +211,11 @@ "world.item.ServerItemCooldownsMixin", "world.item.TeleportRandomlyConsumeEffectMixin", "world.item.crafting.AbstractCookingRecipeMixin", - "world.item.crafting.AbstractCookingRecipeSerializerMixin", - "world.item.crafting.CustomRecipeSerializerMixin", "world.item.crafting.IngredientMixin", "world.item.crafting.RecipeManagerMixin", - "world.item.crafting.ShapedRecipe_SerializerMixin", "world.item.crafting.ShapedRecipeMixin", - "world.item.crafting.ShapelessRecipe_SerializerMixin", "world.item.crafting.ShapelessRecipeMixin", - "world.item.crafting.SingleItemRecipe_SerializerMixin", "world.item.crafting.SingleItemRecipeMixin", - "world.item.crafting.SmithingTransformRecipe_SerializerMixin", "world.item.crafting.SmithingTransformRecipeMixin", "world.item.enchantment.EnchantmentMixin", "world.level.BaseSpawnerMixin", diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java b/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java index 999f80b0134..86433b2234d 100644 --- a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java +++ b/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java @@ -59,6 +59,11 @@ public Optional> findRegistry( .map(r -> (Registry) r); } + @Override + public Stream> streamRegistries() { + return Stream.empty(); + } + @Override public Stream> streamRegistries(final ResourceKey root) { return Stream.of(); diff --git a/testplugins/src/main/java/org/spongepowered/test/advancement/AdvancementTest.java b/testplugins/src/main/java/org/spongepowered/test/advancement/AdvancementTest.java index 78e61eb768f..34e9cbeeef4 100644 --- a/testplugins/src/main/java/org/spongepowered/test/advancement/AdvancementTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/advancement/AdvancementTest.java @@ -29,8 +29,8 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; +import org.spongepowered.api.advancement.Advancement; import org.spongepowered.api.advancement.AdvancementProgress; -import org.spongepowered.api.advancement.AdvancementTemplate; import org.spongepowered.api.advancement.AdvancementTree; import org.spongepowered.api.advancement.AdvancementTypes; import org.spongepowered.api.advancement.DisplayInfo; @@ -43,7 +43,6 @@ import org.spongepowered.api.advancement.criteria.trigger.FilteredTriggerConfiguration; import org.spongepowered.api.advancement.criteria.trigger.Trigger; import org.spongepowered.api.block.BlockTypes; -import org.spongepowered.api.command.exception.CommandException; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.data.persistence.AbstractDataBuilder; import org.spongepowered.api.data.persistence.DataContainer; @@ -58,13 +57,15 @@ import org.spongepowered.api.event.filter.cause.First; import org.spongepowered.api.event.item.inventory.ChangeInventoryEvent; import org.spongepowered.api.event.item.inventory.container.InteractContainerEvent; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterDataEvent; import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.item.inventory.BlockCarrier; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.query.QueryTypes; import org.spongepowered.api.item.inventory.type.CarriedInventory; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.RegistryRegistrationSet; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; @@ -75,50 +76,194 @@ @Plugin("advancementtest") public final class AdvancementTest implements LoadableModule { + public static final String NAMESPACE = "advancementtest"; + + public static final class Triggers { + + public static final class Holder { + + private static final RegistryRegistrationSet> TRIGGERS = Triggers.TRIGGER_BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder> TRIGGER_BUILDER = RegistryRegistrationSet.builder(RegistryTypes.TRIGGER, Sponge::game); + + public static final DefaultedRegistryReference> INVENTORY_CHANGE_TRIGGER = Triggers.TRIGGER_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "my_inventory_trigger"), + () -> Trigger.builder() + .dataSerializableConfig(InventoryChangeTriggerConfig.class) + .listener(triggerEvent -> { + final ItemStack stack = triggerEvent.trigger().configuration().stack; + final int found = triggerEvent.player().inventory().query(QueryTypes.ITEM_STACK_IGNORE_QUANTITY, stack).totalQuantity(); + triggerEvent.setResult(stack.quantity() <= found); + }) + .name("my_inventory_trigger") + .build() + ); + } + + public static final class AdvancementCriteria { + + public static final AdvancementCriterion SOME_DIRT = AdvancementCriterion.builder().trigger( + Triggers.INVENTORY_CHANGE_TRIGGER.get(), + FilteredTrigger.builder() + .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT))) + .build()).name("some_dirt").build(); + + public static final AdvancementCriterion LOTS_OF_DIRT = AdvancementCriterion.builder().trigger( + Triggers.INVENTORY_CHANGE_TRIGGER.get(), + FilteredTrigger.builder() + .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT, 64))) + .build()).name("lots_of_dirt").build(); + + public static final AdvancementCriterion TONS_OF_DIRT = AdvancementCriterion.builder().trigger( + Triggers.INVENTORY_CHANGE_TRIGGER.get(), + FilteredTrigger.builder() + .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT, 64*9))) + .build()).name("tons_of_dirt").build(); + + public static final ScoreAdvancementCriterion COUNTER_1 = ScoreAdvancementCriterion.builder().goal(10).name("counter").build(); + public static final AdvancementCriterion COUNTER_1_BYPASS = AdvancementCriterion.dummy(); + + public static final ScoreAdvancementCriterion COUNTER_2 = ScoreAdvancementCriterion.builder().goal(20).name("counter").build(); + + public static final AdvancementCriterion A = AdvancementCriterion.builder().name("A").build(); + public static final AdvancementCriterion B = AdvancementCriterion.builder().name("B").build(); + public static final AdvancementCriterion C = AdvancementCriterion.builder().name("C").build(); + public static final AdvancementCriterion D = AdvancementCriterion.builder().name("D").build(); + public static final AdvancementCriterion E = AdvancementCriterion.builder().name("E").build(); + public static final AdvancementCriterion F = AdvancementCriterion.builder().name("F").build(); + + public static final AdvancementCriterion COMBINATION = OrCriterion.of( + AdvancementCriteria.A, + AndCriterion.of(AdvancementCriteria.B, OrCriterion.of(AdvancementCriteria.C, AdvancementCriteria.D)), + AndCriterion.of(AdvancementCriteria.E, AdvancementCriteria.F)); + } + + public static final class Advancements { + + public static final class Holder { + + private static final RegistryRegistrationSet ADVANCEMENTS = Advancements.ADVANCEMENT_BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder ADVANCEMENT_BUILDER = RegistryRegistrationSet.builder(RegistryTypes.ADVANCEMENT, Sponge::server); + + public static final DefaultedRegistryReference ROOT_ADVANCEMENT = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "root"), + () -> Advancement.builder() + .criterion(AdvancementCriterion.dummy()) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.COMMAND_BLOCK) + .title(Component.text("Advancement Tests")) + .description(Component.text("Dummy trigger. Granted manually after testplugin is enabled")) + .build()) + .root().background(ResourceKey.minecraft("textures/gui/advancements/backgrounds/stone.png")) + .build()); + + public static final DefaultedRegistryReference SOME_DIRT = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "some_dirt"), + () -> Advancement.builder() + .criterion(AdvancementCriteria.SOME_DIRT) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.DIRT) + .title(Component.text("Got dirt!")) + .type(AdvancementTypes.TASK) + .build()) + .parent(Advancements.ROOT_ADVANCEMENT.location()) + .build()); + + public static final DefaultedRegistryReference LOTS_OF_DIRT = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "lots_of_dirt"), + () -> Advancement.builder() + .criterion(AdvancementCriteria.LOTS_OF_DIRT) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.DIRT) + .title(Component.text("Got more dirt!")) + .type(AdvancementTypes.GOAL) + .build()) + .parent(Advancements.SOME_DIRT.location()) + .build()); + + public static final DefaultedRegistryReference TONS_OF_DIRT = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "tons_of_dirt"), + () -> Advancement.builder() + .criterion(AdvancementCriteria.TONS_OF_DIRT) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.DIRT) + .title(Component.text("Got tons of dirt!")) + .type(AdvancementTypes.CHALLENGE) + .hidden(true) + .build()) + .parent(Advancements.LOTS_OF_DIRT.location()) + .build()); + + public static final DefaultedRegistryReference COUNTER_1 = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "counting"), + () -> Advancement.builder() + .criterion(OrCriterion.of(AdvancementCriteria.COUNTER_1, AdvancementCriteria.COUNTER_1_BYPASS)) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.CHEST) + .title(Component.text("Open some chests.")) + .type(AdvancementTypes.GOAL) + .build()) + .parent(Advancements.ROOT_ADVANCEMENT.location()) + .build()); + + public static final DefaultedRegistryReference COUNTER_2 = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "counting_more"), + () -> Advancement.builder() + .criterion(AdvancementCriteria.COUNTER_2) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.CHEST) + .title(Component.text("Open more chests")) + .type(AdvancementTypes.CHALLENGE) + .build()) + .parent(Advancements.COUNTER_1.location()) + .build()); + + public static final DefaultedRegistryReference COMBINATION = Advancements.ADVANCEMENT_BUILDER.register( + ResourceKey.of(AdvancementTest.NAMESPACE, "combination"), + () -> Advancement.builder() + .criterion(AdvancementCriteria.COMBINATION) + .displayInfo(DisplayInfo.builder() + .icon(ItemTypes.CHEST) + .title(Component.text("A || (B & (C || D)) || (E & F)")) + .description(Component.text("ABE ABF ACDE ACDF")) + .type(AdvancementTypes.CHALLENGE) + .build()) + .parent(Advancements.COUNTER_1.location()) + .build()); + } + @Inject private PluginContainer plugin; @Inject private Logger logger; private boolean enabled = false; - private AdvancementTemplate rootAdvancement; - private Trigger inventoryChangeTrigger; private TriggerListeners listeners = new TriggerListeners(); - private ScoreAdvancementCriterion counter1; - private AdvancementCriterion counter1Bypass; - private ScoreAdvancementCriterion counter2; - private AdvancementTemplate counterAdvancement1; - private AdvancementTemplate counterAdvancement2; @Override public void enable(final CommandContext ctx) { this.enabled = true; Sponge.eventManager().registerListeners(this.plugin, this.listeners); - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } - ctx.cause().first(ServerPlayer.class).map(player -> player.progress(this.rootAdvancement).grant()); + Sponge.server().dataPackManager().reload().join(); + ctx.cause().first(ServerPlayer.class).map(player -> player.progress(Advancements.ROOT_ADVANCEMENT.get()).grant()); } @Override public void disable(final CommandContext ctx) { this.enabled = false; Sponge.eventManager().unregisterListeners(this.listeners); - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } + Sponge.server().dataPackManager().reload(); } @Listener private void onTreeAdjust(final AdvancementTreeEvent.GenerateLayout event) { final AdvancementTree tree = event.tree(); - if (this.rootAdvancement != null && tree.key().equals(this.rootAdvancement.key())) { - final TreeLayoutElement layoutElement1 = tree.layoutElement(this.counterAdvancement1).get(); - final TreeLayoutElement layoutElement2 = tree.layoutElement(this.counterAdvancement2).get(); + Advancements.ROOT_ADVANCEMENT.find(event.registryHolder()).filter(tree.rootAdvancement()::equals).ifPresent(advancement -> { + final TreeLayoutElement layoutElement1 = tree.layoutElement(Advancements.COUNTER_1.get(event.registryHolder())).get(); + final TreeLayoutElement layoutElement2 = tree.layoutElement(Advancements.COUNTER_2.get(event.registryHolder())).get(); layoutElement1.setPosition(layoutElement2.position()); layoutElement2.setPosition(layoutElement2.position().add(-1,2)); - } + }); } @Listener @@ -137,170 +282,43 @@ private void onTrigger(final CriterionEvent.Trigger event) { } @Listener - private void onTriggerRegistry(final RegisterRegistryValueEvent.BuiltIn> event) { + private void onTriggerRegistry(final RegisterDataEvent event) { Sponge.dataManager().registerBuilder(InventoryChangeTriggerConfig.class, new InventoryChangeTriggerConfig.Builder()); - this.inventoryChangeTrigger = Trigger.builder() - .dataSerializableConfig(InventoryChangeTriggerConfig.class) - .listener(triggerEvent -> { - final ItemStack stack = triggerEvent.trigger().configuration().stack; - final int found = triggerEvent.player().inventory().query(QueryTypes.ITEM_STACK_IGNORE_QUANTITY, stack).totalQuantity(); - triggerEvent.setResult(stack.quantity() <= found); - }) - .name("my_inventory_trigger") - .build(); - event.registry(RegistryTypes.TRIGGER).register(ResourceKey.of(this.plugin, "my_inventory_trigger"), this.inventoryChangeTrigger); } @Listener - private void onAdvancementRegistry(final RegisterDataPackValueEvent event) { + private void onRegisterRegistryValueEvent(final RegisterRegistryValueEvent event) { if (!this.enabled) { return; } - AdvancementTemplate rootAdvancement = AdvancementTemplate.builder() - .criterion(AdvancementCriterion.dummy()) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.COMMAND_BLOCK) - .title(Component.text("Advancement Tests")) - .description(Component.text("Dummy trigger. Granted manually after testplugin is enabled")) - .build()) - .root().background(ResourceKey.minecraft("textures/gui/advancements/backgrounds/stone.png")) - .key(ResourceKey.of(this.plugin, "root")) - .build(); - event.register(rootAdvancement); - this.rootAdvancement = rootAdvancement; - - final AdvancementCriterion someDirtCriterion = AdvancementCriterion.builder().trigger( - this.inventoryChangeTrigger, - FilteredTrigger.builder() - .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT))) - .build() - ).name("some_dirt").build(); - - final AdvancementTemplate someDirt = AdvancementTemplate.builder() - .criterion(someDirtCriterion) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.DIRT) - .title(Component.text("Got dirt!")) - .type(AdvancementTypes.TASK) - .build()) - .parent(this.rootAdvancement) - .key(ResourceKey.of(this.plugin, "some_dirt")) - .build(); - event.register(someDirt); - - final AdvancementCriterion lotsOfDirtCriterion = AdvancementCriterion.builder().trigger( - this.inventoryChangeTrigger, - FilteredTrigger.builder() - .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT, 64))) - .build() - ).name("lots_of_dirt").build(); - - final AdvancementTemplate lotsOfDirt = AdvancementTemplate.builder() - .criterion(lotsOfDirtCriterion) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.DIRT) - .title(Component.text("Got more dirt!")) - .type(AdvancementTypes.GOAL) - .build()) - .parent(someDirt) - .key(ResourceKey.of(this.plugin, "lots_of_dirt")) - .build(); - event.register(lotsOfDirt); - - final AdvancementCriterion tonsOfDirtCriterion = AdvancementCriterion.builder().trigger( - this.inventoryChangeTrigger, - FilteredTrigger.builder() - .config(new InventoryChangeTriggerConfig(ItemStack.of(ItemTypes.DIRT, 64*9))) - .build() - ).name("tons_of_dirt").build(); - - final AdvancementTemplate tonsOfDirt = AdvancementTemplate.builder() - .criterion(tonsOfDirtCriterion) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.DIRT) - .title(Component.text("Got tons of dirt!")) - .type(AdvancementTypes.CHALLENGE) - .hidden(true) - .build()) - .parent(lotsOfDirt) - .key(ResourceKey.of(this.plugin, "tons_of_dirt")) - .build(); - event.register(tonsOfDirt); - - this.counter1 = ScoreAdvancementCriterion.builder().goal(10).name("counter").build(); - this.counter1Bypass = AdvancementCriterion.dummy(); - AdvancementTemplate counterAdvancement1 = AdvancementTemplate.builder() - .criterion(OrCriterion.of(this.counter1, this.counter1Bypass)) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.CHEST) - .title(Component.text("Open some chests.")) - .type(AdvancementTypes.GOAL) - .build()) - .parent(this.rootAdvancement) - .key(ResourceKey.of(this.plugin, "counting")) - .build(); - event.register(counterAdvancement1); - this.counterAdvancement1 = counterAdvancement1; - - this.counter2 = ScoreAdvancementCriterion.builder().goal(20).name("counter").build(); - AdvancementTemplate counterAdvancement2 = AdvancementTemplate.builder() - .criterion(this.counter2) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.CHEST) - .title(Component.text("Open more chests")) - .type(AdvancementTypes.CHALLENGE) - .build()) - .parent(counterAdvancement1) - .key(ResourceKey.of(this.plugin, "counting_more")) - .build(); - event.register(counterAdvancement2); - this.counterAdvancement2 = counterAdvancement2; - - final AdvancementCriterion a = AdvancementCriterion.builder().name("A").build(); - final AdvancementCriterion b = AdvancementCriterion.builder().name("B").build(); - final AdvancementCriterion c = AdvancementCriterion.builder().name("C").build(); - final AdvancementCriterion d = AdvancementCriterion.builder().name("D").build(); - final AdvancementCriterion e = AdvancementCriterion.builder().name("E").build(); - final AdvancementCriterion f = AdvancementCriterion.builder().name("F").build(); - final AdvancementCriterion combinationCriterion = OrCriterion.of(a, AndCriterion.of(b, OrCriterion.of(c, d)), AndCriterion.of(e, f)); - final AdvancementTemplate combinationAdvancement = AdvancementTemplate.builder() - .criterion(combinationCriterion) - .displayInfo(DisplayInfo.builder() - .icon(ItemTypes.CHEST) - .title(Component.text("A || (B & (C || D)) || (E & F)")) - .description(Component.text("ABE ABF ACDE ACDF")) - .type(AdvancementTypes.CHALLENGE) - .build()) - .parent(counterAdvancement1) - .key(ResourceKey.of(this.plugin, "combination")) - .build(); - event.register(combinationAdvancement); + event.register(Triggers.Holder.TRIGGERS); + event.register(Advancements.Holder.ADVANCEMENTS); } class TriggerListeners { @Listener private void onContainerEvent(final ChangeInventoryEvent event, @First final ServerPlayer player) { - AdvancementTest.this.inventoryChangeTrigger.trigger(player); + Triggers.INVENTORY_CHANGE_TRIGGER.get().trigger(player); } @Listener private void onConainterEvent(final InteractContainerEvent.Open event, @First final ServerPlayer player) { - final AdvancementProgress progress1 = player.progress(AdvancementTest.this.counterAdvancement1); + final AdvancementProgress progress1 = player.progress(Advancements.COUNTER_1.get()); if (progress1.achieved()) { - final AdvancementProgress progress2 = player.progress(AdvancementTest.this.counterAdvancement2); - progress2.require(AdvancementTest.this.counter2).add(1); + final AdvancementProgress progress2 = player.progress(Advancements.COUNTER_2.get()); + progress2.require(AdvancementCriteria.COUNTER_2).add(1); } else { - progress1.require(AdvancementTest.this.counter1).add(1); + progress1.require(AdvancementCriteria.COUNTER_1).add(1); final Object carrier = ((CarriedInventory) event.container()).carrier().orElse(null); if (carrier instanceof BlockCarrier) { if (((BlockCarrier) carrier).location().blockType().isAnyOf(BlockTypes.TRAPPED_CHEST)) { - progress1.require(AdvancementTest.this.counter1Bypass).grant(); + progress1.require(AdvancementCriteria.COUNTER_1_BYPASS).grant(); } } } diff --git a/testplugins/src/main/java/org/spongepowered/test/chat/ChatTest.java b/testplugins/src/main/java/org/spongepowered/test/chat/ChatTest.java index 58e6a797240..cfac23369b4 100644 --- a/testplugins/src/main/java/org/spongepowered/test/chat/ChatTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/chat/ChatTest.java @@ -39,9 +39,8 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.api.Game; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; -import org.spongepowered.api.adventure.ChatTypeTemplate; +import org.spongepowered.api.adventure.ChatType; import org.spongepowered.api.adventure.ChatTypes; import org.spongepowered.api.adventure.ResolveOperations; import org.spongepowered.api.adventure.SpongeComponents; @@ -58,11 +57,14 @@ import org.spongepowered.api.event.filter.data.GetValue; import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.StartedEngineEvent; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.event.message.PlayerChatEvent; import org.spongepowered.api.event.network.ServerSideConnectionEvent; import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.RegistryRegistrationSet; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.util.locale.Locales; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; @@ -77,11 +79,26 @@ @Plugin("chattest") public class ChatTest implements LoadableModule { + public static final class ChatTypes { + + public static final class Holder { + + public static final RegistryRegistrationSet CHAT_TYPES = ChatTypes.BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder BUILDER = RegistryRegistrationSet.builder(RegistryTypes.CHAT_TYPE, Sponge::server); + + public static final DefaultedRegistryReference INVERTED_CHAT_ORDER = ChatTypes.BUILDER.register( + ResourceKey.of("chattest", "inverted"), + () -> ChatType.builder().translationKey("%s by <%s>") + .addContent().addSender() + .build()); + } + private static final Logger LOGGER = LogManager.getLogger(); private static final BossBar INFO_BAR = BossBar.bossBar(Component.translatable("chattest.bars.info"), 1f, BossBar.Color.PINK, BossBar.Overlay.PROGRESS); - public static final ResourceKey INVERTED_CHAT_ORDER = ResourceKey.of("chattest", "inverted"); private final Game game; private final PluginContainer container; @@ -103,14 +120,8 @@ private void constructed(final ConstructPluginEvent event) { } @Listener - private void onServerStarted(final StartedEngineEvent event) - { - // TODO register this earlier - static context? - final ChatTypeTemplate template = ChatTypeTemplate.builder().translationKey("%s by <%s>") - .addContent().addSender() - .key(INVERTED_CHAT_ORDER) - .build(); - Sponge.server().dataPackManager().save(template); + private void onRegisterRegistryValueEvent(final RegisterRegistryValueEvent event) { + event.register(ChatTypes.Holder.CHAT_TYPES); } @Override @@ -204,7 +215,7 @@ private void onChat(final PlayerChatEvent event, final @Root ServerPlayer player event.setMessage(event.message().color(NamedTextColor.GREEN)); } else if (event instanceof final PlayerChatEvent.Submit submitEvent) { - submitEvent.setChatType(ChatTypes.key(INVERTED_CHAT_ORDER)); + submitEvent.setChatType(ChatTypes.INVERTED_CHAT_ORDER); final Optional optPlayerName = event.player().flatMap(p -> p.get(Keys.DISPLAY_NAME)); final TextComponent name = Component.text("Prefix", NamedTextColor.RED) .append(Component.text(" | ", NamedTextColor.GOLD)) diff --git a/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java b/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java index 3a604ec6d66..eee6d6f3372 100644 --- a/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java +++ b/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java @@ -36,6 +36,7 @@ import org.spongepowered.api.command.registrar.tree.CommandCompletionProviders; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.command.registrar.tree.CommandTreeNodeTypes; +import org.spongepowered.api.registry.RegistryHolder; import java.util.Collections; import java.util.List; @@ -76,9 +77,9 @@ public boolean canExecute(@NonNull final CommandCause cause) { } @Override - public CommandTreeNode.Root commandTree() { + public CommandTreeNode.Root commandTree(final RegistryHolder registryHolder) { return CommandTreeNode.root() - .child("s1", CommandTreeNodeTypes.RESOURCE_LOCATION.get().createNode() + .child("s1", CommandTreeNodeTypes.RESOURCE_LOCATION.get(registryHolder).createNode() .executable() .completions(CommandCompletionProviders.ALL_RECIPES)); } diff --git a/testplugins/src/main/java/org/spongepowered/test/command/raw/RawCommand.java b/testplugins/src/main/java/org/spongepowered/test/command/raw/RawCommand.java index 7d2f8c81815..54a7eb2e19b 100644 --- a/testplugins/src/main/java/org/spongepowered/test/command/raw/RawCommand.java +++ b/testplugins/src/main/java/org/spongepowered/test/command/raw/RawCommand.java @@ -35,6 +35,7 @@ import org.spongepowered.api.command.parameter.ArgumentReader; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.command.registrar.tree.CommandTreeNodeTypes; +import org.spongepowered.api.registry.RegistryHolder; import java.util.Arrays; import java.util.List; @@ -98,11 +99,11 @@ public Component usage(@NonNull final CommandCause cause) { } @Override - public CommandTreeNode.@NonNull Root commandTree() { - final CommandTreeNode.Argument firstStringKey = CommandTreeNodeTypes.STRING.get().createNode() + public CommandTreeNode.@NonNull Root commandTree(final RegistryHolder registryHolder) { + final CommandTreeNode.Argument firstStringKey = CommandTreeNodeTypes.STRING.get(registryHolder).createNode() .customCompletions().executable(); final CommandTreeNode.Argument secondStringKey = - CommandTreeNodeTypes.STRING.get().createNode().customCompletions().executable().redirect(firstStringKey); + CommandTreeNodeTypes.STRING.get(registryHolder).createNode().customCompletions().executable().redirect(firstStringKey); firstStringKey.child("s2", secondStringKey); return CommandTreeNode.root().executable().child("s1", firstStringKey); } diff --git a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java index d548efe103c..fdd2a5a3028 100644 --- a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java @@ -64,7 +64,7 @@ public void onRegisterRegistryGameScoped(final RegisterRegistryEvent.GameScoped @Listener public void onRegisterRegistryValuesGameScoped(final RegisterRegistryValueEvent.GameScoped event) { - event.registry(GAME_CUSTOM_REGISTRY).register(GAME_CUSTOM_VALUE.location(), 10); + event.registry(GAME_CUSTOM_REGISTRY, r -> r.register(GAME_CUSTOM_VALUE.location(), 10)); } @Listener @@ -74,7 +74,7 @@ public void onRegisterRegistryServerScoped(final RegisterRegistryEvent.EngineSco @Listener public void onRegisterRegistryValuesServerScoped(final RegisterRegistryValueEvent.EngineScoped event) { - event.registry(SERVER_CUSTOM_REGISTRY).register(SERVER_CUSTOM_VALUE.location(), 5); + event.registry(SERVER_CUSTOM_REGISTRY, r -> r.register(SERVER_CUSTOM_VALUE.location(), 5)); } @Listener @@ -84,7 +84,7 @@ public void onRegisterRegistryClientScoped(final RegisterRegistryEvent.EngineSco @Listener public void onRegisterRegistryValuesClientScoped(final RegisterRegistryValueEvent.EngineScoped event) { - event.registry(CLIENT_CUSTOM_REGISTRY).register(CLIENT_CUSTOM_VALUE.location(), 3); + event.registry(CLIENT_CUSTOM_REGISTRY, r -> r.register(CLIENT_CUSTOM_VALUE.location(), 3)); } @Listener diff --git a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java index e82b08214bf..36495a6884e 100644 --- a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java @@ -32,25 +32,25 @@ import org.spongepowered.api.command.Command; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.cause.entity.damage.DamageFunction; import org.spongepowered.api.event.cause.entity.damage.DamageModifier; import org.spongepowered.api.event.cause.entity.damage.DamageScalings; import org.spongepowered.api.event.cause.entity.damage.DamageType; -import org.spongepowered.api.event.cause.entity.damage.DamageTypeTemplate; import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.event.entity.AttackEntityEvent; import org.spongepowered.api.event.entity.DamageEntityEvent; import org.spongepowered.api.event.filter.cause.Root; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterTagEvent; +import org.spongepowered.api.registry.DefaultedRegistryReference; import org.spongepowered.api.registry.RegistryKey; +import org.spongepowered.api.registry.RegistryRegistrationSet; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.tag.DamageTypeTags; -import org.spongepowered.api.tag.TagTemplate; import org.spongepowered.api.util.Tuple; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; @@ -61,6 +61,21 @@ public class DamageTest implements LoadableModule { private static final ResourceKey EXHAUSTING_DAMAGE = ResourceKey.of("damagetest", "test"); + class Test { + + static final class Registry { + public static final RegistryRegistrationSet DAMAGE_TYPES = BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder BUILDER = RegistryRegistrationSet.builder(RegistryTypes.DAMAGE_TYPE, Sponge::server); + + public static final DefaultedRegistryReference EXHAUSTING_DAMAGE = BUILDER.register( + ResourceKey.of("damagetest", "test"), + () -> DamageType.builder().name("test").scaling(DamageScalings.NEVER.get()) + .exhaustion(100d) + .build()); + } + private final PluginContainer plugin; private final DamageListener listener = new DamageListener(); @@ -95,19 +110,13 @@ private void onRegisterSpongeCommand(final RegisterCommandEvent event) { - final DamageTypeTemplate template = DamageTypeTemplate.builder().name("test").scaling(DamageScalings.NEVER.get()) - .exhaustion(100d) - .key(EXHAUSTING_DAMAGE) - .build(); - event.register(template); + private void onRegisterRegistryValueEvent(final RegisterRegistryValueEvent event) { + event.register(Test.Registry.DAMAGE_TYPES); } @Listener - private void onDamageTypeTagPack(final RegisterDataPackValueEvent> event) { - final TagTemplate template = TagTemplate.builder(DataPacks.DAMAGE_TYPE_TAG).key(DamageTypeTags.BYPASSES_INVULNERABILITY.key()) - .addValue(RegistryKey.of(RegistryTypes.DAMAGE_TYPE, EXHAUSTING_DAMAGE)).build(); - event.register(template); + private void onRegisterTagEvent(final RegisterTagEvent event) { + event.tag(DamageTypeTags.BYPASSES_INVULNERABILITY).append(RegistryKey.of(RegistryTypes.DAMAGE_TYPE, EXHAUSTING_DAMAGE)); } private static class DamageListener { diff --git a/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java index a2785f03f9b..75f5d5a5b52 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/InfiniteTicksDataTest.java @@ -34,7 +34,6 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; import org.spongepowered.api.command.CommandResult; -import org.spongepowered.api.command.exception.CommandException; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.ValueParser; @@ -56,11 +55,10 @@ import org.spongepowered.api.event.entity.living.player.CooldownEvent; import org.spongepowered.api.event.item.inventory.UseItemStackEvent; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.event.world.ChangeWeatherEvent; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.ItemTypes; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.RecipeType; import org.spongepowered.api.item.recipe.RecipeTypes; import org.spongepowered.api.item.recipe.cooking.CookingRecipe; @@ -136,23 +134,15 @@ public InfiniteTicksDataTest(final PluginContainer plugin) { @Override public void enable(final CommandContext ctx) { this.enabled = true; - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } Sponge.eventManager().registerListeners(this.plugin, new InfiniteTicksDataTest.Listeners()); + Sponge.server().dataPackManager().reload(); } @Override public void disable(final CommandContext ctx) { this.enabled = false; - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } - Sponge.eventManager().registerListeners(this.plugin, new InfiniteTicksDataTest.Listeners()); + Sponge.eventManager().unregisterListeners(this.plugin); + Sponge.server().dataPackManager().reload(); } @Listener @@ -325,24 +315,25 @@ private void onRegisterCommand(final RegisterCommandEvent } @Listener - private void onRecipeRegistry(final RegisterDataPackValueEvent event) { + private void onRecipeRegistry(final RegisterRegistryValueEvent event) { if (!this.enabled) { return; } - event.register(this.createCookingRecipe(RecipeTypes.BLASTING.get(), "infinite_blasting_sponge")); - event.register(this.createCookingRecipe(RecipeTypes.CAMPFIRE_COOKING.get(), "infinite_campire_cooking_sponge")); - event.register(this.createCookingRecipe(RecipeTypes.SMELTING.get(), "infinite_smelting_sponge")); - event.register(this.createCookingRecipe(RecipeTypes.SMOKING.get(), "infinite_smoking_sponge")); + event.registry(RegistryTypes.RECIPE, registry -> { + registry.register(ResourceKey.of(this.plugin, "infinite_blasting_sponge"), this.createCookingRecipe(RecipeTypes.BLASTING.get())); + registry.register(ResourceKey.of(this.plugin, "infinite_campire_cooking_sponge"), this.createCookingRecipe(RecipeTypes.CAMPFIRE_COOKING.get())); + registry.register(ResourceKey.of(this.plugin, "infinite_smelting_sponge"), this.createCookingRecipe(RecipeTypes.SMELTING.get())); + registry.register(ResourceKey.of(this.plugin, "infinite_smoking_sponge"), this.createCookingRecipe(RecipeTypes.SMOKING.get())); + }); } - private RecipeRegistration createCookingRecipe(final RecipeType type, final String key) { + private CookingRecipe createCookingRecipe(final RecipeType type) { return CookingRecipe.builder() .type(type) .ingredient(ItemTypes.SPONGE.get()) .result(ItemTypes.WET_SPONGE.get()) .cookingTime(Ticks.infinite()) - .key(ResourceKey.of(this.plugin, key)) .build(); } diff --git a/testplugins/src/main/java/org/spongepowered/test/map/MapTest.java b/testplugins/src/main/java/org/spongepowered/test/map/MapTest.java index cc69c8f3bcc..c618bdfeb28 100644 --- a/testplugins/src/main/java/org/spongepowered/test/map/MapTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/map/MapTest.java @@ -510,7 +510,7 @@ private CommandResult setMapNether(final CommandContext ctx) throws CommandExcep } final Optional nether = Sponge.server().worldManager().world(DefaultWorldKeys.THE_NETHER); if (!nether.isPresent()) { - final CompletableFuture loadedNether = Sponge.server().worldManager().loadWorld(DefaultWorldKeys.THE_NETHER); + final CompletableFuture> loadedNether = Sponge.server().worldManager().loadWorld(DefaultWorldKeys.THE_NETHER); loadedNether.whenComplete((v, e) -> { if (e != null) { audience.sendMessage(Component.text("Failed to load nether world!", NamedTextColor.GREEN)); diff --git a/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java b/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java index 491fa5c59e3..6c16f49adbe 100644 --- a/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/recipe/RecipeTest.java @@ -30,7 +30,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.exception.CommandException; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.meta.BannerPatternLayer; @@ -38,14 +37,13 @@ import org.spongepowered.api.data.type.DyeColor; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.query.QueryTypes; -import org.spongepowered.api.item.recipe.RecipeRegistration; import org.spongepowered.api.item.recipe.RecipeTypes; import org.spongepowered.api.item.recipe.cooking.CookingRecipe; import org.spongepowered.api.item.recipe.crafting.CraftingRecipe; @@ -82,192 +80,168 @@ public RecipeTest(final PluginContainer plugin) { @Override public void enable(final CommandContext ctx) { this.enabled = true; - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } + Sponge.server().dataPackManager().reload(); } @Override public void disable(final CommandContext ctx) { this.enabled = false; - try { - Sponge.server().commandManager().process("reload"); - } catch (final CommandException e) { - e.printStackTrace(); - } + Sponge.server().dataPackManager().reload(); } @SuppressWarnings("unchecked") @Listener - private void onRecipeRegistry(final RegisterDataPackValueEvent event) { + private void onRecipeRegistry(final RegisterRegistryValueEvent event) { if (!this.enabled) { return; } // Standard recipes and ItemStack(with nbt) ingredient and results + event.registry(RegistryTypes.RECIPE, registry -> { + final Ingredient whiteRock = Ingredient.of(ItemTypes.POLISHED_DIORITE.get()); + final Ingredient whiteBed = Ingredient.of(ItemTypes.WHITE_BED.get()); + final ItemStack bedrock = ItemStack.of(ItemTypes.BEDROCK); - final Ingredient whiteRock = Ingredient.of(ItemTypes.POLISHED_DIORITE.get()); - final Ingredient whiteBed = Ingredient.of(ItemTypes.WHITE_BED.get()); - final ItemStack bedrock = ItemStack.of(ItemTypes.BEDROCK); - - final RecipeRegistration whiteBedrockRecipe = CraftingRecipe.shapedBuilder().rows() + final CraftingRecipe whiteBedrockRecipe = CraftingRecipe.shapedBuilder().rows() .row(whiteRock, whiteRock, whiteRock) .row(whiteRock, whiteBed, whiteRock) .row(whiteRock, whiteRock, whiteRock) .result(bedrock.copy()) - .key(ResourceKey.of(this.plugin, "white_bedrock")) .build(); - event.register(whiteBedrockRecipe); + registry.register(ResourceKey.of(this.plugin, "white_bedrock"), whiteBedrockRecipe); - final Ingredient redRock = Ingredient.of(ItemTypes.POLISHED_GRANITE); - final Ingredient redBed = Ingredient.of(ItemTypes.RED_BED); - final ItemStack redBedRock = bedrock.copy(); - redBedRock.offer(Keys.CUSTOM_NAME, Component.text("Bedrock", NamedTextColor.RED)); + final Ingredient redRock = Ingredient.of(ItemTypes.POLISHED_GRANITE); + final Ingredient redBed = Ingredient.of(ItemTypes.RED_BED); + final ItemStack redBedRock = bedrock.copy(); + redBedRock.offer(Keys.CUSTOM_NAME, Component.text("Bedrock", NamedTextColor.RED)); - final RecipeRegistration redBedrockRecipe = CraftingRecipe.shapedBuilder().rows() + final CraftingRecipe redBedrockRecipe = CraftingRecipe.shapedBuilder().rows() .aisle("ggg", "gbg", "ggg") .where('g', redRock) .where('b', redBed) .result(redBedRock) - .key(ResourceKey.of(this.plugin, "red_bedrock")) .build(); - event.register(redBedrockRecipe); + registry.register(ResourceKey.of(this.plugin, "red_bedrock"), redBedrockRecipe); - final ItemStack moreBedrock = bedrock.copy(); - moreBedrock.setQuantity(9); - final RecipeRegistration moreBedrockRecipe = CraftingRecipe.shapedBuilder().rows() + final ItemStack moreBedrock = bedrock.copy(); + moreBedrock.setQuantity(9); + final CraftingRecipe moreBedrockRecipe = CraftingRecipe.shapedBuilder().rows() .aisle("ggg", "gbg", "ggg") .where('g', redRock) .where('b', Ingredient.of(bedrock.copy())) .result(moreBedrock) - .key(ResourceKey.of(this.plugin, "more_red_bedrock")) .build(); - event.register(moreBedrockRecipe); + registry.register(ResourceKey.of(this.plugin, "more_red_bedrock"), moreBedrockRecipe); - final RecipeRegistration cheapGoldenAppleRecipe = CraftingRecipe.shapelessBuilder() + final CraftingRecipe cheapGoldenAppleRecipe = CraftingRecipe.shapelessBuilder() .addIngredients(ItemTypes.YELLOW_WOOL, ItemTypes.APPLE) .result(ItemStack.of(ItemTypes.GOLDEN_APPLE)) - .key(ResourceKey.of(this.plugin, "cheap_golden_apple")) .build(); - event.register(cheapGoldenAppleRecipe); + registry.register(ResourceKey.of(this.plugin, "cheap_golden_apple"), cheapGoldenAppleRecipe); - final RecipeRegistration expensiveGoldenAppleRecipe = CraftingRecipe.shapelessBuilder() + final CraftingRecipe expensiveGoldenAppleRecipe = CraftingRecipe.shapelessBuilder() .addIngredients(ItemTypes.YELLOW_WOOL, ItemTypes.ENCHANTED_GOLDEN_APPLE) .result(ItemStack.of(ItemTypes.GOLDEN_APPLE)) - .key(ResourceKey.of(this.plugin, "expensive_golden_apple")) .build(); - event.register(expensiveGoldenAppleRecipe); + registry.register(ResourceKey.of(this.plugin, "expensive_golden_apple"), expensiveGoldenAppleRecipe); - final Ingredient bedrocks = Ingredient.of(bedrock, redBedRock); - final RecipeRegistration bedrocksToGranite = CraftingRecipe.shapelessBuilder() + final Ingredient bedrocks = Ingredient.of(bedrock, redBedRock); + final CraftingRecipe bedrocksToGranite = CraftingRecipe.shapelessBuilder() .addIngredients(bedrocks, bedrocks) .result(ItemStack.of(ItemTypes.GRANITE, 13)) - .key(ResourceKey.of(this.plugin, "bedrocks_to_granite")) .build(); - event.register(bedrocksToGranite); + registry.register(ResourceKey.of(this.plugin, "bedrocks_to_granite"), bedrocksToGranite); - final RecipeRegistration diamondToCoalRecipe = CookingRecipe.builder().type(RecipeTypes.SMELTING) + final CookingRecipe diamondToCoalRecipe = CookingRecipe.builder().type(RecipeTypes.SMELTING) .ingredient(Ingredient.of(ItemTypes.DIAMOND)) .result(ItemTypes.COAL) .experience(0) - .key(ResourceKey.of(this.plugin, "diamond_to_coal")) .build(); - event.register(diamondToCoalRecipe); + registry.register(ResourceKey.of(this.plugin, "diamond_to_coal"), diamondToCoalRecipe); - final RecipeRegistration burnPaperAndSticksRecipe = CookingRecipe.builder().type(RecipeTypes.SMELTING) + final CookingRecipe burnPaperAndSticksRecipe = CookingRecipe.builder().type(RecipeTypes.SMELTING) .ingredient(Ingredient.of(ItemTypes.PAPER, ItemTypes.STICK)) .result(ItemTypes.GUNPOWDER) .experience(1) .cookingTime(Ticks.of(1)) - .key(ResourceKey.of(this.plugin, "burn_paper_and_sticks")) .build(); - event.register(burnPaperAndSticksRecipe); + registry.register(ResourceKey.of(this.plugin, "burn_paper_and_sticks"), burnPaperAndSticksRecipe); - final RecipeRegistration charcoalToCoalRecipe = CookingRecipe.builder().type(RecipeTypes.BLASTING) + final CookingRecipe charcoalToCoalRecipe = CookingRecipe.builder().type(RecipeTypes.BLASTING) .ingredient(Ingredient.of(ItemTypes.CHARCOAL)) .result(ItemTypes.COAL) - .key(ResourceKey.of(this.plugin, "charcoal_to_coal")) .build(); - event.register(charcoalToCoalRecipe); + registry.register(ResourceKey.of(this.plugin, "charcoal_to_coal"), charcoalToCoalRecipe); - final ItemStack redderBedrock = bedrock.copy(); - redderBedrock.offer(Keys.CUSTOM_NAME, Component.text("Bedrock", NamedTextColor.DARK_RED)); + final ItemStack redderBedrock = bedrock.copy(); + redderBedrock.offer(Keys.CUSTOM_NAME, Component.text("Bedrock", NamedTextColor.DARK_RED)); - final RecipeRegistration removeRedOnBedrock = CookingRecipe.builder().type(RecipeTypes.BLASTING) + final CookingRecipe removeRedOnBedrock = CookingRecipe.builder().type(RecipeTypes.BLASTING) .ingredient(Ingredient.of(redBedRock)) .result(redderBedrock) .cookingTime(Ticks.of(20)) .experience(100) - .key(ResourceKey.of(this.plugin, "redder_bedrock")) .build(); - event.register(removeRedOnBedrock); + registry.register(ResourceKey.of(this.plugin, "redder_bedrock"), removeRedOnBedrock); - final RecipeRegistration overcookedPorkchopRecipe = CookingRecipe.builder().type(RecipeTypes.SMOKING) + final CookingRecipe overcookedPorkchopRecipe = CookingRecipe.builder().type(RecipeTypes.SMOKING) .ingredient(Ingredient.of(ItemTypes.COOKED_PORKCHOP)) .result(ItemTypes.COAL) - .key(ResourceKey.of(this.plugin, "overcooked_porkchop")) .build(); - event.register(overcookedPorkchopRecipe); + registry.register(ResourceKey.of(this.plugin, "overcooked_porkchop"), overcookedPorkchopRecipe); - final RecipeRegistration sticksToTorches = CookingRecipe.builder().type(RecipeTypes.CAMPFIRE_COOKING) + final CookingRecipe sticksToTorches = CookingRecipe.builder().type(RecipeTypes.CAMPFIRE_COOKING) .ingredient(Ingredient.of(ItemTypes.STICK)) .result(ItemTypes.TORCH) .cookingTime(Ticks.of(20)) - .key(ResourceKey.of(this.plugin, "stick_to_torch")) .build(); - event.register(sticksToTorches); + registry.register(ResourceKey.of(this.plugin, "stick_to_torch"), sticksToTorches); - final RecipeRegistration stonecutter1 = StoneCutterRecipe.builder() + final StoneCutterRecipe stonecutter1 = StoneCutterRecipe.builder() .ingredient(ItemTypes.BEDROCK) .result(ItemStack.of(ItemTypes.BLACK_CONCRETE, 32)) - .key(ResourceKey.of(this.plugin, "cut_bedrock_to_concrete")) .build(); - final RecipeRegistration stonecutter2 = StoneCutterRecipe.builder() + final StoneCutterRecipe stonecutter2 = StoneCutterRecipe.builder() .ingredient(ItemTypes.BEDROCK) .result(ItemStack.of(ItemTypes.BLACK_GLAZED_TERRACOTTA, 16)) - .key(ResourceKey.of(this.plugin, "cut_bedrock_to_terracotta")) .build(); - final RecipeRegistration stonecutter3 = StoneCutterRecipe.builder() + final StoneCutterRecipe stonecutter3 = StoneCutterRecipe.builder() .ingredient(ItemTypes.BEDROCK) .result(ItemStack.of(ItemTypes.BLACK_WOOL, 64)) - .key(ResourceKey.of(this.plugin, "cut_bedrock_wool")) .build(); - event.register(stonecutter1); - event.register(stonecutter2); - event.register(stonecutter3); + registry.register(ResourceKey.of(this.plugin, "cut_bedrock_to_concrete"), stonecutter1); + registry.register(ResourceKey.of(this.plugin, "cut_bedrock_to_terracotta"), stonecutter2); + registry.register(ResourceKey.of(this.plugin, "cut_bedrock_wool"), stonecutter3); - // Predicate Ingredients + // Predicate Ingredients - final Predicate hardnessPredicate = stack -> stack.type().block().map(b -> b.defaultState().get(Keys.DESTROY_SPEED).orElse(0d) > 20).orElse(false); // e.g. obsidian - final Ingredient hardBlock = Ingredient.of(ResourceKey.of(this.plugin, "hardblock"), hardnessPredicate, ItemStack.of(ItemTypes.OBSIDIAN)); - final RecipeRegistration hardblockToWool = + final Predicate hardnessPredicate = stack -> stack.type().block().map(b -> b.defaultState().get(Keys.DESTROY_SPEED).orElse(0d) > 20).orElse(false); // e.g. obsidian + final Ingredient hardBlock = Ingredient.of(ResourceKey.of(this.plugin, "hardblock"), hardnessPredicate, ItemStack.of(ItemTypes.OBSIDIAN)); + final CraftingRecipe hardblockToWool = ShapelessCraftingRecipe.builder().addIngredients(hardBlock).result(ItemStack.of(ItemTypes.WHITE_WOOL)) - .key(ResourceKey.of(this.plugin, "hardblock_to_wool")) - .build(); + .build(); - event.register(hardblockToWool); + registry.register(ResourceKey.of(this.plugin, "hardblock_to_wool"), hardblockToWool); - // Function Results + // Function Results - final ItemStack villagerEgg = ItemStack.of(ItemTypes.VILLAGER_SPAWN_EGG); - final RecipeRegistration villagerSpawnEggRecipe = ShapedCraftingRecipe.builder() + final ItemStack villagerEgg = ItemStack.of(ItemTypes.VILLAGER_SPAWN_EGG); + final CraftingRecipe villagerSpawnEggRecipe = ShapedCraftingRecipe.builder() .aisle(" e ", "eve", " e ") .where('v', Ingredient.of(ItemTypes.BOOK)) .where('e', Ingredient.of(ItemTypes.EMERALD_BLOCK)) @@ -277,15 +251,14 @@ private void onRecipeRegistry(final RegisterDataPackValueEvent player = Sponge.server().causeStackManager().currentCause().first(ServerPlayer.class); final Optional biome = player.map(p -> p.world().biome(p.blockPosition())); final String name = biome.map(present -> RegistryTypes.BIOME.keyFor(player.get().world(), present)).map(ResourceKey::toString).orElse("Unknown"); - final Integer biomeTemperature = biome.map(Biome::temperature).map(d -> (int) (d*10)).orElse(0); - final Integer biomeHumidity = biome.map(Biome::humidity).map(d -> (int) (d*10)).orElse(0); + final Integer biomeTemperature = biome.map(Biome::temperature).map(d -> (int) (d * 10)).orElse(0); + final Integer biomeHumidity = biome.map(Biome::humidity).map(d -> (int) (d * 10)).orElse(0); final TextComponent temperature = Component.text("Temperature: ").append(Component.text(biomeTemperature)); final TextComponent humidity = Component.text("Humidity: ").append(Component.text(biomeHumidity)); writtenBook.offer(Keys.CUSTOM_NAME, Component.text("Biome Data: " + name)); @@ -302,33 +275,30 @@ private void onRecipeRegistry(final RegisterDataPackValueEvent { final int blacks = grid.query(QueryTypes.ITEM_TYPE, ItemTypes.BLACK_WOOL).capacity(); final int whites = grid.query(QueryTypes.ITEM_TYPE, ItemTypes.WHITE_WOOL).capacity(); return blacks > whites ? ItemStack.of(ItemTypes.BLACK_WOOL, 3) : ItemStack.of(ItemTypes.WHITE_WOOL, 3); }, ItemStack.of(ItemTypes.GRAY_WOOL)) - .key(ResourceKey.of(this.plugin, "black_or_white")) .build(); - event.register(blackOrWhiteRecipe); + registry.register(ResourceKey.of(this.plugin, "black_or_white"), blackOrWhiteRecipe); - // Custom results dont work well in cooking recipes - final ItemStack anvil = ItemStack.of(ItemTypes.DAMAGED_ANVIL); - final RecipeRegistration cookedAnvilRecipe = CookingRecipe.builder().type(RecipeTypes.BLASTING) + // Custom results dont work well in cooking recipes + final ItemStack anvil = ItemStack.of(ItemTypes.DAMAGED_ANVIL); + final CookingRecipe cookedAnvilRecipe = CookingRecipe.builder().type(RecipeTypes.BLASTING) .ingredient(ItemTypes.IRON_BLOCK) .result(inv -> anvil.copy(), anvil.copy()) - .key(ResourceKey.of(this.plugin, "cooked_anvil")) .build(); - event.register(cookedAnvilRecipe); + registry.register(ResourceKey.of(this.plugin, "cooked_anvil"), cookedAnvilRecipe); - final RecipeRegistration cutPlanksRecipe = StoneCutterRecipe.builder() + final StoneCutterRecipe cutPlanksRecipe = StoneCutterRecipe.builder() .ingredient(ItemTypes.OAK_PLANKS) .result(input -> { if (new Random().nextBoolean()) { @@ -336,11 +306,10 @@ private void onRecipeRegistry(final RegisterDataPackValueEvent { if (inv.capacity() != 9) { return false; @@ -378,47 +347,43 @@ private void onRecipeRegistry(final RegisterDataPackValueEvent inv.slots().stream().map(Slot::peek) - .map(item -> (item.type().isAnyOf(ItemTypes.WET_SPONGE) ? ItemTypes.SPONGE : ItemTypes.AIR).get()) - .map(ItemStack::of) - .collect(Collectors.toList())) + .map(item -> (item.type().isAnyOf(ItemTypes.WET_SPONGE) ? ItemTypes.SPONGE : ItemTypes.AIR).get()) + .map(ItemStack::of) + .collect(Collectors.toList())) .result(ItemStack.of(ItemTypes.WATER_BUCKET)) - .key(ResourceKey.of(this.plugin, "squeeze_sponge_recipe")) .build(); - event.register(squeezeSpongeRecipe); + registry.register(ResourceKey.of(this.plugin, "squeeze_sponge_recipe"), squeezeSpongeRecipe); - // Smithing recipes + // Smithing recipes - final RecipeRegistration ironToGoldIngot = SmithingRecipe.builder() + final SmithingRecipe ironToGoldIngot = SmithingRecipe.builder() .template(ItemTypes.PAPER) .base(ItemTypes.IRON_INGOT) .addition(ItemTypes.NETHERITE_INGOT) .result(ItemStack.of(ItemTypes.GOLD_INGOT)) - .key(ResourceKey.of(this.plugin, "iron_to_gold_ingot")) .build(); - event.register(ironToGoldIngot); + registry.register(ResourceKey.of(this.plugin, "iron_to_gold_ingot"), ironToGoldIngot); - final ItemStack chainMail = ItemStack.of(ItemTypes.CHAINMAIL_CHESTPLATE); - chainMail.offer(Keys.CUSTOM_NAME, Component.text("Heavy Chainmail", NamedTextColor.DARK_GRAY)); - chainMail.offer(Keys.LORE, Arrays.asList(Component.text("Smithing occured", NamedTextColor.DARK_GRAY))); - final RecipeRegistration smithChainmail = SmithingRecipe.builder() + final ItemStack chainMail = ItemStack.of(ItemTypes.CHAINMAIL_CHESTPLATE); + chainMail.offer(Keys.CUSTOM_NAME, Component.text("Heavy Chainmail", NamedTextColor.DARK_GRAY)); + chainMail.offer(Keys.LORE, Arrays.asList(Component.text("Smithing occured", NamedTextColor.DARK_GRAY))); + final SmithingRecipe smithChainmail = SmithingRecipe.builder() .template(ItemTypes.PAPER) .base(ItemTypes.IRON_CHESTPLATE) .addition(ItemTypes.FIRE_CHARGE) .result(chainMail) - .key(ResourceKey.of(this.plugin, "smith_chainmail")) .build(); - event.register(smithChainmail); - + registry.register(ResourceKey.of(this.plugin, "smith_chainmail"), smithChainmail); + }); } } diff --git a/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java b/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java index fef2244b238..950584de7ff 100644 --- a/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java @@ -42,12 +42,11 @@ import org.spongepowered.api.command.parameter.managed.ValueParameter; import org.spongepowered.api.command.parameter.managed.standard.VariableValueParameters; import org.spongepowered.api.data.type.HandTypes; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.RegisterDataPackValueEvent; +import org.spongepowered.api.event.lifecycle.RegisterTagEvent; import org.spongepowered.api.fluid.FluidType; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.ItemTypes; @@ -57,7 +56,6 @@ import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.tag.BlockTypeTags; import org.spongepowered.api.tag.Tag; -import org.spongepowered.api.tag.TagTemplate; import org.spongepowered.api.tag.Taggable; import org.spongepowered.api.util.blockray.RayTrace; import org.spongepowered.api.world.LocatableBlock; @@ -86,89 +84,56 @@ public TagTest(final PluginContainer pluginContainer, final Logger logger) { private static final TypeToken> FLUID_TYPE_TAG_TOKEN = new TypeToken>() {}; @Listener - private void registerTags(final RegisterDataPackValueEvent<@NonNull TagTemplate> event) { + private void registerTags(final RegisterTagEvent event) { this.logger.info("Adding tags."); - final TagTemplate tagRegistration = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(ResourceKey.of(this.pluginContainer, "wool")) - .addValue(BlockTypes.SHORT_GRASS) - .build(); - - event.register(tagRegistration); - - final TagTemplate woolLog = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(BlockTypeTags.WOOL.key()) - .addValue(BlockTypes.OAK_LOG) - .build(); - - event.register(woolLog); - - final TagTemplate woolGrass = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(ResourceKey.minecraft("wool")) - .addValue(BlockTypes.GRASS_BLOCK) - .build(); - - event.register(woolGrass); - - final TagTemplate underwaterDiamond = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(BlockTypeTags.UNDERWATER_BONEMEALS.key()) - .addValue(BlockTypes.DIAMOND_BLOCK) - .build(); - - event.register(underwaterDiamond); - - final TagTemplate ores = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(ResourceKey.of(this.pluginContainer, "ores")) - .addValue(BlockTypes.COAL_ORE) - .addValue(BlockTypes.IRON_ORE) - .addValue(BlockTypes.LAPIS_ORE) - .addValue(BlockTypes.REDSTONE_ORE) - .addValue(BlockTypes.EMERALD_ORE) - .addValue(BlockTypes.DIAMOND_ORE) - .addValue(BlockTypes.NETHER_QUARTZ_ORE) - .addChild(BlockTypeTags.GOLD_ORES) // Test gold ore child. - .build(); - - event.register(ores); - - final TagTemplate oresAndBlocks = TagTemplate.builder(DataPacks.BLOCK_TAG) - .key(ResourceKey.of(this.pluginContainer, "oresandblocks")) - .addValue(BlockTypes.COAL_BLOCK) - .addValue(BlockTypes.IRON_BLOCK) - .addValue(BlockTypes.LAPIS_BLOCK) - .addValue(BlockTypes.REDSTONE_BLOCK) - .addValue(BlockTypes.GOLD_BLOCK) - .addValue(BlockTypes.EMERALD_BLOCK) - .addValue(BlockTypes.DIAMOND_BLOCK) - .addValue(BlockTypes.QUARTZ_BLOCK) - .addChild(ores) // Test child TagTemplate - .build(); - - event.register(oresAndBlocks); + event.tag(Tag.of(RegistryTypes.BLOCK_TYPE, ResourceKey.of(this.pluginContainer, "wool"))) + .append(BlockTypes.SHORT_GRASS); + + event.tag(BlockTypeTags.WOOL).append(BlockTypes.OAK_LOG); + + event.tag(Tag.of(RegistryTypes.BLOCK_TYPE, ResourceKey.minecraft("wool"))) + .append(BlockTypes.GRASS_BLOCK); + + event.tag(BlockTypeTags.UNDERWATER_BONEMEALS).append(BlockTypes.DIAMOND_BLOCK); + + final Tag ores = Tag.of(RegistryTypes.BLOCK_TYPE, ResourceKey.of(this.pluginContainer, "ores")); + + event.tag(ores) + .append(BlockTypes.COAL_ORE) + .append(BlockTypes.IRON_ORE) + .append(BlockTypes.LAPIS_ORE) + .append(BlockTypes.REDSTONE_ORE) + .append(BlockTypes.EMERALD_ORE) + .append(BlockTypes.DIAMOND_ORE) + .append(BlockTypes.NETHER_QUARTZ_ORE) + .append(BlockTypeTags.GOLD_ORES) // Test gold ore child. + ; + + event.tag(Tag.of(RegistryTypes.BLOCK_TYPE, ResourceKey.of(this.pluginContainer, "oresandblocks"))) + .append(BlockTypes.COAL_BLOCK) + .append(BlockTypes.IRON_BLOCK) + .append(BlockTypes.LAPIS_BLOCK) + .append(BlockTypes.REDSTONE_BLOCK) + .append(BlockTypes.GOLD_BLOCK) + .append(BlockTypes.EMERALD_BLOCK) + .append(BlockTypes.DIAMOND_BLOCK) + .append(BlockTypes.QUARTZ_BLOCK) + .append(ores) // Test child TagTemplate + ; final ResourceKey nonExistentKey = ResourceKey.of("notrealnamespace", "notrealvalue"); - final TagTemplate brokenChildTag = TagTemplate.builder(DataPacks.ITEM_TAG) - .key(ResourceKey.of(this.pluginContainer, "brokenchildtag")) - .addChild(Tag.of(RegistryTypes.ITEM_TYPE, nonExistentKey), true) - .build(); - - event.register(brokenChildTag); - final TagTemplate brokenValueTag = TagTemplate.builder(DataPacks.ITEM_TAG) - .key(ResourceKey.of(this.pluginContainer, "brokenvaluetag")) - .addValue(RegistryKey.of(RegistryTypes.ITEM_TYPE, nonExistentKey)) - .build(); + event.tag(Tag.of(RegistryTypes.ITEM_TYPE, ResourceKey.of(this.pluginContainer, "brokenchildtag"))) + .append(Tag.of(RegistryTypes.ITEM_TYPE, nonExistentKey)); - event.register(brokenValueTag); - - final TagTemplate stillWorkingTag = TagTemplate.builder(DataPacks.ITEM_TAG) - .key(ResourceKey.of(this.pluginContainer, "stillworkingtag")) - .addValue(RegistryKey.of(RegistryTypes.ITEM_TYPE, nonExistentKey), false) - .addChild(Tag.of(RegistryTypes.ITEM_TYPE, nonExistentKey), false) - .addValue(ItemTypes.REDSTONE) - .build(); + event.tag(Tag.of(RegistryTypes.ITEM_TYPE, ResourceKey.of(this.pluginContainer, "brokenvaluetag"))) + .append(RegistryKey.of(RegistryTypes.ITEM_TYPE, nonExistentKey)); - event.register(stillWorkingTag); + event.tag(Tag.of(RegistryTypes.ITEM_TYPE, ResourceKey.of(this.pluginContainer, "stillworkingtag"))) + .append(RegistryKey.of(RegistryTypes.ITEM_TYPE, nonExistentKey)) + .append(Tag.of(RegistryTypes.ITEM_TYPE, nonExistentKey)) + .append(ItemTypes.REDSTONE); } @Listener diff --git a/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java b/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java index 358e3364690..129f7f861c6 100644 --- a/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java @@ -38,29 +38,26 @@ import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.CommonParameters; import org.spongepowered.api.command.parameter.Parameter; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.WorldTypeTemplate; import org.spongepowered.api.world.WorldTypes; +import org.spongepowered.api.world.generation.ChunkGenerator; import org.spongepowered.api.world.portal.PortalLogic; -import org.spongepowered.api.world.server.DataPackManager; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.api.world.server.WorldTemplate; +import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.api.world.server.WorldArchetypeTypes; +import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; import java.io.IOException; -import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; @@ -163,7 +160,7 @@ private CommandResult loadWorld(final CommandContext context, final Parameter.Va if (t != null) { context.cause().audience().sendMessage(Identity.nil(), Component.text(t.getMessage())); } else { - if (r != null) { + if (r.isPresent()) { context.cause().audience().sendMessage(Identity.nil(), Component.text("World loaded successfully!")); } else { context.cause().audience().sendMessage(Identity.nil(), Component.text("World failed to load!")); @@ -177,17 +174,12 @@ private CommandResult loadWorld(final CommandContext context, final Parameter.Va private CommandResult createWorld(final CommandContext context,final Parameter.Value worldKeyParameter, final Parameter.Value worldTypeParameter) { final ResourceKey key = context.requireOne(worldKeyParameter); final WorldType worldType = context.requireOne(worldTypeParameter); - final WorldTemplate template = WorldTemplate.builder() - .from(WorldTemplate.overworld()) - .key(key) - .add(Keys.WORLD_TYPE, worldType) - .add(Keys.PERFORM_SPAWN_LOGIC, true) - .build(); - - this.game.server().worldManager().loadWorld(template).whenComplete((r, t) -> { + final WorldArchetypeType worldArchetypeType = WorldArchetypeType.of(worldType, ChunkGenerator.overworld()); + + this.game.server().worldManager().loadWorld(key, ServerWorldProperties.LoadOptions.create(worldArchetypeType)).whenComplete((r, t) -> { if (t != null) { context.cause().audience().sendMessage(Identity.nil(), Component.text(t.getMessage())); - } else if (r != null) { + } else if (r.isPresent()) { context.cause().audience().sendMessage(Identity.nil(), Component.text("World created successfully!")); } else { context.cause().audience().sendMessage(Identity.nil(), Component.text("World failed to create!")); @@ -281,39 +273,29 @@ private CommandResult whereami(final CommandContext context, final Parameter.Val private CommandResult worldTypes(final CommandContext commandContext) { - final Optional optPlayer = commandContext.cause().first(ServerPlayer.class); for (final WorldType wt : WorldTypes.registry().stream().toList()) { - final WorldTypeTemplate template = WorldTypeTemplate.builder().fromValue(wt).key(ResourceKey.of(this.plugin, "test")).build(); - final DataContainer dataContainer = template.toContainer(); - optPlayer.ifPresent(player -> player.sendMessage(Component.text(template.key().toString()))); - System.out.println(template.key()); - try { - System.out.println(DataFormats.JSON.get().write(dataContainer)); - final WorldTypeTemplate rebuiltTemplate = WorldTypeTemplate.builder().fromDataPack(dataContainer) - .key(ResourceKey.of(this.plugin, "custom" + template.key().value())).build(); - } catch (final IOException e) { - e.printStackTrace(); - } + final ResourceKey key = wt.key(RegistryTypes.WORLD_TYPE); + wt.toDataPack(Sponge.server()).ifPresentOrElse(d -> { + try { + System.out.println(String.format("%s: ", DataFormats.JSON.get().write(d))); + } catch (IOException e) { + e.printStackTrace(); + } + }, () -> System.out.println(String.format("%s: Is unserializable", key))); } return CommandResult.success(); } private CommandResult worldTemplates(final CommandContext commandContext) { - final DataPackManager dm = Sponge.server().dataPackManager(); - final List templates = dm.list(DataPacks.WORLD); - for (final ResourceKey key : templates) { - - try { - final Optional template = dm.load(DataPacks.WORLD, key).join(); - if (template.isPresent()) { - System.out.println(key + DataFormats.JSON.get().write(template.get().toContainer())); - } else { - System.out.println(key + " (no template)"); + for (final WorldArchetypeType archetypeType : WorldArchetypeTypes.registry().stream().toList()) { + final ResourceKey key = archetypeType.key(RegistryTypes.WORLD_ARCHETYPE_TYPE); + archetypeType.toDataPack(Sponge.server()).ifPresentOrElse(d -> { + try { + System.out.println(String.format("%s: ", DataFormats.JSON.get().write(d))); + } catch (IOException e) { + e.printStackTrace(); } - } catch (final Exception e) { - System.err.println(key + " " + e.getMessage()); - } - + }, () -> System.out.println(String.format("%s: Is unserializable", key))); } return CommandResult.success(); } diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java index 78e35a2572e..91f785a1e9b 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/BiomeTest.java @@ -35,15 +35,13 @@ import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.datapack.DataPackTypes; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.effect.particle.ParticleTypes; import org.spongepowered.api.effect.sound.SoundTypes; import org.spongepowered.api.entity.EntityCategories; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.world.biome.Biome; -import org.spongepowered.api.world.biome.BiomeTemplate; import org.spongepowered.api.world.biome.Biomes; import org.spongepowered.api.world.biome.ambient.ParticleConfig; import org.spongepowered.api.world.biome.ambient.SoundConfig; @@ -51,7 +49,6 @@ import org.spongepowered.api.world.generation.feature.DecorationSteps; import org.spongepowered.api.world.generation.feature.FeatureType; import org.spongepowered.api.world.generation.feature.PlacedFeatures; -import org.spongepowered.api.world.server.DataPackManager; import java.util.Arrays; import java.util.Collections; @@ -102,28 +99,26 @@ private CommandResult info(final CommandContext ctx, final Parameter.Value naturalSpawners = defaultBiome.spawners().get(EntityCategories.MONSTER.get()); - Collections.shuffle(naturalSpawners); - final List spawner = Arrays.asList(naturalSpawners.get(0)); + public void register(final RegisterRegistryValueEvent event) { + event.registry(RegistryTypes.BIOME, (h, s) -> { + final Biome defaultBiome = Biomes.PLAINS.get(h); + final List naturalSpawners = defaultBiome.spawners().get(EntityCategories.MONSTER.get()); + Collections.shuffle(naturalSpawners); + final List spawner = Arrays.asList(naturalSpawners.get(0)); - final BiomeTemplate template = BiomeTemplate.builder().fromValue(defaultBiome) - .add(Keys.FEATURES, Map.of(DecorationSteps.LAKES.get(), List.of(PlacedFeatures.LAKE_LAVA_SURFACE.get()))) + s.register(ResourceKey.of(NAMESPACE, CUSTOM_PLAINS), Biome.builder().from(defaultBiome) + .add(Keys.FEATURES, Map.of(DecorationSteps.LAKES.get(), List.of(PlacedFeatures.LAKE_LAVA_SURFACE.get(h)))) .add(Keys.CARVERS, List.of()) .add(Keys.NATURAL_SPAWNERS, Map.of(EntityCategories.MONSTER.get(), spawner)) - .add(Keys.AMBIENT_ADDITIONAL_SOUND, SoundConfig.factory().ofAdditional(SoundTypes.ENTITY_CREEPER_PRIMED.get(), 0.001)) - .add(Keys.AMBIENT_PARTICLE, ParticleConfig.of(ParticleTypes.BUBBLE.get(), 0.01f)) - .key(ResourceKey.of(NAMESPACE, CUSTOM_PLAINS)).build(); - Sponge.server().dataPackManager().save(template); + .add(Keys.AMBIENT_ADDITIONAL_SOUND, SoundConfig.factory().ofAdditional(SoundTypes.ENTITY_CREEPER_PRIMED.get(h), 0.001)) + .add(Keys.AMBIENT_PARTICLE, ParticleConfig.of(ParticleTypes.BUBBLE.get(h), 0.01f)) + .build()); - final Biome defaultBiome2 = Biomes.FLOWER_FOREST.get(Sponge.server()); - final BiomeTemplate template2 = BiomeTemplate.builder().fromValue(defaultBiome2) + final Biome defaultBiome2 = Biomes.FLOWER_FOREST.get(h); + s.register(ResourceKey.of(NAMESPACE, CUSTOM_FOREST), Biome.builder().from(defaultBiome2) .add(Keys.NATURAL_SPAWNERS, Map.of(EntityCategories.MONSTER.get(), spawner)) - .key(ResourceKey.of(NAMESPACE, CUSTOM_FOREST)).build(); - Sponge.server().dataPackManager().save(template2); - - return CommandResult.success(); + .build()); + }, RegistryTypes.PLACED_FEATURE); } private CommandResult list(CommandContext ctx, final Parameter.Value filterParam) { @@ -133,16 +128,6 @@ private CommandResult list(CommandContext ctx, final Parameter.Value fil final Registry registry = this.registry(); registry.streamEntries().filter(e -> invert == e.key().toString().toUpperCase().contains(filter)) .forEach(e -> ctx.sendMessage(Identity.nil(), Component.text(" - " + e.key(), NamedTextColor.GRAY))); - - final DataPackManager dpm = Sponge.server().dataPackManager(); - dpm.find(DataPackTypes.BIOME).forEach((pack, keys) -> { - ctx.sendMessage(Identity.nil(), Component.text(pack.name() + ": " + pack.description() , NamedTextColor.DARK_AQUA)); - keys.forEach(key -> ctx.sendMessage(Identity.nil(), Component.text(" - " + key, NamedTextColor.GRAY))); - }); - - dpm.load(DataPacks.BIOME, ResourceKey.of(NAMESPACE, CUSTOM_PLAINS)).join().ifPresent(template -> { - ctx.sendMessage(Identity.nil(), Component.text("BiomeTemplate loaded from disk is present " + template.key(), NamedTextColor.DARK_AQUA)); - }); return CommandResult.success(); } @@ -157,7 +142,6 @@ public Command.Parameterized biomeCmd() { return Command.builder() .addChild(Command.builder().addParameter(filter).executor(ctx -> this.list(ctx, filter)).build(), "list") .addChild(Command.builder().addParameter(biomeParam).executor(ctx -> this.info(ctx, biomeParam)).build(), "info") - .addChild(Command.builder().executor(this::register).build(), "register") .build(); } } diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/CarverTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/CarverTest.java index bcea24e7cfe..3880a25e97d 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/CarverTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/CarverTest.java @@ -28,17 +28,15 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; -import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.world.generation.carver.Carver; -import org.spongepowered.api.world.generation.carver.CarverTemplate; import org.spongepowered.api.world.generation.carver.CarverTypes; import org.spongepowered.api.world.generation.carver.Carvers; -import java.io.IOException; public class CarverTest { @@ -52,20 +50,14 @@ private CommandResult carvers(final CommandContext ctx) { ctx.sendMessage(Identity.nil(), Component.text(" - " + e.key(), NamedTextColor.GRAY)); }); - final CarverTemplate template = CarverTemplate.builder().fromValue(Carvers.CAVE.get()).key(ResourceKey.of("carvertest", "custom_carver")).build(); - final DataContainer container = template.toContainer(); - try { - final CarverTemplate rebuiltTemplate = CarverTemplate.builder().fromDataPack(container).key(ResourceKey.of("carvertest", "custom_carver")).build(); - Sponge.server().dataPackManager().save(rebuiltTemplate); - - } catch (IOException e) { - throw new IllegalStateException(e); - } - final Carver reconfigured = CarverTypes.CAVE.get().configure(container); - return CommandResult.success(); } + public void register(final RegisterRegistryValueEvent event) { + event.registry(RegistryTypes.CARVER, (h, s) -> + s.register(ResourceKey.of("carvertest", "custom_carver"), Carver.builder().from(Carvers.CAVE.get(h)).build())); + } + Command.Parameterized carverCmd() { return Command.builder() diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/FeatureTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/FeatureTest.java index a2179accebf..d53a0a6e6e3 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/FeatureTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/FeatureTest.java @@ -35,17 +35,17 @@ import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.RegistryRegistrationSet; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.util.Direction; import org.spongepowered.api.util.blockray.RayTrace; import org.spongepowered.api.world.LocatableBlock; import org.spongepowered.api.world.generation.feature.Feature; -import org.spongepowered.api.world.generation.feature.FeatureTemplate; import org.spongepowered.api.world.generation.feature.Features; import org.spongepowered.api.world.generation.feature.PlacedFeature; -import org.spongepowered.api.world.generation.feature.PlacedFeatureTemplate; import org.spongepowered.api.world.generation.feature.PlacedFeatures; -import org.spongepowered.api.world.server.DataPackManager; import org.spongepowered.api.world.server.ServerLocation; import java.util.Optional; @@ -53,6 +53,38 @@ public class FeatureTest { + public static final class CustomFeatures { + + public static final class Holder { + + public static final RegistryRegistrationSet FEATURES = CustomFeatures.BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder BUILDER = RegistryRegistrationSet.builder(RegistryTypes.FEATURE, Sponge::server); + + public static final DefaultedRegistryReference FEATURE = CustomFeatures.BUILDER.register( + ResourceKey.of("featuretest", "test"), + (h) -> Feature.builder().from(Features.TREES_PLAINS.get(h)).build()); + } + + public static final class CustomPlacedFeatures { + + public static final class Holder { + + public static final RegistryRegistrationSet PLACED_FEATURES = CustomPlacedFeatures.BUILDER.build(); + } + + private static final RegistryRegistrationSet.Builder BUILDER = RegistryRegistrationSet.builder(RegistryTypes.PLACED_FEATURE, Sponge::server); + + public static final DefaultedRegistryReference PLACED_FEATURE = CustomPlacedFeatures.BUILDER.register( + ResourceKey.of("featuretest", "test"), + (h) -> PlacedFeature.builder().from(PlacedFeatures.TREES_PLAINS.get(h)).build()); + + public static final DefaultedRegistryReference PLACED_FEATURE_2 = CustomPlacedFeatures.BUILDER.register( + ResourceKey.of("featuretest", "test2"), + (h) -> PlacedFeature.builder().from(PlacedFeatures.TREES_PLAINS.get(h)).feature(CustomFeatures.FEATURE.get(h)).build()); + } + CommandResult placeFeature(final CommandContext commandContext, final Parameter.Value param) { return FeatureTest.place(commandContext, param, Features.TREES_PLAINS.get(), Feature::place); } @@ -84,30 +116,6 @@ public static RayTrace viewRay(final ServerPlayer player) { return RayTrace.block().select(RayTrace.nonAir()).limit(100).sourceEyePosition(player).direction(player); } - CommandResult registerFeature(final CommandContext ctx) { - final DataPackManager dpm = Sponge.server().dataPackManager(); - - final FeatureTemplate featureTemplate = FeatureTemplate.builder().fromValue(Features.TREES_PLAINS.get()) - .key(ResourceKey.of("featuretest", "test")) - .build(); - - final PlacedFeatureTemplate placedFeatureTemplate1 = PlacedFeatureTemplate.builder().fromValue(PlacedFeatures.TREES_PLAINS.get()) - .key(ResourceKey.of("featuretest", "test")) - .build(); - - final PlacedFeatureTemplate placedFeatureTemplate2 = PlacedFeatureTemplate.builder().fromValue(PlacedFeatures.TREES_PLAINS.get()) - .feature(featureTemplate) - .key(ResourceKey.of("featuretest", "test2")) - .build(); - - - dpm.save(featureTemplate); - dpm.save(placedFeatureTemplate1); - dpm.save(placedFeatureTemplate2); - - return CommandResult.success(); - } - private CommandResult listFeatures(CommandContext ctx, final Parameter.Value filterParam) { final Optional rawFilter = ctx.one(filterParam); final String filter = rawFilter.orElse("minecraft:").toUpperCase(); @@ -131,11 +139,11 @@ Command.Parameterized featureCmd() { .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listFeatures(ctx, filter)).build(), "list") .addChild(Command.builder().addParameter(feature).executor(ctx -> this.placeFeature(ctx, feature)).build(), "placeFeature") .addChild(Command.builder().addParameter(placedFeature).executor(ctx -> this.placePlaced(ctx, placedFeature)).build(), "placePlaced") - .addChild(Command.builder().executor(this::registerFeature).build(), "register") .build(); } - - - + public void register(final RegisterRegistryValueEvent event) { + event.register(FeatureTest.CustomFeatures.Holder.FEATURES); + event.register(FeatureTest.CustomPlacedFeatures.Holder.PLACED_FEATURES, FeatureTest.CustomFeatures.Holder.FEATURES.registryType()); + } } diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/NoiseTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/NoiseTest.java index ac91d25c63c..14781e4a5b6 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/NoiseTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/NoiseTest.java @@ -28,18 +28,17 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; -import org.spongepowered.api.world.generation.config.noise.DensityFunctionTemplate; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.world.generation.config.noise.DensityFunctions; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigTemplate; +import org.spongepowered.api.world.generation.config.noise.Noise; +import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigs; -import org.spongepowered.api.world.generation.config.noise.NoiseTemplate; import org.spongepowered.api.world.generation.config.noise.Noises; -import org.spongepowered.api.world.server.DataPackManager; import java.util.Optional; @@ -65,37 +64,21 @@ private CommandResult listNoise(final CommandContext ctx, final Parameter.Value< return CommandResult.success(); } - private CommandResult registerNoise(final CommandContext commandContext) { - final DataPackManager dpm = Sponge.server().dataPackManager(); + public void register(final RegisterRegistryValueEvent event) { + event.registry(RegistryTypes.NOISE_GENERATOR_CONFIG, (h, s) -> + s.register(ResourceKey.of("noisetest", "test"), NoiseGeneratorConfig.builder().from(NoiseGeneratorConfigs.CAVES.get(h)).build())); - final NoiseGeneratorConfigTemplate noiseGenCfgTemplate = NoiseGeneratorConfigTemplate.builder().fromValue(NoiseGeneratorConfigs.CAVES.get()) - .key(ResourceKey.of("noisetest", "test")) - .build(); - - final NoiseTemplate noiseTemplate = NoiseTemplate.builder().fromValue(Noises.CALCITE.get()) - .key(ResourceKey.of("noisetest", "calcite_copy")) - .build(); + event.registry(RegistryTypes.NOISE, (h, s) -> + s.register(ResourceKey.of("noisetest", "calcite_copy"), Noise.builder().from(Noises.CALCITE.get(h)).build())); - final DensityFunctionTemplate overWorldDensity = DensityFunctionTemplate.builder().fromValue(DensityFunctions.OVERWORLD_BASE_3D_NOISE.get()) - .key(ResourceKey.of("noisetest", "overworld_base3d_copy")) - .build(); - - try { - dpm.save(noiseGenCfgTemplate); - dpm.save(noiseTemplate); - dpm.save(overWorldDensity); - } catch (Exception e) { - e.printStackTrace(); - } - - return CommandResult.success(); +// event.registry(RegistryTypes.DENSITY_FUNCTION, (h, s) -> +// s.register(ResourceKey.of("noisetest", "overworld_base3d_copy"), DensityFunction.builder().build())); } Command.Parameterized noiseCmd() { final Parameter.Value filter = Parameter.string().key("filter").optional().build(); return Command.builder() .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listNoise(ctx, filter)).build(), "list") - .addChild(Command.builder().executor(this::registerNoise).build(), "register") .build(); } diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java index 249bbec70a8..16633b8653d 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java @@ -31,47 +31,35 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; -import org.spongepowered.api.command.CommandCompletion; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.data.persistence.DataFormats; -import org.spongepowered.api.datapack.DataPack; -import org.spongepowered.api.datapack.DataPackTypes; -import org.spongepowered.api.datapack.DataPacks; import org.spongepowered.api.entity.living.player.server.ServerPlayer; -import org.spongepowered.api.event.cause.entity.SpawnTypes; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.BiomeTags; import org.spongepowered.api.util.Direction; import org.spongepowered.api.util.blockray.RayTrace; import org.spongepowered.api.world.LocatableBlock; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.generation.feature.DecorationSteps; -import org.spongepowered.api.world.generation.structure.SchematicTemplate; import org.spongepowered.api.world.generation.structure.Structure; import org.spongepowered.api.world.generation.structure.StructurePlacement; -import org.spongepowered.api.world.generation.structure.StructureSetTemplate; +import org.spongepowered.api.world.generation.structure.StructureSet; import org.spongepowered.api.world.generation.structure.StructureSets; -import org.spongepowered.api.world.generation.structure.StructureTemplate; import org.spongepowered.api.world.generation.structure.StructureTypes; import org.spongepowered.api.world.generation.structure.Structures; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPool; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolElement; -import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolTemplate; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPools; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorListTemplate; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorLists; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorTypes; -import org.spongepowered.api.world.schematic.Schematic; -import org.spongepowered.api.world.server.DataPackManager; import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.math.vector.Vector3i; import java.io.IOException; -import java.util.Collection; +import java.util.List; import java.util.Optional; import java.util.Random; @@ -81,41 +69,44 @@ private CommandResult placeStructure(final CommandContext commandContext, final return FeatureTest.place(commandContext, param, Structures.DESERT_PYRAMID.get(), Structure::place); } - private CommandResult registerStructure(final CommandContext ctx) { - final DataPackManager dpm = Sponge.server().dataPackManager(); + public void register(final RegisterRegistryValueEvent event) { +// event.registry(RegistryTypes.STRUCTURE, (h, s) -> +// s.register(ResourceKey.of("featuretest", "test"), Structure.builder().build())); - final StructureTemplate structureTemplate = StructureTemplate.builder().fromValue(Structures.IGLOO.get()) - .key(ResourceKey.of("featuretest", "test")) - .build(); - - dpm.save(structureTemplate); - - return CommandResult.success(); - } - - private CommandResult registerStructureSets(final CommandContext ctx) { - final DataPackManager dpm = Sponge.server().dataPackManager(); + event.registry(RegistryTypes.STRUCTURE_SET, (h, s) -> { + s.register(ResourceKey.of("structuresettest", "igloo_2"), StructureSet.builder().from(StructureSets.IGLOOS.get(h)).build()); - final StructureSetTemplate template1 = StructureSetTemplate.builder().fromValue(StructureSets.IGLOOS.get()) - .key(ResourceKey.of("structuresettest", "igloo_2")) - .build(); + s.register(ResourceKey.of("structuresettest", "igloo_or_hut"), StructureSet.builder() + .add(Structures.IGLOO.get(h), 1) + .add(Structures.SWAMP_HUT.get(h), 1) + .placement(StructurePlacement.builder().randomSpread(1).spacing(16).separation(8).build()) + .build()); + }, RegistryTypes.STRUCTURE); - final StructurePlacement placement = StructurePlacement.builder().randomSpread(1).spacing(16).separation(8).build(); - final StructureSetTemplate template2 = StructureSetTemplate.builder() - .add(Structures.IGLOO.get(), 1) - .add(Structures.SWAMP_HUT.get(), 1) - .placement(placement) - .key(ResourceKey.of("structuresettest", "igloo_or_hut")) - .build(); + event.registry(RegistryTypes.PROCESSOR_LIST, (h, s) -> + s.register(ResourceKey.of("processortest", "test"), ProcessorList.builder().from(ProcessorLists.MOSSIFY_70_PERCENT.get(h)).build())); - dpm.save(template1); - dpm.save(template2); + event.registry(RegistryTypes.JIGSAW_POOL, (h, s) -> { + s.register(ResourceKey.of("jigsawtest", "test"), JigsawPool.builder().from(JigsawPools.VILLAGE_DESERT_DECOR.get(h)).build()); - final StructurePlacement strongholdPlacement = StructurePlacement.builder().concentricRings(Vector3i.ONE, 1) - .distance(32).spread(3).count(128).preferredBiomes(BiomeTags.STRONGHOLD_BIASED_TO) - .build(); + final JigsawPoolElement.Projection projection = JigsawPoolElement.factory().rigid(); + final ProcessorList noProcessing = ProcessorLists.EMPTY.get(h); + final JigsawPoolElement element1 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/desert/desert_lamp_1"), noProcessing).apply(projection); + final JigsawPoolElement element2 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/plains/plains_lamp_1"), noProcessing).apply(projection); + final JigsawPoolElement element3 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/snowy/snowy_lamp_post_01"), noProcessing).apply(projection); + final JigsawPoolElement element4 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/savanna/savanna_lamp_post_01"), noProcessing).apply(projection); + final JigsawPoolElement element5 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/taiga/taiga_lamp_post_1"), noProcessing).apply(projection); - return CommandResult.success(); + final ResourceKey lamptest = ResourceKey.of("jigsawtest", "lamps"); + s.register(lamptest, JigsawPool.builder() + .add(element1, 1) + .add(element2, 1) + .add(element3, 1) + .add(element4, 1) + .add(element5, 1) + .name(lamptest) + .build()); + }); } private CommandResult listStructures(CommandContext ctx, final Parameter.Value filterParam) { @@ -167,7 +158,7 @@ private CommandResult listSchematics(final CommandContext ctx, final Parameter.V final String filter = rawFilter.orElse("minecraft:").toUpperCase(); boolean invert = rawFilter.isPresent(); - final DataPackManager dpm = Sponge.server().dataPackManager(); + /*final DataPackManager dpm = Sponge.server().dataPackManager(); dpm.find(DataPackTypes.SCHEMATIC).forEach((pack, keys) -> { if (keys.isEmpty()) { return; @@ -179,7 +170,7 @@ private CommandResult listSchematics(final CommandContext ctx, final Parameter.V ctx.sendMessage(Identity.nil(), Component.text(" - " + key + " loaded " + loaded.isPresent(), NamedTextColor.GRAY)); }); - }); + });*/ return CommandResult.success(); } @@ -199,20 +190,20 @@ private CommandResult listJigsaw(final CommandContext ctx, final Parameter.Value private CommandResult placeSchematic(final CommandContext ctx, final Parameter.Value schematicParam) { - final DataPackManager dpm = Sponge.server().dataPackManager(); - final ResourceKey key = ctx.one(schematicParam).orElse(ResourceKey.minecraft("village/desert/houses/desert_small_house_1")); - final Optional> pack = dpm.findPack(DataPackTypes.SCHEMATIC, key); - final Optional player = ctx.cause().first(ServerPlayer.class); - if (pack.isPresent()) { - final Optional loaded = dpm.load(pack.get(), key).join(); - if (loaded.isPresent() && player.isPresent()) { - final Schematic schematic = loaded.get().schematic(); - final RayTrace ray = FeatureTest.viewRay(player.get()); - final ServerLocation location = ray.execute().orElseThrow().selectedObject().serverLocation().relativeTo(Direction.UP); - schematic.applyToWorld(location.world(), location.blockPosition(), SpawnTypes.CUSTOM); - ctx.sendMessage(Identity.nil(), Component.text("Placed Schematic: " + key + " from pack " + pack.get().name(), NamedTextColor.DARK_AQUA)); - } - } +// final DataPackManager dpm = Sponge.server().dataPackManager(); +// final ResourceKey key = ctx.one(schematicParam).orElse(ResourceKey.minecraft("village/desert/houses/desert_small_house_1")); +// final Optional> pack = dpm.findPack(DataPackTypes.SCHEMATIC, key); +// final Optional player = ctx.cause().first(ServerPlayer.class); +// if (pack.isPresent()) { +// final Optional loaded = dpm.load(pack.get(), key).join(); +// if (loaded.isPresent() && player.isPresent()) { +// final Schematic schematic = loaded.get().schematic(); +// final RayTrace ray = FeatureTest.viewRay(player.get()); +// final ServerLocation location = ray.execute().orElseThrow().selectedObject().serverLocation().relativeTo(Direction.UP); +// schematic.applyToWorld(location.world(), location.blockPosition(), SpawnTypes.CUSTOM); +// ctx.sendMessage(Identity.nil(), Component.text("Placed Schematic: " + key + " from pack " + pack.get().name(), NamedTextColor.DARK_AQUA)); +// } +// } return CommandResult.success(); } @@ -263,62 +254,12 @@ private CommandResult listProcessors(final CommandContext ctx, final Parameter.V return CommandResult.success(); } - private CommandResult registerProcessor(final CommandContext ctx) { - final DataPackManager dpm = Sponge.server().dataPackManager(); - - - final ProcessorListTemplate template = ProcessorListTemplate.builder() - .fromValue(ProcessorLists.MOSSIFY_70_PERCENT.get()) - .key(ResourceKey.of("processortest", "test")) - .build(); - - dpm.save(template); - - return CommandResult.success(); - } - - private CommandResult registerJigsaw(final CommandContext ctx) { - final DataPackManager dpm = Sponge.server().dataPackManager(); - - - final JigsawPoolTemplate template1 = JigsawPoolTemplate.builder() - .fromValue(JigsawPools.VILLAGE_DESERT_DECOR.get()) - .key(ResourceKey.of("jigsawtest", "test")) - .build(); - - - final JigsawPoolElement.Projection projection = JigsawPoolElement.factory().rigid(); - final ProcessorList noProcessing = ProcessorLists.EMPTY.get(); - final JigsawPoolElement element1 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/desert/desert_lamp_1"), noProcessing).apply(projection); - final JigsawPoolElement element2 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/plains/plains_lamp_1"), noProcessing).apply(projection); - final JigsawPoolElement element3 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/snowy/snowy_lamp_post_01"), noProcessing).apply(projection); - final JigsawPoolElement element4 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/savanna/savanna_lamp_post_01"), noProcessing).apply(projection); - final JigsawPoolElement element5 = JigsawPoolElement.factory().single(ResourceKey.minecraft("village/taiga/taiga_lamp_post_1"), noProcessing).apply(projection); - final ResourceKey lamptest = ResourceKey.of("jigsawtest", "lamps"); - final JigsawPoolTemplate template2 = JigsawPoolTemplate.builder() - .add(element1, 1) - .add(element2, 1) - .add(element3, 1) - .add(element4, 1) - .add(element5, 1) - .name(lamptest) - .key(lamptest) - .build(); - - dpm.save(template1); - dpm.save(template2); - - return CommandResult.success(); - } - - Command.Parameterized structureCmd() { final Parameter.Value structure = Parameter.registryElement(TypeToken.get(Structure.class), RegistryTypes.STRUCTURE, "minecraft").key("structure").optional().build(); final Parameter.Value filter = Parameter.string().key("filter").optional().build(); return Command.builder() .addChild(Command.builder().addParameter(structure).executor(ctx -> this.placeStructure(ctx, structure)).build(), "placeStructure") .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listStructures(ctx, filter)).build(), "list") - .addChild(Command.builder().executor(this::registerStructure).build(), "register") .addChild(Command.builder().addParameter(structure).executor(ctx -> this.structureInfo(ctx, structure)).build(), "info") .build(); } @@ -327,7 +268,6 @@ Command.Parameterized setsCmd() { final Parameter.Value filter = Parameter.string().key("filter").optional().build(); return Command.builder() .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listStructureSets(ctx, filter)).build(), "list") - .addChild(Command.builder().executor(this::registerStructureSets).build(), "register") .build(); } @@ -335,10 +275,11 @@ Command.Parameterized schematicCmd() { final Parameter.Value processorList = Parameter.registryElement(TypeToken.get(ProcessorList.class), RegistryTypes.PROCESSOR_LIST, "minecraft").key("processor_list").optional().build(); final Parameter.Value schematic = Parameter.resourceKey().key("schematic").optional().build(); final Parameter.Value structure = Parameter.resourceKey().key("structure").completer((ctx, input) -> { - final DataPackManager dpm = Sponge.server().dataPackManager(); - return dpm.find(DataPackTypes.SCHEMATIC).values().stream().flatMap(Collection::stream).map(ResourceKey::toString) - .filter(s -> s.startsWith(input) || s.startsWith("minecraft:" + input)) - .map(CommandCompletion::of).toList(); + return List.of(); +// final DataPackManager dpm = Sponge.server().dataPackManager(); +// return dpm.find(DataPackTypes.SCHEMATIC).values().stream().flatMap(Collection::stream).map(ResourceKey::toString) +// .filter(s -> s.startsWith(input) || s.startsWith("minecraft:" + input)) +// .map(CommandCompletion::of).toList(); }).optional().build(); final Parameter.Value filter = Parameter.string().key("filter").optional().build(); return Command.builder() @@ -354,7 +295,6 @@ Command.Parameterized jigsawCmd() { return Command.builder() .addChild(Command.builder().addParameter(jigsawPool).executor(ctx -> this.placeJigsaw(ctx, jigsawPool)).build(), "place") .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listJigsaw(ctx, filter)).build(), "list") - .addChild(Command.builder().executor(this::registerJigsaw).build(), "register") .build(); } @@ -362,7 +302,6 @@ Command.Parameterized processorCmd() { final Parameter.Value filter = Parameter.string().key("filter").optional().build(); return Command.builder() .addChild(Command.builder().addParameter(filter).executor(ctx -> this.listProcessors(ctx, filter)).build(), "list") - .addChild(Command.builder().executor(this::registerProcessor).build(), "register") .build(); } diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java index abab4bb1adc..302325f9469 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java @@ -25,9 +25,6 @@ package org.spongepowered.test.worldgen; import com.google.inject.Inject; -import net.kyori.adventure.identity.Identity; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockTypes; @@ -35,41 +32,27 @@ import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; -import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryEntry; import org.spongepowered.api.registry.RegistryReference; import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.BlockTypeTags; import org.spongepowered.api.util.RandomProvider; -import org.spongepowered.api.util.Range; -import org.spongepowered.api.world.DefaultWorldKeys; -import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.WorldTypeEffects; -import org.spongepowered.api.world.WorldTypeTemplate; import org.spongepowered.api.world.WorldTypes; import org.spongepowered.api.world.biome.AttributedBiome; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.biome.BiomeAttributes; import org.spongepowered.api.world.biome.Biomes; -import org.spongepowered.api.world.biome.provider.BiomeProvider; import org.spongepowered.api.world.biome.provider.MultiNoiseBiomeConfig; -import org.spongepowered.api.world.generation.ChunkGenerator; import org.spongepowered.api.world.generation.config.SurfaceRule; import org.spongepowered.api.world.generation.config.noise.NoiseConfig; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; -import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigs; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.api.world.server.WorldManager; -import org.spongepowered.api.world.server.WorldTemplate; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; -import org.spongepowered.test.world.WorldTest; import java.util.List; import java.util.Optional; @@ -115,62 +98,71 @@ private void onRegisterCommand(final RegisterCommandEvent ; } + @Listener + private void onRegisterRegistryValue(final RegisterRegistryValueEvent event) { + this.biomeTest.register(event); + this.carverTest.register(event); + this.featureTest.register(event); + this.noiseTest.register(event); + this.structureTest.register(event); + } + private CommandResult seededWorld(final CommandContext ctx, final Parameter.Value stringParam) { final String seed = ctx.one(stringParam).orElse("random"); - final WorldTemplate template = - WorldTemplate.builder().from(WorldTemplate.overworld()).add(Keys.SEED, (long) seed.hashCode()) - .key(ResourceKey.of(this.plugin, seed)) - .add(Keys.IS_LOAD_ON_STARTUP, false) - .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) - .build(); - final Optional optPlayer = ctx.cause().first(ServerPlayer.class); - Sponge.server().worldManager().loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); +// final WorldTemplate template = +// WorldTemplate.builder().from(WorldTemplate.overworld()).add(Keys.SEED, (long) seed.hashCode()) +// .key(ResourceKey.of(this.plugin, seed)) +// .add(Keys.IS_LOAD_ON_STARTUP, false) +// .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) +// .build(); +// final Optional optPlayer = ctx.cause().first(ServerPlayer.class); +// Sponge.server().worldManager().loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); return CommandResult.success(); } private CommandResult worldType(final CommandContext commandContext) { - final WorldTypeTemplate.Builder builder = WorldTypeTemplate.builder() - .add(Keys.WORLD_TYPE_EFFECT, WorldTypeEffects.OVERWORLD) - .add(Keys.SCORCHING, true) - .add(Keys.NATURAL_WORLD_TYPE, false) - .add(Keys.COORDINATE_MULTIPLIER, 128d) - .add(Keys.HAS_SKYLIGHT, false) - .add(Keys.HAS_CEILING, false) - .add(Keys.PIGLIN_SAFE, true) - .add(Keys.BEDS_USABLE, false) - .add(Keys.RESPAWN_ANCHOR_USABLE, false) - .add(Keys.INFINIBURN, BlockTypeTags.WOOL) - .add(Keys.WORLD_FLOOR, 0) - .add(Keys.HAS_RAIDS, false) - .add(Keys.WORLD_HEIGHT, 2000) - .add(Keys.WORLD_LOGICAL_HEIGHT, 2000) - .add(Keys.SPAWN_LIGHT_LIMIT, 5) - .add(Keys.SPAWN_LIGHT_RANGE, Range.intRange(5, 10)) - .add(Keys.AMBIENT_LIGHTING, 0.5f) - .add(Keys.CREATE_DRAGON_FIGHT, true) - .key(ResourceKey.of(this.plugin, "customworldtype")); - final WorldTypeTemplate template = builder.build(); - Sponge.server().dataPackManager().save(template); +// final WorldTypeTemplate.Builder builder = WorldTypeTemplate.builder() +// .add(Keys.WORLD_TYPE_EFFECT, WorldTypeEffects.OVERWORLD) +// .add(Keys.SCORCHING, true) +// .add(Keys.NATURAL_WORLD_TYPE, false) +// .add(Keys.COORDINATE_MULTIPLIER, 128d) +// .add(Keys.HAS_SKYLIGHT, false) +// .add(Keys.HAS_CEILING, false) +// .add(Keys.PIGLIN_SAFE, true) +// .add(Keys.BEDS_USABLE, false) +// .add(Keys.RESPAWN_ANCHOR_USABLE, false) +// .add(Keys.INFINIBURN, BlockTypeTags.WOOL) +// .add(Keys.WORLD_FLOOR, 0) +// .add(Keys.HAS_RAIDS, false) +// .add(Keys.WORLD_HEIGHT, 2000) +// .add(Keys.WORLD_LOGICAL_HEIGHT, 2000) +// .add(Keys.SPAWN_LIGHT_LIMIT, 5) +// .add(Keys.SPAWN_LIGHT_RANGE, Range.intRange(5, 10)) +// .add(Keys.AMBIENT_LIGHTING, 0.5f) +// .add(Keys.CREATE_DRAGON_FIGHT, true) +// .key(ResourceKey.of(this.plugin, "customworldtype")); +// final WorldTypeTemplate template = builder.build(); +// Sponge.server().dataPackManager().save(template); return CommandResult.success(); } private CommandResult world(CommandContext commandContext) { - final WorldManager wm = Sponge.server().worldManager(); - final ResourceKey worldKey = ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS); - final Optional customBiome = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS)); - final Optional customBiome2 = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_FOREST)); - if (customBiome.isPresent()) { - final RegistryReference ref = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome.get()); - final RegistryReference ref2 = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome2.get()); - final MultiNoiseBiomeConfig cfg = MultiNoiseBiomeConfig.builder() - .addBiome(AttributedBiome.of(ref, BiomeAttributes.point(0.1f, -0.6f, 0.1f, -0.5f, 0f, -1f, 0.0f))) - .addBiome(AttributedBiome.of(ref2, BiomeAttributes.point(0.4f, -1f, 0.5f, -0.2f, 0f, -0.95f, 0.0f))) - .build(); - final var chunkGen = ChunkGenerator.noise(BiomeProvider.multiNoise(cfg), ChunkGenerator.overworld().config()); - final WorldTemplate template = WorldTemplate.builder().add(Keys.CHUNK_GENERATOR, chunkGen).key(worldKey).build(); - final Optional optPlayer = commandContext.cause().first(ServerPlayer.class); - wm.loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); - } +// final WorldManager wm = Sponge.server().worldManager(); +// final ResourceKey worldKey = ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS); +// final Optional customBiome = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS)); +// final Optional customBiome2 = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_FOREST)); +// if (customBiome.isPresent()) { +// final RegistryReference ref = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome.get()); +// final RegistryReference ref2 = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome2.get()); +// final MultiNoiseBiomeConfig cfg = MultiNoiseBiomeConfig.builder() +// .addBiome(AttributedBiome.of(ref, BiomeAttributes.point(0.1f, -0.6f, 0.1f, -0.5f, 0f, -1f, 0.0f))) +// .addBiome(AttributedBiome.of(ref2, BiomeAttributes.point(0.4f, -1f, 0.5f, -0.2f, 0f, -0.95f, 0.0f))) +// .build(); +// final var chunkGen = ChunkGenerator.noise(BiomeProvider.multiNoise(cfg), ChunkGenerator.overworld().config()); +// final WorldTemplate template = WorldTemplate.builder().add(Keys.CHUNK_GENERATOR, chunkGen).key(worldKey).build(); +// final Optional optPlayer = commandContext.cause().first(ServerPlayer.class); +// wm.loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); +// } return CommandResult.success(); } @@ -232,14 +224,14 @@ private CommandResult createRandomWorld(final CommandContext context) { } - final NoiseGeneratorConfig noiseGenConfig = NoiseGeneratorConfig.builder() - .spawnTargets(NoiseGeneratorConfigs.OVERWORLD.get().spawnTargets()) - .noiseConfig(noiseConfig) - .surfaceRule(customSurfaceRule) -// .seaLevel(random.nextInt(61 - 1) + 1 + random.nextInt(30)) // 2 rolls - .seaLevel(63) - .key(ResourceKey.of(this.plugin, "test")) - .build().config(); +// final NoiseGeneratorConfig noiseGenConfig = NoiseGeneratorConfig.builder() +// .spawnTargets(NoiseGeneratorConfigs.OVERWORLD.get().spawnTargets()) +// .noiseConfig(noiseConfig) +// .surfaceRule(customSurfaceRule) +//// .seaLevel(random.nextInt(61 - 1) + 1 + random.nextInt(30)) // 2 rolls +// .seaLevel(63) +// .key(ResourceKey.of(this.plugin, "test")) +// .build().config(); final ResourceKey worldKey = ResourceKey.of(this.plugin, owner.toLowerCase()); final List attributedBiomes = biomes.stream().map(biomeRef -> { @@ -262,31 +254,31 @@ private CommandResult createRandomWorld(final CommandContext context) { final MultiNoiseBiomeConfig biomeCfg = MultiNoiseBiomeConfig.builder().addBiomes(attributedBiomes).build(); final Optional customworldtype = WorldTypes.registry().findValue(ResourceKey.of(this.plugin, "customworldtype")); - final WorldTemplate customTemplate = WorldTemplate.builder() - .from(WorldTemplate.overworld()) - .key(worldKey) - .add(Keys.WORLD_TYPE, customworldtype.orElse(WorldTypes.OVERWORLD.get())) - .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) - .add(Keys.IS_LOAD_ON_STARTUP, false) - .add(Keys.PERFORM_SPAWN_LOGIC, true) - .add(Keys.SEED, random.nextLong()) - .add(Keys.DISPLAY_NAME, Component.text("Custom world by " + owner)) - .add(Keys.CHUNK_GENERATOR, ChunkGenerator.noise(BiomeProvider.multiNoise(biomeCfg), noiseGenConfig)) - .build(); - - if (player.world().key().equals(worldKey)) { - final ServerWorld world = wm.world(DefaultWorldKeys.DEFAULT).get(); - player.setLocation(ServerLocation.of(world, world.properties().spawnPosition())); - } - context.sendMessage(Identity.nil(), Component.text("Generating your world...").append(Component.newline()) - .append(Component.text("with " + biomes.size() + " biomes")).append(Component.newline()) - ); - wm.deleteWorld(worldKey).thenCompose(b -> wm.loadWorld(customTemplate)).thenAccept(w -> WorldTest.transportToWorld(player, w)).exceptionally(e -> { - context.sendMessage(Identity.nil(), Component.text("Failed to teleport!", NamedTextColor.DARK_RED)); - e.printStackTrace(); - return null; - } - ); +// final WorldTemplate customTemplate = WorldTemplate.builder() +// .from(WorldTemplate.overworld()) +// .key(worldKey) +// .add(Keys.WORLD_TYPE, customworldtype.orElse(WorldTypes.OVERWORLD.get())) +// .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) +// .add(Keys.IS_LOAD_ON_STARTUP, false) +// .add(Keys.PERFORM_SPAWN_LOGIC, true) +// .add(Keys.SEED, random.nextLong()) +// .add(Keys.DISPLAY_NAME, Component.text("Custom world by " + owner)) +// .add(Keys.CHUNK_GENERATOR, ChunkGenerator.noise(BiomeProvider.multiNoise(biomeCfg), noiseGenConfig)) +// .build(); +// +// if (player.world().key().equals(worldKey)) { +// final ServerWorld world = wm.world(DefaultWorldKeys.DEFAULT).get(); +// player.setLocation(ServerLocation.of(world, world.properties().spawnPosition())); +// } +// context.sendMessage(Identity.nil(), Component.text("Generating your world...").append(Component.newline()) +// .append(Component.text("with " + biomes.size() + " biomes")).append(Component.newline()) +// ); +// wm.deleteWorld(worldKey).thenCompose(b -> wm.loadWorld(customTemplate)).thenAccept(w -> WorldTest.transportToWorld(player, w)).exceptionally(e -> { +// context.sendMessage(Identity.nil(), Component.text("Failed to teleport!", NamedTextColor.DARK_RED)); +// e.printStackTrace(); +// return null; +// } +// ); return CommandResult.success(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java index 9d4f91c42b2..c987d086652 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java @@ -51,7 +51,6 @@ public abstract class IntegratedServerMixin_Vanilla extends MinecraftServerMixin lifecycle.establishServerFeatures(); - lifecycle.establishServerRegistries(this); lifecycle.callStartingEngineEvent(this); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java index 5d985daca65..9434845c9c8 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java @@ -24,12 +24,16 @@ */ package org.spongepowered.vanilla.mixin.core.server; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.launch.Launch; import org.spongepowered.vanilla.VanillaServer; @@ -49,4 +53,10 @@ public String getServerModName() { private void vanilla$callStoppingEngineEvent(final CallbackInfo ci) { Launch.instance().lifecycle().callStoppingEngineEvent(this); } + + @ModifyExpressionValue(method = "lambda$reloadResources$28", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { + ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); + return original; + } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java index bf3232e8cf8..87778d0115f 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java @@ -47,7 +47,6 @@ public abstract class DedicatedServerMixin_Vanilla extends MinecraftServerMixin_ lifecycle.establishServerFeatures(); - lifecycle.establishServerRegistries(this); lifecycle.callStartingEngineEvent(this); } From 9f2a749cec05386052eed2e5912eb72399334d06 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 9 Mar 2025 02:17:43 +0200 Subject: [PATCH 214/586] Fix Sponge client registry rework related changes --- .../org/spongepowered/common/registry/RegistryHolderLogic.java | 2 +- .../common/mixin/core/resources/RegistryDataLoaderMixin.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 05aaa04ae42..82958eb0f7f 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -237,7 +237,7 @@ public void freezeSpongeDynamicRegistries(final boolean force) { final net.minecraft.core.Registry> registry = this.roots.get(RegistryRoots.SPONGE); registry.stream() .filter(r -> force || (((WritableRegistryBridge) r).bridge$eventCalled() && ((WritableRegistryBridge) r).bridge$pendingDependencies() - .allMatch(t -> this.findRegistry(t).map(v -> ((MappedRegistryAccessor) v).accessor$frozen() || ((WritableRegistryBridge) v).bridge$eventCalled()).orElse(false)))) + .allMatch(t -> this.findRegistry(t).map(v -> ((MappedRegistryAccessor) v).accessor$frozen() && ((WritableRegistryBridge) v).bridge$eventCalled()).orElse(false)))) .forEach(r -> dependencies.addEntry( ((Registry) r).type(), new SpongeRegistryDependencyEntry<>(r, ((WritableRegistryBridge) r).bridge$pendingDependencies().toList()))); dependencies.orderByDependencies(($, v) -> v.cookie().freeze()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index fd22bfbd74d..4eda0dd3ca2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -87,9 +87,11 @@ public class RegistryDataLoaderMixin { @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + // TODO: Remote layer final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); final Lifecycle lifecycle = Launch.instance().lifecycle(); instance.stream() + .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) .forEach((k, v) -> { ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( From 528e321347d21fdd9fe42e802ee0a2dde57e62fe Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 8 Mar 2025 23:02:46 -0800 Subject: [PATCH 215/586] fix(smelting): correctly call ResourceKey.location when throwing events A mistaken port of these mixins to the supported platforms lead to a class cast exception that would get caught each tick, but cause significant lag. This fixes the cast and makes furnaces work again. Fixes #4183 --- .../block/entity/AbstractFurnaceBlockEntityMixin_Forge.java | 2 +- .../level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 70f73c27a0b..669887df478 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -121,7 +121,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingProgress; // dont tick down diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index 0399c4fc49d..0ca7b931140 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -121,7 +121,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingProgress; // dont tick down From 434571a567a601792fb8bc455a5753770b39b53d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 10 Mar 2025 22:15:01 +0100 Subject: [PATCH 216/586] Fix registry events on modded platforms --- .../registries/GameDataMixin_Forge.java | 6 +++ .../registries/GameDataMixin_Neo.java | 6 +++ .../common/launch/Lifecycle.java | 2 + .../spongepowered/common/SpongeLifecycle.java | 5 +++ .../registries/BuiltInRegistriesMixin.java | 9 +--- .../BuiltInRegistriesMixin_Vanilla.java | 41 +++++++++++++++++++ .../resources/mixins.spongevanilla.core.json | 1 + 7 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java index d2b9406b895..6a554756ef9 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java @@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.entity.SpongeEntityTypes; +import org.spongepowered.common.launch.Launch; @Mixin(GameData.class) public class GameDataMixin_Forge { @@ -45,4 +46,9 @@ public class GameDataMixin_Forge { SpongeEntityTypes.register((Registry>) vanillaRegistry); } } + + @Inject(method = "postRegisterEvents", at = @At("HEAD")) + private static void forge$onRegisterEvents(final CallbackInfo ci) { + Launch.instance().lifecycle().establishGlobalRegistries(); + } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java index 90a19a2dce8..c0f4b79475f 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java @@ -34,6 +34,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.entity.SpongeEntityTypes; +import org.spongepowered.common.launch.Launch; @Mixin(GameData.class) public class GameDataMixin_Neo { @@ -44,4 +45,9 @@ public class GameDataMixin_Neo { SpongeEntityTypes.register((Registry>) registry); } } + + @Inject(method = "postRegisterEvents", at = @At("HEAD")) + private static void neo$onRegisterEvents(final CallbackInfo ci) { + Launch.instance().lifecycle().establishGlobalRegistries(); + } } diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 868011ab5b2..93889ac9091 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -52,6 +52,8 @@ public interface Lifecycle { void establishEarlyGlobalRegistries(); + void establishGlobalRegistries(); + void establishDataProviders(); void callRegisterDataEvent(); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 7ca2055c0ad..54d0e09f68c 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -123,6 +123,11 @@ public void establishEarlyGlobalRegistries() { holder.setRootMinecraftRegistry((Registry>) BuiltInRegistries.REGISTRY); SpongeRegistries.registerEarlyGlobalRegistries(holder); + } + + @Override + public void establishGlobalRegistries() { + final SpongeRegistryHolder holder = (SpongeRegistryHolder) this.game; // Plugin registries this.game.eventManager().post(new AbstractRegisterRegistryEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java index 872a14e721c..5181201e6d4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.core.registries; - import net.minecraft.core.registries.BuiltInRegistries; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -32,15 +31,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.launch.Launch; - @Mixin(BuiltInRegistries.class) public abstract class BuiltInRegistriesMixin { - // We hook in here if we extend existing vanilla BuiltInRegistries with our own - // This methods should then be called during bootstrap - - @Inject(method = "freeze", at = @At(value = "HEAD")) - private static void impl$onFreeze(final CallbackInfo ci) { + @Inject(method = "bootStrap", at = @At(value = "HEAD")) + private static void impl$beforeCreateContents(final CallbackInfo ci) { Launch.instance().lifecycle().establishEarlyGlobalRegistries(); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java new file mode 100644 index 00000000000..063ea2639cb --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java @@ -0,0 +1,41 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.registries; + +import net.minecraft.core.registries.BuiltInRegistries; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.launch.Launch; + +@Mixin(BuiltInRegistries.class) +public abstract class BuiltInRegistriesMixin_Vanilla { + + @Inject(method = "bootStrap", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/registries/BuiltInRegistries;freeze()V")) + private static void impl$beforeFreeze(final CallbackInfo ci) { + Launch.instance().lifecycle().establishGlobalRegistries(); + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 8e173858998..88656f6f6f0 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -21,6 +21,7 @@ "network.ConnectionMixin_Vanilla", "network.protocol.common.ClientboundCustomPayloadPacketMixin_Vanilla", "network.protocol.common.ServerboundCustomPayloadPacketMixin_Vanilla", + "registries.BuiltInRegistriesMixin_Vanilla", "server.BootstrapMixin_Vanilla", "server.MinecraftServerMixin_Vanilla", "server.commands.SpreadPlayersCommandMixin_Vanilla", From b30e8e9e627c9ea0de9d3085e923694c8f5786c3 Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 11 Mar 2025 19:24:42 +0200 Subject: [PATCH 217/586] Implement WorldArchetype --- SpongeAPI | 2 +- .../registry/SpongeBuilderProvider.java | 3 + ...pongeServerWorldPropertiesLoadOptions.java | 8 +- .../world/server/SpongeWorldArchetype.java | 58 ++++++ .../world/server/SpongeWorldManager.java | 18 +- .../world/server/SpongeWorldTypeBuilder.java | 5 - .../spongepowered/test/world/WorldTest.java | 3 +- .../test/worldgen/WorldGenTest.java | 177 +++++++++--------- 8 files changed, 173 insertions(+), 101 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java diff --git a/SpongeAPI b/SpongeAPI index 7dd5188d083..93d4552bf51 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 7dd5188d0835a883697165867eb7aa051befac9b +Subproject commit 93d4552bf5131d2deae2aadd2d0b4b113423b8c8 diff --git a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java index e6e08443838..5694031f9ad 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java @@ -131,6 +131,7 @@ import org.spongepowered.api.world.schematic.PaletteType; import org.spongepowered.api.world.schematic.Schematic; import org.spongepowered.api.world.server.TicketType; +import org.spongepowered.api.world.server.WorldArchetype; import org.spongepowered.api.world.server.WorldArchetypeType; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.api.world.volume.stream.StreamOptions; @@ -237,6 +238,7 @@ import org.spongepowered.common.world.server.SpongeLocatableBlockBuilder; import org.spongepowered.common.world.server.SpongeServerWorldPropertiesLoadOptions; import org.spongepowered.common.world.server.SpongeTicketTypeBuilder; +import org.spongepowered.common.world.server.SpongeWorldArchetype; import org.spongepowered.common.world.server.SpongeWorldArchetypeType; import org.spongepowered.common.world.server.SpongeWorldTypeBuilder; import org.spongepowered.common.world.volume.stream.SpongeStreamOptionsBuilder; @@ -389,6 +391,7 @@ public void registerDefaultBuilders() { .register(TicketType.Builder.class, SpongeTicketTypeBuilder::new) .register(PortalLogic.Builder.class, SpongePortalLogicBuilder::new) .register(ServerWorldProperties.LoadOptions.Builder.class, SpongeServerWorldPropertiesLoadOptions.BuilderImpl::new) + .register(WorldArchetype.Builder.class, SpongeWorldArchetype.BuilderImpl::new) ; } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java index 608cf6d9629..80f51b4f370 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java @@ -25,7 +25,7 @@ package org.spongepowered.common.world.server; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.api.world.server.WorldArchetype; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import java.util.Optional; @@ -67,10 +67,10 @@ public Optional> loadCallback() { } } - public record CreateOperationImpl(WorldArchetypeType worldArchetype, @Nullable Consumer callback) implements CreateOperation { + public record CreateOperationImpl(WorldArchetype worldArchetype, @Nullable Consumer callback) implements CreateOperation { @Override - public WorldArchetypeType worldArchetype() { + public WorldArchetype worldArchetype() { return this.worldArchetype; } @@ -100,7 +100,7 @@ public LoadStep load() { } @Override - public CreateStep create(final WorldArchetypeType worldArchetype) { + public CreateStep create(final WorldArchetype worldArchetype) { this.createOperation = new CreateOperationImpl(worldArchetype, null); return this; } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java new file mode 100644 index 00000000000..1728a715daa --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java @@ -0,0 +1,58 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import org.spongepowered.api.world.generation.config.WorldGenerationConfig; +import org.spongepowered.api.world.server.WorldArchetype; +import org.spongepowered.api.world.server.WorldArchetypeType; + +import java.util.Objects; +import java.util.Optional; + +public record SpongeWorldArchetype(WorldArchetypeType type, Optional generationConfig) implements WorldArchetype { + + public static final class BuilderImpl implements WorldArchetype.Builder { + + private WorldArchetypeType type; + private WorldGenerationConfig generationConfig; + + @Override + public Builder type(final WorldArchetypeType type) { + this.type = type; + return this; + } + + @Override + public Builder generationConfig(final WorldGenerationConfig generationConfig) { + this.generationConfig = generationConfig; + return this; + } + + @Override + public WorldArchetype build() { + return new SpongeWorldArchetype(Objects.requireNonNull(this.type, "type"), Optional.ofNullable(this.generationConfig)); + } + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 247262f26b5..d806d3828f4 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -62,6 +62,7 @@ import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner; +import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.storage.LevelDataAndDimensions; import net.minecraft.world.level.storage.LevelStorageSource; @@ -79,7 +80,10 @@ import org.spongepowered.api.util.file.DeleteFileVisitor; import org.spongepowered.api.world.DefaultWorldKeys; import org.spongepowered.api.world.WorldType; +import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.api.world.server.WorldArchetype; +import org.spongepowered.api.world.server.WorldArchetypeType; import org.spongepowered.api.world.server.WorldManager; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.common.SpongeCommon; @@ -279,7 +283,7 @@ public CompletableFuture> loadWorld(final ResourceKey key, try { final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(key); try { - final LevelDataLoadResult result = this.loadLevelData(key, () -> this.createLevelData(registryKey, (LevelStem) (Object) createOperation.worldArchetype())); + final LevelDataLoadResult result = this.loadLevelData(key, () -> this.createLevelData(registryKey, createOperation.worldArchetype())); createOperation.createCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.data())); return this.loadWorld0(registryKey, result, storageSource); } catch (final Exception e) { @@ -386,7 +390,7 @@ public CompletableFuture> loadProperties(final R final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOptions.createOperation().orElse(null); if (createOperation != null && !this.worldExists(key)) { final ServerWorldProperties properties = (ServerWorldProperties) this.loadLevelData(key, () -> this.createLevelData( - registryKey, (LevelStem) (Object) createOperation.worldArchetype())).data(); + registryKey, createOperation.worldArchetype())).data(); createOperation.createCallback().ifPresent(c -> c.accept(properties)); return CompletableFuture.completedFuture(Optional.of(properties)); } @@ -683,7 +687,8 @@ public void createNonDefaultLevels() { try { final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(worldKey); try { - final LevelDataLoadResult levelData = this.loadLevelData(storageSource, registryKey, () -> this.createLevelData(registryKey, levelStem)); + final LevelDataLoadResult levelData = this.loadLevelData(storageSource, registryKey, () -> + this.createLevelData(registryKey, WorldArchetype.of((WorldArchetypeType) (Object) levelStem))); if (!((PrimaryLevelDataBridge) levelData.data()).bridge$loadOnStartup()) { SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey); continue; @@ -771,12 +776,13 @@ private LevelDataLoadResult readLevelData(final net.minecraft.resources.Resource } - private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, - final LevelStem levelStem) { + private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, final WorldArchetype archetype) { + final LevelStem levelStem = (LevelStem) (Object) archetype.type(); final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.location())); return new LevelDataLoadResult( - new PrimaryLevelData(levelSettings, defaultLevelData.worldGenOptions(), SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem); + new PrimaryLevelData(levelSettings, (WorldOptions) archetype.generationConfig().orElse((WorldGenerationConfig) defaultLevelData.worldGenOptions()), + SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem); } private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelData, final String directoryName) { diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index 2c02abb62c8..e531e249561 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -24,12 +24,10 @@ */ package org.spongepowered.common.world.server; -import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -43,7 +41,6 @@ import org.spongepowered.api.util.Range; import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.WorldTypeEffect; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; @@ -72,8 +69,6 @@ public WorldType.Builder add(final Key> key, final V valu @Override public WorldType.Builder reset() { this.data = DataManipulator.mutableOf(); - final DimensionType defaultOverworld = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(BuiltinDimensionTypes.OVERWORLD); - this.from((WorldType) (Object) defaultOverworld); return this; } diff --git a/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java b/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java index 129f7f861c6..3c8768dd0bd 100644 --- a/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/world/WorldTest.java @@ -50,6 +50,7 @@ import org.spongepowered.api.world.portal.PortalLogic; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.api.world.server.WorldArchetype; import org.spongepowered.api.world.server.WorldArchetypeType; import org.spongepowered.api.world.server.WorldArchetypeTypes; import org.spongepowered.api.world.server.storage.ServerWorldProperties; @@ -176,7 +177,7 @@ private CommandResult createWorld(final CommandContext context,final Parameter.V final WorldType worldType = context.requireOne(worldTypeParameter); final WorldArchetypeType worldArchetypeType = WorldArchetypeType.of(worldType, ChunkGenerator.overworld()); - this.game.server().worldManager().loadWorld(key, ServerWorldProperties.LoadOptions.create(worldArchetypeType)).whenComplete((r, t) -> { + this.game.server().worldManager().loadWorld(key, ServerWorldProperties.LoadOptions.create(WorldArchetype.of(worldArchetypeType))).whenComplete((r, t) -> { if (t != null) { context.cause().audience().sendMessage(Identity.nil(), Component.text(t.getMessage())); } else if (r.isPresent()) { diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java index 302325f9469..fc3ae38cc06 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/WorldGenTest.java @@ -25,6 +25,9 @@ package org.spongepowered.test.worldgen; import com.google.inject.Inject; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockTypes; @@ -32,6 +35,7 @@ import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.command.parameter.Parameter; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; @@ -40,19 +44,35 @@ import org.spongepowered.api.registry.RegistryEntry; import org.spongepowered.api.registry.RegistryReference; import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.tag.BlockTypeTags; import org.spongepowered.api.util.RandomProvider; +import org.spongepowered.api.util.Range; +import org.spongepowered.api.world.DefaultWorldKeys; +import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.api.world.WorldType; +import org.spongepowered.api.world.WorldTypeEffects; import org.spongepowered.api.world.WorldTypes; import org.spongepowered.api.world.biome.AttributedBiome; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.biome.BiomeAttributes; import org.spongepowered.api.world.biome.Biomes; +import org.spongepowered.api.world.biome.provider.BiomeProvider; import org.spongepowered.api.world.biome.provider.MultiNoiseBiomeConfig; +import org.spongepowered.api.world.generation.ChunkGenerator; import org.spongepowered.api.world.generation.config.SurfaceRule; +import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.generation.config.noise.NoiseConfig; +import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfig; +import org.spongepowered.api.world.generation.config.noise.NoiseGeneratorConfigs; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.api.world.server.WorldArchetype; +import org.spongepowered.api.world.server.WorldArchetypeType; import org.spongepowered.api.world.server.WorldManager; +import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; +import org.spongepowered.test.world.WorldTest; import java.util.List; import java.util.Optional; @@ -92,7 +112,6 @@ private void onRegisterCommand(final RegisterCommandEvent .addChild(Command.builder().executor(this::createRandomWorld).build(), "createrandomworld", "crw") .addChild(Command.builder().executor(this::world).build(), "world") .addChild(Command.builder().addParameter(stringParam).executor(commandContext -> this.seededWorld(commandContext, stringParam)).build(), "seededworld") - .addChild(Command.builder().executor(this::worldType).build(), "worldtype") .build() ,"wgentest") ; @@ -105,64 +124,58 @@ private void onRegisterRegistryValue(final RegisterRegistryValueEvent event) { this.featureTest.register(event); this.noiseTest.register(event); this.structureTest.register(event); + event.registry(RegistryTypes.WORLD_TYPE, r -> + r.register(ResourceKey.of(this.plugin, "customworldtype"), WorldType.builder() + .add(Keys.WORLD_TYPE_EFFECT, WorldTypeEffects.OVERWORLD) + .add(Keys.SCORCHING, true) + .add(Keys.NATURAL_WORLD_TYPE, false) + .add(Keys.COORDINATE_MULTIPLIER, 128d) + .add(Keys.HAS_SKYLIGHT, false) + .add(Keys.HAS_CEILING, false) + .add(Keys.PIGLIN_SAFE, true) + .add(Keys.BEDS_USABLE, false) + .add(Keys.RESPAWN_ANCHOR_USABLE, false) + .add(Keys.INFINIBURN, BlockTypeTags.WOOL) + .add(Keys.WORLD_FLOOR, 0) + .add(Keys.HAS_RAIDS, false) + .add(Keys.WORLD_HEIGHT, 2000) + .add(Keys.WORLD_LOGICAL_HEIGHT, 2000) + .add(Keys.SPAWN_LIGHT_LIMIT, 5) + .add(Keys.SPAWN_LIGHT_RANGE, Range.intRange(5, 10)) + .add(Keys.AMBIENT_LIGHTING, 0.5f) + .add(Keys.CREATE_DRAGON_FIGHT, true).build())); } private CommandResult seededWorld(final CommandContext ctx, final Parameter.Value stringParam) { final String seed = ctx.one(stringParam).orElse("random"); -// final WorldTemplate template = -// WorldTemplate.builder().from(WorldTemplate.overworld()).add(Keys.SEED, (long) seed.hashCode()) -// .key(ResourceKey.of(this.plugin, seed)) -// .add(Keys.IS_LOAD_ON_STARTUP, false) -// .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) -// .build(); -// final Optional optPlayer = ctx.cause().first(ServerPlayer.class); -// Sponge.server().worldManager().loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); - return CommandResult.success(); - } - - private CommandResult worldType(final CommandContext commandContext) { -// final WorldTypeTemplate.Builder builder = WorldTypeTemplate.builder() -// .add(Keys.WORLD_TYPE_EFFECT, WorldTypeEffects.OVERWORLD) -// .add(Keys.SCORCHING, true) -// .add(Keys.NATURAL_WORLD_TYPE, false) -// .add(Keys.COORDINATE_MULTIPLIER, 128d) -// .add(Keys.HAS_SKYLIGHT, false) -// .add(Keys.HAS_CEILING, false) -// .add(Keys.PIGLIN_SAFE, true) -// .add(Keys.BEDS_USABLE, false) -// .add(Keys.RESPAWN_ANCHOR_USABLE, false) -// .add(Keys.INFINIBURN, BlockTypeTags.WOOL) -// .add(Keys.WORLD_FLOOR, 0) -// .add(Keys.HAS_RAIDS, false) -// .add(Keys.WORLD_HEIGHT, 2000) -// .add(Keys.WORLD_LOGICAL_HEIGHT, 2000) -// .add(Keys.SPAWN_LIGHT_LIMIT, 5) -// .add(Keys.SPAWN_LIGHT_RANGE, Range.intRange(5, 10)) -// .add(Keys.AMBIENT_LIGHTING, 0.5f) -// .add(Keys.CREATE_DRAGON_FIGHT, true) -// .key(ResourceKey.of(this.plugin, "customworldtype")); -// final WorldTypeTemplate template = builder.build(); -// Sponge.server().dataPackManager().save(template); + final Optional optPlayer = ctx.cause().first(ServerPlayer.class); + Sponge.server().worldManager().loadWorld(ResourceKey.of(this.plugin, seed), + ServerWorldProperties.LoadOptions.create( + WorldArchetype.of( + WorldArchetypeType.of(WorldTypes.OVERWORLD.get(), ChunkGenerator.overworld()), + WorldGenerationConfig.builder().seed(seed.hashCode()).build()), + (properties) -> properties.offer(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE))) + .thenAccept(w -> w.ifPresent(world -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, world)))); return CommandResult.success(); } private CommandResult world(CommandContext commandContext) { -// final WorldManager wm = Sponge.server().worldManager(); -// final ResourceKey worldKey = ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS); -// final Optional customBiome = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS)); -// final Optional customBiome2 = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_FOREST)); -// if (customBiome.isPresent()) { -// final RegistryReference ref = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome.get()); -// final RegistryReference ref2 = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome2.get()); -// final MultiNoiseBiomeConfig cfg = MultiNoiseBiomeConfig.builder() -// .addBiome(AttributedBiome.of(ref, BiomeAttributes.point(0.1f, -0.6f, 0.1f, -0.5f, 0f, -1f, 0.0f))) -// .addBiome(AttributedBiome.of(ref2, BiomeAttributes.point(0.4f, -1f, 0.5f, -0.2f, 0f, -0.95f, 0.0f))) -// .build(); -// final var chunkGen = ChunkGenerator.noise(BiomeProvider.multiNoise(cfg), ChunkGenerator.overworld().config()); -// final WorldTemplate template = WorldTemplate.builder().add(Keys.CHUNK_GENERATOR, chunkGen).key(worldKey).build(); -// final Optional optPlayer = commandContext.cause().first(ServerPlayer.class); -// wm.loadWorld(template).thenAccept(w -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, w))); -// } + final WorldManager wm = Sponge.server().worldManager(); + final ResourceKey worldKey = ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS); + final Optional customBiome = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_PLAINS)); + final Optional customBiome2 = this.biomeRegistry().findValue(ResourceKey.of(BiomeTest.NAMESPACE, BiomeTest.CUSTOM_FOREST)); + if (customBiome.isPresent()) { + final RegistryReference ref = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome.get()); + final RegistryReference ref2 = RegistryReference.referenced(Sponge.server(), RegistryTypes.BIOME, customBiome2.get()); + final MultiNoiseBiomeConfig cfg = MultiNoiseBiomeConfig.builder() + .addBiome(AttributedBiome.of(ref, BiomeAttributes.point(0.1f, -0.6f, 0.1f, -0.5f, 0f, -1f, 0.0f))) + .addBiome(AttributedBiome.of(ref2, BiomeAttributes.point(0.4f, -1f, 0.5f, -0.2f, 0f, -0.95f, 0.0f))) + .build(); + final var chunkGen = ChunkGenerator.noise(BiomeProvider.multiNoise(cfg), ChunkGenerator.overworld().config()); + final Optional optPlayer = commandContext.cause().first(ServerPlayer.class); + wm.loadWorld(worldKey, ServerWorldProperties.LoadOptions.create(WorldArchetype.of(WorldArchetypeType.of(WorldTypes.OVERWORLD.get(), chunkGen)))) + .thenAccept(w -> w.ifPresent(world -> optPlayer.ifPresent(player -> WorldTest.transportToWorld(player, world)))); + } return CommandResult.success(); } @@ -224,14 +237,14 @@ private CommandResult createRandomWorld(final CommandContext context) { } -// final NoiseGeneratorConfig noiseGenConfig = NoiseGeneratorConfig.builder() -// .spawnTargets(NoiseGeneratorConfigs.OVERWORLD.get().spawnTargets()) -// .noiseConfig(noiseConfig) -// .surfaceRule(customSurfaceRule) -//// .seaLevel(random.nextInt(61 - 1) + 1 + random.nextInt(30)) // 2 rolls -// .seaLevel(63) -// .key(ResourceKey.of(this.plugin, "test")) -// .build().config(); + final NoiseGeneratorConfig noiseGenConfig = NoiseGeneratorConfig.builder() + .spawnTargets(NoiseGeneratorConfigs.OVERWORLD.get().spawnTargets()) + .noiseRouter(NoiseGeneratorConfigs.OVERWORLD.get().noiseRouter()) + .noiseConfig(noiseConfig) + .surfaceRule(customSurfaceRule) +// .seaLevel(random.nextInt(61 - 1) + 1 + random.nextInt(30)) // 2 rolls + .seaLevel(63) + .build(); final ResourceKey worldKey = ResourceKey.of(this.plugin, owner.toLowerCase()); final List attributedBiomes = biomes.stream().map(biomeRef -> { @@ -254,31 +267,27 @@ private CommandResult createRandomWorld(final CommandContext context) { final MultiNoiseBiomeConfig biomeCfg = MultiNoiseBiomeConfig.builder().addBiomes(attributedBiomes).build(); final Optional customworldtype = WorldTypes.registry().findValue(ResourceKey.of(this.plugin, "customworldtype")); -// final WorldTemplate customTemplate = WorldTemplate.builder() -// .from(WorldTemplate.overworld()) -// .key(worldKey) -// .add(Keys.WORLD_TYPE, customworldtype.orElse(WorldTypes.OVERWORLD.get())) -// .add(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE) -// .add(Keys.IS_LOAD_ON_STARTUP, false) -// .add(Keys.PERFORM_SPAWN_LOGIC, true) -// .add(Keys.SEED, random.nextLong()) -// .add(Keys.DISPLAY_NAME, Component.text("Custom world by " + owner)) -// .add(Keys.CHUNK_GENERATOR, ChunkGenerator.noise(BiomeProvider.multiNoise(biomeCfg), noiseGenConfig)) -// .build(); -// -// if (player.world().key().equals(worldKey)) { -// final ServerWorld world = wm.world(DefaultWorldKeys.DEFAULT).get(); -// player.setLocation(ServerLocation.of(world, world.properties().spawnPosition())); -// } -// context.sendMessage(Identity.nil(), Component.text("Generating your world...").append(Component.newline()) -// .append(Component.text("with " + biomes.size() + " biomes")).append(Component.newline()) -// ); -// wm.deleteWorld(worldKey).thenCompose(b -> wm.loadWorld(customTemplate)).thenAccept(w -> WorldTest.transportToWorld(player, w)).exceptionally(e -> { -// context.sendMessage(Identity.nil(), Component.text("Failed to teleport!", NamedTextColor.DARK_RED)); -// e.printStackTrace(); -// return null; -// } -// ); + + if (player.world().key().equals(worldKey)) { + final ServerWorld world = wm.world(DefaultWorldKeys.DEFAULT).get(); + player.setLocation(ServerLocation.of(world, world.properties().spawnPosition())); + } + context.sendMessage(Identity.nil(), Component.text("Generating your world...").append(Component.newline()) + .append(Component.text("with " + biomes.size() + " biomes")).append(Component.newline()) + ); + wm.deleteWorld(worldKey).thenCompose(b -> wm.loadWorld(worldKey, ServerWorldProperties.LoadOptions.create( + WorldArchetype.of( + WorldArchetypeType.of(customworldtype.orElse(WorldTypes.OVERWORLD.get()), ChunkGenerator.noise(BiomeProvider.multiNoise(biomeCfg), noiseGenConfig)), + WorldGenerationConfig.builder().seed(random.nextLong()).build()), + (properties) -> { + properties.offer(Keys.SERIALIZATION_BEHAVIOR, SerializationBehavior.NONE); + properties.offer(Keys.DISPLAY_NAME, Component.text("Custom world by " + owner)); + }) + )).thenAccept(w -> w.ifPresent(world -> WorldTest.transportToWorld(player, world))).exceptionally(e -> { + context.sendMessage(Identity.nil(), Component.text("Failed to teleport!", NamedTextColor.DARK_RED)); + e.printStackTrace(); + return null; + }); return CommandResult.success(); From 5548003a85d9ac0e234ea97b065428892b24bd44 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 12 Mar 2025 23:52:45 +0200 Subject: [PATCH 218/586] Freeze sponge registries after vanilla --- .../core/minecraftforge/registries/GameDataMixin_Forge.java | 5 +++++ .../mixin/core/neoforge/registries/GameDataMixin_Neo.java | 5 +++++ .../java/org/spongepowered/common/launch/Lifecycle.java | 2 ++ src/main/java/org/spongepowered/common/SpongeLifecycle.java | 5 +++-- .../test/customregistry/CustomRegistryTest.java | 3 ++- .../core/registries/BuiltInRegistriesMixin_Vanilla.java | 5 +++++ 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java index 6a554756ef9..3d05bd93b3f 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java @@ -51,4 +51,9 @@ public class GameDataMixin_Forge { private static void forge$onRegisterEvents(final CallbackInfo ci) { Launch.instance().lifecycle().establishGlobalRegistries(); } + + @Inject(method = "freezeData", at = @At("TAIL")) + private static void forge$onFreezeData(final CallbackInfo ci) { + Launch.instance().lifecycle().endEstablishGlobalRegistries(); + } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java index c0f4b79475f..7489a1b533c 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java @@ -50,4 +50,9 @@ public class GameDataMixin_Neo { private static void neo$onRegisterEvents(final CallbackInfo ci) { Launch.instance().lifecycle().establishGlobalRegistries(); } + + @Inject(method = "freezeData", at = @At("TAIL")) + private static void neo$onFreezeData(final CallbackInfo ci) { + Launch.instance().lifecycle().endEstablishGlobalRegistries(); + } } diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 93889ac9091..9f0654f6fcc 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -54,6 +54,8 @@ public interface Lifecycle { void establishGlobalRegistries(); + void endEstablishGlobalRegistries(); + void establishDataProviders(); void callRegisterDataEvent(); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 54d0e09f68c..b7973a5b71a 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -137,9 +137,10 @@ public void establishGlobalRegistries() { this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game, holder.streamRegistries().collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())))); + } - // Freeze Dynamic Registries - Values are now available - holder.registryHolder().freezeSpongeDynamicRegistries(true); + public void endEstablishGlobalRegistries() { + ((SpongeRegistryHolder) this.game).registryHolder().freezeSpongeDynamicRegistries(true); } @Override diff --git a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java index fdd2a5a3028..a3b4704ebea 100644 --- a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java @@ -37,6 +37,7 @@ import org.spongepowered.api.registry.RegistryKey; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.plugin.builtin.jvm.Plugin; @Plugin("customregistrytest") @@ -64,7 +65,7 @@ public void onRegisterRegistryGameScoped(final RegisterRegistryEvent.GameScoped @Listener public void onRegisterRegistryValuesGameScoped(final RegisterRegistryValueEvent.GameScoped event) { - event.registry(GAME_CUSTOM_REGISTRY, r -> r.register(GAME_CUSTOM_VALUE.location(), 10)); + event.registry(GAME_CUSTOM_REGISTRY, (h, r) -> r.register(GAME_CUSTOM_VALUE.location(), 10), RegistryTypes.ITEM_TYPE); } @Listener diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java index 063ea2639cb..595724dd0f9 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java @@ -38,4 +38,9 @@ public abstract class BuiltInRegistriesMixin_Vanilla { private static void impl$beforeFreeze(final CallbackInfo ci) { Launch.instance().lifecycle().establishGlobalRegistries(); } + + @Inject(method = "freeze", at = @At("TAIL")) + private static void impl$afterFreeze(final CallbackInfo ci) { + Launch.instance().lifecycle().endEstablishGlobalRegistries(); + } } From 49de73579a64322b0de166a60c1a7427ab463a70 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 13 Mar 2025 21:35:12 +0100 Subject: [PATCH 219/586] Pin ForgeGradle version --- forge/build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 66ca13d9f9b..b6be6ff2de5 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -17,7 +17,7 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("net.minecraftforge.gradle") version "[6.0.24,6.2)" + alias(libs.plugins.forgeGradle) } val commonProject = parent!! diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 367fee30d9a..a3e0111a5ff 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -77,5 +77,5 @@ at = { module = "dev.architectury:at", version = "1.0.1" } blossom = { id = "net.kyori.blossom", version = "2.1.0" } indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = "3.1.3" } shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } -vanillaGradle = { id = "org.spongepowered.gradle.vanilla" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } +forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c214a468eef..b49c4b1d140 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4111,6 +4111,14 @@ + + + + + + + + @@ -4126,6 +4134,11 @@ + + + + + From ff46a0dae4f73c115d20f5a7664cc3a259af707f Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 14 Mar 2025 19:41:26 +0200 Subject: [PATCH 220/586] Fix RegisterRegistryEvent#register with dependencies --- .../event/lifecycle/AbstractRegisterRegistryEvent.java | 4 ++-- .../common/registry/RegistryHolderLogic.java | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java index 9d8d3bb5c86..a3e1bf2c4af 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java @@ -81,8 +81,8 @@ public RegistryType register(final ResourceKey key, final boolean isDynam final SpongeRegistryHolder holder = this.getHolder(); final RegistryType type = RegistryType.of(RegistryRoots.SPONGE, key); - holder.createRegistry(type, defaultValues, isDynamic); - return null; + holder.createRegistry(type, defaultValues, isDynamic, dependencies); + return type; } protected abstract SpongeRegistryHolder getHolder(); diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 82958eb0f7f..4d07c196be6 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -114,24 +114,26 @@ public void setRootMinecraftRegistry(final RegistryAccess registryAccess) { this.roots.put(RegistryRoots.MINECRAFT, rootRegistry); } + @SuppressWarnings("unchecked") @Override public Registry registry(final RegistryType type) { - final var root = this.roots.get(Objects.requireNonNull(type, "type").root()); + final var root = (Registry>) this.roots.get(Objects.requireNonNull(type, "type").root()); if (root == null) { throw new ValueNotFoundException(String.format("No '%s' root registry has been defined", type.root())); } - final var registry = root.getOptional((ResourceLocation) (Object) type.location()) + final var registry = root.findValue(type.location()) .orElseThrow(() -> new ValueNotFoundException(String.format("No '%s' registry has been defined in root '%s'", type.location(), type.root()))); return (Registry) registry; } + @SuppressWarnings("unchecked") @Override public Optional> findRegistry(final RegistryType type) { - final net.minecraft.core.Registry> root = this.roots.get(Objects.requireNonNull(type, "type").root()); + final Registry> root = (Registry>) this.roots.get(Objects.requireNonNull(type, "type").root()); if (root == null) { return Optional.empty(); } - return (Optional>) (Object) root.getOptional((ResourceLocation) (Object) type.location()); + return root.findValue(type.location()); } @Override From d4c4fec0eb52ef3baea0b74e5df2b8e465bcf3a8 Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 14 Mar 2025 21:08:49 +0200 Subject: [PATCH 221/586] Implement FreezeRegistryEvent --- SpongeAPI | 2 +- .../server/MinecraftServerMixin_Forge.java | 14 ++- .../core/server/MinecraftServerMixin_Neo.java | 14 ++- ...aftServer_ReloadableResourcesAccessor.java | 35 ++++++++ .../resources/mixins.sponge.accessors.json | 1 + .../spongepowered/common/SpongeLifecycle.java | 5 ++ .../bridge/server/MinecraftServerBridge.java | 5 ++ .../lifecycle/FreezeRegistryEventImpl.java | 90 +++++++++++++++++++ .../server/MinecraftServerMixin_API.java | 8 +- .../core/server/MinecraftServerMixin.java | 21 +++++ .../customregistry/CustomRegistryTest.java | 24 ++++- .../server/MinecraftServerMixin_Vanilla.java | 10 +++ 12 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServer_ReloadableResourcesAccessor.java create mode 100644 src/main/java/org/spongepowered/common/event/lifecycle/FreezeRegistryEventImpl.java diff --git a/SpongeAPI b/SpongeAPI index 93d4552bf51..96d7013b2ce 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 93d4552bf5131d2deae2aadd2d0b4b113423b8c8 +Subproject commit 96d7013b2ce1ef7dea99890bfa4791cb95a144a4 diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java index 40818502395..e4ae8e4a76a 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java @@ -36,10 +36,17 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.accessor.server.MinecraftServer_ReloadableResourcesAccessor; import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.forge.ForgeServer; +import java.util.Collection; + @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin_Forge implements ForgeServer { @@ -57,8 +64,13 @@ public long[] getTickTime(ResourceKey dim) { } @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) - private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { + private MultiPackResourceManager forge$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } + + @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) + public void forge$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { + ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); + } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java index f793f816f90..1d8b60b7cf3 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java @@ -36,10 +36,17 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.accessor.server.MinecraftServer_ReloadableResourcesAccessor; import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.neoforge.NeoServer; +import java.util.Collection; + @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin_Neo implements NeoServer { @@ -57,8 +64,13 @@ public long[] getTickTime(ResourceKey dim) { } @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) - private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { + private MultiPackResourceManager neo$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } + + @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) + public void neo$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { + ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); + } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServer_ReloadableResourcesAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServer_ReloadableResourcesAccessor.java new file mode 100644 index 00000000000..a2415a92606 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServer_ReloadableResourcesAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.server; + +import net.minecraft.server.packs.resources.CloseableResourceManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(targets = "net.minecraft.server.MinecraftServer$ReloadableResources") +public interface MinecraftServer_ReloadableResourcesAccessor { + + @Accessor("resourceManager") CloseableResourceManager accessor$resourceManager(); +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index b8ab6c2177f..92e22caf3d8 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -33,6 +33,7 @@ "network.protocol.handshake.ClientIntentionPacketAccessor", "resources.RegistryDataLoader_LoaderAccessor", "resources.ResourceKeyAccessor", + "server.MinecraftServer_ReloadableResourcesAccessor", "server.MinecraftServerAccessor", "server.level.ChunkMap_TrackedEntityAccessor", "server.level.ChunkMapAccessor", diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index b7973a5b71a..f3af01149e5 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -56,6 +56,7 @@ import org.spongepowered.common.event.lifecycle.RegisterChannelEventImpl; import org.spongepowered.common.event.lifecycle.RegisterDataEventImpl; import org.spongepowered.common.event.lifecycle.RegisterFactoryEventImpl; +import org.spongepowered.common.event.lifecycle.FreezeRegistryEventImpl; import org.spongepowered.common.event.lifecycle.RegisterTagEventImpl; import org.spongepowered.common.event.manager.SpongeEventManager; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -141,6 +142,8 @@ public void establishGlobalRegistries() { public void endEstablishGlobalRegistries() { ((SpongeRegistryHolder) this.game).registryHolder().freezeSpongeDynamicRegistries(true); + + this.game.eventManager().post(new FreezeRegistryEventImpl.PostImpl.GameImpl(Cause.of(EventContext.empty(), this.game), this.game)); } @Override @@ -235,6 +238,8 @@ public void establishClientRegistries(final Client client) { this.game, client, client.streamRegistries(RegistryRoots.SPONGE).collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())))); ((SpongeRegistryHolder) client).registryHolder().freezeSpongeDynamicRegistries(true); + + this.game.eventManager().post(FreezeRegistryEventImpl.PostImpl.EngineImpl.client(Cause.of(EventContext.empty(), this.game), this.game, client)); } @Override diff --git a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java index b6f7c9c4085..9d4e6a54def 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java @@ -30,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Game; import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.common.registry.RegistryHolderLogic; import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.user.SpongeUserManager; @@ -48,4 +49,8 @@ public interface MinecraftServerBridge { BlockableEventLoop bridge$spongeMainThreadExecutor(); void bridge$reloadServerRegistries(RegistryHolder holder); + + void bridge$reloadedServerRegistries(RegistryHolderLogic holder); + + RegistryHolderLogic bridge$registryHolder(); } diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/FreezeRegistryEventImpl.java b/src/main/java/org/spongepowered/common/event/lifecycle/FreezeRegistryEventImpl.java new file mode 100644 index 00000000000..ff6eb36f7be --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/lifecycle/FreezeRegistryEventImpl.java @@ -0,0 +1,90 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.lifecycle; + +import io.leangen.geantyref.TypeToken; +import org.spongepowered.api.Client; +import org.spongepowered.api.Engine; +import org.spongepowered.api.Game; +import org.spongepowered.api.Server; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.lifecycle.FreezeRegistryEvent; +import org.spongepowered.api.registry.RegistryHolder; + +public abstract class FreezeRegistryEventImpl extends AbstractLifecycleEvent implements FreezeRegistryEvent { + + protected FreezeRegistryEventImpl(final Cause cause, final Game game) { + super(cause, game); + } + + public static abstract class PostImpl extends FreezeRegistryEventImpl implements Post { + + protected PostImpl(final Cause cause, final Game game) { + super(cause, game); + } + + public static final class GameImpl extends PostImpl implements GameScoped { + + public GameImpl(final Cause cause, final Game game) { + super(cause, game); + } + + @Override + public RegistryHolder holder() { + return this.game; + } + } + + public static final class EngineImpl extends PostImpl implements EngineScoped { + + private final RegistryHolder registryHolder; + private final TypeToken paramType; + + private EngineImpl(final Cause cause, final Game game, final RegistryHolder registryHolder, final TypeToken paramType) { + super(cause, game); + this.registryHolder = registryHolder; + this.paramType = paramType; + } + + @Override + public TypeToken paramType() { + return this.paramType; + } + + @Override + public RegistryHolder holder() { + return this.registryHolder; + } + + public static EngineImpl server(final Cause cause, final Game game, final RegistryHolder registryHolder) { + return new EngineImpl<>(cause, game, registryHolder, TypeToken.get(Server.class)); + } + + public static EngineImpl client(final Cause cause, final Game game, final RegistryHolder registryHolder) { + return new EngineImpl<>(cause, game, registryHolder, TypeToken.get(Client.class)); + } + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index d4d9abc6887..6ce7054e45e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import com.llamalad7.mixinextras.sugar.Local; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.identity.Identity; @@ -38,7 +37,6 @@ import net.minecraft.core.registries.Registries; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; -import net.minecraft.server.WorldStem; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.packs.repository.PackRepository; @@ -155,19 +153,17 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe private ServerScoreboard api$scoreboard; private SpongeGameProfileManager api$profileManager; private MapStorage api$mapStorage; - private RegistryHolderLogic api$registryHolder; private SpongeUserManager api$userManager; private SpongeDataPackManager api$dataPackManager; private final BlockDestructionIdCache api$blockDestructionIdCache = new BlockDestructionIdCache(0, AtomicInteger::decrementAndGet); @Inject(method = "", at = @At("TAIL")) - public void api$initializeSpongeFieldsfinal(final CallbackInfo ci, @Local(argsOnly = true) final WorldStem levelStem) { + public void api$initializeSpongeFieldsfinal(final CallbackInfo ci) { this.api$scheduler = new ServerScheduler(); this.api$worldManager = new SpongeWorldManager((MinecraftServer) (Object) this); this.api$playerDataHandler = new SpongePlayerDataManager(this); this.api$teleportHelper = new SpongeTeleportHelper(); this.api$mapStorage = new SpongeMapStorage(); - this.api$registryHolder = ((SpongeRegistryHolder) levelStem.resourceManager()).registryHolder(); this.api$userManager = new SpongeUserManager((MinecraftServer) (Object) this); this.api$dataPackManager = new SpongeDataPackManager((MinecraftServer) (Object) this, this.storageSource.getLevelPath(LevelResource.DATAPACK_DIR)); } @@ -502,6 +498,6 @@ public MapStorage mapStorage() { @Override public RegistryHolderLogic registryHolder() { - return this.api$registryHolder; + return ((MinecraftServerBridge) this).bridge$registryHolder(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 29504b2c2be..f001ae44bb5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -37,6 +37,7 @@ import net.minecraft.obfuscate.DontObfuscate; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.packs.repository.PackRepository; @@ -57,6 +58,7 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContext; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.world.LoadWorldEvent; import org.spongepowered.api.event.world.UnloadWorldEvent; @@ -94,9 +96,11 @@ import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.config.inheritable.InheritableConfigHandle; import org.spongepowered.common.config.inheritable.WorldConfig; +import org.spongepowered.common.event.lifecycle.FreezeRegistryEventImpl; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.generation.GenerationPhase; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.RegistryHolderLogic; import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; @@ -158,6 +162,7 @@ protected boolean shouldRun(@NonNull Runnable runnable) { return MinecraftServerMixin.this.serverThread; } }; + private RegistryHolderLogic impl$registryHolder; @Override public Subject subject() { @@ -458,4 +463,20 @@ public String toString() { ((SpongeRegistryHolder) holder).setRootMinecraftRegistry(this.shadow$registryAccess()); Launch.instance().lifecycle().beginEstablishServerRegistries(holder); } + + @Inject(method = "", at = @At("TAIL")) + public void impl$onInit(final CallbackInfo ci, final @Local(argsOnly = true) WorldStem levelStem) { + this.bridge$reloadedServerRegistries(((SpongeRegistryHolder) levelStem.resourceManager()).registryHolder()); + } + + @Override + public void bridge$reloadedServerRegistries(final RegistryHolderLogic holder) { + this.impl$registryHolder = holder; + Sponge.game().eventManager().post(FreezeRegistryEventImpl.PostImpl.EngineImpl.server(Cause.of(EventContext.empty(), Sponge.game()), Sponge.game(), holder)); + } + + @Override + public RegistryHolderLogic bridge$registryHolder() { + return this.impl$registryHolder; + } } diff --git a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java index a3b4704ebea..7a60114589d 100644 --- a/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/customregistry/CustomRegistryTest.java @@ -29,9 +29,11 @@ import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.FreezeRegistryEvent; import org.spongepowered.api.event.lifecycle.RegisterRegistryEvent; import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; import org.spongepowered.api.event.lifecycle.StartingEngineEvent; +import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.registry.DefaultedRegistryReference; import org.spongepowered.api.registry.DefaultedRegistryType; import org.spongepowered.api.registry.RegistryKey; @@ -40,6 +42,8 @@ import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.plugin.builtin.jvm.Plugin; +import java.util.Map; + @Plugin("customregistrytest") public final class CustomRegistryTest { @@ -60,7 +64,10 @@ public final class CustomRegistryTest { @Listener public void onRegisterRegistryGameScoped(final RegisterRegistryEvent.GameScoped event) { - event.register(GAME_REG_KEY, true); + event.register(GAME_REG_KEY, true, (h) -> { + ItemTypes.BEDROCK.get(h); + return Map.of(); + }, RegistryTypes.ITEM_TYPE); } @Listener @@ -88,6 +95,21 @@ public void onRegisterRegistryValuesClientScoped(final RegisterRegistryValueEven event.registry(CLIENT_CUSTOM_REGISTRY, r -> r.register(CLIENT_CUSTOM_VALUE.location(), 3)); } + @Listener + public void onRegisterFreezeGameScoped(final FreezeRegistryEvent.Post.GameScoped event) { + final int gameValue = GAME_CUSTOM_VALUE.get(event.holder()); + } + + @Listener + public void onRegisterFreezeServerScoped(final FreezeRegistryEvent.Post.EngineScoped event) { + final int serverValue = SERVER_CUSTOM_VALUE.get(event.holder()); + } + + @Listener + public void onRegisterFreezeClientScoped(final FreezeRegistryEvent.Post.EngineScoped event) { + final int clientValue = CLIENT_CUSTOM_VALUE.get(event.holder()); + } + @Listener public void onServerStarting(final StartingEngineEvent event) { final int gameValue = GAME_CUSTOM_VALUE.get(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java index 9434845c9c8..8215f95222a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java @@ -31,12 +31,17 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.accessor.server.MinecraftServer_ReloadableResourcesAccessor; import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.vanilla.VanillaServer; +import java.util.Collection; + @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin_Vanilla implements VanillaServer { @@ -59,4 +64,9 @@ public String getServerModName() { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } + + @Inject(method = "lambda$reloadResources$29", at = @At("TAIL")) + public void impl$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { + ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); + } } From 21b3f7d05f311f9a667d3e1743dda94cf38d67d7 Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 14 Mar 2025 21:27:07 +0200 Subject: [PATCH 222/586] spotlessApply --- src/main/java/org/spongepowered/common/SpongeLifecycle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index f3af01149e5..edf6ad602fd 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -52,11 +52,11 @@ import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.event.lifecycle.AbstractRegisterRegistryEvent; import org.spongepowered.common.event.lifecycle.AbstractRegisterRegistryValueEvent; +import org.spongepowered.common.event.lifecycle.FreezeRegistryEventImpl; import org.spongepowered.common.event.lifecycle.RegisterBuilderEventImpl; import org.spongepowered.common.event.lifecycle.RegisterChannelEventImpl; import org.spongepowered.common.event.lifecycle.RegisterDataEventImpl; import org.spongepowered.common.event.lifecycle.RegisterFactoryEventImpl; -import org.spongepowered.common.event.lifecycle.FreezeRegistryEventImpl; import org.spongepowered.common.event.lifecycle.RegisterTagEventImpl; import org.spongepowered.common.event.manager.SpongeEventManager; import org.spongepowered.common.event.tracking.PhaseTracker; From e2f584062bf0fb1eae160b2e6633f1f42e9b8ab9 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 15 Mar 2025 02:43:03 +0200 Subject: [PATCH 223/586] Add fallback when no matching level stem is found Store the world key in level data in order to use it as fallback to retrieve the level stem. This can happen when worlds are moved or copied and the new world key would not be present in the old level data. Addionally, when using the Sponge WorldManager methods to move or copy a world, automatically update the relevant entries. --- .../world/server/SpongeWorldManager.java | 46 +++++++++++++++---- .../level/storage/PrimaryLevelDataMixin.java | 6 +++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index d806d3828f4..0746a4f8861 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -283,7 +283,7 @@ public CompletableFuture> loadWorld(final ResourceKey key, try { final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(key); try { - final LevelDataLoadResult result = this.loadLevelData(key, () -> this.createLevelData(registryKey, createOperation.worldArchetype())); + final LevelDataLoadResult result = this.initializeLevelData(key, () -> this.createLevelData(registryKey, createOperation.worldArchetype())); createOperation.createCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.data())); return this.loadWorld0(registryKey, result, storageSource); } catch (final Exception e) { @@ -389,7 +389,7 @@ public CompletableFuture> loadProperties(final R final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOptions.createOperation().orElse(null); if (createOperation != null && !this.worldExists(key)) { - final ServerWorldProperties properties = (ServerWorldProperties) this.loadLevelData(key, () -> this.createLevelData( + final ServerWorldProperties properties = (ServerWorldProperties) this.initializeLevelData(key, () -> this.createLevelData( registryKey, createOperation.worldArchetype())).data(); createOperation.createCallback().ifPresent(c -> c.accept(properties)); return CompletableFuture.completedFuture(Optional.of(properties)); @@ -520,6 +520,15 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr } catch (final IOException e) { throw new CompletionException(e); } + + try { + final Optional levelData = this.loadLevelData(copyRegistryKey); + if (levelData.isPresent()) { + this.saveLevelDat(levelData.get().data(), copyKey); + } + } catch (final IOException e) { + throw new CompletionException(e); + } }).thenApplyAsync($ -> { return true; }, SpongeCommon.server()); @@ -528,6 +537,7 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr @Override public CompletableFuture moveWorld(final ResourceKey key, final ResourceKey movedKey) { final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); + final net.minecraft.resources.ResourceKey movedKeyKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(movedKey, "movedKey")); if (Level.OVERWORLD.equals(registryKey)) { return CompletableFuture.completedFuture(false); @@ -570,6 +580,15 @@ public CompletableFuture moveWorld(final ResourceKey key, final Resourc } catch (final IOException e) { throw new CompletionException(e); } + + try { + final Optional levelData = this.loadLevelData(movedKeyKey); + if (levelData.isPresent()) { + this.saveLevelDat(levelData.get().data(), movedKey); + } + } catch (final IOException e) { + throw new CompletionException(e); + } }).thenApplyAsync($ -> { return true; }, SpongeCommon.server()); @@ -716,11 +735,15 @@ public void prepareLevels() { ((SpongeUserManager) Sponge.server().userManager()).init(); } - private LevelDataLoadResult loadLevelData(final ResourceKey key, final Supplier loader) { - return this.loadLevelData(key, loader, Optional::of); + private LevelDataLoadResult initializeLevelData(final ResourceKey key, final Supplier loader) { + return this.initializeLevelData(key, loader, Optional::of); + } + + private Optional initializeLevelDataOptional(final ResourceKey key, final Supplier> loader) { + return this.initializeLevelData(key, loader, Function.identity()); } - private T loadLevelData(final ResourceKey key, final Supplier loader, final Function> mapper) { + private T initializeLevelData(final ResourceKey key, final Supplier loader, final Function> mapper) { final T result = loader.get(); mapper.apply(result).ifPresent(r -> { final DimensionType dimensionType = r.stem().type().value(); @@ -740,14 +763,14 @@ private Optional loadLevelData(final net.minecraft.resource private Optional loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey) { - return this.loadLevelData((ResourceKey) (Object) registryKey.location(), () -> + return this.initializeLevelDataOptional((ResourceKey) (Object) registryKey.location(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) - .map(t -> this.readLevelData(registryKey, t)), Function.identity()); + .map(t -> this.readLevelData(registryKey, t))); } private LevelDataLoadResult loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey, final Supplier defaultSupplier) { - return this.loadLevelData((ResourceKey) (Object) registryKey.location(), () -> + return this.initializeLevelData((ResourceKey) (Object) registryKey.location(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) .map(t -> this.readLevelData(registryKey, t)) .orElseGet(defaultSupplier)); @@ -772,7 +795,12 @@ private LevelDataLoadResult readLevelData(final net.minecraft.resources.Resource final net.minecraft.core. RegistryAccess.Frozen access = this.server.registryAccess(); final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions( dataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); - return new LevelDataLoadResult((PrimaryLevelData) levelData.worldData(), levelData.dimensions().dimensions().getValueOrThrow(Registries.levelToLevelStem(registryKey))); + return new LevelDataLoadResult((PrimaryLevelData) levelData.worldData(), + levelData.dimensions().dimensions().getOptional(Registries.levelToLevelStem(registryKey)) + .or(() -> Optional.ofNullable(((PrimaryLevelDataBridge) levelData.worldData()).bridge$spongeData().key()) + .flatMap(worldKey -> levelData.dimensions().dimensions().getOptional(Registries.levelToLevelStem( + SpongeWorldManager.createRegistryKey(worldKey))))) + .orElseThrow(() -> new IllegalStateException("The world has no valid WorldArchetype!"))); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 8b79a84e067..bbfac650f1a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -307,6 +307,8 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat public void bridge$readSpongeLevelData(final Dynamic dynamic) { dynamic.get(Constants.Sponge.Data.V2.SPONGE_DATA).get().ifSuccess(v2 -> { v2.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(this.impl$spongeData::setUniqueId); + v2.get(Constants.Sponge.World.WORLD_KEY).read(ResourceLocation.CODEC).result() + .map(org.spongepowered.api.ResourceKey.class::cast).ifPresent(this.impl$spongeData::setKey); v2.get(Constants.Map.MAP_UUID_INDEX).readMap(Codec.STRING, UUIDUtil.CODEC).result().ifPresent(value -> { final BiMap mapIndex = HashBiMap.create(); @@ -333,6 +335,10 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat final CompoundTag data = new CompoundTag(); data.putUUID(Constants.Sponge.World.UNIQUE_ID, this.impl$spongeData.uniqueId()); + if (this.impl$spongeData.key() != null) { + data.putString(Constants.Sponge.World.WORLD_KEY, this.impl$spongeData.key().formatted()); + } + // Map Storage final CompoundTag mapUUIDIndexTag = new CompoundTag(); MapUtil.saveMapUUIDIndex(mapUUIDIndexTag, this.impl$mapUUIDIndex); From 19e13ffaf76c35da3c488f53f9ff162cac771f61 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 14 Mar 2025 19:44:53 -0700 Subject: [PATCH 224/586] feat(content): update to 1.21.5-pre2 --- gradle.properties | 2 +- .../inventory/AbstractContainerMenuAccessor.java | 3 +++ .../inventory/ClickCreativeMenuTransaction.java | 4 ++-- .../transaction/inventory/ClickMenuTransaction.java | 4 ++-- .../event/tracking/phase/packet/PacketPhase.java | 6 +++--- .../event/tracking/phase/packet/PacketPhaseUtil.java | 7 ++++--- .../ServerGamePacketListenerImplMixin_Inventory.java | 4 ++-- .../AbstractContainerMenuMixin_Inventory.java | 9 +++++---- .../server/level/ServerPlayer_Mixin_Inventory.java | 11 ++++++++--- 9 files changed, 30 insertions(+), 20 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3248e710c96..12ba5733b29 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w10a +minecraftVersion=1.21.5-pre2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractContainerMenuAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractContainerMenuAccessor.java index b08dd86d7c6..1ce430b88f2 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractContainerMenuAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractContainerMenuAccessor.java @@ -31,6 +31,7 @@ import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; import java.util.List; @@ -43,4 +44,6 @@ public interface AbstractContainerMenuAccessor { @Accessor("containerListeners") List accessor$containerListeners(); + @Invoker("synchronizeCarriedToRemote") void accessor$synchronizeCarriedToRemote(); + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickCreativeMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickCreativeMenuTransaction.java index 281f3025672..64a92cae7e4 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickCreativeMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickCreativeMenuTransaction.java @@ -107,10 +107,10 @@ public void postProcessEvent(PhaseContext<@NonNull ?> context, ClickContainerEve @Override boolean isContainerEventAllowed(final PhaseContext<@Nullable ?> context) { - if (!(context instanceof InventoryPacketContext)) { + if (!(context instanceof InventoryPacketContext ipc)) { return false; } - final int containerId = ((InventoryPacketContext) context).getPacket().getContainerId(); + final int containerId = ipc.getPacket().containerId(); return containerId != this.player.containerMenu.containerId; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java index 1100799f243..a407e19c478 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java @@ -106,10 +106,10 @@ public void postProcessEvent(final PhaseContext<@NonNull ?> context, final Click boolean isContainerEventAllowed( final PhaseContext<@NonNull ?> context ) { - if (!(context instanceof InventoryPacketContext)) { + if (!(context instanceof InventoryPacketContext ipc)) { return false; } - final int containerId = ((InventoryPacketContext) context).getPacket().getContainerId(); + final int containerId = ipc.getPacket().containerId(); return containerId != this.player.containerMenu.containerId; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java index 37803950dc0..75ee68ad551 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java @@ -234,11 +234,11 @@ public PhaseContext populateContext(final Packet packet, final ServerPlaye // Inventory packet specific methods private static BasicInventoryPacketState fromWindowPacket(final ServerboundContainerClickPacket windowPacket) { - final int mode = 0x01 << 9 << windowPacket.getClickType().ordinal(); - final int packed = windowPacket.getButtonNum(); + final int mode = 0x01 << 9 << windowPacket.clickType().ordinal(); + final int packed = windowPacket.buttonNum(); final int unpacked = mode == Constants.Networking.MODE_DRAG ? (0x01 << 6 << (packed >> 2 & 3)) | (0x01 << 3 << (packed & 3)) : (0x01 << (packed & 3)); - final BasicInventoryPacketState inventory = PacketPhase.fromState(PacketPhase.clickType(windowPacket.getSlotNum()) | mode | unpacked); + final BasicInventoryPacketState inventory = PacketPhase.fromState(PacketPhase.clickType(windowPacket.slotNum()) | mode | unpacked); if (inventory == PacketPhase.Inventory.INVENTORY) { SpongeCommon.logger().warn(String.format("Unable to find InventoryPacketState handler for click window packet: %s", windowPacket)); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 1f0bc3e84b0..eb890959bf3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -66,6 +66,7 @@ import org.spongepowered.common.accessor.world.entity.EntityAccessor; import org.spongepowered.common.accessor.world.entity.animal.sheep.SheepAccessor; import org.spongepowered.common.accessor.world.entity.animal.wolf.WolfAccessor; +import org.spongepowered.common.accessor.world.inventory.AbstractContainerMenuAccessor; import org.spongepowered.common.accessor.world.inventory.SlotAccessor; import org.spongepowered.common.bridge.network.protocol.PacketBridge; import org.spongepowered.common.bridge.world.level.block.TrackableBlockBridge; @@ -136,9 +137,9 @@ public static void handleCursorRestore(final Player player, final Transaction context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), + try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.slotNum(), packet.buttonNum(), packet.clickType(), this.player )) { if (menu instanceof MenuBridge bridge) { final SpongeInventoryMenu spongeMenu = bridge.bridge$getMenu(); if (spongeMenu != null) { - spongeMenu.onClick(packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player, ((Container) menu)); + spongeMenu.onClick(packet.slotNum(), packet.buttonNum(), packet.clickType(), this.player, ((Container) menu)); } } menu.sendAllDataToRemote(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index 79f0556afd9..b8693d4b25a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -34,6 +34,7 @@ import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.ContainerSynchronizer; import net.minecraft.world.inventory.DataSlot; +import net.minecraft.world.inventory.RemoteSlot; import net.minecraft.world.inventory.ResultSlot; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -78,7 +79,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon @Final @Shadow private List containerListeners; @Shadow private boolean suppressRemoteUpdates; @Final @Shadow private List dataSlots; - @Shadow @Final private NonNullList remoteSlots; + @Shadow @Final private NonNullList remoteSlots; @Shadow @Nullable private ContainerSynchronizer synchronizer; @Shadow protected abstract void shadow$doClick(int param0, int param1, ClickType param2, Player param3); @@ -303,9 +304,9 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon listener.slotChanged(((AbstractContainerMenu) (Object) this), i, oldStack); } if (synchronize) { - final ItemStack remoteStack = this.remoteSlots.get(i); - if (!ItemStack.matches(remoteStack, newStack)) { - this.remoteSlots.set(i, newStack.copy()); + final RemoteSlot remoteStack = this.remoteSlots.get(i); + if (!remoteStack.matches(oldStack)) { + remoteStack.force(oldStack); if (this.synchronizer != null) { this.synchronizer.sendSlotChange(((AbstractContainerMenu) (Object) this), i, newStack); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/server/level/ServerPlayer_Mixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/server/level/ServerPlayer_Mixin_Inventory.java index 56d338199cd..1f74135c450 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/server/level/ServerPlayer_Mixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/server/level/ServerPlayer_Mixin_Inventory.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.mixin.inventory.impl.server.level; -import net.minecraft.core.NonNullList; import net.minecraft.network.protocol.game.ClientboundSetPlayerInventoryPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; +import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -38,6 +38,8 @@ import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; +import java.util.List; + @Mixin(targets = "net/minecraft/server/level/ServerPlayer$1") public abstract class ServerPlayer_Mixin_Inventory { @@ -46,12 +48,15 @@ public abstract class ServerPlayer_Mixin_Inventory { // @formatter:on @Inject(method = "sendInitialData", at = @At("RETURN")) - private void inventory$sendOffhand(final AbstractContainerMenu containerMenu, final NonNullList $$1, final ItemStack $$2, final int[] $$3, final CallbackInfo ci) { + private void inventory$sendOffhand( + final AbstractContainerMenu containerMenu, final List $$1, final ItemStack $$2, + final int[] $$3, final CallbackInfo ci + ) { if (containerMenu == this.this$0.inventoryMenu) { return; } - final org.spongepowered.api.item.inventory.Slot offhand + final Slot offhand = ((org.spongepowered.api.entity.living.player.server.ServerPlayer) this.this$0).inventory().offhand(); this.this$0.connection.send( new ClientboundSetPlayerInventoryPacket(((SlotAdapter) offhand).getOrdinal(), ItemStackUtil.toNative(offhand.peek()))); From 41d46ba49cafa1c9663fe037bb0b64ed5ad83d23 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 14 Mar 2025 20:05:29 -0700 Subject: [PATCH 225/586] revert fix(crash): avoid a possible movement-fix crash The underlying bug was fixed now with the same isEmpty check. This reverts commit b039b78fecee8e13fe1f77a3ee4b32a0e7624f39. --- .../common/mixin/core/world/entity/EntityMixin.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 7a8d9889fc8..e2dc0df2ed2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -186,11 +186,10 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow @javax.annotation.Nullable public PortalProcessor portalProcess; @Shadow public abstract boolean save(final CompoundTag $$0); @Shadow public abstract Level level(); - - @Shadow @Final private List movementThisTick; // @formatter:on + private boolean impl$isConstructing = true; private VanishState impl$vanishState = VanishState.unvanished(); protected boolean impl$transient = false; @@ -735,16 +734,7 @@ public void stopRiding() { original.call(block, world, pos, state, entity); this.impl$lastCollidedBlockPos = pos; } - } - @Inject(method = "removeLatestMovementRecordingBatch", at = @At("HEAD"), cancellable = true) - private void impl$catchEmptyRemoval(CallbackInfo ci) { - // This prevents a no element exception leading to a crash. It is highly possible that - // this is a bug, but whether it's from Vanilla or Sponge, I'm not certain. It's also possible - // this can be triggered by a rogue client missending packets, leading to a player being - if (this.movementThisTick.isEmpty()) { - ci.cancel(); - } } @WrapOperation(method = "lambda$checkInsideBlocks$0", From e7b99d3e57ea1de0a835ee0f7f98ca2bfb42e9c7 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 15 Mar 2025 18:51:35 +0200 Subject: [PATCH 226/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 1b0e82f73c8..8dcad8b075e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 1b0e82f73c8ce64a292c59823e19ce8a6f03fe43 +Subproject commit 8dcad8b075ee33f7691431decec0694a147ceabf From 8224a7396efeacdb7796b23c8eca2f8cdfb212a0 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 15 Mar 2025 20:28:40 +0200 Subject: [PATCH 227/586] Fix Keys.ARMOR_MATERIAL --- .../common/data/provider/item/stack/ArmorItemStackData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index 45679626783..d95803a0a08 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -55,7 +55,7 @@ public static void register(final DataProviderRegistrator registrator) { return null; } return equippable.assetId() - .map(rl -> (ResourceKey) (Object) rl) + .map(rl -> (ResourceKey) (Object) rl.location()) .flatMap(rk -> RegistryTypes.ARMOR_MATERIAL.get().findEntry(rk)) .map(RegistryEntry::value) .orElse(null); From cbc49363d976b393237fb6a9d4c5f4705abc3f47 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 19 Mar 2025 17:05:33 +0200 Subject: [PATCH 228/586] Fix CommandTreeNodeTypes & FlatGeneratorConfigs registry scope --- SpongeAPI | 2 +- .../vanilla/generator/world/level/LevelDataRegistries.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 8dcad8b075e..bd5ca35ee39 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8dcad8b075ee33f7691431decec0694a147ceabf +Subproject commit bd5ca35ee392f7a92d47f8ad0bfe5a28a9dc4405 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java index 0df1b2fe9bd..dd4262bcb91 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java @@ -103,7 +103,7 @@ public static List levelDataRegistries(final Context context) { "FLAT_GENERATOR_CONFIG", context.relativeClass("world.generation.config.flat", "FlatGeneratorConfig"), Registries.FLAT_LEVEL_GENERATOR_PRESET, - a -> true, RegistryScope.GAME + a -> true, RegistryScope.SERVER ), new RegistryEntriesGenerator<>( "world.generation.config.noise", From a064b0d78836552538fbdb7c61831d079d95fba2 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 19 Mar 2025 18:33:16 +0200 Subject: [PATCH 229/586] Remove worldExists check from world creation This doesn't really make sense as the plugin author might have just copied region files to the world directly or they are intending to override the exists level data. --- .../spongepowered/common/world/server/SpongeWorldManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 0746a4f8861..286d165175c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -279,7 +279,7 @@ public CompletableFuture> loadWorld(final ResourceKey key, } final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOption.createOperation().orElse(null); - if (createOperation != null && !this.worldExists(key)) { + if (createOperation != null) { try { final LevelStorageSource.LevelStorageAccess storageSource = this.getLevelStorageAccess(key); try { @@ -388,7 +388,7 @@ public CompletableFuture> loadProperties(final R } final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOptions.createOperation().orElse(null); - if (createOperation != null && !this.worldExists(key)) { + if (createOperation != null) { final ServerWorldProperties properties = (ServerWorldProperties) this.initializeLevelData(key, () -> this.createLevelData( registryKey, createOperation.worldArchetype())).data(); createOperation.createCallback().ifPresent(c -> c.accept(properties)); From 94f48bef9d69aa2dd85ec43415971f2669f5f65e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 20 Mar 2025 21:46:33 -0700 Subject: [PATCH 230/586] feat(minecraft): update to 1.21.5-rc1 --- gradle.properties | 2 +- .../block/entity/BlockEntityMixin_API.java | 3 + .../mixin/core/item/EmptyMapItemMixin.java | 65 ++++++++++--------- .../mixin/core/world/item/MapItemMixin.java | 18 +++-- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/gradle.properties b/gradle.properties index 12ba5733b29..43f27e8df74 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.5-pre2 +minecraftVersion=1.21.5-rc1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java index 34fcbb17ae5..cae3f7d2329 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java @@ -70,6 +70,9 @@ public abstract class BlockEntityMixin_API implements BlockEntity { @Shadow public abstract void shadow$setChanged(); //@formatter:on + @Shadow + public abstract CompoundTag saveWithFullMetadata(HolderLookup.Provider $$0); + @Nullable private LocatableBlock api$LocatableBlock; private boolean api$canTickRequested = false; private boolean api$canTick; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java index 2f957a927e3..3ca44f87ef7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/item/EmptyMapItemMixin.java @@ -25,16 +25,16 @@ package org.spongepowered.common.mixin.core.item; import com.google.common.collect.Sets; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.component.DataComponents; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.EmptyMapItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.MapItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.saveddata.maps.MapId; -import org.objectweb.asm.Opcodes; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.HandType; import org.spongepowered.api.data.value.Value; @@ -47,8 +47,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.storage.MapItemSavedDataBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -61,17 +61,12 @@ public abstract class EmptyMapItemMixin { @Redirect(method = "use", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/MapItem;create(Lnet/minecraft/world/level/Level;IIBZZ)Lnet/minecraft/world/item/ItemStack;")) - private ItemStack impl$createMapWithSpongeData(final Level level, final int x, final int y, final byte scale, - final boolean trackingPosition, final boolean unlimitedTracking, - final Level level2, - final net.minecraft.world.entity.player.Player playerIn, - final InteractionHand usedHand) { - if (level.isClientSide()) { // ignore on client - return MapItem.create(level, x, y, scale, trackingPosition, unlimitedTracking); - } - + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/item/MapItem;create(Lnet/minecraft/server/level/ServerLevel;IIBZZ)Lnet/minecraft/world/item/ItemStack;")) + private ItemStack impl$createMapWithSpongeData( + final ServerLevel level, final int x, final int y, final byte scale, + final boolean trackingPosition, final boolean unlimitedTracking, final Level level2, + final net.minecraft.world.entity.player.Player playerIn, final InteractionHand usedHand) { final Player player = (Player) playerIn; try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { @@ -81,15 +76,15 @@ public abstract class EmptyMapItemMixin { frame.addContext(EventContextKeys.USED_ITEM, player.itemInHand(handType).asImmutable()); final Set> mapValues = Sets.newHashSet( - Value.immutableOf(Keys.MAP_LOCATION, Vector2i.from((int)playerIn.getX(), (int)playerIn.getZ())), - Value.immutableOf(Keys.MAP_WORLD, ((ServerWorld)level).key()), - Value.immutableOf(Keys.MAP_TRACKS_PLAYERS, trackingPosition), - Value.immutableOf(Keys.MAP_UNLIMITED_TRACKING, unlimitedTracking), - Value.immutableOf(Keys.MAP_SCALE, (int)scale) - // No need to have the defaults - //Value.immutableOf(Keys.MAP_CANVAS, MapCanvas.blank()), - //Value.immutableOf(Keys.MAP_LOCKED, Constants.Map.DEFAULT_MAP_LOCKED), - //Value.immutableOf(Keys.MAP_DECORATIONS, Sets.newHashSet()) + Value.immutableOf(Keys.MAP_LOCATION, Vector2i.from((int) playerIn.getX(), (int) playerIn.getZ())), + Value.immutableOf(Keys.MAP_WORLD, ((ServerWorld) level).key()), + Value.immutableOf(Keys.MAP_TRACKS_PLAYERS, trackingPosition), + Value.immutableOf(Keys.MAP_UNLIMITED_TRACKING, unlimitedTracking), + Value.immutableOf(Keys.MAP_SCALE, (int) scale) + // No need to have the defaults + //Value.immutableOf(Keys.MAP_CANVAS, MapCanvas.blank()), + //Value.immutableOf(Keys.MAP_LOCKED, Constants.Map.DEFAULT_MAP_LOCKED), + //Value.immutableOf(Keys.MAP_DECORATIONS, Sets.newHashSet()) ); final Optional optMapInfo = SpongeCommonEventFactory.fireCreateMapEvent(frame.currentCause(), mapValues); @@ -104,15 +99,21 @@ public abstract class EmptyMapItemMixin { } } - @Inject(method = "use", at = @At(value = "FIELD", - target = "Lnet/minecraft/world/level/Level;isClientSide:Z", opcode = Opcodes.GETFIELD), - locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - private void impl$returnFailResultIfMapWasNotCreated(final Level level, - final net.minecraft.world.entity.player.Player playerIn, - final InteractionHand handIn, - final CallbackInfoReturnable cir, - final ItemStack itemstack) { - if (itemstack.isEmpty()) { + @Inject( + method = "use", + slice = @Slice( + from = @At(value = "CONSTANT", args = "classValue=net/minecraft/server/level/ServerLevel"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;consume(ILnet/minecraft/world/entity/LivingEntity;)V") + ), + at = @At(value = "FIELD", target = "Lnet/minecraft/world/InteractionResult;SUCCESS:Lnet/minecraft/world/InteractionResult$Success;"), + cancellable = true + ) + private void impl$returnFailResultIfMapWasNotCreated( + final Level level, final net.minecraft.world.entity.player.Player player, + final InteractionHand hand, final CallbackInfoReturnable cir, + @Local ItemStack stack + ) { + if (stack.isEmpty()) { cir.cancel(); cir.setReturnValue(InteractionResult.FAIL); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/MapItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/MapItemMixin.java index 0563739bcbc..e1bc6f99b6c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/MapItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/MapItemMixin.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.item; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.MapItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.saveddata.maps.MapId; @@ -33,17 +35,19 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.storage.MapItemSavedDataBridge; @Mixin(MapItem.class) public class MapItemMixin { - @Inject(method = "createNewSavedData", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Level;setMapData(Lnet/minecraft/world/level/saveddata/maps/MapId;Lnet/minecraft/world/level/saveddata/maps/MapItemSavedData;)V"), - locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "createNewSavedData", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;setMapData(Lnet/minecraft/world/level/saveddata/maps/MapId;Lnet/minecraft/world/level/saveddata/maps/MapItemSavedData;)V" + ) + ) private static void impl$storeMapId( - final Level level, + final ServerLevel level, final int x, final int y, final int scale, @@ -51,8 +55,8 @@ public class MapItemMixin { final boolean unlimitedTracking, final ResourceKey dimension, final CallbackInfoReturnable cir, - final MapItemSavedData data, - final MapId id + final @Local MapItemSavedData data, + final @Local MapId id ) { ((MapItemSavedDataBridge) data).bridge$initMapId(id.id()); } From 9dd097b7c728d36a9bd219c46cd12b3569868cdc Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 21 Mar 2025 16:15:43 +0200 Subject: [PATCH 231/586] Split InteractContainerEvent.Close to Pre and Post --- SpongeAPI | 2 +- .../transaction/inventory/CloseMenuTransaction.java | 6 +----- .../event/server/level/ServerPlayerMixin_Inventory.java | 7 +++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index bd5ca35ee39..e72f1c51264 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit bd5ca35ee392f7a92d47f8ad0bfe5a28a9dc4405 +Subproject commit e72f1c51264fc165fab5e1c6d3cf960520be82d2 diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java index 984ef319772..ed1cb202a9b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java @@ -84,13 +84,9 @@ public Optional generateEvent( final PhaseContext<@NonNull ?> context, @Nullable final GameTransaction<@NonNull ?> parent, final ImmutableList> gameTransactions, final Cause currentCause ) { - // TODO: API-14 post events? - if (true) { - return Optional.empty(); - } final ItemStackSnapshot resultingCursor = ItemStackUtil.snapshotOf(this.player.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(this.cursor, resultingCursor); - final InteractContainerEvent.Close event = SpongeEventFactory.createInteractContainerEventClose(currentCause, (Container) this.menu, + final InteractContainerEvent.Close.Post event = SpongeEventFactory.createInteractContainerEventClosePost(currentCause, (Container) this.menu, cursorTransaction, (Container) this.menu, this.slotTransactions == null ? Collections.emptyList() : this.slotTransactions); return Optional.of(event); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 29c6c199e2c..bf6c0878b28 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -85,7 +85,6 @@ import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.mixin.inventory.event.entity.player.PlayerMixin_Inventory; -import java.util.Collections; import java.util.Map; @Mixin(ServerPlayer.class) @@ -259,9 +258,9 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$serverLevel()); final ItemStackSnapshot resultingCursor = ItemStackUtil.snapshotOf(this.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(resultingCursor, resultingCursor); - final InteractContainerEvent.Close event = SpongeEventFactory.createInteractContainerEventClose( + final InteractContainerEvent.Close event = SpongeEventFactory.createInteractContainerEventClosePre( tracker.currentCause(), (org.spongepowered.api.item.inventory.Container) this.containerMenu, - cursorTransaction, (Inventory) this.containerMenu, Collections.emptyList()); + cursorTransaction); SpongeCommon.post(event); PacketPhaseUtil.handleCursorRestore((ServerPlayer) (Object) this, event.cursorTransaction(), event.isCancelled()); if (event.isCancelled() && !(this.containerMenu instanceof InventoryMenu)) { @@ -294,7 +293,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$serverLevel()); final PhaseContext<@NonNull ?> context = tracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { + try (final EffectTransactor ignored = transactor.logCloseInventory(context, player)) { original.call(instance, player); instance.broadcastChanges(); TrackingUtil.processBlockCaptures(context); From 4f0d92ec484dc242f7216dd89e5dbbd6133f611a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Sat, 22 Mar 2025 21:44:11 +0100 Subject: [PATCH 232/586] fix missing explosion sound/particle also prepared no particle/sound options --- .../core/server/level/ServerLevelMixin.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index f51966d74e7..13778ed4a3d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -27,13 +27,14 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; -import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.bossevents.CustomBossEvents; import net.minecraft.server.level.ServerChunkCache; @@ -42,6 +43,7 @@ import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.PlayerList; +import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.ProgressListener; import net.minecraft.world.RandomSequences; @@ -55,6 +57,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -289,19 +292,16 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } @Override - public void bridge$handleExplosionPacket(final ServerGamePacketListenerImpl instance, Explosion apiExplosion, - final ClientboundExplodePacket packet) { - if (apiExplosion.shouldPlaySmoke()) { - // TODO no sound? - // TODO control which particle is used (API) - // TODO control sound? (ViewerPacketUtil.resolveEvent) - var newPacket = new ClientboundExplodePacket(packet.center(), packet.playerKnockback(), packet.explosionParticle(), packet.explosionSound()); - instance.send(newPacket); - } - else { - packet.playerKnockback().ifPresent(kb -> instance.send(new ClientboundSetEntityMotionPacket(instance.player.getId(), kb))); - // TODO play sound? - } + public void bridge$handleExplosionPacket(final ServerGamePacketListenerImpl instance, Explosion apiExplosion, final ClientboundExplodePacket packet) { + // TODO control particle in API + ParticleOptions particleData = new BlockParticleOption(ParticleTypes.BLOCK, Blocks.AIR.defaultBlockState()); // "no" particle + particleData = packet.explosionParticle(); + // TODO control sound in API + var soundEvent = Holder.direct(new SoundEvent(ResourceLocation.parse("sponge:none"), Optional.of(0f))); // "no" sound + soundEvent = packet.explosionSound(); + // TODO apiExplosion.shouldPlaySmoke() is not initialized correctly + var newPacket = new ClientboundExplodePacket(packet.center(), packet.playerKnockback(), particleData, soundEvent); + instance.send(newPacket); } @Override public void bridge$setManualSave(final boolean state) { From a1e3d93a670344691b9e29c097e1ac8193427eb9 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Sun, 23 Mar 2025 20:58:00 +0100 Subject: [PATCH 233/586] fix missing cause/context on fluid flow events --- .../common/event/tracking/phase/tick/FluidTickContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/FluidTickContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/FluidTickContext.java index 1dfe23f74a7..809d08e0adf 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/FluidTickContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/FluidTickContext.java @@ -50,7 +50,7 @@ public FluidTickContext source(final Object owner) { if (owner instanceof LocatableBlock) { final LocatableBlock locatableBlock = (LocatableBlock) owner; final Block block = ((BlockState) locatableBlock.blockState()).getBlock(); - this.providesModifier = !(block instanceof LiquidBlock); + this.providesModifier = true; this.world = locatableBlock.world(); if (block instanceof TrackableBridge) { final TrackableBridge trackable = (TrackableBridge) block; From c2c1f983f4a55cab32e1b028ad054f914d1824fc Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 24 Mar 2025 19:28:18 +0100 Subject: [PATCH 234/586] fix missing cause on piston events --- .../org/spongepowered/common/event/tracking/TrackingUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java index 2aaa04ea7d7..e023b93dec7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java @@ -328,7 +328,7 @@ public static boolean fireMinecraftBlockEvent( return tick.getAsBoolean(); } final BlockEventTickContext phaseContext = TickPhase.Tick.BLOCK_EVENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)); - phaseContext.source(source); + phaseContext.source(blockEvent); final UUID user = ((TrackableBlockEventDataBridge) (Object) event).bridge$getSourceUserUUID(); if (user != null) { From b6ca717239589371ac0a93dcf85eae20e505fedd Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 24 Mar 2025 20:31:12 +0100 Subject: [PATCH 235/586] use internal blockstate for BlockEntity#block this fixes moving piston blockentity returning its moved state --- .../world/level/block/entity/BlockEntityMixin_API.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java index 34fcbb17ae5..8629f9f4c34 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java @@ -63,6 +63,7 @@ public abstract class BlockEntityMixin_API implements BlockEntity { @Shadow @Final private net.minecraft.world.level.block.entity.BlockEntityType type; @Shadow protected net.minecraft.world.level.Level level; @Shadow protected boolean remove; + @Shadow private net.minecraft.world.level.block.state.BlockState blockState; @Shadow public abstract BlockPos shadow$getBlockPos(); @Shadow public abstract CompoundTag shadow$saveWithFullMetadata(HolderLookup.Provider $$0); @Shadow @Final protected BlockPos worldPosition; @@ -179,7 +180,7 @@ public final BlockEntityType type() { @Override public BlockState block() { - return (BlockState) this.level.getBlockState(this.shadow$getBlockPos()); + return (BlockState) this.blockState; } @Override From 4123018c7bf084c5bb2fdde43aca6f23f5e1d8dc Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Mon, 24 Mar 2025 20:31:29 +0100 Subject: [PATCH 236/586] implement missing Piston data --- .../data/provider/block/state/MovingPistonData.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/MovingPistonData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/MovingPistonData.java index c5e3f41c9dd..c1e81e95837 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/MovingPistonData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/MovingPistonData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.block.state; import net.minecraft.world.level.block.piston.MovingPistonBlock; +import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -42,7 +43,13 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.DIRECTION) .get(h -> DirectionUtil.getFor(h.getValue(MovingPistonBlock.FACING))) .set((h, v) -> DirectionUtil.set(h, v, MovingPistonBlock.FACING)) - .supports(h -> h.getBlock() instanceof MovingPistonBlock); + .supports(h -> h.getBlock() instanceof MovingPistonBlock) + .asImmutable(PistonMovingBlockEntity.class) + .create(Keys.BLOCK_STATE) + .get(h -> (org.spongepowered.api.block.BlockState) h.getMovedState()) + .create(Keys.IS_EXTENDED) + .get(PistonMovingBlockEntity::isExtending) + ; } // @formatter:on } From 0d1d07414d0047e130c08bd84bc343194a5b6a97 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 25 Mar 2025 18:30:51 -0700 Subject: [PATCH 237/586] feat(minecraft): update to 1.21.5 Minimal changes required here since all the snapshots have been updates. --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index c3d36c2581d..5c9f03302be 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c3d36c2581d0e9047c0265041e92f6225396b779 +Subproject commit 5c9f03302bec24677214645d9f135f4b8fd317a1 diff --git a/gradle.properties b/gradle.properties index 43f27e8df74..0c56afda37b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.5-rc1 +minecraftVersion=1.21.5 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index dcb1489e2b7..a5268ccaf3d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -8820,6 +8820,14 @@ + + + + + + + + From 3c92e3e8fab6d4391e184a247cdcc5d2f258875d Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 26 Mar 2025 20:29:01 +0100 Subject: [PATCH 238/586] introduce scoped registry holder using PhaseTracker --- SpongeAPI | 2 +- .../vanilla/generator/RegistryScope.java | 2 +- .../spongepowered/common/SpongeCommon.java | 17 +++++++++++++++- .../spongepowered/common/SpongeLifecycle.java | 17 +++++++++------- .../data/provider/entity/PaintingData.java | 2 +- .../item/stack/BookPagesItemStackData.java | 2 +- .../provider/item/stack/ItemStackData.java | 20 ++++++++++++------- .../damage/SpongeDamageSourceBuilder.java | 2 +- .../SpongeRandomEnchantmentListBuilder.java | 4 ++-- .../common/registry/SpongeRegistryKey.java | 6 ++++++ .../common/registry/SpongeRegistryType.java | 6 ++++++ .../world/schematic/SchematicTranslator.java | 6 +++--- 12 files changed, 61 insertions(+), 25 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index cb1550649db..53b9cfebe8a 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit cb1550649db77878cfc511dfa7c48ae76cf4c164 +Subproject commit 53b9cfebe8aa1151286781bfdc52790792830716 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryScope.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryScope.java index cbcbf2c6e9a..28bea4c642e 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryScope.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryScope.java @@ -63,7 +63,7 @@ void populateRegistryGetter(final Builder builder, final CodeBlock registryType) SERVER { @Override protected CodeBlock registryKeyToReference() { - return CodeBlock.of("asDefaultedReference($T::server)", Types.SPONGE); + return CodeBlock.of("asScopedReference()", Types.SPONGE); } @Override diff --git a/src/main/java/org/spongepowered/common/SpongeCommon.java b/src/main/java/org/spongepowered/common/SpongeCommon.java index 7238fe6e054..7105478eb50 100644 --- a/src/main/java/org/spongepowered/common/SpongeCommon.java +++ b/src/main/java/org/spongepowered/common/SpongeCommon.java @@ -37,7 +37,9 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Event; import org.spongepowered.common.applaunch.config.core.SpongeConfigs; +import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.common.scheduler.AsyncScheduler; import org.spongepowered.common.scheduler.ServerScheduler; @@ -100,8 +102,21 @@ public static RegistryAccess.Frozen vanillaRegistryAccess() { return SpongeCommon.server().registryAccess(); } + public static SpongeRegistryHolder scopedHolder() { + var holder = PhaseTracker.getInstance().currentCause().first(SpongeRegistryHolder.class); + // If we have a holder in scope use it directly unless it is game + if (holder.isEmpty() || holder.get() == SpongeCommon.game()) { + + if (SpongeCommon.game().isServerAvailable()) { + return (SpongeRegistryHolder) SpongeCommon.server(); + } + return SpongeCommon.game(); + } + return holder.get(); + } + public static Registry vanillaRegistry(ResourceKey> key) { - return SpongeCommon.vanillaRegistryAccess().lookupOrThrow(key); + return (Registry) SpongeCommon.scopedHolder().lookupOrThrow(key); } public static ServerScheduler serverScheduler() { diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index edf6ad602fd..02201c770b2 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -212,13 +212,16 @@ public void beginEstablishServerRegistries(final RegistryHolder server) { @Override public void processServerRegistries(final RegistryHolder server, final Stream> registries) { - final Map, org.spongepowered.api.registry.Registry> map = - registries.collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())); - if (!map.isEmpty()) { - map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$setRegistryHolder(server)); - this.game.eventManager().post(AbstractRegisterRegistryValueEvent.EngineScopedImpl.server(Cause.of(EventContext.empty(), this.game), this.game, server, map)); - map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$markEventCalled()); - ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(false); + try (var frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.pushCause(server); + final Map, org.spongepowered.api.registry.Registry> map = + registries.collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())); + if (!map.isEmpty()) { + map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$setRegistryHolder(server)); + this.game.eventManager().post(AbstractRegisterRegistryValueEvent.EngineScopedImpl.server(Cause.of(EventContext.empty(), this.game), this.game, server, map)); + map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$markEventCalled()); + ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(false); + } } } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java index 97771ab0dfc..b1d40e15cd5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java @@ -53,7 +53,7 @@ public static void register(final DataProviderRegistrator registrator) { .setAnd((h, v) -> { if (!h.level().isClientSide) { final Holder oldArt = h.getVariant(); - var newArt = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); + var newArt = SpongeCommon.vanillaRegistry(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); h.setVariant(newArt); ((HangingEntityAccessor) h).invoker$setDirection(h.getDirection()); if (!h.survives()) { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BookPagesItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BookPagesItemStackData.java index e064bad1c6f..6c1bc57d3b4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BookPagesItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BookPagesItemStackData.java @@ -71,7 +71,7 @@ private static boolean set(final ItemStack holder, final List value if (value.isEmpty()) { return BookPagesItemStackData.delete(holder, component); } - final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); + final var registry = SpongeCommon.vanillaRegistry(Registries.ENCHANTMENT); holder.update(component, ItemEnchantments.EMPTY, ench -> { final ItemEnchantments.Mutable mutable = new ItemEnchantments.Mutable(ench); mutable.keySet().clear(); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 31fa397b85f..cb8ae6766e7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -112,7 +112,13 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(ItemStack.class) .create(Keys.BURN_TIME) - .get(h -> SpongeCommon.server().fuelValues().burnDuration(h)) + .get(h -> { + if (SpongeCommon.game().isServerAvailable()) { + return SpongeCommon.server().fuelValues().burnDuration(h); + } else { + return null; + } + }) .create(Keys.CONTAINER_ITEM) .get(h -> (ItemType) h.getItem().getCraftingRemainder().getItem()) .create(Keys.DISPLAY_NAME) @@ -395,12 +401,12 @@ private static DataTransactionResult deleteAndTransactUseCooldown(final ItemStac return DataTransactionResult.successNoData(); } return cooldown.cooldownGroup() - .map(group -> DataTransactionResult.successRemove(List.of( - Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())), - Value.immutableOf(Keys.COOLDOWN_GROUP, (ResourceKey) (Object) group) - ))).orElseGet(() -> DataTransactionResult.successRemove(List.of( - Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())) - ))); + .map(group -> DataTransactionResult.successRemove(List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())), + Value.immutableOf(Keys.COOLDOWN_GROUP, (ResourceKey) (Object) group) + ))).orElseGet(() -> DataTransactionResult.successRemove(List.of( + Value.immutableOf(Keys.COOLDOWN, Ticks.of(cooldown.ticks())) + ))); } } diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java index c2141f4b563..6cbc695fee1 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageSourceBuilder.java @@ -63,7 +63,7 @@ public DamageSource build() throws IllegalStateException { @Override public DamageSource.Builder type(final DamageType damageType) { - final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.DAMAGE_TYPE); + final var registry = SpongeCommon.vanillaRegistry(Registries.DAMAGE_TYPE); this.damageType = registry.wrapAsHolder((net.minecraft.world.damagesource.DamageType) (Object) damageType); return this; } diff --git a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java index 7c2699c0549..f1aa873f21c 100644 --- a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java +++ b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java @@ -93,7 +93,7 @@ public List build() throws IllegalStateException { if (this.pool == null || this.pool.isEmpty()) { Objects.requireNonNull(this.item, "The item cannot be null"); this.randomSource.setSeed(this.seed + this.option); - final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); + final var registry = SpongeCommon.vanillaRegistry(Registries.ENCHANTMENT); var stream = registry.listElements().map($$0x -> (Holder)$$0x); enchantments = EnchantmentHelper.selectEnchantment(this.randomSource, ItemStackUtil.toNative(this.item), this.level, stream); } else { @@ -139,7 +139,7 @@ public static List fromNative(final List list) } public static List toNative(final List list) { - final var registry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); + final var registry = SpongeCommon.vanillaRegistry(Registries.ENCHANTMENT); return list.stream().map(ench -> { var mcEnch = registry.wrapAsHolder((net.minecraft.world.item.enchantment.Enchantment) (Object) ench.type()); return new EnchantmentInstance(mcEnch, ench.level()); diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistryKey.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistryKey.java index 66e72475fd7..de085046aec 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeRegistryKey.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistryKey.java @@ -30,6 +30,7 @@ import org.spongepowered.api.registry.RegistryKey; import org.spongepowered.api.registry.RegistryReference; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.SpongeCommon; import java.util.Objects; import java.util.StringJoiner; @@ -65,6 +66,11 @@ public final DefaultedRegistryReference asDefaultedReference(fi return new SpongeDefaultedRegistryReference<>((RegistryKey) this, defaultHolder); } + @Override + public final DefaultedRegistryReference asScopedReference() { + return new SpongeDefaultedRegistryReference<>((RegistryKey) this, SpongeCommon::scopedHolder); + } + @Override public int hashCode() { return Objects.hash(this.registry, this.location); diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistryType.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistryType.java index be1c0fdaa89..d7327b0942d 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeRegistryType.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistryType.java @@ -28,6 +28,7 @@ import org.spongepowered.api.registry.DefaultedRegistryType; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.SpongeCommon; import java.util.Objects; import java.util.StringJoiner; @@ -58,6 +59,11 @@ public final DefaultedRegistryType asDefaultedType(final Suppli return new SpongeDefaultedRegistryType<>(this.root, this.location, Objects.requireNonNull(defaultHolder, "defaultHolder")); } + @Override + public DefaultedRegistryType asScopedType() { + return new SpongeDefaultedRegistryType<>(this.root, this.location, SpongeCommon::scopedHolder); + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java index 54b41bbb76d..cc781ad9926 100644 --- a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java +++ b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java @@ -327,7 +327,7 @@ private static void deserializeBiomeContainer( .orElseThrow(() -> new InvalidDataException("Missing BiomePalette as required by the schematic spec")); final Set biomeKeys = biomeMap.keys(false); - final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BIOME)); + final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.vanillaRegistry(Registries.BIOME)); biomePalette = new MutableBimapPalette<>( PaletteTypes.BIOME_PALETTE.get(), biomeRegistry, @@ -454,7 +454,7 @@ public DataView addTo(final Schematic schematic, final DataView data) { final Registry blockRegistry = VolumeStreamUtils.nativeToSpongeRegistry( - SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BLOCK)); + SpongeCommon.vanillaRegistry(Registries.BLOCK)); SchematicTranslator.writePaletteToView( blockData, palette, blockRegistry, Constants.Sponge.Schematic.BLOCK_PALETTE, BlockState::type, @@ -506,7 +506,7 @@ public DataView addTo(final Schematic schematic, final DataView data) { // Should never reach here. } - final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.server().registryAccess().lookupOrThrow(Registries.BIOME)); + final Registry biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(SpongeCommon.vanillaRegistry(Registries.BIOME)); SchematicTranslator.writePaletteToView( biomeContainer, biomePalette, biomeRegistry, Constants.Sponge.Schematic.BIOME_PALETTE, From e624c20d8e5d7220e4f9a60e8835fac0557df9b2 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Thu, 27 Mar 2025 18:49:13 +0100 Subject: [PATCH 239/586] no violation of cause --- .../org/spongepowered/common/SpongeCommon.java | 7 +++---- .../org/spongepowered/common/SpongeLifecycle.java | 6 ++++-- .../common/event/tracking/PhaseTracker.java | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spongepowered/common/SpongeCommon.java b/src/main/java/org/spongepowered/common/SpongeCommon.java index 7105478eb50..c91b1b648e0 100644 --- a/src/main/java/org/spongepowered/common/SpongeCommon.java +++ b/src/main/java/org/spongepowered/common/SpongeCommon.java @@ -103,16 +103,15 @@ public static RegistryAccess.Frozen vanillaRegistryAccess() { } public static SpongeRegistryHolder scopedHolder() { - var holder = PhaseTracker.getInstance().currentCause().first(SpongeRegistryHolder.class); + var holder = PhaseTracker.getInstance().startupRegistryHolder(); // If we have a holder in scope use it directly unless it is game - if (holder.isEmpty() || holder.get() == SpongeCommon.game()) { - + if (holder == null) { if (SpongeCommon.game().isServerAvailable()) { return (SpongeRegistryHolder) SpongeCommon.server(); } return SpongeCommon.game(); } - return holder.get(); + return holder; } public static Registry vanillaRegistry(ResourceKey> key) { diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 02201c770b2..0ddc1a9d09d 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -212,8 +212,8 @@ public void beginEstablishServerRegistries(final RegistryHolder server) { @Override public void processServerRegistries(final RegistryHolder server, final Stream> registries) { - try (var frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(server); + try { + PhaseTracker.getInstance().startupRegistryHolder(server); final Map, org.spongepowered.api.registry.Registry> map = registries.collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())); if (!map.isEmpty()) { @@ -222,6 +222,8 @@ public void processServerRegistries(final RegistryHolder server, final Stream ((WritableRegistryBridge) r).bridge$markEventCalled()); ((SpongeRegistryHolder) server).registryHolder().freezeSpongeDynamicRegistries(false); } + } finally { + PhaseTracker.getInstance().startupRegistryHolder(null); } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 07d1a166e4c..93c253d7d14 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -49,6 +49,7 @@ import org.spongepowered.api.event.EventContext; import org.spongepowered.api.event.EventContextKey; import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.scheduler.Task; import org.spongepowered.api.util.Ticks; import org.spongepowered.common.SpongeCommon; @@ -59,6 +60,7 @@ import org.spongepowered.common.event.tracking.phase.plugin.PluginPhase; import org.spongepowered.common.event.tracking.phase.tick.TickPhase; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.Preconditions; import org.spongepowered.common.util.PrettyPrinter; @@ -259,6 +261,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world private final Deque> phaseContextProviders = new ArrayDeque<>(); final PhaseStack stack = new PhaseStack(); private final SpongeCauseStackManager api = new SpongeCauseStackManager(); + private @Nullable SpongeRegistryHolder startupRegistryHolder; PhaseTracker() { for (int i = 0; i < PhaseTracker.INITIAL_POOL_SIZE; i++) { @@ -868,6 +871,18 @@ public CauseStackManager apiAccess() { return this.api; } + public void startupRegistryHolder(final RegistryHolder holder) { + if (holder instanceof SpongeRegistryHolder srh) { + this.startupRegistryHolder = srh; + } else { + this.startupRegistryHolder = null; + } + } + + public @Nullable SpongeRegistryHolder startupRegistryHolder() { + return this.startupRegistryHolder; + } + /** * We insert implicit phases for plugin created frames. */ From 98f14b4883c15ca0ab025ec298ffd83f226f2fcd Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 30 Mar 2025 14:45:09 +0300 Subject: [PATCH 240/586] Remove container open/close logic from CloseMenuTransaction Missed this in 9dd097b. --- .../context/transaction/TransactionSink.java | 2 +- .../inventory/CloseMenuTransaction.java | 77 +++---------------- 2 files changed, 11 insertions(+), 68 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index 9750f0fc839..863fc2fdcc7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -373,7 +373,7 @@ default EffectTransactor logOpenInventory(final Player player) { } default EffectTransactor logCloseInventory(final PhaseContext<@NonNull ?> current, final Player player) { - final CloseMenuTransaction transaction = new CloseMenuTransaction(player, current.isClientSide()); + final CloseMenuTransaction transaction = new CloseMenuTransaction(player); this.logTransaction(transaction); return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance())); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java index ed1cb202a9b..dcc849187fc 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CloseMenuTransaction.java @@ -25,14 +25,8 @@ package org.spongepowered.common.event.tracking.context.transaction.inventory; import com.google.common.collect.ImmutableList; -import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; -import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.inventory.Slot; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -40,7 +34,6 @@ import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.item.inventory.ChangeInventoryEvent; import org.spongepowered.api.event.item.inventory.container.InteractContainerEvent; import org.spongepowered.api.item.inventory.Container; import org.spongepowered.api.item.inventory.ItemStackSnapshot; @@ -58,18 +51,16 @@ import java.util.Optional; import java.util.function.BiConsumer; -public class CloseMenuTransaction extends MenuBasedTransaction { +public class CloseMenuTransaction extends MenuBasedTransaction { private final ServerPlayer player; private final ItemStackSnapshot cursor; - private boolean clientSource; private @MonotonicNonNull List slotTransactions; - public CloseMenuTransaction(final Player player, final boolean clientSource) { + public CloseMenuTransaction(final Player player) { super(TransactionTypes.INTERACT_CONTAINER_EVENT.get(), player.containerMenu); this.player = (ServerPlayer) player; this.cursor = ItemStackUtil.snapshotOf(player.containerMenu.getCarried()); - this.clientSource = clientSource; } @Override @@ -80,9 +71,9 @@ public CloseMenuTransaction(final Player player, final boolean clientSource) { } @Override - public Optional generateEvent( + public Optional generateEvent( final PhaseContext<@NonNull ?> context, @Nullable final GameTransaction<@NonNull ?> parent, - final ImmutableList> gameTransactions, final Cause currentCause + final ImmutableList> gameTransactions, final Cause currentCause ) { final ItemStackSnapshot resultingCursor = ItemStackUtil.snapshotOf(this.player.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(this.cursor, resultingCursor); @@ -92,15 +83,9 @@ public Optional generateEvent( } @Override - public void restore(final PhaseContext<@NonNull ?> context, final InteractContainerEvent event) { - if (this.clientSource) { - // If client closed container we need to reopen it - this.reopen(this.player, this.menu); - } + public void restore(final PhaseContext<@NonNull ?> context, final InteractContainerEvent.Close.Post event) { PacketPhaseUtil.handleCursorRestore(this.player, event.cursorTransaction(), event.isCancelled()); - if (event instanceof ChangeInventoryEvent) { - PacketPhaseUtil.handleSlotRestore(this.player, this.menu, ((ChangeInventoryEvent) event).transactions(), event.isCancelled()); - } + PacketPhaseUtil.handleSlotRestore(this.player, this.menu, event.transactions(), event.isCancelled()); this.player.inventoryMenu.broadcastChanges(); // prevent double capture } @@ -120,26 +105,17 @@ public boolean absorbSlotTransaction( } @Override - public void postProcessEvent(final PhaseContext<@NonNull ?> context, final InteractContainerEvent event) { - if (!this.clientSource) { - // Server closed send packet to client - this.player.connection.send(new ClientboundContainerClosePacket(this.player.containerMenu.containerId)); - } - // Finish closing container - this.player.containerMenu = this.player.inventoryMenu; - + public void postProcessEvent(final PhaseContext<@NonNull ?> context, final InteractContainerEvent.Close.Post event) { // And restore cursor if needed PacketPhaseUtil.handleCursorRestore(this.player, event.cursorTransaction(), event.isCancelled()); - if (event instanceof ChangeInventoryEvent) { - PacketPhaseUtil.handleSlotRestore(this.player, this.menu, ((ChangeInventoryEvent) event).transactions(), event.isCancelled()); - } + PacketPhaseUtil.handleSlotRestore(this.player, this.menu, event.transactions(), event.isCancelled()); this.player.inventoryMenu.broadcastChanges(); // prevent double capture } @Override - public boolean markCancelledTransactions(final InteractContainerEvent event, - final ImmutableList> gameTransactions) { + public boolean markCancelledTransactions(final InteractContainerEvent.Close.Post event, + final ImmutableList> gameTransactions) { if (event.isCancelled()) { event.cursorTransaction().invalidate(); return true; @@ -151,37 +127,4 @@ public boolean markCancelledTransactions(final InteractContainerEvent event, public void addToPrinter(final PrettyPrinter printer) { } - - private void reopen(final ServerPlayer player, final AbstractContainerMenu container) { - if (container.getSlot(0) == null) { - return; - } - if (!(container instanceof InventoryMenu)) { - // Inventory closed by client, reopen window and send container - player.containerMenu = container; - final Slot slot = container.getSlot(0); - final net.minecraft.world.Container slotInventory = slot.container; - final net.minecraft.network.chat.@Nullable Component title; - // TODO get name from last open - if (slotInventory instanceof MenuProvider) { - title = ((MenuProvider) slotInventory).getDisplayName(); - } else { - // expected fallback for unknown types - title = null; - } - slotInventory.startOpen(player); - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title)); - // resync data to client - container.broadcastFullState(); - } else { - // TODO: Maybe print a warning or throw an exception here? - // The player gui cannot be opened from the - // server so allowing this event to be cancellable when the - // GUI has been closed already would result - // in opening the wrong GUI window. - } - - } - - } From 4718623aecd3f61fb0ea126417d0f18413b3dbf2 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Sat, 29 Mar 2025 09:10:08 +0100 Subject: [PATCH 241/586] fix typo --- .../vanilla/generator/world/entities/EntityRegistries.java | 2 +- .../{WollfVariantMixin_API.java => WolfVariantMixin_API.java} | 2 +- src/mixins/resources/mixins.sponge.api.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{WollfVariantMixin_API.java => WolfVariantMixin_API.java} (94%) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 0a33a6c086c..d99ca8c48f9 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -233,7 +233,7 @@ public static List registryEntries(final Context context) { new RegistryEntriesGenerator<>( "data.type", "WolfVariants", - "WOLF_VAIRANT", + "WOLF_VARIANT", context.relativeClass("data.type", "WolfVariant"), Registries.WOLF_VARIANT ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfVariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfVariantMixin_API.java index 9a9e8013290..ae87aa379c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WollfVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WolfVariantMixin_API.java @@ -28,5 +28,5 @@ import org.spongepowered.asm.mixin.Mixin; @Mixin(WolfVariant.class) -public class WollfVariantMixin_API implements org.spongepowered.api.data.type.WolfVariant { +public class WolfVariantMixin_API implements org.spongepowered.api.data.type.WolfVariant { } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 639210f4640..6af919666ac 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -180,7 +180,7 @@ "minecraft.world.entity.animal.TurtleMixin_API", "minecraft.world.entity.animal.WaterAnimalMixin_API", "minecraft.world.entity.animal.WolfMixin_API", - "minecraft.world.entity.animal.WollfVariantMixin_API", + "minecraft.world.entity.animal.WolfVariantMixin_API", "minecraft.world.entity.animal.allay.AllayMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", From 7c836231b9b331145b3cdb603436755ff9a8bb13 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Sun, 30 Mar 2025 17:40:36 +0200 Subject: [PATCH 242/586] fix InventoryMenu#setTitle --- .../common/inventory/custom/SpongeInventoryMenu.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java index e8cfe985ed2..85845e1d45f 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java @@ -125,7 +125,7 @@ public void setTitle(final Component title) { this.title = title; this.tracked.forEach((c, p) -> { var container = (AbstractContainerMenu) c; - var connection = (ServerGamePacketListenerImpl) p.connection(); + var connection = (ServerGamePacketListenerImpl) p.connectionState(); var packet = new ClientboundOpenScreenPacket(container.containerId, container.getType(), SpongeAdventure.asVanilla(this.title)); connection.send(packet); container.broadcastFullState(); From dcca0dec23962bb0af757aaa4dcbbb04db29e5f1 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Sun, 30 Mar 2025 21:51:49 +0200 Subject: [PATCH 243/586] implement BLOCK_CRUMBLE/TRAIL particleoptions --- SpongeAPI | 2 +- .../effect/particle/SpongeParticleHelper.java | 24 +++++++++++++++++-- .../registry/loader/SpongeRegistryLoader.java | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 53b9cfebe8a..bc8706fb2f1 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 53b9cfebe8aa1151286781bfdc52790792830716 +Subproject commit bc8706fb2f1170446a80ae91b9b5e48a84b4b2ef diff --git a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java index 79d7f2da8f5..e4507a3123e 100644 --- a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java +++ b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java @@ -33,12 +33,14 @@ import net.minecraft.core.particles.SculkChargeParticleOptions; import net.minecraft.core.particles.ShriekParticleOption; import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.core.particles.TrailParticleOption; import net.minecraft.core.particles.VibrationParticleOption; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundBundlePacket; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; import net.minecraft.util.ARGB; +import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.effect.particle.ParticleEffect; @@ -49,8 +51,10 @@ import org.spongepowered.api.util.Ticks; import org.spongepowered.api.world.PositionSource; import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3f; +import org.spongepowered.math.vector.Vector3i; import java.util.ArrayList; import java.util.Collections; @@ -95,8 +99,11 @@ private static CachedParticlePacket getNamedPacket(final ParticleEffect effect, // The only way we can see what options are supported for a particular named particle // is to compare the internal type's deserializer to some static deserializer fields. // If only mojang had some type akin to our ParticleEffect... - if (internalType == ParticleTypes.BLOCK || internalType == ParticleTypes.BLOCK_MARKER - || internalType == ParticleTypes.FALLING_DUST || internalType == ParticleTypes.DUST_PILLAR) { + if (internalType == ParticleTypes.BLOCK || + internalType == ParticleTypes.BLOCK_MARKER || + internalType == ParticleTypes.FALLING_DUST || + internalType == ParticleTypes.DUST_PILLAR || + internalType == ParticleTypes.BLOCK_CRUMBLE) { //This particle type supports a block state option. final BlockState state = effect.optionOrDefault(ParticleOptions.BLOCK_STATE).get(); final BlockParticleOption particleData = new BlockParticleOption( @@ -148,6 +155,13 @@ private static CachedParticlePacket getNamedPacket(final ParticleEffect effect, (net.minecraft.core.particles.ParticleType) internalType, ARGB.color(ARGB.as8BitChannel((float) opacity), color.red(), color.green(), color.blue())); return new NamedCachedPacket(particleData, offset, quantity, velocity); + } else if (internalType == ParticleTypes.TRAIL) { + // This particle type color, destination and duration + final var dest = effect.optionOrDefault(ParticleOptions.TARGET).orElse(Vector3d.ZERO); + final var duration = effect.optionOrDefault(ParticleOptions.TRAVEL_TIME).orElse(Ticks.of(20)); + final var color = effect.optionOrDefault(ParticleOptions.COLOR).map(c -> ARGB.color(c.red(), c.green(), c.blue())).orElse(16545810); + final var particleData = new TrailParticleOption(VecHelper.toVanillaVector3d(dest), color, (int) duration.ticks()); + return new NamedCachedPacket(particleData, offset, quantity, velocity); } // Otherwise, we don't really know how to get a valid ParticleOptions. Sorry mods! @@ -196,6 +210,12 @@ public static ParticleEffect spongeParticleOptions(final net.minecraft.core.part Vector3f.from(colorOptions.getRed(), colorOptions.getGreen(), colorOptions.getBlue()).mul(255)), ParticleOptions.OPACITY.get(), colorOptions.getAlpha() )); + } else if (effect instanceof TrailParticleOption(Vec3 target, int color, int duration)) { + return new SpongeParticleEffect((ParticleType) type, Map.of( + ParticleOptions.COLOR.get(), Color.of(Vector3i.from(ARGB.red(color), ARGB.green(color), ARGB.blue(color))), + ParticleOptions.TRAVEL_TIME.get(), Ticks.of(duration), + ParticleOptions.TARGET.get(), VecHelper.toVector3d(target) + )); } return new SpongeParticleEffect((ParticleType) type, Collections.emptyMap()); diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index 5f48b0b3477..1f1590dcbf7 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -384,6 +384,7 @@ public static RegistryLoader> particleOption() { l.add(ParticleOptions.TO_COLOR, k -> new SpongeParticleOption<>(Color.class)); l.add(ParticleOptions.TRAVEL_TIME, k -> new SpongeParticleOption<>(Ticks.class)); l.add(ParticleOptions.VELOCITY, k -> new SpongeParticleOption<>(Vector3d.class)); + l.add(ParticleOptions.TARGET, k -> new SpongeParticleOption<>(Vector3d.class)); }); } From 8691a3fd5a6577dc3b890bd20c2cdf977db733df Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 31 Mar 2025 02:19:35 +0300 Subject: [PATCH 244/586] Implement virtual component rendering options --- SpongeAPI | 2 +- .../AudienceVirtualComponentRenderer.java | 9 +++- .../common/adventure/SpongeAdventure.java | 45 ++++++++++--------- .../adventure/SpongeResolveOperation.java | 29 +++++++++++- .../registry/loader/SpongeRegistryLoader.java | 1 + 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index bc8706fb2f1..356e1fa2ba9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit bc8706fb2f1170446a80ae91b9b5e48a84b4b2ef +Subproject commit 356e1fa2ba91d1937bc0dec916f0d95bf509e58f diff --git a/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java b/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java index f5e63433c95..d33a05fbb5e 100644 --- a/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java +++ b/src/main/java/org/spongepowered/common/adventure/AudienceVirtualComponentRenderer.java @@ -34,13 +34,20 @@ public final class AudienceVirtualComponentRenderer implements VirtualComponentRenderer { private final Function apply; + private final String fallbackString; - AudienceVirtualComponentRenderer(final Function apply) { + AudienceVirtualComponentRenderer(final Function apply, final String fallbackString) { this.apply = apply; + this.fallbackString = fallbackString; } @Override public @NonNull ComponentLike apply(final @NonNull Audience context) { return this.apply.apply(context); } + + @Override + public @NonNull String fallbackString() { + return this.fallbackString; + } } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index b226624fc24..9774be599ea 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -31,7 +31,6 @@ import com.mojang.serialization.codecs.PrimitiveCodec; import io.netty.util.AttributeKey; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.key.Key; import net.kyori.adventure.serializer.configurate4.ConfigurateComponentSerializer; @@ -99,10 +98,10 @@ import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; import org.spongepowered.api.adventure.ResolveOperation; import org.spongepowered.api.adventure.SpongeComponents; import org.spongepowered.api.command.CommandCause; -import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.registry.DefaultedRegistryReference; import org.spongepowered.api.util.Tristate; @@ -168,16 +167,31 @@ public String toString() { } }; - public static final ComponentRenderer SPONGE_COMPONENT_RENDERER = new TranslatableComponentRenderer<>() { + public static final ComponentRenderer SPONGE_VIRTUAL_COMPONENT_RENDERER = new ComponentRenderer() { @Override - protected @NonNull Component renderVirtual(final @NonNull VirtualComponent component, final @NonNull SpongeRendererContext context) { + public @NotNull Component render(final @NotNull Component component, final @NotNull SpongeRendererContext context) { + if (component instanceof final VirtualComponent virtualComponent) { + return this.renderVirtual(virtualComponent, context); + } + return component; + } + + public @NonNull Component renderVirtual(final @NonNull VirtualComponent component, final @NonNull SpongeRendererContext context) { context.markContainsVirtualComponents(); if (component.renderer() instanceof final AudienceVirtualComponentRenderer audienceVirtualComponentRenderer && context.audience() != null) { return audienceVirtualComponentRenderer.apply(context.audience()).asComponent(); } - return super.renderVirtual(component, context); + return component; + } + }; + + public static final ComponentRenderer SPONGE_COMPONENT_RENDERER = new TranslatableComponentRenderer<>() { + + @Override + protected @NonNull Component renderVirtual(final @NonNull VirtualComponent component, final @NonNull SpongeRendererContext context) { + return SpongeAdventure.SPONGE_VIRTUAL_COMPONENT_RENDERER.render(component, context); } @Override @@ -831,29 +845,18 @@ public static class Factory implements SpongeComponents.Factory { public final @NonNull Component render( final @NonNull Component component, final @NonNull CommandCause senderContext, - @Nullable Audience viewer, + final @NonNull Audience viewer, final @NonNull DefaultedRegistryReference firstOperation, final @NonNull DefaultedRegistryReference @NonNull ... otherOperations ) { Component output = Objects.requireNonNull(component, "component"); Objects.requireNonNull(senderContext, "senderContext"); - // Unwrap the Audience to an entity - while (viewer instanceof ForwardingAudience.Single single && !(viewer instanceof Entity)) { - viewer = single.audience(); - } - final @Nullable Entity backing; - if (viewer instanceof Entity entity) { - backing = entity; - } else { - backing = null; - } - output = ((SpongeResolveOperation) Objects.requireNonNull(firstOperation, "firstOperation").get()) - .resolve(output, senderContext, backing); + .resolve(output, senderContext, viewer); for (final DefaultedRegistryReference ref : otherOperations) { - output = ((SpongeResolveOperation) ref.get()).resolve(output, senderContext, backing); + output = ((SpongeResolveOperation) ref.get()).resolve(output, senderContext, viewer); } return output; } @@ -875,8 +878,8 @@ public ComponentFlattener flattener() { } @Override - public VirtualComponent receiverVirtualComponent(final @NonNull Function apply) { - return Component.virtual(Audience.class, new AudienceVirtualComponentRenderer(apply)); + public VirtualComponent receiverVirtualComponent(final @NonNull Function apply, final @NonNull String fallbackValue) { + return Component.virtual(Audience.class, new AudienceVirtualComponentRenderer(apply, fallbackValue)); } } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java index f1cffa0dd28..96beb63ed18 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java @@ -25,10 +25,13 @@ package org.spongepowered.common.adventure; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import net.kyori.adventure.translation.GlobalTranslator; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.ComponentUtils; +import org.apache.commons.lang3.NotImplementedException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -44,7 +47,23 @@ public abstract class SpongeResolveOperation implements ResolveOperation { private static final Logger LOGGER = LogManager.getLogger(); - public abstract Component resolve(final Component input, final CommandCause senderContext, final @Nullable Entity viewer); + public Component resolve(final Component input, final CommandCause senderContext, Audience viewer) { + // Unwrap the Audience to an entity + while (viewer instanceof ForwardingAudience.Single single && !(viewer instanceof Entity)) { + viewer = single.audience(); + } + final @Nullable Entity backing; + if (viewer instanceof Entity entity) { + backing = entity; + } else { + backing = null; + } + return this.resolve(input, senderContext, backing); + } + + public Component resolve(final Component input, final CommandCause senderContext, final @Nullable Entity viewer) { + throw new NotImplementedException(); + } public static SpongeResolveOperation newCustomTranslations() { return new SpongeResolveOperation() { @@ -76,4 +95,12 @@ public Component resolve(final Component input, final CommandCause senderContext }; } + public static SpongeResolveOperation newVirtualComponents() { + return new SpongeResolveOperation() { + @Override + public Component resolve(final Component input, final CommandCause senderContext, final Audience viewer) { + return SpongeAdventure.SPONGE_VIRTUAL_COMPONENT_RENDERER.render(input, new SpongeRendererContext(null, viewer)); + } + }; + } } diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index 1f1590dcbf7..db0d4af33a2 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -410,6 +410,7 @@ public static RegistryLoader resolveOperation() { return RegistryLoader.of(l -> { l.add(ResolveOperations.CONTEXTUAL_COMPONENTS, SpongeResolveOperation::newContextualComponents); l.add(ResolveOperations.CUSTOM_TRANSLATIONS, SpongeResolveOperation::newCustomTranslations); + l.add(ResolveOperations.VIRTUAL_COMPONENTS, SpongeResolveOperation::newVirtualComponents); }); } From 3841a60b1c67e2a30ab0e1cd7dd229d080d29a0a Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 2 Apr 2025 17:45:41 +0200 Subject: [PATCH 245/586] log exception when failing to parse commands on startup --- .../command/brigadier/dispatcher/SpongeCommandDispatcher.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeCommandDispatcher.java b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeCommandDispatcher.java index dce0439d857..11830d960cb 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeCommandDispatcher.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeCommandDispatcher.java @@ -379,6 +379,10 @@ private ParseResults parseNodes0( try { child.parse(reader, context); } catch (final RuntimeException ex) { + if (!SpongeCommon.game().isServerAvailable()) { + // Log exception during startup + SpongeCommon.logger().error("Failed to parse command", ex); + } throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().createWithContext(reader, ex.getMessage()); } // Sponge Start: if we didn't consume anything we don't want Brig to complain at us. From 35cc8c81cc41a164e6c2a63e668620d9718355b0 Mon Sep 17 00:00:00 2001 From: Anselm Brehme Date: Wed, 2 Apr 2025 18:28:13 +0200 Subject: [PATCH 246/586] don't log CommandSyntaxException --- .../core/commands/execution/tasks/ExecuteCommandMixin.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/execution/tasks/ExecuteCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/execution/tasks/ExecuteCommandMixin.java index 79ca01c297b..6f582a30406 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/execution/tasks/ExecuteCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/execution/tasks/ExecuteCommandMixin.java @@ -106,6 +106,10 @@ public abstract class ExecuteCommandMixin { )); return result; } + catch (CommandSyntaxException e) + { + throw e; + } catch (Exception e) { var owner = Optional.ofNullable(mapping) .flatMap(CommandMapping::plugin) From daa5d168f1fc925324d6ef11717c4e92a2e7b959 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 9 Apr 2025 15:15:04 +0300 Subject: [PATCH 247/586] Expose world's WorldArchetype & WorldArchetypeType --- SpongeAPI | 2 +- .../level/storage/ServerLevelDataBridge.java | 11 +++++++++++ .../provider/world/WorldPropertiesData.java | 6 ++++++ .../world/server/SpongeWorldArchetype.java | 19 +++++++++++++++++++ .../server/SpongeWorldArchetypeType.java | 7 +++++++ .../level/storage/PrimaryLevelDataMixin.java | 5 +++++ 6 files changed, 49 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 356e1fa2ba9..de5564d39d0 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 356e1fa2ba91d1937bc0dec916f0d95bf509e58f +Subproject commit de5564d39d01e2721f5521a77836d3fc1bff001a diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java index 1200f059f8d..9780ca08df2 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java @@ -26,9 +26,12 @@ import com.google.common.collect.MapMaker; import net.kyori.adventure.text.Component; +import net.minecraft.core.Holder; import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.storage.LevelData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -80,6 +83,14 @@ public interface ServerLevelDataBridge { return null; } + default @Nullable ChunkGenerator bridge$chunkGenerator() { + return null; + } + + default LevelStem bridge$levelStem() { + return new LevelStem(Holder.direct(this.bridge$dimensionType()), this.bridge$chunkGenerator()); + } + default boolean bridge$customDifficulty() { return false; } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index 9f6b4029aca..73b96f28960 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -37,6 +37,8 @@ import org.spongepowered.api.world.border.WorldBorder; import org.spongepowered.api.world.difficulty.Difficulty; import org.spongepowered.api.world.generation.config.WorldGenerationConfig; +import org.spongepowered.api.world.server.WorldArchetype; +import org.spongepowered.api.world.server.WorldArchetypeType; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; @@ -91,6 +93,8 @@ public static void register(final DataProviderRegistrator registrator) { .get(ServerLevelDataBridge::bridge$performsSpawnLogic) .create(Keys.IS_LOAD_ON_STARTUP) .get(ServerLevelDataBridge::bridge$loadOnStartup) + .create(Keys.WORLD_ARCHETYPE_TYPE) + .get(h -> (WorldArchetypeType) (Object) h.bridge$levelStem()) .asMutable(PrimaryLevelData.class) .create(Keys.WORLD_DIFFICULTY) .set((h, v) -> h.setDifficulty((net.minecraft.world.Difficulty) (Object) v)) @@ -115,6 +119,8 @@ public static void register(final DataProviderRegistrator registrator) { .set(PrimaryLevelDataBridge::bridge$setPerformsSpawnLogic) .create(Keys.IS_LOAD_ON_STARTUP) .set(PrimaryLevelDataBridge::bridge$setLoadOnStartup) + .create(Keys.WORLD_ARCHETYPE) + .get(h -> WorldArchetype.of((WorldArchetypeType) (Object) h.bridge$levelStem(), (WorldGenerationConfig) ((PrimaryLevelData) h).worldGenOptions())) ; } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java index 1728a715daa..6af24a13e5f 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetype.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.world.server; +import org.spongepowered.api.util.Builder; import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.server.WorldArchetype; import org.spongepowered.api.world.server.WorldArchetypeType; @@ -38,6 +39,10 @@ public static final class BuilderImpl implements WorldArchetype.Builder { private WorldArchetypeType type; private WorldGenerationConfig generationConfig; + public BuilderImpl() { + this.reset(); + } + @Override public Builder type(final WorldArchetypeType type) { this.type = type; @@ -50,6 +55,20 @@ public Builder generationConfig(final WorldGenerationConfig generationConfig) { return this; } + @Override + public Builder from(final WorldArchetype value) { + this.type = value.type(); + value.generationConfig().ifPresent(c -> this.generationConfig = c); + return this; + } + + @Override + public Builder reset() { + this.type = null; + this.generationConfig = null; + return this; + } + @Override public WorldArchetype build() { return new SpongeWorldArchetype(Objects.requireNonNull(this.type, "type"), Optional.ofNullable(this.generationConfig)); diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java index 7146348657a..5639e6d4cd0 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java @@ -52,6 +52,13 @@ public WorldArchetypeType.Builder chunkGenerator(final ChunkGenerator chunkGener return this; } + @Override + public WorldArchetypeType.Builder from(final WorldArchetypeType value) { + this.worldType = value.worldType(); + this.chunkGenerator = value.chunkGenerator(); + return this; + } + @Override public WorldArchetypeType.Builder reset() { this.worldType = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index bbfac650f1a..38b672e74ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -122,6 +122,11 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat return this.impl$dimensionType; } + @Override + public @Nullable ChunkGenerator bridge$chunkGenerator() { + return this.impl$chunkGenerator; + } + @Override public void bridge$dimensionType(final DimensionType type, final boolean updatePlayers) { this.impl$dimensionType = type; From 2bed0e3c62cd623225653d76ba2ab08bad6b157c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 19 Apr 2025 17:36:22 +0200 Subject: [PATCH 248/586] Rewrite attack and damage events (#4138) * Rewrite attack and damage events * Damage step API improvements * Update and optimize attack injections * Optimize damage injections * Only allow adding modifiers * Rename methods in DamageModifier --- SpongeAPI | 2 +- .../LivingEntityMixin_Forge_Damage.java | 81 ++++ .../player/PlayerMixin_Forge_Attack_Impl.java | 48 --- .../player/PlayerMixin_Forge_Damage.java | 30 +- .../resources/mixins.spongeforge.core.json | 4 +- .../mixins.spongeforge.core.shared.json | 4 +- .../LivingEntityMixin_Neo_Attack_Impl.java | 62 --- .../entity/LivingEntityMixin_Neo_Damage.java | 112 +++++ .../player/PlayerMixin_Neo_Attack_Impl.java | 60 --- .../entity/player/PlayerMixin_Neo_Damage.java | 71 ++++ .../resources/mixins.spongeneo.core.json | 4 +- .../world/entity/TrackedAttackBridge.java} | 16 +- .../world/entity/TrackedDamageBridge.java | 40 +- .../entity/damage/SpongeAttackTracker.java | 127 ++++++ .../entity/damage/SpongeDamageModifier.java | 81 ++++ .../cause/entity/damage/SpongeDamageStep.java | 261 ++++++++++++ ...ierType.java => SpongeDamageStepType.java} | 9 +- .../entity/damage/SpongeDamageTracker.java | 215 ++++++++++ .../registry/SpongeBuilderProvider.java | 3 + .../registry/SpongeFactoryProvider.java | 3 + .../common/registry/SpongeRegistries.java | 2 +- .../registry/loader/SpongeRegistryLoader.java | 45 +- .../common/util/DamageEventUtil.java | 361 ---------------- .../level/ServerPlayerMixin_Attack_impl.java | 81 ---- .../core/world/entity/ExperienceOrbMixin.java | 8 +- .../entity/LivingEntityMixin_Attack_Impl.java | 397 ------------------ .../entity/LivingEntityMixin_Damage.java | 231 ++++++++++ .../LivingEntityMixin_Shared_Attack_Impl.java | 52 --- .../LivingEntityMixin_Shared_Damage.java | 68 +++ .../core/world/entity/MobMixin_Attack.java | 114 +++++ .../world/entity/MobMixin_Attack_Impl.java | 77 ---- .../boss/enderdragon/EndCrystalMixin.java | 6 +- .../entity/decoration/ArmorStandMixin.java | 73 ++-- .../decoration/BlockAttachedEntityMixin.java | 8 +- .../entity/decoration/ItemFrameMixin.java | 11 +- .../world/entity/item/ItemEntityMixin.java | 9 +- .../entity/player/PlayerMixin_Attack.java | 309 ++++++++++++++ .../player/PlayerMixin_Attack_Impl.java | 318 -------------- .../player/PlayerMixin_Shared_Damage.java | 63 +++ .../entity/projectile/ShulkerBulletMixin.java | 8 +- .../entity/vehicle/MinecartTNTMixin.java | 7 +- .../entity/vehicle/VehicleEntityMixin.java | 8 +- .../enchantment/EnchantmentMixin_Attack.java | 68 +++ src/mixins/resources/mixins.sponge.core.json | 9 +- .../spongepowered/test/damage/DamageTest.java | 133 ++++-- .../entity/LivingEntityMixin_Attack_Impl.java | 71 ---- .../LivingEntityMixin_Vanilla_Damage.java | 113 +++++ .../player/PlayerMixin_Vanilla_Damage.java | 25 +- .../resources/mixins.spongevanilla.core.json | 4 +- .../mixins.spongevanilla.core.shared.json | 4 +- 50 files changed, 2194 insertions(+), 1722 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Attack_Impl.java rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Attack_Impl.java => forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Damage.java (57%) delete mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Attack_Impl.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java delete mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Attack_Impl.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java rename src/{mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin.java => main/java/org/spongepowered/common/bridge/world/entity/TrackedAttackBridge.java} (76%) rename forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Attack_Impl.java => src/main/java/org/spongepowered/common/bridge/world/entity/TrackedDamageBridge.java (56%) create mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java create mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifier.java create mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStep.java rename src/main/java/org/spongepowered/common/event/cause/entity/damage/{SpongeDamageModifierType.java => SpongeDamageStepType.java} (82%) create mode 100644 src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin_Attack_impl.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Attack_Impl.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin_Attack.java delete mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Attack_Impl.java => vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java (62%) diff --git a/SpongeAPI b/SpongeAPI index de5564d39d0..267c5df1e0f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit de5564d39d01e2721f5521a77836d3fc1bff001a +Subproject commit 267c5df1e0fe396a0ffc7f7768bb845dff092bfe diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java new file mode 100644 index 00000000000..78d36540f89 --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java @@ -0,0 +1,81 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraftforge.event.entity.living.ShieldBlockEvent; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.common.item.util.ItemStackUtil; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBridge { + + @ModifyConstant(method = "actuallyHurt", constant = @Constant(floatValue = 0), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingHurt(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"))) + private float damage$doNotReturnEarly(final float constant) { + return Float.NaN; + } + + @WrapOperation(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/ForgeEventFactory;onShieldBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)Lnet/minecraftforge/event/entity/living/ShieldBlockEvent;")) + private ShieldBlockEvent damage$modifyBeforeAndAfterShield(final LivingEntity self, final DamageSource source, final float originalDamage, final Operation operation) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return operation.call(self, source, originalDamage); + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(self.getUseItem())); + float damage = (float) step.applyChildrenBefore(originalDamage); + final ShieldBlockEvent event; + if (step.isSkipped()) { + event = new ShieldBlockEvent(self, source, damage); + event.setCanceled(true); + } else { + event = operation.call(self, source, damage); + if (!event.isCanceled()) { + damage -= event.getBlockedDamage(); + } + } + step.applyChildrenAfter(damage); + return event; + } + + @ModifyArg(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingDamage(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F")) + private float damage$firePostEvent_Living(final float damage) { + return this.damage$firePostEvent(damage); + } +} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Attack_Impl.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Attack_Impl.java deleted file mode 100644 index 91996604abb..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Attack_Impl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.world.entity.player; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.event.entity.player.CriticalHitEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.util.DamageEventUtil; - -@Mixin(Player.class) -public class PlayerMixin_Forge_Attack_Impl { - private DamageEventUtil.Attack attackImpl$attack; - - @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;getCriticalHit(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/entity/Entity;ZF)Lnet/minecraftforge/event/entity/player/CriticalHitEvent;")) - private CriticalHitEvent attackImpl$critHook(final Player player, final Entity target, final boolean vanillaCritical, final float damageModifier) { - final CriticalHitEvent event = ForgeHooks.getCriticalHit(player, target, vanillaCritical, damageModifier); - if (event != null) { - this.attackImpl$attack.functions().add(DamageEventUtil.provideCriticalAttackFunction(this.attackImpl$attack.sourceEntity(), event.getDamageModifier())); - } - return event; - } -} diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Attack_Impl.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Damage.java similarity index 57% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Attack_Impl.java rename to forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Damage.java index 90e32691442..efffd9fb1e6 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Attack_Impl.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/player/PlayerMixin_Forge_Damage.java @@ -22,31 +22,29 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.mixin.core.world.entity.player; +package org.spongepowered.forge.mixin.core.world.entity.player; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.common.util.DamageEventUtil; +import org.spongepowered.forge.mixin.core.world.entity.LivingEntityMixin_Forge_Damage; @Mixin(Player.class) -public abstract class PlayerMixin_Vanilla_Attack_Impl { - private DamageEventUtil.Attack attackImpl$attack; +public abstract class PlayerMixin_Forge_Damage extends LivingEntityMixin_Forge_Damage { - /** - * Captures the crit multiplier as a function - */ - @ModifyConstant(method = "attack", constant = @Constant(floatValue = 1.5F), - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnownMovement()Lnet/minecraft/world/phys/Vec3;")) - ) - public float attackImpl$critHook(final float constant) { - // if (isCritical) damage *= 1.5F; - final var bonusDamageFunc = DamageEventUtil.provideCriticalAttackFunction(this.attackImpl$attack.sourceEntity(), constant); - this.attackImpl$attack.functions().add(bonusDamageFunc); - return constant; + @ModifyConstant(method = "actuallyHurt", constant = @Constant(floatValue = 0), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingHurt(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"))) + private float damage$doNotReturnEarly(final float constant) { + return Float.NaN; + } + + @ModifyArg(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingDamage(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F")) + private float damage$firePostEvent_Player(final float damage) { + return this.damage$firePostEvent(damage); } } diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 68f35f28eb2..7aae2731cc6 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -29,9 +29,9 @@ "server.network.ServerGamePacketListenerImplMixin_Forge", "tags.TagLoaderMixin_Forge", "world.entity.LivingEntityMixin_Forge", - "world.entity.LivingEntityMixin_Forge_Attack_Impl", + "world.entity.LivingEntityMixin_Forge_Damage", "world.entity.item.ItemEntityMixin_Forge", - "world.entity.player.PlayerMixin_Forge_Attack_Impl", + "world.entity.player.PlayerMixin_Forge_Damage", "world.entity.vehicle.BoatMixin_Forge", "world.level.ServerExplosionMixin_Forge", "world.level.block.FireBlockMixin_Forge", diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json index b322779182e..e23ba17fbba 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json @@ -5,8 +5,8 @@ "priority": 1301, "mixins": [ "server.level.ServerEntityMixin_Shared", - "world.entity.LivingEntityMixin_Shared_Attack_Impl", - "world.entity.player.PlayerMixin_Shared_Attack_Impl", + "world.entity.LivingEntityMixin_Shared_Damage", + "world.entity.player.PlayerMixin_Shared_Damage", "world.entity.projectile.FishingHookMixin_Shared" ], "overwrites": { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Attack_Impl.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Attack_Impl.java deleted file mode 100644 index 0701bb119c5..00000000000 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Attack_Impl.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.mixin.core.world.entity; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.LivingEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.util.DamageEventUtil; - -@Mixin(LivingEntity.class) -public class LivingEntityMixin_Neo_Attack_Impl { - - protected DamageEventUtil.DamageEventResult attackImpl$actuallyHurtResult; - - /** - * Set absorbed damage after calling {@link LivingEntity#setAbsorptionAmount} in which we called the event - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 2, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", shift = At.Shift.AFTER)) - public float attackImpl$setAbsorbed(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtResult.damageAbsorbed().orElse(0f); - } - - /** - * Prevents {@link ServerPlayer#awardStat} from running before event - */ - @Redirect(method = "getDamageAfterMagicAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V")) - public void attackImpl$onAwardStatDamageResist(final ServerPlayer instance, final ResourceLocation resourceLocation, final int i) { - // do nothing - } - -} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java new file mode 100644 index 00000000000..c9b309cc362 --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java @@ -0,0 +1,112 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.world.entity.LivingEntity; +import net.neoforged.neoforge.common.damagesource.DamageContainer; +import net.neoforged.neoforge.event.entity.living.LivingShieldBlockEvent; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.common.item.util.ItemStackUtil; + +import java.util.Stack; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridge { + + @Shadow protected Stack damageContainers; + + @Override + public float damage$getContainerDamage(final float damage) { + return this.damageContainers.peek().getNewDamage(); + } + + @Override + public void damage$setContainerDamage(final float damage) { + this.damageContainers.peek().setNewDamage(damage); + } + + @SuppressWarnings("UnstableApiUsage") + @WrapOperation(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onDamageBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;Z)Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;")) + private LivingShieldBlockEvent damage$modifyBeforeAndAfterShield(final LivingEntity self, final DamageContainer container, final boolean blocked, final Operation operation) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null || !blocked) { // don't capture when vanilla wouldn't block + return operation.call(self, container, false); + } + + final float originalDamage = container.getNewDamage(); + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(self.getUseItem())); + float damage = (float) step.applyChildrenBefore(originalDamage); + container.setNewDamage(damage); + final LivingShieldBlockEvent event; + if (step.isSkipped()) { + event = new LivingShieldBlockEvent(self, container, true); + event.setBlocked(true); + } else { + event = operation.call(self, container, true); + container.setBlockedDamage(event); + damage = container.getNewDamage(); + } + step.applyChildrenAfter(damage); + return event; + } + + @WrapWithCondition(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setBlockedDamage(Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;)V")) + private boolean damage$cancelSetBlockedDamage(final DamageContainer container, final LivingShieldBlockEvent event) { + // We already did it above + return false; + } + + @ModifyVariable(method = "actuallyHurt", ordinal = 1, + at = @At(value = "INVOKE_ASSIGN", target = "Lnet/neoforged/neoforge/common/CommonHooks;onLivingDamagePre(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;)F")) + private float damage$modifyBeforeAbsorption(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ABSORPTION, damage, this); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setReduction(Lnet/neoforged/neoforge/common/damagesource/DamageContainer$Reduction;F)V"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onLivingDamagePre(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;)F"))) + private boolean damage$skipAbsorption(final DamageContainer container, final DamageContainer.Reduction reduction, final float absorbed) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } + + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) + private float damage$firePostEvent_Living(final float damage) { + return this.damage$firePostEvent(damage); + } +} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Attack_Impl.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Attack_Impl.java deleted file mode 100644 index 4973ee5e62b..00000000000 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Attack_Impl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.mixin.core.world.entity.player; - -import net.minecraft.world.entity.player.Player; -import net.neoforged.neoforge.event.entity.player.CriticalHitEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.util.DamageEventUtil; -import org.spongepowered.neoforge.mixin.core.world.entity.LivingEntityMixin_Neo_Attack_Impl; - -@Mixin(Player.class) -public class PlayerMixin_Neo_Attack_Impl extends LivingEntityMixin_Neo_Attack_Impl { - private DamageEventUtil.Attack attackImpl$attack; - - @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/event/entity/player/CriticalHitEvent;isCriticalHit()Z")) - private boolean attackImpl$critHook(final CriticalHitEvent event) { - if (event.isCriticalHit()) { - this.attackImpl$attack.functions().add(DamageEventUtil.provideCriticalAttackFunction(this.attackImpl$attack.sourceEntity(), event.getDamageMultiplier())); - return true; - } - return false; - } - - /** - * Set absorbed damage after calling {@link Player#setAbsorptionAmount} in which we called the event - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 2, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V", shift = At.Shift.AFTER)) - public float attackImpl$setAbsorbed(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtResult.damageAbsorbed().orElse(0f); - } -} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java new file mode 100644 index 00000000000..e25fc9102cd --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java @@ -0,0 +1,71 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.world.entity.player; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; +import net.neoforged.neoforge.common.damagesource.DamageContainer; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.neoforge.mixin.core.world.entity.LivingEntityMixin_Neo_Damage; + +@Mixin(Player.class) +public abstract class PlayerMixin_Neo_Damage extends LivingEntityMixin_Neo_Damage implements TrackedAttackBridge { + + @Shadow public abstract double shadow$entityInteractionRange(); + + @Override + public double attack$interactionRangeSquared() { + return Mth.square(this.shadow$entityInteractionRange()); + } + + @ModifyVariable(method = "actuallyHurt", ordinal = 1, + at = @At(value = "INVOKE_ASSIGN", target = "Lnet/neoforged/neoforge/common/CommonHooks;onLivingDamagePre(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;)F")) + private float damage$modifyBeforeAbsorption(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ABSORPTION, damage, this); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setReduction(Lnet/neoforged/neoforge/common/damagesource/DamageContainer$Reduction;F)V"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onLivingDamagePre(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;)F"))) + private boolean damage$skipAbsorption(final DamageContainer container, final DamageContainer.Reduction reduction, final float absorbed) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } + + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) + private float damage$firePostEvent_Player(final float damage) { + return this.damage$firePostEvent(damage); + } +} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index edf633ff4ef..135ad8490aa 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -28,10 +28,10 @@ "tags.TagLoaderMixin_NeoForge", "world.entity.EntityMixin_Neo", "world.entity.LivingEntityMixin_Neo", - "world.entity.LivingEntityMixin_Neo_Attack_Impl", + "world.entity.LivingEntityMixin_Neo_Damage", "world.entity.animal.SnowGolemMixin_Neo", "world.entity.item.ItemEntityMixin_Neo", - "world.entity.player.PlayerMixin_Neo_Attack_Impl", + "world.entity.player.PlayerMixin_Neo_Damage", "world.entity.projectile.FishingHookMixin_Neo", "world.entity.vehicle.AbstractBoatMixin_Neo", "world.level.ServerExplosionMixin_NeoForge", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin.java b/src/main/java/org/spongepowered/common/bridge/world/entity/TrackedAttackBridge.java similarity index 76% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin.java rename to src/main/java/org/spongepowered/common/bridge/world/entity/TrackedAttackBridge.java index 7968d13b542..debf57e2a62 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/TrackedAttackBridge.java @@ -22,12 +22,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.item.enchantment; +package org.spongepowered.common.bridge.world.entity; -import net.minecraft.world.item.enchantment.Enchantment; -import org.spongepowered.asm.mixin.Mixin; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; -@Mixin(Enchantment.class) -public abstract class EnchantmentMixin { +public interface TrackedAttackBridge { + @Nullable + SpongeAttackTracker attack$tracker(); + + // Neo hook + default double attack$interactionRangeSquared() { + return 9; + } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Attack_Impl.java b/src/main/java/org/spongepowered/common/bridge/world/entity/TrackedDamageBridge.java similarity index 56% rename from forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Attack_Impl.java rename to src/main/java/org/spongepowered/common/bridge/world/entity/TrackedDamageBridge.java index 1cb83895595..6ba9a52c8f3 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Attack_Impl.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/TrackedDamageBridge.java @@ -22,25 +22,33 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.mixin.core.world.entity; +package org.spongepowered.common.bridge.world.entity; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stat; -import net.minecraft.world.entity.LivingEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; -@Mixin(LivingEntity.class) -public class LivingEntityMixin_Forge_Attack_Impl { +public interface TrackedDamageBridge { - /** - * Prevents {@link ServerPlayer#awardStat} from running before event - */ - @Redirect(method = "getDamageAfterMagicAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/stats/Stat;I)V")) - public void attackImpl$onAwardStatDamageResist(final ServerPlayer instance, final Stat resourceLocation, final int i) { - // do nothing + @Nullable + SpongeDamageTracker damage$tracker(); + + default float damage$firePostEvent(float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return damage; + } + damage = tracker.endStep(DamageStepTypes.ABSORPTION, damage); + damage = tracker.callDamagePostEvent((org.spongepowered.api.entity.Entity) this, damage); + this.damage$setContainerDamage(damage); + return damage; } + // Neo hook + default void damage$setContainerDamage(final float damage) {} + + // Neo hook + default float damage$getContainerDamage(final float damage) { + return damage; + } } diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java new file mode 100644 index 00000000000..820fbcd3a13 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java @@ -0,0 +1,127 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.cause.entity.damage; + +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.api.event.entity.AttackEntityEvent; +import org.spongepowered.api.event.entity.DamageCalculationEvent; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.item.util.ItemStackUtil; + +public class SpongeAttackTracker extends SpongeDamageTracker { + private final ItemStack weapon; + private final ItemStackSnapshot weaponSnapshot; + + private float attackStrength; + private boolean strongSprint = false; + + public SpongeAttackTracker(final DamageCalculationEvent.Pre preEvent, final DamageSource source, final ItemStack weapon) { + super(preEvent, source); + this.weapon = weapon; + this.weaponSnapshot = ItemStackUtil.snapshotOf(weapon); + } + + @Override + public AttackEntityEvent.Pre preEvent() { + return (AttackEntityEvent.Pre) super.preEvent(); + } + + @Override + public AttackEntityEvent.Post postEvent() { + return (AttackEntityEvent.Post) super.postEvent(); + } + + public ItemStack weapon() { + return this.weapon; + } + + public ItemStackSnapshot weaponSnapshot() { + return this.weaponSnapshot; + } + + public float attackStrength() { + return this.attackStrength; + } + + public void setAttackStrength(final float attackStrength) { + this.attackStrength = attackStrength; + } + + public boolean isStrongSprint() { + return this.strongSprint; + } + + public void setStrongSprint(final boolean strongSprint) { + this.strongSprint = strongSprint; + } + + public boolean callAttackPostEvent(final Entity entity, final DamageSource source, float finalDamage, final float knockbackModifier) { + if (this.postEvent != null) { + throw new IllegalStateException("Post event already fired"); + } + + finalDamage = (float) this.newStep(DamageStepTypes.END).apply(finalDamage); + + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + SpongeDamageTracker.generateCauseFor(source, frame); + + final AttackEntityEvent.Post event = SpongeEventFactory.createAttackEntityEventPost(frame.currentCause(), + knockbackModifier, knockbackModifier, entity, this, this.preEvent.baseDamage(), finalDamage); + + this.postEvent = event; + return SpongeCommon.post(event); + } + } + + public static @Nullable SpongeAttackTracker callAttackPreEvent(final Entity entity, final DamageSource source, final float baseDamage, final ItemStack weapon) { + final SpongeAttackTracker tracker; + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + SpongeDamageTracker.generateCauseFor(source, frame); + + final AttackEntityEvent.Pre event = SpongeEventFactory.createAttackEntityEventPre(frame.currentCause(), entity, baseDamage); + if (SpongeCommon.post(event)) { + return null; + } + + tracker = new SpongeAttackTracker(event, source, weapon); + } + + tracker.newStep(DamageStepTypes.START).apply(baseDamage); + return tracker; + } + + public static @Nullable SpongeAttackTracker of(final DamageSource source) { + return source.getDirectEntity() instanceof TrackedAttackBridge tracked ? tracked.attack$tracker() : null; + } +} diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifier.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifier.java new file mode 100644 index 00000000000..e5c90842f13 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifier.java @@ -0,0 +1,81 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.cause.entity.damage; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.cause.entity.damage.DamageModifier; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; + +public record SpongeDamageModifier(DamageStepType type, Optional> frameModifier, Optional damageFunction) implements DamageModifier { + + public static class Builder implements DamageModifier.Builder { + private @Nullable DamageStepType type; + private @Nullable Consumer frame; + private Function function; + + public Builder() { + this.reset(); + } + + @Override + public DamageModifier.Builder reset() { + this.type = null; + this.frame = null; + this.function = (step, damage) -> damage; + return this; + } + + @Override + public DamageModifier.Builder type(DamageStepType type) { + this.type = Objects.requireNonNull(type, "type"); + return this; + } + + @Override + public DamageModifier.Builder frameModifier(Consumer frame) { + this.frame = Objects.requireNonNull(frame, "frame"); + return this; + } + + @Override + public DamageModifier.Builder damageFunction(Function function) { + this.function = Objects.requireNonNull(function, "function"); + return this; + } + + @Override + public DamageModifier build() { + if (this.type == null) { + throw new IllegalStateException("type must be set"); + } + return new SpongeDamageModifier(this.type, Optional.ofNullable(this.frame), Optional.ofNullable(this.function)); + } + } +} diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStep.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStep.java new file mode 100644 index 00000000000..a3564a43653 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStep.java @@ -0,0 +1,261 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.cause.entity.damage; + +import com.google.common.collect.ImmutableList; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.cause.entity.damage.DamageModifier; +import org.spongepowered.api.event.cause.entity.damage.DamageStep; +import org.spongepowered.api.event.cause.entity.damage.DamageStepHistory; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; +import org.spongepowered.common.event.tracking.PhaseTracker; + +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.Set; +import java.util.StringJoiner; +import java.util.function.Consumer; + +public final class SpongeDamageStep implements DamageStep { + private static final Logger LOGGER = LogManager.getLogger(); + + private final SpongeDamageTracker tracker; + private final DamageStepType type; + private final @Nullable SpongeDamageStep parent; + private final @Nullable Consumer frameModifier; + private final DamageModifier.@Nullable Function damageFunction; + + private Cause cause; + private boolean skipped; + + private OptionalDouble damageBeforeChildren = OptionalDouble.empty(); + private OptionalDouble damageBeforeSelf = OptionalDouble.empty(); + private OptionalDouble damageAfterSelf = OptionalDouble.empty(); + private OptionalDouble damageAfterChildren = OptionalDouble.empty(); + + private List childrenBefore; + private List childrenAfter; + + public SpongeDamageStep(final SpongeDamageTracker tracker, final DamageStepType type, final Object[] causes) { + this.tracker = tracker; + this.parent = null; + this.type = type; + this.frameModifier = (frame) -> { + SpongeDamageTracker.generateCauseFor(tracker.source, frame); + for (Object cause : causes) { + frame.pushCause(cause); + } + }; + this.damageFunction = null; + } + + public SpongeDamageStep(final SpongeDamageStep parent, final DamageModifier modifier) { + this.tracker = parent.tracker; + this.parent = parent; + this.type = modifier.type(); + this.frameModifier = modifier.frameModifier().orElse(null); + this.damageFunction = modifier.damageFunction().orElse(null); + } + + void populateChildren() { + this.populateChildren(new HashSet<>()); + } + + private void populateChildren(final Set parentTypes) { + parentTypes.add(this.type); + + final ImmutableList.Builder before = ImmutableList.builder(); + for (final DamageModifier modifier : this.tracker.preEvent().modifiersBefore(this.type)) { + if (parentTypes.contains(modifier.type())) { + LOGGER.warn("Modifier {} is supposed to be a child before step {} but this would cause a cycle so it will be ignored.", modifier, this); + } else { + before.add(new SpongeDamageStep(this, modifier)); + } + } + this.childrenBefore = before.build(); + + final ImmutableList.Builder after = ImmutableList.builder(); + for (final DamageModifier modifier : this.tracker.preEvent().modifiersAfter(this.type)) { + if (parentTypes.contains(modifier.type())) { + LOGGER.warn("Modifier {} is supposed to be a child after step {} but this would cause a cycle so it will be ignored.", modifier, this); + } else { + after.add(new SpongeDamageStep(this, modifier)); + } + } + this.childrenAfter = after.build(); + + final PhaseTracker phaseTracker = PhaseTracker.getInstance(); + try (final CauseStackManager.StackFrame frame = this.frameModifier == null ? null : phaseTracker.pushCauseFrame()) { + if (frame != null) { + try { + this.frameModifier.accept(frame); + } catch (final Throwable t) { + LOGGER.error("Failed to apply frame modifier of step {}", this, t); + } + } + + this.cause = phaseTracker.currentCause(); + + for (final SpongeDamageStep child : this.childrenBefore) { + child.populateChildren(parentTypes); + } + for (final SpongeDamageStep child : this.childrenAfter) { + child.populateChildren(parentTypes); + } + } + + parentTypes.remove(this.type); + } + + @Override + public DamageStepType type() { + return this.type; + } + + @Override + public Cause cause() { + return this.cause; + } + + @Override + public boolean isSkipped() { + return this.skipped; + } + + @Override + public void setSkipped(boolean skipped) { + if (this.damageAfterSelf.isPresent()) { + throw new IllegalStateException("Step can only be skipped before occurring"); + } + this.skipped = skipped; + } + + @Override + public OptionalDouble damageBeforeChildren() { + return this.damageBeforeChildren; + } + + @Override + public OptionalDouble damageBeforeSelf() { + return this.damageBeforeSelf; + } + + @Override + public OptionalDouble damageAfterSelf() { + return this.damageAfterSelf; + } + + @Override + public OptionalDouble damageAfterChildren() { + return this.damageAfterChildren; + } + + @Override + public DamageStepHistory history() { + return this.tracker; + } + + @Override + public Optional parent() { + return Optional.ofNullable(this.parent); + } + + @Override + public List childrenBefore() { + return (List) this.childrenBefore; + } + + @Override + public List childrenAfter() { + return (List) this.childrenAfter; + } + + @Override + public String toString() { + // don't add the parent to avoid infinite recursion + return new StringJoiner(", ", SpongeDamageStep.class.getSimpleName() + "[", "]") + .add("type=" + this.type) + .add("cause=" + this.cause) + .add("frameModifier=" + this.frameModifier) + .add("damageFunction=" + this.damageFunction) + .add("skipped=" + this.skipped) + .add("damageBeforeChildren=" + this.damageBeforeChildren) + .add("damageBeforeSelf=" + this.damageBeforeSelf) + .add("damageAfterSelf=" + this.damageAfterSelf) + .add("damageAfterChildren=" + this.damageAfterChildren) + .add("childrenBefore=" + this.childrenBefore) + .add("childrenAfter=" + this.childrenAfter) + .toString(); + } + + public double applyChildrenBefore(double damage) { + if (this.damageBeforeChildren.isPresent()) { + throw new IllegalStateException(); + } + + this.damageBeforeChildren = OptionalDouble.of(damage); + for (final SpongeDamageStep child : this.childrenBefore) { + damage = child.apply(damage); + } + this.damageBeforeSelf = OptionalDouble.of(damage); + return damage; + } + + public double applyChildrenAfter(double damage) { + if (this.damageAfterSelf.isPresent() || this.damageBeforeSelf.isEmpty()) { + throw new IllegalStateException(); + } + + if (this.skipped) { + damage = this.damageBeforeSelf.getAsDouble(); + } + + this.damageAfterSelf = OptionalDouble.of(damage); + for (final SpongeDamageStep child : this.childrenAfter) { + damage = child.apply(damage); + } + this.damageAfterChildren = OptionalDouble.of(damage); + return damage; + } + + public double apply(double damage) { + damage = this.applyChildrenBefore(damage); + if (!this.skipped && this.damageFunction != null) { + try { + damage = this.damageFunction.modify(this, damage); + } catch (final Throwable t) { + LOGGER.error("Failed to apply damage function of step {}", this, t); + } + } + damage = this.applyChildrenAfter(damage); + return damage; + } +} diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifierType.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStepType.java similarity index 82% rename from src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifierType.java rename to src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStepType.java index f17035514b7..959438dabd1 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageModifierType.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageStepType.java @@ -25,16 +25,15 @@ package org.spongepowered.common.event.cause.entity.damage; import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.event.cause.entity.damage.DamageModifierType; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; import org.spongepowered.api.registry.RegistryTypes; -public final class SpongeDamageModifierType implements DamageModifierType { +public final class SpongeDamageStepType implements DamageStepType { @Override public String toString() { - return RegistryTypes.DAMAGE_MODIFIER_TYPE.get().findValueKey(this) + return RegistryTypes.DAMAGE_STEP_TYPE.get().findValueKey(this) .map(ResourceKey::toString) - .map("DamageModifierType[%s]"::formatted) - .orElse(super.toString()); + .orElseGet(super::toString); } } diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java new file mode 100644 index 00000000000..a4492c6123f --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java @@ -0,0 +1,215 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.cause.entity.damage; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.player.Player; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.entity.damage.DamageStep; +import org.spongepowered.api.event.cause.entity.damage.DamageStepHistory; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.api.event.entity.DamageCalculationEvent; +import org.spongepowered.api.event.entity.DamageEntityEvent; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.bridge.CreatorTrackedBridge; +import org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge; +import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.util.VecHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class SpongeDamageTracker implements DamageStepHistory { + private static final Logger LOGGER = LogManager.getLogger(); + + private final List rootSteps = new ArrayList<>(); + protected final DamageCalculationEvent.Pre preEvent; + protected final DamageSource source; + protected DamageCalculationEvent.Post postEvent; + + public SpongeDamageTracker(final DamageCalculationEvent.Pre preEvent, final DamageSource source) { + this.preEvent = preEvent; + this.source = source; + } + + @Override + public List rootSteps() { + return Collections.unmodifiableList(this.rootSteps); + } + + public DamageCalculationEvent.Pre preEvent() { + return this.preEvent; + } + + public DamageCalculationEvent.Post postEvent() { + if (this.postEvent == null) { + throw new IllegalStateException("Post event not yet fired"); + } + return this.postEvent; + } + + public SpongeDamageStep newStep(final DefaultedRegistryReference typeRef, final Object... causes) { + final DamageStepType type = typeRef.get(); + final SpongeDamageStep step = new SpongeDamageStep(this, type, causes); + step.populateChildren(); + + if (this.postEvent != null) { + LOGGER.warn("A new root step {} is being captured after the post event.", step.type()); + } + + if (!this.rootSteps.isEmpty()) { + final SpongeDamageStep previous = this.rootSteps.getLast(); + if (previous.damageAfterChildren().isEmpty()) { + LOGGER.warn("A new root step {} is being captured but previous root step {} hasn't finished.", step.type(), previous.type()); + this.rootSteps.removeLast(); + } + } + + this.rootSteps.add(step); + return step; + } + + public float startStep(final DefaultedRegistryReference typeRef, final float damage, final Object... causes) { + return (float) this.newStep(typeRef, causes).applyChildrenBefore(damage); + } + + public @Nullable SpongeDamageStep currentStep(final DefaultedRegistryReference typeRef) { + if (this.rootSteps.isEmpty()) { + LOGGER.warn("Expected a current root step of type {} but no step has been captured yet.", typeRef.location()); + return null; + } + + final DamageStepType type = typeRef.get(); + final SpongeDamageStep step = this.rootSteps.getLast(); + if (step.type() != type) { + LOGGER.warn("Expected a current root step of type {} but got {}.", type, step.type()); + return null; + } + return step; + } + + public float endStep(final DefaultedRegistryReference typeRef, final float damage) { + final SpongeDamageStep step = this.currentStep(typeRef); + return step == null ? damage : (float) step.applyChildrenAfter(damage); + } + + public boolean isSkipped(final DefaultedRegistryReference typeRef) { + final SpongeDamageStep step = this.currentStep(typeRef); + return step != null && step.isSkipped(); + } + + public @Nullable SpongeDamageStep lastStep(final DefaultedRegistryReference typeRef) { + final DamageStepType type = typeRef.get(); + for (int i = this.rootSteps.size() - 1; i >= 0; i--) { + final SpongeDamageStep step = this.rootSteps.get(i); + if (step.type() == type) { + return step; + } + } + return null; + } + + public float damageAfter(final DefaultedRegistryReference typeRef) { + final SpongeDamageStep step = this.lastStep(typeRef); + return step == null ? 0 : (float) step.damageAfterChildren().orElse(0); + } + + public float callDamagePostEvent(final Entity entity, float finalDamage) { + if (this.postEvent != null) { + throw new IllegalStateException("Post event already fired"); + } + + finalDamage = (float) this.newStep(DamageStepTypes.END).apply(finalDamage); + + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + SpongeDamageTracker.generateCauseFor((DamageSource) this.preEvent.source(), frame); + + final DamageEntityEvent.Post event = SpongeEventFactory.createDamageEntityEventPost(frame.currentCause(), + entity, this, this.preEvent.baseDamage(), finalDamage); + + this.postEvent = event; + if (SpongeCommon.post(event)) { + return 0; + } + return (float) event.finalDamage(); + } + } + + protected static void generateCauseFor(final DamageSource source, final CauseStackManager.StackFrame frame) { + if (source.getDirectEntity() instanceof org.spongepowered.api.entity.Entity entity) { + if (!(entity instanceof Player) && entity instanceof CreatorTrackedBridge creatorBridge) { + creatorBridge.tracker$getCreatorUUID().ifPresent(creator -> frame.addContext(EventContextKeys.CREATOR, creator)); + creatorBridge.tracker$getNotifierUUID().ifPresent(notifier -> frame.addContext(EventContextKeys.NOTIFIER, notifier)); + } + } else if (((DamageSourceBridge) source).bridge$blockLocation() != null) { + final ServerLocation location = ((DamageSourceBridge) source).bridge$blockLocation(); + final BlockPos blockPos = VecHelper.toBlockPos(location); + final LevelChunkBridge chunkBridge = (LevelChunkBridge) ((net.minecraft.world.level.Level) location.world()).getChunkAt(blockPos); + chunkBridge.bridge$getBlockCreatorUUID(blockPos).ifPresent(creator -> frame.addContext(EventContextKeys.CREATOR, creator)); + chunkBridge.bridge$getBlockNotifierUUID(blockPos).ifPresent(notifier -> frame.addContext(EventContextKeys.NOTIFIER, notifier)); + } + frame.pushCause(source); + } + + public static @Nullable SpongeDamageTracker callDamagePreEvent(final Entity entity, final DamageSource source, final float baseDamage) { + final SpongeDamageTracker tracker; + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + SpongeDamageTracker.generateCauseFor(source, frame); + + final DamageEntityEvent.Pre event = SpongeEventFactory.createDamageEntityEventPre(frame.currentCause(), entity, baseDamage); + if (SpongeCommon.post(event)) { + return null; + } + + tracker = new SpongeDamageTracker(event, source); + } + + tracker.newStep(DamageStepTypes.START).apply(baseDamage); + return tracker; + } + + public static DamageEntityEvent.@Nullable Post callDamageEvents(final Entity entity, final DamageSource source, final float baseDamage) { + final @Nullable SpongeDamageTracker tracker = SpongeDamageTracker.callDamagePreEvent(entity, source, baseDamage); + if (tracker == null) { + return null; + } + final DamageStep step = tracker.currentStep(DamageStepTypes.START); + final float finalDamage = step == null ? baseDamage : (float) step.damageAfterChildren().orElse(baseDamage); + tracker.callDamagePostEvent(entity, finalDamage); + return (DamageEntityEvent.Post) tracker.postEvent; + } +} diff --git a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java index 5694031f9ad..821ca0dcb09 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java @@ -68,6 +68,7 @@ import org.spongepowered.api.entity.attribute.AttributeModifier; import org.spongepowered.api.entity.living.player.tab.TabListEntry; import org.spongepowered.api.event.EventContextKey; +import org.spongepowered.api.event.cause.entity.damage.DamageModifier; import org.spongepowered.api.event.cause.entity.damage.DamageType; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.fluid.FluidStack; @@ -179,6 +180,7 @@ import org.spongepowered.common.entity.attribute.SpongeAttributeModifierBuilder; import org.spongepowered.common.entity.player.tab.TabListEntryBuilder; import org.spongepowered.common.event.SpongeEventContextKeyBuilder; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageModifier; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSourceBuilder; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTypeBuilder; import org.spongepowered.common.fluid.SpongeFluidStackBuilder; @@ -292,6 +294,7 @@ public void registerDefaultBuilders() { .register(Team.Builder.class, SpongeTeamBuilder::new) .register(Scoreboard.Builder.class, SpongeScoreboardBuilder::new) .register(DamageSource.Builder.class, SpongeDamageSourceBuilder::new) + .register(DamageModifier.Builder.class, SpongeDamageModifier.Builder::new) .register(Explosion.Builder.class, SpongeExplosionBuilder::new) .register(BlockState.Builder.class, SpongeBlockStateBuilder::new) .register(BlockSnapshot.Builder.class, SpongeBlockSnapshot.BuilderImpl::unpooled) diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index 8891c2041ad..201ebe38af7 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -46,6 +46,7 @@ import org.spongepowered.api.effect.ForwardingViewer; import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.event.EventListenerRegistration; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackComparators; @@ -123,6 +124,7 @@ import org.spongepowered.common.effect.SpongeCustomForwardingViewer; import org.spongepowered.common.entity.effect.SpongeVanishState; import org.spongepowered.common.event.SpongeEventListenerRegistration; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType; import org.spongepowered.common.event.tracking.BlockChangeFlagManager; import org.spongepowered.common.item.SpongeItemStack; import org.spongepowered.common.item.SpongeItemStackSnapshot; @@ -244,6 +246,7 @@ public void registerDefaultFactories() { .registerFactory(RegistryReference.Factory.class, new SpongeRegistryReference.FactoryImpl()) .registerFactory(BlockVolumeFactory.class, new SpongeBlockVolumeFactory()) .registerFactory(DamageSource.Factory.class, new SpongeDamageSourceFactory()) + .registerFactory(DamageStepType.Factory.class, SpongeDamageStepType::new) .registerFactory(PaletteReference.Factory.class, new SpongePaletteReferenceFactory()) .registerFactory(EntityArchetypeEntry.Factory.class, new SpongeEntityArchetypeEntryFactory()) .registerFactory(ServerLocationCreator.Factory.class, new SpongeServerLocationCreatorFactory()) diff --git a/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java b/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java index a377af375e3..29ba343d72a 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeRegistries.java @@ -63,7 +63,6 @@ public static void registerEarlyGlobalRegistries(final SpongeRegistryHolder hold holder.createFrozenRegistry(RegistryTypes.BODY_PART, SpongeRegistryLoader.bodyPart()); holder.createFrozenRegistry(RegistryTypes.CLICK_TYPE, SpongeRegistryLoader.clickType()); holder.createFrozenRegistry(RegistryTypes.CHUNK_REGENERATE_FLAG, SpongeRegistryLoader.chunkRegenerateFlag()); - holder.createFrozenRegistry(RegistryTypes.DAMAGE_MODIFIER_TYPE, SpongeRegistryLoader.damageModifierType()); holder.createFrozenRegistry(RegistryTypes.DISMOUNT_TYPE, SpongeRegistryLoader.dismountType()); holder.createFrozenRegistry(RegistryTypes.GOAL_EXECUTOR_TYPE, SpongeRegistryLoader.goalExecutorType()); holder.createFrozenRegistry(RegistryTypes.GOAL_TYPE, SpongeRegistryLoader.goalType()); @@ -95,6 +94,7 @@ private static void registerEarlyDynamicRegistries(final SpongeRegistryHolder ho holder.createRegistry(RegistryTypes.COMMAND_REGISTRAR_TYPE, CommandRegistryLoader.commandRegistrarType(), true); holder.createRegistry(RegistryTypes.PLACEHOLDER_PARSER, DynamicSpongeRegistryLoader.placeholderParser(), true); holder.createRegistry(RegistryTypes.TELEPORT_HELPER_FILTER, DynamicSpongeRegistryLoader.teleportHelperFilter(), true); + holder.createRegistry(RegistryTypes.DAMAGE_STEP_TYPE, SpongeRegistryLoader.damageStepType(), true); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index db0d4af33a2..b8f9f664823 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -65,8 +65,8 @@ import org.spongepowered.api.event.cause.entity.MovementTypes; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.event.cause.entity.SpawnTypes; -import org.spongepowered.api.event.cause.entity.damage.DamageModifierType; -import org.spongepowered.api.event.cause.entity.damage.DamageModifierTypes; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.inventory.menu.ClickType; import org.spongepowered.api.item.inventory.menu.ClickTypes; @@ -126,7 +126,7 @@ import org.spongepowered.common.event.cause.entity.SpongeMovementType; import org.spongepowered.common.event.cause.entity.SpongeSpawnType; import org.spongepowered.common.event.cause.entity.SpongeSpawnTypes; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageModifierType; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType; import org.spongepowered.common.inventory.menu.handler.SpongeClickType; import org.spongepowered.common.inventory.query.SpongeOneParamQueryType; import org.spongepowered.common.inventory.query.SpongeQueryTypes; @@ -219,25 +219,26 @@ public static RegistryLoader> clickType() { ))); } - public static RegistryLoader damageModifierType() { - return RegistryLoader.of(l -> l.mapping(SpongeDamageModifierType::new, m -> m.add( - DamageModifierTypes.ABSORPTION, - DamageModifierTypes.ARMOR, - DamageModifierTypes.ARMOR_ENCHANTMENT, - DamageModifierTypes.ATTACK_COOLDOWN, - DamageModifierTypes.CRITICAL_HIT, - DamageModifierTypes.DEFENSIVE_POTION_EFFECT, - DamageModifierTypes.DIFFICULTY, - DamageModifierTypes.HARD_HAT, - DamageModifierTypes.MAGIC, - DamageModifierTypes.NEGATIVE_POTION_EFFECT, - DamageModifierTypes.OFFENSIVE_POTION_EFFECT, - DamageModifierTypes.SHIELD, - DamageModifierTypes.SWEEPING, - DamageModifierTypes.WEAPON_ENCHANTMENT, - DamageModifierTypes.WEAPON_BONUS, - DamageModifierTypes.ATTACK_STRENGTH, - DamageModifierTypes.FREEZING_BONUS + public static RegistryLoader damageStepType() { + return RegistryLoader.of(l -> l.mapping(SpongeDamageStepType::new, m -> m.add( + DamageStepTypes.ABSORPTION, + DamageStepTypes.ARMOR, + DamageStepTypes.ARMOR_ENCHANTMENT, + DamageStepTypes.BASE_COOLDOWN, + DamageStepTypes.CRITICAL_HIT, + DamageStepTypes.DEFENSIVE_POTION_EFFECT, + DamageStepTypes.ENCHANTMENT_COOLDOWN, + DamageStepTypes.END, + DamageStepTypes.FREEZING_BONUS, + DamageStepTypes.HARD_HAT, + DamageStepTypes.MAGIC, + DamageStepTypes.NEGATIVE_POTION_EFFECT, + DamageStepTypes.OFFENSIVE_POTION_EFFECT, + DamageStepTypes.SHIELD, + DamageStepTypes.START, + DamageStepTypes.SWEEPING, + DamageStepTypes.WEAPON_BONUS, + DamageStepTypes.WEAPON_ENCHANTMENT ))); } diff --git a/src/main/java/org/spongepowered/common/util/DamageEventUtil.java b/src/main/java/org/spongepowered/common/util/DamageEventUtil.java index cef66e91d88..ac40ff9fc85 100644 --- a/src/main/java/org/spongepowered/common/util/DamageEventUtil.java +++ b/src/main/java/org/spongepowered/common/util/DamageEventUtil.java @@ -25,111 +25,19 @@ package org.spongepowered.common.util; import net.minecraft.core.BlockPos; -import net.minecraft.core.component.DataComponents; -import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; -import net.minecraft.world.damagesource.CombatRules; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.ItemEnchantments; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.AABB; -import org.apache.commons.lang3.mutable.MutableFloat; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.EventContext; -import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.cause.entity.damage.DamageFunction; -import org.spongepowered.api.event.cause.entity.damage.DamageModifier; -import org.spongepowered.api.event.cause.entity.damage.DamageModifierType; -import org.spongepowered.api.event.cause.entity.damage.DamageModifierTypes; -import org.spongepowered.api.event.entity.AttackEntityEvent; -import org.spongepowered.api.event.entity.DamageEntityEvent; -import org.spongepowered.api.registry.DefaultedRegistryReference; -import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.bridge.CreatorTrackedBridge; -import org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge; -import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.item.util.ItemStackUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.DoubleUnaryOperator; import java.util.function.Predicate; public final class DamageEventUtil { - private DamageEventUtil() { - } - - - @SuppressWarnings("ConstantConditions") - public static DamageFunction createHardHatModifier(final ItemStack headItem, final float multiplier) { - final var snapshot = ItemStackUtil.snapshotOf(headItem); - final var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.HARD_HAT, snapshot); - return new DamageFunction(modifier, damage -> damage * multiplier); - } - - /** - * LivingEntity#getDamageAfterArmorAbsorb - */ - public static DamageFunction createArmorModifiers(final LivingEntity living, final DamageSource damageSource) { - final DoubleUnaryOperator function = dmg -> CombatRules.getDamageAfterAbsorb(living, (float) dmg, - damageSource, living.getArmorValue(), (float) living.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); - final var modifier = DamageEventUtil.buildDamageReductionModifierWithFrame(DamageModifierTypes.ARMOR, living, Attributes.ARMOR_TOUGHNESS); - - return DamageFunction.of(modifier, function); - } - - /** - * LivingEntity#getDamageAfterMagicAbsorb - */ - public static DamageFunction createResistanceModifier(final LivingEntity living) { - final var effect = living.getEffect(MobEffects.DAMAGE_RESISTANCE); - var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.DEFENSIVE_POTION_EFFECT, effect); - return new DamageFunction(modifier, DamageEventUtil.createResistanceFunction(living)); - } - - public static DoubleUnaryOperator createResistanceFunction(final LivingEntity living) { - final var effect = living.getEffect(MobEffects.DAMAGE_RESISTANCE); - final int base = effect == null ? 0 : (effect.getAmplifier() + 1) * 5; - final int modifier = 25 - base; - return damage -> Math.max(((damage * modifier) / 25.0F), 0.0f); - } - - - /** - * LivingEntity#getDamageAfterMagicAbsorb - */ - public static DamageFunction createEnchantmentModifiers(final LivingEntity living, final float damageProtection) { - final DoubleUnaryOperator func = damage -> CombatRules.getDamageAfterMagicAbsorb((float) damage, damageProtection); - final var modifier = DamageEventUtil.buildDamageReductionModifierWithFrame(DamageModifierTypes.ARMOR_ENCHANTMENT, living); - return new DamageFunction(modifier, func); - } - - public static DamageFunction createAbsorptionModifier(final LivingEntity living, final float absorptionAmount) { - final var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.ABSORPTION, living); - return new DamageFunction(modifier, damage -> Math.max(damage - absorptionAmount, 0.0F)); - } - public static ServerLocation findFirstMatchingBlock(final Entity entity, final AABB bb, final Predicate predicate) { final int i = Mth.floor(bb.minX); final int j = Mth.floor(bb.maxX + 1.0D); @@ -156,273 +64,4 @@ public static ServerLocation findFirstMatchingBlock(final Entity entity, final A // Entity is source of fire return ((org.spongepowered.api.entity.Entity) entity).serverLocation(); } - - /** - * This applies various contexts based on the type of {@link DamageSource}, whether - * it's provided by sponge or vanilla. This is not stack neutral, which is why it requires - * a {@link CauseStackManager.StackFrame} reference to push onto the stack. - */ - public static void generateCauseFor(final DamageSource damageSource, final CauseStackManager.StackFrame frame) { - if (damageSource.getDirectEntity() instanceof org.spongepowered.api.entity.Entity entity) { - if (!(entity instanceof Player) && entity instanceof CreatorTrackedBridge creatorBridge) { - creatorBridge.tracker$getCreatorUUID().ifPresent(creator -> frame.addContext(EventContextKeys.CREATOR, creator)); - creatorBridge.tracker$getNotifierUUID().ifPresent(notifier -> frame.addContext(EventContextKeys.NOTIFIER, notifier)); - } - } else if (((DamageSourceBridge) damageSource).bridge$blockLocation() != null) { - final ServerLocation location = ((DamageSourceBridge) damageSource).bridge$blockLocation(); - final BlockPos blockPos = VecHelper.toBlockPos(location); - final LevelChunkBridge chunkBridge = (LevelChunkBridge) ((net.minecraft.world.level.Level) location.world()).getChunkAt(blockPos); - chunkBridge.bridge$getBlockCreatorUUID(blockPos).ifPresent(creator -> frame.addContext(EventContextKeys.CREATOR, creator)); - chunkBridge.bridge$getBlockNotifierUUID(blockPos).ifPresent(notifier -> frame.addContext(EventContextKeys.NOTIFIER, notifier)); - } - frame.pushCause(damageSource); - } - - /** - * Mirrors {@link EnchantmentHelper#modifyDamage} - */ - public static List createAttackEnchantmentFunction(final ItemStack weapon, final Entity entity, final DamageSource damageSource) { - final var enchantments = weapon.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); - final var snapshot = ItemStackUtil.snapshotOf(weapon); - - return enchantments.entrySet().stream().map(entry -> { - final var enchantment = entry.getKey().value(); - final int level = entry.getIntValue(); - - final var modifier = DamageEventUtil.buildAttackEnchantmentModifier(DamageModifierTypes.WEAPON_ENCHANTMENT, snapshot, enchantment); - - return new DamageFunction(modifier, damage -> - DamageEventUtil.enchantmentDamageFunction(weapon, entity, damageSource, damage, enchantment, level)); - }).toList(); - } - - public static DamageFunction provideSeparateEnchantmentFromBaseDamageFunction(final float baseDamage, final ItemStack weapon) { - final var modifier = DamageEventUtil.buildAttackEnchantmentModifier(DamageModifierTypes.WEAPON_ENCHANTMENT, ItemStackUtil.snapshotOf(weapon)); - return new DamageFunction(modifier, damage -> damage - baseDamage); - } - - public static DamageFunction provideCooldownEnchantmentStrengthFunction(final ItemStack weapon, final float attackStrength) { - final var snapshot = ItemStackUtil.snapshotOf(weapon); - final var modifier = DamageEventUtil.buildAttackEnchantmentModifier(DamageModifierTypes.ATTACK_STRENGTH, snapshot); - return new DamageFunction(modifier, damage -> damage * attackStrength); - } - - private static double enchantmentDamageFunction(final ItemStack weapon, final Entity entity, - final DamageSource damageSource, final double damage, final Enchantment enchantment, final int level) { - var totalDamage = new MutableFloat(damage); - enchantment.modifyDamage((ServerLevel) entity.level(), level, weapon, entity, damageSource, totalDamage); - return totalDamage.doubleValue(); - } - - public static DamageFunction provideCriticalAttackFunction(final Player player, double criticalModifier) { - final var modifier = DamageEventUtil.buildAttackDamageModifier(DamageModifierTypes.CRITICAL_HIT, player); - final DoubleUnaryOperator function = (damage) -> damage * criticalModifier; - return new DamageFunction(modifier, function); - } - - public static DamageFunction provideCooldownAttackStrengthFunction(final Player player, final float attackStrength) { - final var modifier = DamageEventUtil.buildAttackDamageModifier(DamageModifierTypes.ATTACK_COOLDOWN, player); - final DoubleUnaryOperator function = (damage) -> damage * (0.2F + attackStrength * attackStrength * 0.8F); - return new DamageFunction(modifier, function); - } - - public static DamageFunction provideWeaponAttackDamageBonusFunction(final Entity targetEntity, final ItemStack weapon, final DamageSource damageSource) { - final var modifier = DamageEventUtil.buildAttackDamageModifier(DamageModifierTypes.WEAPON_BONUS, targetEntity); - final DoubleUnaryOperator function = (damage) -> damage + weapon.getItem().getAttackDamageBonus(targetEntity, (float) damage, damageSource); - return new DamageFunction(modifier, function); - } - - public static DamageFunction provideSweepingDamageRatioFunction(final ItemStack held, final Player player, final double attackDamage) { - final var modifier = DamageEventUtil.buildAttackEnchantmentModifier(DamageModifierTypes.SWEEPING, ItemStackUtil.snapshotOf(held)); - return DamageFunction.of(modifier, damage -> damage + player.getAttributeValue(Attributes.SWEEPING_DAMAGE_RATIO) * attackDamage); - } - - @SuppressWarnings("ConstantConditions") - public static DamageFunction createShieldFunction(final LivingEntity entity) { - final var snapshot = ItemStackUtil.snapshotOf(entity.getUseItem()); - final var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.SHIELD, entity, snapshot); - return new DamageFunction(modifier, (damage) -> 0); - } - - public static DamageFunction createFreezingBonus(final LivingEntity entity, final DamageSource damageSource, float multiplier) { - final var modifier = DamageEventUtil.buildDamageReductionModifier(DamageModifierTypes.FREEZING_BONUS, damageSource, entity); - return new DamageFunction(modifier, (damage) -> damage * multiplier); - } - - private static DamageModifier buildDamageReductionModifierWithFrame(final DefaultedRegistryReference modifierType, Object... causes) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - for (final Object cause : causes) { - frame.pushCause(cause); - } - return DamageModifier.builder().damageReductionGroup() - .cause(frame.currentCause()).type(modifierType).build(); - } - } - - private static DamageModifier buildAttackDamageModifier(final DefaultedRegistryReference modifierType, Object... causes) { - return DamageModifier.builder().attackDamageGroup() - .cause(Cause.of(EventContext.empty(), Arrays.asList(causes))).type(modifierType).build(); - } - - private static DamageModifier buildAttackEnchantmentModifier(final DefaultedRegistryReference modifierType, Object... causes) { - return DamageModifier.builder().attackEnchantmentGroup() - .cause(Cause.of(EventContext.empty(), Arrays.asList(causes))).type(modifierType).build(); - } - - private static DamageModifier buildDamageReductionModifier(final DefaultedRegistryReference modifierType, Object... causes) { - return DamageModifier.builder().damageReductionGroup() - .cause(Cause.of(EventContext.empty(), Arrays.asList(causes))).type(modifierType).build(); - } - - public static AttackEntityEvent callPlayerAttackEntityEvent(final Attack attack, final float knockbackModifier) { - final boolean isMainthread = !attack.sourceEntity().level().isClientSide; - if (isMainthread) { - PhaseTracker.getInstance().pushCause(attack.dmgSource()); - } - final var currentCause = isMainthread - ? PhaseTracker.getInstance().currentCause() - : Cause.of(EventContext.empty(), attack.dmgSource()); - final var event = attack.postEvent(knockbackModifier, currentCause); - if (isMainthread) { - PhaseTracker.getInstance().popCause(); - } - return event; - } - - /** - * {@link Mob#doHurtTarget} - */ - public static AttackEntityEvent callMobAttackEvent(final Attack attack, final float knockbackModifier) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(attack.dmgSource()); - return attack.postEvent(knockbackModifier, frame.currentCause()); - } - } - - /** - * For {@link Entity#hurt} overrides without super call: - * {@link net.minecraft.world.entity.decoration.BlockAttachedEntity#hurt} - * {@link net.minecraft.world.entity.vehicle.VehicleEntity#hurt} - * {@link net.minecraft.world.entity.decoration.ItemFrame#hurt} - * {@link net.minecraft.world.entity.vehicle.MinecartTNT#hurt} - * {@link net.minecraft.world.entity.boss.enderdragon.EndCrystal#hurt} - * {@link net.minecraft.world.entity.projectile.ShulkerBullet#hurt} - * {@link net.minecraft.world.entity.ExperienceOrb#hurt} - * {@link net.minecraft.world.entity.item.ItemEntity#hurt} - */ - public static AttackEntityEvent callOtherAttackEvent( - final Entity targetEntity, - final DamageSource damageSource, - final double damage) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(damageSource); - final AttackEntityEvent event = SpongeEventFactory.createAttackEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) targetEntity, new ArrayList<>(), 0, damage); - SpongeCommon.post(event); - return event; - } - } - - public static DamageEventResult callLivingDamageEntityEvent(final Hurt hurt, final ActuallyHurt actuallyHurt) { - - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - DamageEventUtil.generateCauseFor(actuallyHurt.dmgSource(), frame); - - final List originalFunctions = new ArrayList<>(); - originalFunctions.addAll(hurt.functions()); - originalFunctions.addAll(actuallyHurt.functions()); - final var event = SpongeEventFactory.createDamageEntityEvent(frame.currentCause(), - (org.spongepowered.api.entity.Entity) actuallyHurt.entity(), - originalFunctions, - actuallyHurt.baseDamage()); - - if (actuallyHurt.dmgSource() != SpongeDamageSources.IGNORED) { // Basically, don't throw an event if it's our own damage source - SpongeCommon.post(event); - } - - return new DamageEventResult(event, - actuallyHurt.dmgSource(), - DamageEventUtil.findDamageBefore(event, DamageModifierTypes.SHIELD), - DamageEventUtil.findDamageDifference(event, DamageModifierTypes.SHIELD), - DamageEventUtil.findDamageBefore(event, DamageModifierTypes.HARD_HAT), - DamageEventUtil.findDamageBefore(event, DamageModifierTypes.ARMOR), - DamageEventUtil.findDamageDifference(event, DamageModifierTypes.DEFENSIVE_POTION_EFFECT), // TODO Math.max(0, resisted)? - DamageEventUtil.findDamageDifference(event, DamageModifierTypes.ABSORPTION) - ); - } - - } - - private static Optional findDamageDifference(DamageEntityEvent event, DefaultedRegistryReference type) { - return DamageEventUtil.findModifier(event, type).map(event::damage).map(tuple -> tuple.first() - tuple.second()).map(Double::floatValue); - } - - - private static Optional findDamageBefore(DamageEntityEvent event, DefaultedRegistryReference type) { - return DamageEventUtil.findModifier(event, type).map(event::damage).map(Tuple::first).map(Double::floatValue); - } - - private static Optional findModifier(DamageEntityEvent event, DefaultedRegistryReference type) { - return event.originalFunctions().stream() - .map(DamageFunction::modifier) - .filter(mod -> type.get().equals(mod.type())) - .findFirst(); - } - - - public static DamageEntityEvent callSimpleDamageEntityEvent(final DamageSource source, final Entity targetEntity, final double amount) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - DamageEventUtil.generateCauseFor(source, frame); - final var event = SpongeEventFactory.createDamageEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) targetEntity, new ArrayList<>(), amount); - SpongeCommon.post(event); - return event; - } - } - - - - - public record DamageEventResult(DamageEntityEvent event, - DamageSource source, - Optional damageToShield, - Optional damageBlockedByShield, - Optional damageToHelmet, - Optional damageToArmor, - Optional damageResisted, - Optional damageAbsorbed - ) { - - } - - - public record Hurt(DamageSource dmgSource, List functions) { - - } - - public record ActuallyHurt(LivingEntity entity, - List functions, - DamageSource dmgSource, - float baseDamage) { - - } - - public record Attack(T sourceEntity, - Entity target, - ItemStack weapon, - DamageSource dmgSource, - float strengthScale, - float baseDamage, - List functions) { - - private AttackEntityEvent postEvent(final float knockbackModifier, final Cause cause) { - final var event = SpongeEventFactory.createAttackEntityEvent( - cause, - (org.spongepowered.api.entity.Entity) this.target, - this.functions, - knockbackModifier, - this.baseDamage); - SpongeCommon.post(event); - return event; - } - - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin_Attack_impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin_Attack_impl.java deleted file mode 100644 index cb063381820..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin_Attack_impl.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server.level; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.mixin.core.world.entity.player.PlayerMixin_Attack_Impl; -import org.spongepowered.common.util.DamageEventUtil; - -import java.util.ArrayList; - -@Mixin(value = ServerPlayer.class, priority = 900) -public abstract class ServerPlayerMixin_Attack_impl extends PlayerMixin_Attack_Impl { - - @Override - protected void attackImpl$enchanttDamageFunc(Entity $$0, CallbackInfo ci) { - final var weapon = this.attackImpl$attack.weapon(); - // this.getEnchantedDamage(targetEntity, damage, damageSource) - damage; - final var functions = DamageEventUtil.createAttackEnchantmentFunction(weapon, this.attackImpl$attack.target(), this.attackImpl$attack.dmgSource()); - final var separateFunc = DamageEventUtil.provideSeparateEnchantmentFromBaseDamageFunction(this.attackImpl$attack.baseDamage(), weapon); - // enchantmentDamage *= attackStrength; - final var strengthScaleFunc = DamageEventUtil.provideCooldownEnchantmentStrengthFunction(weapon, this.attackImpl$attack.strengthScale()); - - this.attackImpl$attack.functions().addAll(functions); - this.attackImpl$attack.functions().add(separateFunc); - this.attackImpl$attack.functions().add(strengthScaleFunc); - } - - @Override - protected double attackImpl$beforeSweepHurt( - final Player instance, final Entity sweepTarget, final Operation original - ) { - final var distanceToSqr = original.call(instance, sweepTarget); - if (!(distanceToSqr < 9.0)) { - return distanceToSqr; // Too far - no event - } - - final var mainAttack = this.attackImpl$attack; - final var mainAttackDamage = this.attackImpl$finalDamageAmounts.getOrDefault("minecraft:attack_damage", 0.0).floatValue(); - - var sweepAttack = new DamageEventUtil.Attack<>(mainAttack.sourceEntity(), sweepTarget, mainAttack.weapon(), mainAttack.dmgSource(), mainAttack.strengthScale(), 1, new ArrayList<>()); - // float sweepBaseDamage = 1.0F + (float)this.getAttributeValue(Attributes.SWEEPING_DAMAGE_RATIO) * attackDamage; - sweepAttack.functions().add(DamageEventUtil.provideSweepingDamageRatioFunction(mainAttack.weapon(), mainAttack.sourceEntity(), mainAttackDamage)); - // float sweepFullDamage = this.getEnchantedDamage(sweepTarget, sweepBaseDamage, $$3) * strengthScale; - sweepAttack.functions().addAll(DamageEventUtil.createAttackEnchantmentFunction(mainAttack.weapon(), sweepTarget, mainAttack.dmgSource())); - sweepAttack.functions().add(DamageEventUtil.provideCooldownEnchantmentStrengthFunction(mainAttack.weapon(), mainAttack.strengthScale())); - - this.attackImpl$attackEvent = DamageEventUtil.callPlayerAttackEntityEvent(sweepAttack, 1.0F); - if (attackImpl$attackEvent.isCancelled()) { - return Double.MAX_VALUE; - } - - return distanceToSqr; - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java index 451d8b72663..f3172f61959 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ExperienceOrbMixin.java @@ -26,14 +26,14 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ExperienceOrb; +import org.spongepowered.api.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.util.DamageEventUtil; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @Mixin(ExperienceOrb.class) public abstract class ExperienceOrbMixin extends EntityMixin { @@ -48,8 +48,8 @@ public abstract class ExperienceOrbMixin extends EntityMixin { @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ExperienceOrb;markHurt()V")) - private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java deleted file mode 100644 index e9f46905c2d..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.entity; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.stats.Stats; -import net.minecraft.tags.DamageTypeTags; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import org.apache.logging.log4j.Level; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.*; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.util.DamageEventUtil; -import org.spongepowered.common.util.PrettyPrinter; - -import java.util.ArrayList; - -@Mixin(value = LivingEntity.class, priority = 900) -public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implements LivingEntityBridge { - - //@formatter:off - @Shadow protected abstract void shadow$playHurtSound(DamageSource param0); - @Shadow protected abstract void shadow$hurtHelmet(final DamageSource $$0, final float $$1); - @Shadow protected abstract void shadow$hurtCurrentlyUsedShield(final float $$0); - @Shadow protected abstract void shadow$blockUsingShield(final LivingEntity $$0); - @Shadow protected abstract void shadow$hurtArmor(DamageSource source, float damage); - @Shadow protected abstract float shadow$getKnockback(final Entity $$0, final DamageSource $$1); - @Shadow public abstract float shadow$getAbsorptionAmount(); - @Shadow public abstract @NonNull ItemStack shadow$getWeaponItem(); - @Shadow public abstract void setAbsorptionAmount(final float $$0); - @Shadow protected int attackStrengthTicker; - @Shadow protected float lastHurt; - private float attackImpl$baseDamage; - // @formatter:on - - private float attackImpl$lastHurt; - private int attackImpl$InvulnerableTime; - - protected DamageEventUtil.Hurt attackImpl$hurt; - protected DamageEventUtil.ActuallyHurt attackImpl$actuallyHurt; - protected DamageEventUtil.DamageEventResult attackImpl$actuallyHurtResult; - protected float attackImpl$actuallyHurtFinalDamage; - protected boolean attackImpl$actuallyHurtCancelled; - protected float attackImpl$actuallyHurtBlockedDamage; - - /** - * Forge onLivingAttack Hook - */ - @Inject(method = "hurtServer", at = @At("HEAD"), cancellable = true) - private void attackImpl$beforeHurt(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { - if (source == null) { - new PrettyPrinter(60).centre().add("Null DamageSource").hr() - .addWrapped("Sponge has found a null damage source! This should NEVER happen " - + "as the DamageSource is used for all sorts of calculations. Usually" - + " this can be considered developer error. Please report the following" - + " stacktrace to the most appropriate mod/plugin available.") - .add() - .add(new IllegalArgumentException("Null DamageSource")) - .log(SpongeCommon.logger(), Level.WARN); - cir.setReturnValue(false); - } - this.attackImpl$baseDamage = damageTaken; - } - - /** - * Prepare {@link org.spongepowered.common.util.DamageEventUtil.Hurt} for damage event - */ - @Inject(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I")) - private void attackImpl$preventEarlyBlock1(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { - this.attackImpl$hurt = new DamageEventUtil.Hurt($$0, new ArrayList<>()); - } - - /** - * Prevents shield usage before event - * Captures the blocked damage as a function - */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V")) - private void attackImpl$preventEarlyBlock1(final LivingEntity instance, final float damageToShield) { - // this.hurtCurrentlyUsedShield(damageToShield); - this.attackImpl$hurt.functions().add(DamageEventUtil.createShieldFunction(instance)); - } - - /** - * Prevents shield usage before event - */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V")) - private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final LivingEntity livingDamageSource) { - // this.blockUsingShield(livingDamageSource); - } - - /** - * Capture the bonus freezing damage as a function - */ - @Inject(method = "hurtServer", at = @At(value = "CONSTANT", args = "floatValue=5.0F")) - private void attackImpl$freezingBonus(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { - this.attackImpl$hurt.functions().add(DamageEventUtil.createFreezingBonus((LivingEntity) (Object) this, $$0, 5.0F)); - } - - /** - * Prevents {@link #shadow$hurtHelmet} before the event - * Captures the hard hat damage reduction as a function - */ - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$hardHat(final LivingEntity instance, final DamageSource $$0, final float $$1) { - // this.hurtHelmet($$0, $$1); - this.attackImpl$hurt.functions().add(DamageEventUtil.createHardHatModifier(instance.getItemBySlot(EquipmentSlot.HEAD), 0.75F)); - } - - /** - * Capture the old values to reset if we end up cancelling or blocking. - */ - @Inject(method = "hurtServer", at = @At(value = "FIELD", - target = "Lnet/minecraft/world/entity/LivingEntity;walkAnimation:Lnet/minecraft/world/entity/WalkAnimationState;")) - private void attackImpl$beforeActuallyHurt(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { - // Save old values - this.attackImpl$lastHurt = this.lastHurt; - this.attackImpl$InvulnerableTime = this.invulnerableTime; - this.attackImpl$actuallyHurtCancelled = false; - } - - @ModifyArg(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 0)) - private float attackImp$useBaseDamage1(final float $$0) { - return this.attackImpl$baseDamage - this.attackImpl$lastHurt; - } - - @ModifyArg(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V", ordinal = 1)) - private float attackImp$useBaseDamage2(final float $$0) { - return this.attackImpl$baseDamage; - } - - /** - * After calling #actuallyHurt (even when invulnerable), if cancelled return early or is still invulnerable - * and reset {@link #lastHurt} and {@link #invulnerableTime} - */ - @Inject(method = "hurtServer", cancellable = true, - at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, - target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt1(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { - if (this.attackImpl$actuallyHurtCancelled || damageTaken <= this.lastHurt) { - this.invulnerableTime = this.attackImpl$InvulnerableTime; - this.lastHurt = this.attackImpl$lastHurt; - cir.setReturnValue(false); - } - } - - /** - * After calling #actuallyHurt, if cancelled return early - * Also reset values - */ - @Inject(method = "hurtServer", cancellable = true, - at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 1, - target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt2(ServerLevel $$0, DamageSource $$1, float $$2, CallbackInfoReturnable cir) { - if (this.attackImpl$actuallyHurtCancelled) { - this.invulnerableTime = this.attackImpl$InvulnerableTime; - cir.setReturnValue(false); - } - } - - - /** - * Set final damage after #actuallyHurt and lastHurt has been set. - */ - @ModifyVariable(method = "hurtServer", argsOnly = true, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;getEntity()Lnet/minecraft/world/entity/Entity;"), - slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;getEntity()Lnet/minecraft/world/entity/Entity;"))) - private float attackImpl$modifyDamageTaken(float damageTaken) { - return this.attackImpl$actuallyHurtFinalDamage; - } - - // TODO - Pending on a Mixin bug: https://github.com/SpongePowered/Mixin/issues/684 -// /** -// * Sets blocked damage after #actuallyHurt -// */ -// @ModifyVariable(method = "hurtServer", ordinal = 1, -// at = @At(value = "INVOKE", -// target = "Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/damagesource/DamageSource;FFZ)V", -// shift = At.Shift.AFTER -// ), -// slice = @Slice( -// from = @At(value = "FIELD", target = "Lnet/minecraft/advancements/CriteriaTriggers;ENTITY_HURT_PLAYER:Lnet/minecraft/advancements/critereon/EntityHurtPlayerTrigger;"), -// to = @At(value = "FIELD", target = "Lnet/minecraft/stats/Stats;DAMAGE_BLOCKED_BY_SHIELD:Lnet/minecraft/resources/ResourceLocation;") -// )) -// private float attackImpl$modifyBlockedDamage(float damageBlocked) { -// return this.attackImpl$actuallyHurtBlockedDamage; -// } - - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void attackImpl$onHurtSound(final LivingEntity instance, final DamageSource $$0) { - if (this.bridge$vanishState().createsSounds()) { - this.shadow$playHurtSound($$0); - } - } - - @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) - private void attackImpl$onMakeSound(final LivingEntity instance, final SoundEvent $$0) { - if (this.bridge$vanishState().createsSounds()) { - instance.makeSound($$0); - } - } - - @Inject(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F")) - protected void attackImpl$startActuallyHurt( - final ServerLevel level, final DamageSource damageSource, - final float originalDamage, final CallbackInfo ci) { - // TODO check for direct call? - this.attackImpl$actuallyHurt = new DamageEventUtil.ActuallyHurt((LivingEntity) (Object) this, new ArrayList<>(), damageSource, originalDamage); - } - - /** - * Prevents LivingEntity#hurtArmor from running before event - * and capture the armor absorption as a function - */ - @Redirect(method = "getDamageAfterArmorAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtArmor(Lnet/minecraft/world/damagesource/DamageSource;F)V")) - protected void attackImpl$onDamageAfterArmorAbsorb(final LivingEntity instance, final DamageSource $$0, final float $$1) { - if (this.attackImpl$actuallyHurt != null) { - // prevents this.hurtArmor($$0, $$1); - // $$1 = CombatRules.getDamageAfterAbsorb(this, $$1, $$0, (float)this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); - var func = DamageEventUtil.createArmorModifiers(instance, this.attackImpl$actuallyHurt.dmgSource()); - this.attackImpl$actuallyHurt.functions().add(func); - } - } - - /** - * Captures the damage resistance as a function - */ - @Inject(method = "getDamageAfterMagicAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getEffect(Lnet/minecraft/core/Holder;)Lnet/minecraft/world/effect/MobEffectInstance;")) - protected void attackImpl$onDamageAfterMagicAbsorb(final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { - if (this.attackImpl$actuallyHurt != null) { - var func = DamageEventUtil.createResistanceModifier(this.attackImpl$actuallyHurt.entity()); - this.attackImpl$actuallyHurt.functions().add(func); - } - } - - - /** - * Captures the damage protection as a function - */ - @WrapOperation(method = "getDamageAfterMagicAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/CombatRules;getDamageAfterMagicAbsorb(FF)F")) - protected float attackImpl$onDetDamageProtection(float damage, float protection, Operation original) { - if (this.attackImpl$actuallyHurt != null) { - var func = DamageEventUtil.createEnchantmentModifiers(this.attackImpl$actuallyHurt.entity(), protection); - this.attackImpl$actuallyHurt.functions().add(func); - } - return original.call(damage, protection); - } - - /** - * Prevents setting absorption before event - * Captures the absorption amount as a functions - * Then calls the DamageEntityEvent - */ - @Inject(method = "setAbsorptionAmount", cancellable = true, at = @At("HEAD")) - protected void attackImpl$onSetAbsorptionAmount(final float newAmount, final CallbackInfo ci) { - if (this.attackImpl$actuallyHurt != null) { - ci.cancel(); // Always cancel this - var oldAmount = this.shadow$getAbsorptionAmount(); - if (oldAmount > 0) { - var func = DamageEventUtil.createAbsorptionModifier(this.attackImpl$actuallyHurt.entity(), oldAmount); - this.attackImpl$actuallyHurt.functions().add(func); - } - - // Use local and clear the variable to prevent re-entry if a plugin modifies the absorption hearts inside the event. - final DamageEventUtil.ActuallyHurt actuallyHurt = this.attackImpl$actuallyHurt; - this.attackImpl$actuallyHurt = null; - - this.attackImpl$actuallyHurtResult = DamageEventUtil.callLivingDamageEntityEvent(this.attackImpl$hurt, actuallyHurt); - - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - this.attackImpl$actuallyHurtCancelled = true; - this.attackImpl$actuallyHurtFinalDamage = 0; - this.attackImpl$actuallyHurtBlockedDamage = 0; - return; // Cancel vanilla behaviour by setting absorbed & finalDamage to 0 - } - - this.attackImpl$actuallyHurtFinalDamage = (float) this.attackImpl$actuallyHurtResult.event().finalDamage(); - this.attackImpl$actuallyHurtResult.damageAbsorbed().ifPresent(absorbed -> this.setAbsorptionAmount(oldAmount - absorbed)); - this.attackImpl$actuallyHurtBlockedDamage = this.attackImpl$actuallyHurtResult.damageBlockedByShield().orElse(0f); - } - } - - /** - * Set final damage after calling {@link LivingEntity#setAbsorptionAmount} in which we called the event - * !!NOTE that var9 is actually decompiled incorrectly!! - * It is NOT the final damage value instead the method parameter is mutated - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 0, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", - ordinal = 0, shift = At.Shift.AFTER), argsOnly = true) - protected float attackImpl$setFinalDamage(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtFinalDamage; - } - - /** - * Replay prevented - * {@link #shadow$hurtCurrentlyUsedShield} and {@link #shadow$blockUsingShield} - * {@link #shadow$hurtHelmet} - * {@link #shadow$hurtArmor} - * {@link ServerPlayer#awardStat} for {@link Stats#DAMAGE_RESISTED} and {@link Stats#DAMAGE_DEALT} - * from {@link LivingEntity#hurt} and #actuallyHurt - *

- * And capture inventory changes if needed - */ - protected void attackImpl$handlePostDamage() { - final var result = this.attackImpl$actuallyHurtResult; - if (result != null && !this.attackImpl$actuallyHurtCancelled) { - final var damageSource = result.source(); - result.damageToShield().ifPresent(dmg -> { - this.shadow$hurtCurrentlyUsedShield(dmg); - if (!damageSource.is(DamageTypeTags.IS_PROJECTILE)) { - if (damageSource.getDirectEntity() instanceof LivingEntity livingSource) { - this.shadow$blockUsingShield(livingSource); - } - } - }); - result.damageToHelmet().ifPresent(dmg -> - this.shadow$hurtHelmet(damageSource, dmg)); - result.damageToArmor().ifPresent(dmg -> - this.shadow$hurtArmor(damageSource, dmg)); - result.damageResisted().ifPresent(dmg -> { - if ((Object) this instanceof ServerPlayer player) { - player.awardStat(Stats.DAMAGE_RESISTED, Math.round(dmg * 10.0F)); - } else if (damageSource.getEntity() instanceof ServerPlayer player) { - player.awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(dmg * 10.0F)); - } - }); - - // Capture inventory change if we modified stacks - if ((result.damageToShield().isPresent() || - result.damageToHelmet().isPresent() || - result.damageToArmor().isPresent()) - && (Object) this instanceof Player player) { - PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); - player.inventoryMenu.broadcastChanges(); // capture - } - } - } - - /** - * Cleanup - * also reverts {@link #attackImpl$beforeActuallyHurt} - */ - @Inject(method = "actuallyHurt", at = @At("RETURN")) - protected void attackImpl$cleanupActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { - this.attackImpl$handlePostDamage(); - this.attackImpl$actuallyHurt = null; - this.attackImpl$actuallyHurtResult = null; - this.lastHurt = this.attackImpl$lastHurt; - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java new file mode 100644 index 00000000000..e2cbc64f6f8 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -0,0 +1,231 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.core.Holder; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; +import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; + +import java.util.Deque; +import java.util.LinkedList; + +@Mixin(value = LivingEntity.class, priority = 900) +public abstract class LivingEntityMixin_Damage extends EntityMixin implements LivingEntityBridge, TrackedDamageBridge { + + //@formatter:off + @Shadow protected abstract float shadow$getKnockback(final Entity entity, final DamageSource source); + @Shadow public abstract @NonNull ItemStack shadow$getWeaponItem(); + @Shadow public abstract ItemStack shadow$getItemBySlot(final EquipmentSlot slot); + @Shadow public abstract @Nullable MobEffectInstance shadow$getEffect(final Holder effect); + @Shadow public abstract double shadow$getAttributeValue(final Holder attribute); + // @formatter:on + + private final Deque damage$trackers = new LinkedList<>(); + private boolean damage$inventoryChanged = false; + + @Override + public final @Nullable SpongeDamageTracker damage$tracker() { + return this.damage$trackers.peekLast(); + } + + @Inject(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isSleeping()Z"), cancellable = true) + private void damage$firePreEvent(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + final SpongeDamageTracker tracker = SpongeDamageTracker.callDamagePreEvent((org.spongepowered.api.entity.Entity) this, source, this.damage$getContainerDamage(damage)); + if (tracker == null) { + cir.setReturnValue(false); + } else { + this.damage$trackers.addLast(tracker); + this.damage$setContainerDamage((float) tracker.preEvent().baseDamage()); + } + } + + @Inject(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V")) + private void damage$onHurtShield(final CallbackInfoReturnable cir) { + this.damage$inventoryChanged = true; + } + + @ModifyVariable(method = "hurtServer", argsOnly = true, at = @At("STORE"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V") + )) + private float damage$setDamageAfterShield(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return damage; + } + final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); + return step == null ? damage : (float) step.damageAfterChildren().getAsDouble(); + } + + @ModifyVariable(method = "hurtServer", at = @At("LOAD"), argsOnly = true, slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;FREEZE_HURTS_EXTRA_TYPES:Lnet/minecraft/tags/TagKey;"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;DAMAGES_HELMET:Lnet/minecraft/tags/TagKey;") + )) + private float damage$modifyBeforeFreezingBonus(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.FREEZING_BONUS, damage, tracker.preEvent().source(), this); + } + + @ModifyVariable(method = "hurtServer", at = @At("STORE"), argsOnly = true, slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;FREEZE_HURTS_EXTRA_TYPES:Lnet/minecraft/tags/TagKey;"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;DAMAGES_HELMET:Lnet/minecraft/tags/TagKey;") + )) + private float damage$modifyAfterFreezingBonus(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.FREEZING_BONUS, damage); + } + + @ModifyVariable(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V"), argsOnly = true) + private float damage$modifyBeforeHardHat(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.HARD_HAT, damage, this.shadow$getItemBySlot(EquipmentSlot.HEAD)); + } + + @WrapWithCondition(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private boolean damage$skipHardHat(final LivingEntity self, final DamageSource source, final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null || !tracker.isSkipped(DamageStepTypes.HARD_HAT)) { + this.damage$inventoryChanged = true; + return true; + } + return false; + } + + @ModifyVariable(method = "hurtServer", at = @At("STORE"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/WalkAnimationState;setSpeed(F)V") + )) + private float damage$modifyAfterHardHat(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.HARD_HAT, damage); + } + + @ModifyVariable(method = "getDamageAfterArmorAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtArmor(Lnet/minecraft/world/damagesource/DamageSource;F)V"), argsOnly = true) + private float damage$modifyBeforeArmor(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ARMOR, damage, this, Attributes.ARMOR_TOUGHNESS); + } + + @WrapWithCondition(method = "getDamageAfterArmorAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtArmor(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private boolean damage$skipArmor(final LivingEntity self, final DamageSource source, final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null || !tracker.isSkipped(DamageStepTypes.ARMOR)) { + this.damage$inventoryChanged = true; + return true; + } + return false; + } + + @ModifyVariable(method = "getDamageAfterArmorAbsorb", at = @At("STORE"), argsOnly = true) + private float damage$modifyAfterArmor(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.ARMOR, damage); + } + + @ModifyVariable(method = "getDamageAfterMagicAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getEffect(Lnet/minecraft/core/Holder;)Lnet/minecraft/world/effect/MobEffectInstance;"), argsOnly = true) + private float damage$modifyBeforeDefensivePotionEffect(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.DEFENSIVE_POTION_EFFECT, damage, this.shadow$getEffect(MobEffects.DAMAGE_RESISTANCE)); + } + + @ModifyVariable(method = "getDamageAfterMagicAbsorb", at = @At("STORE"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getEffect(Lnet/minecraft/core/Holder;)Lnet/minecraft/world/effect/MobEffectInstance;"), + to = @At(value = "FIELD", target = "Lnet/minecraft/stats/Stats;DAMAGE_RESISTED:Lnet/minecraft/resources/ResourceLocation;"))) + private float damage$modifyAfterDefensivePotionEffect(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.DEFENSIVE_POTION_EFFECT, damage); + } + + @WrapOperation(method = "getDamageAfterMagicAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/CombatRules;getDamageAfterMagicAbsorb(FF)F")) + private float damage$modifyBeforeAndAfterArmorEnchantment(float damage, final float protection, final Operation operation) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return operation.call(damage, protection); + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.ARMOR_ENCHANTMENT, this); + damage = (float) step.applyChildrenBefore(damage); + if (!step.isSkipped()) { + damage = operation.call(damage, protection); + } + return (float) step.applyChildrenAfter(damage); + } + + @WrapWithCondition(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;playHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V")) + private boolean damage$onHurtSound(final LivingEntity self, final DamageSource source) { + return this.bridge$vanishState().createsSounds(); + } + + @WrapWithCondition(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) + private boolean damage$onMakeSound(final LivingEntity self, final SoundEvent sound) { + return this.bridge$vanishState().createsSounds(); + } + + @Inject(method = "hurtServer", at = @At("RETURN"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isSleeping()Z", shift = At.Shift.AFTER) + )) + private void damage$removeTrackerAndCaptureInventory(final CallbackInfoReturnable cir) { + this.damage$trackers.removeLast(); + + if (this.damage$inventoryChanged) { + this.damage$inventoryChanged = false; + + if ((Object) this instanceof Player player) { + PhaseTracker.getWorldInstance((ServerLevel) player.level()).getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); + player.inventoryMenu.broadcastChanges(); + } + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Attack_Impl.java deleted file mode 100644 index 323ee6c6143..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Attack_Impl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.entity; - -import net.minecraft.world.entity.LivingEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.common.util.DamageEventUtil; - -// Forge and Vanilla -@Mixin(value = LivingEntity.class, priority = 900) -public class LivingEntityMixin_Shared_Attack_Impl { - - protected DamageEventUtil.DamageEventResult attackImpl$actuallyHurtResult; - - /** - * Set absorbed damage after calling {@link LivingEntity#setAbsorptionAmount} in which we called the event - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 2, - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", ordinal = 0)), - at = @At(value = "STORE", ordinal = 0)) - public float attackImpl$setAbsorbed(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtResult.damageAbsorbed().orElse(0f); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java new file mode 100644 index 00000000000..206e6a53ee4 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; + +// Forge and Vanilla +@Mixin(value = LivingEntity.class, priority = 900) +public abstract class LivingEntityMixin_Shared_Damage implements TrackedDamageBridge { + + @ModifyVariable(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I"), argsOnly = true) + private float damage$setBaseDamage(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : (float) tracker.preEvent().baseDamage(); + } + + @ModifyVariable(method = "actuallyHurt", at = @At("STORE"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterMagicAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getAbsorptionAmount()F", ordinal = 0))) + private float damage$modifyBeforeAbsorption(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ABSORPTION, damage, this); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setAbsorptionAmount(F)V", ordinal = 0)) + private boolean damage$skipAbsorption(final LivingEntity self, final float absorption) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V")) + private boolean damage$skipAbsorptionStat(final ServerPlayer self, final ResourceLocation stat, final int amount) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java new file mode 100644 index 00000000000..0c35598a428 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java @@ -0,0 +1,114 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; + +import java.util.Deque; +import java.util.LinkedList; + +@Mixin(Mob.class) +public abstract class MobMixin_Attack extends LivingEntityMixin_Damage implements TrackedAttackBridge { + private final Deque attack$trackers = new LinkedList<>(); + + @Override + public final @Nullable SpongeAttackTracker attack$tracker() { + return this.attack$trackers.peekLast(); + } + + @Inject( + method = "doHurtTarget", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;modifyDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), + cancellable = true, + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void attack$firePreEvent(final ServerLevel level, final Entity target, final CallbackInfoReturnable cir, + final float damage, final ItemStack weapon, final DamageSource source) { + final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); + if (tracker == null) { + cir.setReturnValue(false); + } else { + this.attack$trackers.addLast(tracker); + } + } + + @WrapOperation(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) + private float attack$modifyBeforeAndAfterWeaponBonus(final Item item, final Entity target, final float originalDamage, final DamageSource source, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker == null) { + return operation.call(item, target, originalDamage, source); + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.WEAPON_BONUS, tracker.weaponSnapshot()); + float damage = (float) step.applyChildrenBefore(originalDamage); + if (!step.isSkipped()) { + damage += operation.call(item, target, damage, source); + } + return (float) step.applyChildrenAfter(damage) - originalDamage; + } + + @WrapOperation(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private boolean attack$firePostEvent(final Entity target, final ServerLevel level, final DamageSource source, float damage, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker != null) { + final float knockbackModifier = this.shadow$getKnockback(target, source); + if (tracker.callAttackPostEvent((org.spongepowered.api.entity.Entity) target, source, damage, knockbackModifier)) { + return false; + } + damage = (float) tracker.postEvent().finalDamage(); + } + return operation.call(target, level, source, damage); + } + + @WrapOperation(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) + private float attack$knockbackModifier(final Mob self, final Entity target, final DamageSource source, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? operation.call(self, target, source) : (float) tracker.postEvent().knockbackModifier(); + } + + @Inject(method = "doHurtTarget", at = @At("RETURN"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;modifyDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;F)F", shift = At.Shift.AFTER))) + private void attack$removeTracker(CallbackInfoReturnable cir) { + this.attack$trackers.removeLast(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java deleted file mode 100644 index 9de678c164e..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack_Impl.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.entity; - -import net.minecraft.core.Holder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.ai.attributes.Attribute; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.util.DamageEventUtil; - -import java.util.ArrayList; - -@Mixin(Mob.class) -public abstract class MobMixin_Attack_Impl extends LivingEntityMixin_Attack_Impl { - - private double impl$hurtTargetDamage; - private double impl$knockbackModifier; - - @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Mob;getAttributeValue(Lnet/minecraft/core/Holder;)D")) - private double attackImpl$onCanGrief(final Mob instance, final Holder attackDamageAttribute) { - this.impl$hurtTargetDamage = instance.getAttributeValue(attackDamageAttribute); - return this.impl$hurtTargetDamage; - } - - @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - private boolean attackImpl$onCanGrief(final net.minecraft.world.entity.Entity targetEntity, final ServerLevel level, final DamageSource damageSource, final float mcFinalDamage) { - final var thisEntity = (Mob) (Object) this; - - float knockbackModifier = this.shadow$getKnockback(targetEntity, damageSource); - - var attack = new DamageEventUtil.Attack<>(thisEntity, targetEntity, this.shadow$getWeaponItem(), damageSource, 1, (float) this.impl$hurtTargetDamage, new ArrayList<>()); - if (this.shadow$level() instanceof ServerLevel) { - // baseDamage = EnchantmentHelper.modifyDamage(level, thisEntity.getWeaponItem(), targetEntity, damageSource, baseDamage);// - attack.functions().addAll(DamageEventUtil.createAttackEnchantmentFunction(attack.weapon(), targetEntity, damageSource)); - } - - final var event = DamageEventUtil.callMobAttackEvent(attack, knockbackModifier); - this.impl$knockbackModifier = event.knockbackModifier(); - - return targetEntity.hurtServer(level, damageSource, (float) event.finalOutputDamage()); - } - - @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/Mob;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) - private float attackImpl$onCanGrief(final Mob instance, final net.minecraft.world.entity.Entity entity, final DamageSource damageSource) { - return (float) this.impl$knockbackModifier; - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java index 65061c79398..e544f39038f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EndCrystalMixin.java @@ -39,10 +39,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.world.entity.boss.enderdragon.EndCrystalBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; import org.spongepowered.common.util.Constants; -import org.spongepowered.common.util.DamageEventUtil; import java.util.Optional; @@ -92,8 +92,8 @@ public abstract class EndCrystalMixin extends EntityMixin implements ExplosiveBr @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;remove(Lnet/minecraft/world/entity/Entity$RemovalReason;)V")) - private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((org.spongepowered.api.entity.Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java index 7ca9cfd76d5..0788bb811e1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.core.world.entity.decoration; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageTypes; @@ -32,6 +34,8 @@ import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.level.gameevent.GameEvent; import org.objectweb.asm.Opcodes; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.event.entity.DamageEntityEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @@ -43,29 +47,27 @@ import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin; -import org.spongepowered.common.util.DamageEventUtil; @Mixin(ArmorStand.class) public abstract class ArmorStandMixin extends LivingEntityMixin { // @formatter:off - @Shadow protected abstract void shadow$causeDamage(ServerLevel level, DamageSource damageSource, float damage); // damageArmorStand - @Shadow protected abstract void shadow$brokenByPlayer(final ServerLevel $$0, final DamageSource $$1); - + @Shadow protected abstract void shadow$causeDamage(ServerLevel level, DamageSource source, float damage); // damageArmorStand + @Shadow protected abstract void shadow$brokenByPlayer(final ServerLevel level, final DamageSource source); // @formatter:on /** * The return value is set to false if the entity should not be completely destroyed. */ private void impl$callDamageBeforeKill(final DamageSource source, final CallbackInfoReturnable cir) { - var event = DamageEventUtil.callSimpleDamageEntityEvent(source, (ArmorStand) (Object) this, Math.max(1000, this.shadow$getHealth())); - if (event.isCancelled()) { + final DamageEntityEvent.Post event = SpongeDamageTracker.callDamageEvents((Entity) this, source, this.shadow$getHealth()); + if (event == null) { cir.setReturnValue(false); - } - if (event.finalDamage() < this.shadow$getHealth()) { // Deal reduced damage? + } else if (event.finalDamage() < this.shadow$getHealth()) { // Deal reduced damage? this.shadow$causeDamage((ServerLevel) this.shadow$level(), source, (float) event.finalDamage()); cir.setReturnValue(false); } @@ -78,7 +80,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;BYPASSES_INVULNERABILITY:Lnet/minecraft/tags/TagKey;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V", ordinal = 0)) - private void impl$fireDamageEventOutOfWorld(final ServerLevel level, final DamageSource source, final float $$1, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventOutOfWorld(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } @@ -88,7 +90,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_EXPLOSION:Lnet/minecraft/tags/TagKey;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByAnything(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$fireDamageEventExplosion(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventExplosion(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } @@ -97,13 +99,13 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * IGNITES_ARMOR_STANDS + isOnFire * BURNS_ARMOR_STANDS + health > 0.5 */ - @Redirect(method = "hurtServer", + @WrapOperation(method = "hurtServer", slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IGNITES_ARMOR_STANDS:Lnet/minecraft/tags/TagKey;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;causeDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void impl$fireDamageEventDamage(final ArmorStand self, final ServerLevel level, final DamageSource source, final float amount) { - var event = DamageEventUtil.callSimpleDamageEntityEvent(source, self, amount); - if (!event.isCancelled()) { - this.shadow$causeDamage(level, source, (float) event.finalDamage()); + private void impl$fireDamageEventDamage(final ArmorStand self, final ServerLevel level, final DamageSource source, final float damage, final Operation operation) { + final DamageEntityEvent.Post event = SpongeDamageTracker.callDamageEvents((Entity) this, source, damage); + if (event != null) { + operation.call(self, level, source, (float) event.finalDamage()); } } @@ -113,7 +115,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { @Inject(method = "hurtServer", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSource;isCreativePlayer()Z")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;playBrokenSound()V"), cancellable = true) - private void impl$fireDamageEventCreativePunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventCreativePunch(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } @@ -123,17 +125,17 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { @Inject(method = "hurtServer", cancellable = true, slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;lastHit:J", opcode = Opcodes.GETFIELD)), at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;broadcastEntityEvent(Lnet/minecraft/world/entity/Entity;B)V")) - private void impl$fireDamageEventFirstPunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventFirstPunch(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { // While this doesn't technically "damage" the armor stand, it feels like damage in other respects, so fire an event. - var event = DamageEventUtil.callSimpleDamageEntityEvent(source, (ArmorStand) (Object) this, 0); - if (event.isCancelled()) { + final DamageEntityEvent.Post event = SpongeDamageTracker.callDamageEvents((Entity) this, source, 0); + if (event == null) { cir.setReturnValue(false); } } @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$beforeBrokenByPlayer(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfoReturnable cir) { + private void impl$beforeBrokenByPlayer(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { if (ShouldFire.DESTRUCT_ENTITY_EVENT && !((LevelBridge) this.shadow$level()).bridge$isFake()) { final var event = SpongeCommonEventFactory.callDestructEntityEventDeath((ArmorStand) (Object) this, null); if (event.isCancelled()) { @@ -145,10 +147,9 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - public void impl$onBrokenByPlayer(final ArmorStand instance, final ServerLevel $$0, final DamageSource $$1) - { - try (final EffectTransactor ignored = PhaseTracker.getWorldInstance($$0).getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { - this.shadow$brokenByPlayer($$0, $$1); + public void impl$onBrokenByPlayer(final ArmorStand self, final ServerLevel level, final DamageSource source) { + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(level).getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { + this.shadow$brokenByPlayer(level, source); } } @@ -157,21 +158,21 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { */ @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void impl$fireDamageEventSecondPunch(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { + private void impl$fireDamageEventSecondPunch(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { this.impl$callDamageBeforeKill(source, cir); } /** - * To avoid a loop between {@link #kill} and {@link ArmorStand#hurt}, - * we make sure that any killing within the {@link ArmorStand#hurt} + * To avoid a loop between {@link #kill} and {@link ArmorStand#hurtServer}, + * we make sure that any killing within the {@link ArmorStand#hurtServer} * method calls this instead of the {@link Overwrite} * - * @param target the killed stand + * @param self the killed stand */ @Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V")) - private void impl$actuallyKill(final ArmorStand target, final ServerLevel level) { - target.remove(RemovalReason.KILLED); - target.gameEvent(GameEvent.ENTITY_DIE); + private void impl$actuallyKill(final ArmorStand self, final ServerLevel level) { + self.remove(RemovalReason.KILLED); + self.gameEvent(GameEvent.ENTITY_DIE); } /** @@ -179,12 +180,12 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * we make sure that any killing within the {@link #shadow$causeDamage} * method calls this instead of the {@link Overwrite} * - * @param target the killed stand + * @param self the killed stand */ @Redirect(method = "causeDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill(Lnet/minecraft/server/level/ServerLevel;)V")) - private void impl$actuallyKill2(final ArmorStand target, final ServerLevel level) { - target.remove(RemovalReason.KILLED); - target.gameEvent(GameEvent.ENTITY_DIE); + private void impl$actuallyKill2(final ArmorStand self, final ServerLevel level) { + self.remove(RemovalReason.KILLED); + self.gameEvent(GameEvent.ENTITY_DIE); } /** @@ -192,7 +193,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { * @reason EntityArmorStand "simplifies" this method to simply call {@link * #shadow$remove(RemovalReason)}. However, this ignores our custom event. * Instead, delegate to the superclass causing it to use - * {@link ArmorStand#hurt(DamageSource, float)} with {@link DamageTypes#GENERIC_KILL} + * {@link ArmorStand#hurtServer} with {@link DamageTypes#GENERIC_KILL} * * This needs to be reimplemented in {@link #impl$actuallyKill}! */ diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java index 763e0ad5bc9..8ae562e80a5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/BlockAttachedEntityMixin.java @@ -26,16 +26,16 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.BlockAttachedEntity; +import org.spongepowered.api.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; -import org.spongepowered.common.util.DamageEventUtil; @Mixin(BlockAttachedEntity.class) public abstract class BlockAttachedEntityMixin extends EntityMixin { @@ -57,8 +57,8 @@ public abstract class BlockAttachedEntityMixin extends EntityMixin { @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;kill(Lnet/minecraft/server/level/ServerLevel;)V")) - private void attackImpl$postEventOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attackImpl$postEventOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java index c09f61c3b90..0ffd03487b8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ItemFrameMixin.java @@ -26,21 +26,20 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; +import org.spongepowered.api.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.util.DamageEventUtil; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @Mixin(net.minecraft.world.entity.decoration.ItemFrame.class) public abstract class ItemFrameMixin extends HangingEntityMixin { @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/decoration/ItemFrame;dropItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Z)V")) - private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, - final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + target = "Lnet/minecraft/world/entity/decoration/ItemFrame;dropItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Z)V")) + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index d570c63db57..2d138fd14f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -26,10 +26,10 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.Item; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.SpongeEventFactory; @@ -47,10 +47,10 @@ import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.data.provider.entity.ItemData; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; import org.spongepowered.common.util.Constants; -import org.spongepowered.common.util.DamageEventUtil; @Mixin(ItemEntity.class) public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityBridge { @@ -146,9 +146,8 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;markHurt()V")) - private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, - final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java new file mode 100644 index 00000000000..c58ded67972 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -0,0 +1,309 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity.player; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.api.event.entity.AttackEntityEvent; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin_Damage; + +import java.util.Deque; +import java.util.LinkedList; + +@SuppressWarnings("ConstantConditions") +@Mixin(value = Player.class, priority = 900) +public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implements TrackedAttackBridge { + + //@formatter:off + @Shadow protected abstract float shadow$getEnchantedDamage(final Entity target, final float damage, final DamageSource source); + @Shadow @Final public InventoryMenu inventoryMenu; + //@formatter:on + + private final Deque attack$trackers = new LinkedList<>(); + + @Override + public final @Nullable SpongeAttackTracker attack$tracker() { + return this.attack$trackers.peekLast(); + } + + @Inject(method = "attack", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0)) + private void attack$firePreEvent(final Entity target, final CallbackInfo ci, final float damage, final ItemStack weapon, final DamageSource source) { + final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); + if (tracker == null) { + ci.cancel(); + } else { + this.attack$trackers.addLast(tracker); + } + } + + @ModifyVariable(method = "attack", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0)) + private float attack$setBaseDamage(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : (float) tracker.preEvent().baseDamage(); + } + + @ModifyExpressionValue(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F")) + private float attack$captureAttackStrength(final float value) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker != null) { + tracker.setAttackStrength(value); + } + return value; + } + + @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 0, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + )) + private float attack$modifyBeforeBaseCooldown(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.BASE_COOLDOWN, damage, this); + } + + @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + )) + private float attack$modifyAfterBaseCooldown(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.BASE_COOLDOWN, damage); + } + + @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 1, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + )) + private float attack$modifyBeforeEnchantmentCooldown(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ENCHANTMENT_COOLDOWN, damage, tracker.weaponSnapshot()); + } + + @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 1, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + )) + private float attack$modifyAfterEnchantmentCooldown(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.ENCHANTMENT_COOLDOWN, damage); + } + + @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 0), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"))) + private void attack$captureStrongSprint(final Entity target, final CallbackInfo ci) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker != null) { + tracker.setStrongSprint(true); + } + } + + @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) + private float attack$modifyBeforeAndAfterWeaponBonus(final Item item, final Entity target, final float originalDamage, final DamageSource source, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker == null) { + return operation.call(item, target, originalDamage, source); + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.WEAPON_BONUS, tracker.weaponSnapshot()); + float damage = (float) step.applyChildrenBefore(originalDamage); + if (!step.isSkipped()) { + damage += operation.call(item, target, damage, source); + } + return (float) step.applyChildrenAfter(damage) - originalDamage; + } + + @ModifyVariable(method = "attack", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") + )) + private float attack$modifyBeforeCriticalHit(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.CRITICAL_HIT, damage, this); + } + + @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") + )) + private float attack$modifyAfterCriticalHit(final float damage) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? damage : tracker.endStep(DamageStepTypes.CRITICAL_HIT, damage); + } + + @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F") + )) + private boolean attack$firePostEvent(final Entity target, final DamageSource source, float damage, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + if (tracker != null) { + final float knockbackModifier = this.shadow$getKnockback(target, source) + (tracker.isStrongSprint() ? 1.0F : 0.0F); + if (tracker.callAttackPostEvent((org.spongepowered.api.entity.Entity) target, source, damage, knockbackModifier)) { + return false; + } + damage = (float) tracker.postEvent().finalDamage(); + } + return operation.call(target, source, damage); + } + + @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) + private float attack$knockbackModifier(final Player self, final Entity target, final DamageSource source, final Operation operation) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null ? operation.call(self, target, source) : ((float) tracker.postEvent().knockbackModifier() - (tracker.isStrongSprint() ? 1.0F : 0.0F)); + } + + @WrapWithCondition(method = "attack", + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) + private boolean attack$preventSound(final Level level, final Player player, final double x, final double y, final double z, + final SoundEvent sound, final SoundSource source, final float volume, final float pitch) { + final SpongeAttackTracker tracker = this.attack$tracker(); + return tracker == null || !tracker.postEvent().isCancelled(); + } + + @Inject(method = "attack", at = @At("RETURN"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0) + )) + private void attack$removeTracker(CallbackInfo ci) { + this.attack$trackers.removeLast(); + } + + @WrapOperation(method = "attack", + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D")) + private double sweepAttack$fireEvents(final Player self, final Entity sweepTarget, final Operation operation) { + final double distanceSquared = operation.call(self, sweepTarget); + if (!(distanceSquared < this.attack$interactionRangeSquared())) { + return distanceSquared; + } + + final SpongeAttackTracker mainTracker = this.attack$tracker(); + if (mainTracker == null) { + return distanceSquared; + } + + final AttackEntityEvent.Post mainEvent = mainTracker.postEvent(); + DamageSource source = (DamageSource) mainEvent.source(); + float damage = (float) (mainEvent.finalDamage() - mainTracker.damageAfter(DamageStepTypes.ENCHANTMENT_COOLDOWN)); + + final SpongeAttackTracker sweepTracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) sweepTarget, source, damage, mainTracker.weapon()); + if (sweepTracker == null) { + return Double.MAX_VALUE; + } + + this.attack$trackers.addLast(sweepTracker); + damage = (float) sweepTracker.preEvent().baseDamage(); + + // In vanilla, this step is outside the loop, but we move it to here so it can be modified per target + SpongeDamageStep step = sweepTracker.newStep(DamageStepTypes.SWEEPING, sweepTracker.weaponSnapshot()); + damage = (float) step.applyChildrenBefore(damage); + if (!step.isSkipped()) { + damage = 1.0F + (float) this.shadow$getAttributeValue(Attributes.SWEEPING_DAMAGE_RATIO) * damage; + } + damage = (float) step.applyChildrenAfter(damage); + + damage = this.shadow$getEnchantedDamage(sweepTarget, damage, source); + + step = sweepTracker.newStep(DamageStepTypes.ENCHANTMENT_COOLDOWN, sweepTracker.weaponSnapshot()); + damage = (float) step.applyChildrenBefore(damage); + if (!step.isSkipped()) { + damage *= mainTracker.attackStrength(); + } + damage = (float) step.applyChildrenAfter(damage); + + if (sweepTracker.callAttackPostEvent((org.spongepowered.api.entity.Entity) sweepTarget, source, damage, 0.4F)) { + this.attack$trackers.removeLast(); + return Double.MAX_VALUE; + } + + return distanceSquared; + } + + @WrapOperation(method = "attack", + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) + private float sweepAttack$cancelEnchantedDamage(final Player self, final Entity sweepTarget, final float damage, final DamageSource source, final Operation operation) { + return damage; // We already did it above + } + + @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V"))) + private void sweepAttack$knockbackModifier(final LivingEntity sweepTarget, double modifier, final double dirX, final double dirZ, final Operation operation) { + final SpongeAttackTracker sweepTracker = this.attack$tracker(); + if (sweepTracker != null) { + modifier = sweepTracker.postEvent().knockbackModifier(); + } + operation.call(sweepTarget, modifier, dirX, dirZ); + } + + @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V"), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"))) + private void sweepAttack$finalDamage(final LivingEntity sweepTarget, final DamageSource source, float damage, final Operation operation) { + final SpongeAttackTracker sweepTracker = this.attack$tracker(); + if (sweepTracker != null) { + damage = (float) sweepTracker.postEvent().finalDamage(); + } + operation.call(sweepTarget, source, damage); + this.attack$trackers.removeLast(); + } + + @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V", shift = At.Shift.AFTER)) + private void attack$captureInventoryChange(final CallbackInfo ci) { + PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext().getTransactor().logPlayerInventoryChange((Player) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD); + this.inventoryMenu.broadcastChanges(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java deleted file mode 100644 index 47f8ea08f90..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.entity.player; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.event.entity.AttackEntityEvent; -import org.spongepowered.api.event.impl.entity.AbstractModifierEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyConstant; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin_Attack_Impl; -import org.spongepowered.common.util.DamageEventUtil; - -import java.util.ArrayList; -import java.util.Map; - -@SuppressWarnings("ConstantConditions") -@Mixin(value = Player.class, priority = 900) -public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_Impl { - - //@formatter:off - @Shadow @Final public InventoryMenu inventoryMenu; - @Shadow public abstract float shadow$getAttackStrengthScale(final float $$0); - - //@formatter:on - - private void impl$playAttackSound(Player thisPlayer, SoundEvent sound) { - if (this.bridge$vanishState().createsSounds()) { - thisPlayer.level().playSound(null, thisPlayer.getX(), thisPlayer.getY(), thisPlayer.getZ(), sound, thisPlayer.getSoundSource()); - } - } - - protected DamageEventUtil.Attack attackImpl$attack; - protected AttackEntityEvent attackImpl$attackEvent; - protected Map attackImpl$finalDamageAmounts; - - protected int attackImpl$attackStrengthTicker; - protected boolean attackImpl$isStrongSprintAttack; - - /** - * Cleanup - */ - @Inject(method = "attack", at = @At("RETURN")) - protected void attackImpl$onReturnCleanup(final Entity $$0, final CallbackInfo ci) { - this.attackImpl$attack = null; - this.attackImpl$attackEvent = null; - this.attackImpl$finalDamageAmounts = null; - } - - /** - * Captures the base damage for the {@link AttackEntityEvent} in {@link #attackImpl$attack} - * and the {@link #attackStrengthTicker} in case we need to roll it back. - * Reset {@link #attackImpl$isStrongSprintAttack} - */ - @Inject(method = "attack", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", shift = At.Shift.BEFORE)) - protected void attackImpl$captureAttackStart(final Entity target, final CallbackInfo ci, final float baseDamage, final ItemStack weapon, final DamageSource source) { - final var strengthScale = this.shadow$getAttackStrengthScale(0.5F); - this.attackImpl$attack = new DamageEventUtil.Attack<>((Player) (Object) this, target, weapon, source, strengthScale, baseDamage, new ArrayList<>()); - this.attackImpl$attackStrengthTicker = this.attackStrengthTicker; - this.attackImpl$isStrongSprintAttack = false; - } - - /** - * Captures the enchantment damage calculations as functions - */ - @Inject(method = "attack", at = @At(value = "INVOKE", ordinal = 0, - target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) - protected void attackImpl$enchanttDamageFunc(final Entity $$0, final CallbackInfo ci) { - // This is overridden in ServerPlayerMixin_Attack_Impl since enchantments can only be calculated on the - // server worlds. - } - - - /** - * Captures the attack-strength damage scaling as a function - */ - @Inject(method = "attack", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V")) - protected void attackImpl$attackStrengthScalingDamageFunc(final Entity $$0, final CallbackInfo ci) { - // damage *= 0.2F + attackStrength * attackStrength * 0.8F; - final var strengthScaleFunc = DamageEventUtil.provideCooldownAttackStrengthFunction((Player) (Object) this, this.attackImpl$attack.strengthScale()); - this.attackImpl$attack.functions().add(strengthScaleFunc); - } - - /** - * Prevents the {@link SoundEvents#PLAYER_ATTACK_KNOCKBACK} from playing before the event. - * Captures if {@link #attackImpl$isStrongSprintAttack} for later - */ - @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 0), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - protected void attackImpl$preventSprintingAttackSound(final Level instance, final Player $$0, final double $$1, final double $$2, final double $$3, final SoundEvent $$4, - final SoundSource $$5, final float $$6, final float $$7) { - // prevent sound - this.attackImpl$isStrongSprintAttack = true; - } - - /** - * Captures the weapon bonus damage as a function - */ - @Inject(method = "attack", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) - protected void attackImpl$attackDamageFunc(final Entity $$0, final CallbackInfo ci) { - // damage += weaponItem.getItem().getAttackDamageBonus(targetEntity, damage, damageSource); - final var bonusDamageFunc = DamageEventUtil.provideWeaponAttackDamageBonusFunction(this.attackImpl$attack.target(), this.attackImpl$attack.weapon(), this.attackImpl$attack.dmgSource()); - this.attackImpl$attack.functions().add(bonusDamageFunc); - } - - /** - * Capture damageSource for sweep attacks event later - * Calculate knockback earlier than vanilla for event - * call the AttackEntityEvent - * Play prevented sound from {@link #attackImpl$preventSprintingAttackSound} - * returns false if canceled, appearing for vanilla as an invulnerable target. {@link #attackImpl$onNoDamageSound} - */ - @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - protected boolean attackImpl$onHurt(final Entity targetEntity, final DamageSource damageSource, final float mcDamage) { - - float knockbackModifier = this.shadow$getKnockback(targetEntity, damageSource) + (this.attackImpl$isStrongSprintAttack ? 1.0F : 0.0F); - this.attackImpl$attackEvent = DamageEventUtil.callPlayerAttackEntityEvent(this.attackImpl$attack, knockbackModifier); - - if (this.attackImpl$attackEvent.isCancelled()) { - // TODO this is actually not really doing anything because a ServerboundSwingPacket also resets it immediatly after - this.attackStrengthTicker = this.attackImpl$attackStrengthTicker; // Reset to old value - return false; - } - - this.attackImpl$finalDamageAmounts = AbstractModifierEvent.finalAmounts(this.attackImpl$attackEvent.originalDamage(), this.attackImpl$attackEvent.modifiers()); - - if (this.attackImpl$isStrongSprintAttack) { - // Play prevented sprint attack sound - this.impl$playAttackSound((Player) (Object) this, SoundEvents.PLAYER_ATTACK_KNOCKBACK); - } - - if (targetEntity.level() instanceof ServerLevel sl) { - return targetEntity.hurtServer(sl, damageSource, (float) this.attackImpl$attackEvent.finalOutputDamage()); - } - - return targetEntity.hurtClient(damageSource); - } - - /** - * Set enchantment damage with value from event - */ - @ModifyVariable(method = "attack", ordinal = 1, - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V", ordinal = 0)), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) - protected float attackImpl$enchentmentDamageFromEvent(final float enchDmg) { - return this.attackImpl$finalDamageAmounts.getOrDefault(ResourceKey.minecraft("attack_enchantment"), 0.0).floatValue(); - } - - /** - * Redirects Player#getKnockback to the attack event value - */ - @Redirect(method = "attack", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F")) - protected float attackImpl$sweepHook(final Player instance, final Entity entity, final DamageSource damageSource) { - return this.attackImpl$attackEvent.knockbackModifier(); - } - - @ModifyConstant(method = "attack", constant = @Constant(floatValue = 1.0F), slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getKnockback(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)F"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) - ) - private float attackImpl$noDoubleAddKb(final float constant) { - return 0.0F; - } - - /** - * Prevents the {@link SoundEvents#PLAYER_ATTACK_NODAMAGE} when event was canceled - */ - @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - protected void attackImpl$onNoDamageSound( - final Level instance, final Player $$0, final double $$1, final double $$2, final double $$3, - final SoundEvent $$4, final SoundSource $$5, final float $$6, final float $$7 - ) { - if (!this.attackImpl$attackEvent.isCancelled()) { - this.impl$playAttackSound((Player) (Object) this, SoundEvents.PLAYER_ATTACK_NODAMAGE); - } - } - - /** - * Call Sweep Attack Events - */ - @WrapOperation(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D")) - protected double attackImpl$beforeSweepHurt(final Player instance, final Entity entity, final Operation original) { - return original.call(instance, entity); - } - - /** - * Redirect Player#getEnchantedDamage to sweep event value - */ - @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) - protected float attackImpl$beforeSweepHurt(final Player instance, final Entity $$0, final float $$1, final DamageSource $$2) { - return (float) this.attackImpl$attackEvent.finalOutputDamage(); - } - - /** - * Redirect {@link LivingEntity#knockback} to use modified event knockback - */ - @Redirect(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) - protected void attackImpl$modifyKnockback(final LivingEntity instance, final double $$0, final double $$1, final double $$2) { - instance.knockback($$0 * this.attackImpl$attackEvent.knockbackModifier(), $$1, $$2); - } - - /** - * Captures inventory changes - */ - @Redirect(method = "attack", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V")) - protected void attackImpl$causeInventoryCapture(final Player instance, final InteractionHand interactionHand, final ItemStack stack) { - instance.setItemInHand(interactionHand, stack); - - // Capture... - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext(); - final TransactionalCaptureSupplier transactor = context.getTransactor(); - transactor.logPlayerInventoryChange(instance, PlayerInventoryTransaction.EventCreator.STANDARD); - this.inventoryMenu.broadcastChanges(); - } - - @Inject(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F")) - protected void attackImpl$startActuallyHurt(final ServerLevel level, DamageSource damageSource, float originalDamage, CallbackInfo ci) { - // TODO check for direct call? - this.attackImpl$actuallyHurt = new DamageEventUtil.ActuallyHurt((LivingEntity) (Object) this, new ArrayList<>(), damageSource, originalDamage); - } - - /** - * Set final damage after calling {@link Player#setAbsorptionAmount} in which we called the event - * !!NOTE that var7 is actually decompiled incorrectly!! - * It is NOT the final damage value instead the method parameter is mutated - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 0, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V", - shift = At.Shift.AFTER), argsOnly = true) - protected float attackImpl$setFinalDamage(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtFinalDamage; - } - - /** - * Cleanup - */ - @Inject(method = "actuallyHurt", at = @At("RETURN")) - protected void attackImpl$afterActuallyHurt(final ServerLevel level, final DamageSource $$0, final float $$1, final CallbackInfo ci) { - this.attackImpl$handlePostDamage(); - this.attackImpl$actuallyHurt = null; - this.attackImpl$actuallyHurtResult = null; - } - - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java new file mode 100644 index 00000000000..1dd64ca7ac7 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java @@ -0,0 +1,63 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.entity.player; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin_Damage; + +// Forge and Vanilla +@Mixin(value = Player.class, priority = 900) +public abstract class PlayerMixin_Shared_Damage extends LivingEntityMixin_Damage { + + @ModifyVariable(method = "actuallyHurt", at = @At("STORE"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getDamageAfterMagicAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAbsorptionAmount()F", ordinal = 0))) + private float damage$modifyBeforeAbsorption(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null ? damage : tracker.startStep(DamageStepTypes.ABSORPTION, damage, this); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V")) + private boolean damage$skipAbsorption(final Player self, final float absorption) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } + + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) + private boolean damage$skipAbsorptionStat(final Player self, final ResourceLocation stat, final int amount) { + final SpongeDamageTracker tracker = this.damage$tracker(); + return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java index 3efc4c01c22..79649ea2e18 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ShulkerBulletMixin.java @@ -26,9 +26,9 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.ShulkerBullet; import net.minecraft.world.phys.HitResult; +import org.spongepowered.api.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -36,7 +36,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; -import org.spongepowered.common.util.DamageEventUtil; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @Mixin(ShulkerBullet.class) public abstract class ShulkerBulletMixin extends ProjectileMixin { @@ -53,8 +53,8 @@ private void onBulletHitBlock(final HitResult result, final CallbackInfo ci) { @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ShulkerBullet;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void attackImpl$onAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index bde38fc5333..7a42f72ca64 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -26,7 +26,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.vehicle.MinecartTNT; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; @@ -40,9 +39,9 @@ import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.explosives.FusedExplosiveBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.Constants; -import org.spongepowered.common.util.DamageEventUtil; import java.util.Optional; @@ -150,8 +149,8 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/MinecartTNT;explode(Lnet/minecraft/world/damagesource/DamageSource;D)V")) - private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((Entity) (Object) this, source, amount).isCancelled()) { + private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((org.spongepowered.api.entity.Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java index de39fb029c3..3ea934f0d1a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java @@ -27,21 +27,21 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.vehicle.VehicleEntity; +import org.spongepowered.api.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; -import org.spongepowered.common.util.DamageEventUtil; @Mixin(VehicleEntity.class) public abstract class VehicleEntityMixin extends EntityMixin { @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/VehicleEntity;shouldSourceDestroy(Lnet/minecraft/world/damagesource/DamageSource;)Z")) - private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, - final float amount, final CallbackInfoReturnable cir) { - if (DamageEventUtil.callOtherAttackEvent((net.minecraft.world.entity.Entity) (Object) this, source, amount).isCancelled()) { + private void attack$onHurt(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { + if (SpongeDamageTracker.callDamageEvents((Entity) this, source, damage) == null) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin_Attack.java new file mode 100644 index 00000000000..95dd69cfd9b --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/enchantment/EnchantmentMixin_Attack.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.item.enchantment; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.ConditionalEffect; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect; +import org.apache.commons.lang3.mutable.MutableFloat; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.item.util.ItemStackUtil; + +import java.util.List; + +@Mixin(Enchantment.class) +public abstract class EnchantmentMixin_Attack { + + @WrapOperation(method = "modifyDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/Enchantment;modifyDamageFilteredValue(Lnet/minecraft/core/component/DataComponentType;Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lorg/apache/commons/lang3/mutable/MutableFloat;)V")) + private void attack$modifyWeaponEnchantment( + final Enchantment self, final DataComponentType>> component, + final ServerLevel level, final int enchantmentLevel, final ItemStack weapon, final Entity target, final DamageSource source, final MutableFloat damage, final Operation operation) { + + final SpongeAttackTracker tracker = SpongeAttackTracker.of(source); + if (tracker == null) { + operation.call(self, component, level, enchantmentLevel, weapon, target, source, damage); + return; + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.WEAPON_ENCHANTMENT, ItemStackUtil.snapshotOf(weapon), self); + damage.setValue((float) step.applyChildrenBefore(damage.floatValue())); + if (!step.isSkipped()) { + operation.call(self, component, level, enchantmentLevel, weapon, target, source, damage); + } + damage.setValue((float) step.applyChildrenAfter(damage.floatValue())); + } +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 83c765bfecd..3474f16504c 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -86,7 +86,6 @@ "server.level.ServerPlayer_ContainerListenerMixin", "server.level.ServerPlayerGameModeMixin", "server.level.ServerPlayerMixin", - "server.level.ServerPlayerMixin_Attack_impl", "server.level.ServerPlayerMixin_HealthScale", "server.level.TicketMixin", "server.network.LegacyQueryHandlerMixin", @@ -129,9 +128,9 @@ "world.entity.LeashableMixin", "world.entity.LightningBoltMixin", "world.entity.LivingEntityMixin", - "world.entity.LivingEntityMixin_Attack_Impl", + "world.entity.LivingEntityMixin_Damage", "world.entity.MobMixin", - "world.entity.MobMixin_Attack_Impl", + "world.entity.MobMixin_Attack", "world.entity.PortalProcessorMixin", "world.entity.ai.goal.BreakDoorGoalMixin", "world.entity.ai.goal.BreedGoalMixin", @@ -173,7 +172,7 @@ "world.entity.npc.VillagerMixin", "world.entity.npc.WanderingTraderMixin", "world.entity.player.PlayerMixin", - "world.entity.player.PlayerMixin_Attack_Impl", + "world.entity.player.PlayerMixin_Attack", "world.entity.projectile.AbstractArrowMixin", "world.entity.projectile.AbstractHurtingProjectileMixin", "world.entity.projectile.EyeOfEnderMixin", @@ -218,7 +217,7 @@ "world.item.crafting.ShapelessRecipeMixin", "world.item.crafting.SingleItemRecipeMixin", "world.item.crafting.SmithingTransformRecipeMixin", - "world.item.enchantment.EnchantmentMixin", + "world.item.enchantment.EnchantmentMixin_Attack", "world.level.BaseSpawnerMixin", "world.level.BlockGetterMixin", "world.level.Explosion_BlockInteractionMixin", diff --git a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java index 36495a6884e..afdcb5b27e9 100644 --- a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java @@ -24,9 +24,16 @@ */ package org.spongepowered.test.damage; +import static net.kyori.adventure.text.Component.text; + import com.google.inject.Inject; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; @@ -34,14 +41,16 @@ import org.spongepowered.api.command.parameter.CommandContext; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.cause.entity.damage.DamageFunction; import org.spongepowered.api.event.cause.entity.damage.DamageModifier; import org.spongepowered.api.event.cause.entity.damage.DamageScalings; +import org.spongepowered.api.event.cause.entity.damage.DamageStep; +import org.spongepowered.api.event.cause.entity.damage.DamageStepType; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.api.event.cause.entity.damage.DamageType; import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.event.entity.AttackEntityEvent; -import org.spongepowered.api.event.entity.DamageEntityEvent; +import org.spongepowered.api.event.entity.DamageCalculationEvent; import org.spongepowered.api.event.filter.cause.Root; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; import org.spongepowered.api.event.lifecycle.RegisterRegistryValueEvent; @@ -51,16 +60,24 @@ import org.spongepowered.api.registry.RegistryRegistrationSet; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.tag.DamageTypeTags; -import org.spongepowered.api.util.Tuple; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; import org.spongepowered.test.LoadableModule; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.OptionalDouble; @Plugin("damagetest") public class DamageTest implements LoadableModule { private static final ResourceKey EXHAUSTING_DAMAGE = ResourceKey.of("damagetest", "test"); + private static final DamageStepType DOUBLE_CRITICAL = DamageStepType.create(); + private static final DamageStepType DOUBLE_DOUBLE_CRITICAL = DamageStepType.create(); + class Test { static final class Registry { @@ -119,39 +136,99 @@ private void onRegisterTagEvent(final RegisterTagEvent event) { event.tag(DamageTypeTags.BYPASSES_INVULNERABILITY).append(RegistryKey.of(RegistryTypes.DAMAGE_TYPE, EXHAUSTING_DAMAGE)); } + @Listener + public void onRegisterDamageStepType(final RegisterRegistryValueEvent.GameScoped event) { + event.registry(RegistryTypes.DAMAGE_STEP_TYPE, (r) -> { + r.register(ResourceKey.of(this.plugin, "double_critical"), DOUBLE_CRITICAL); + r.register(ResourceKey.of(this.plugin, "double_double_critical"), DOUBLE_DOUBLE_CRITICAL); + }); + } + + private static class CustomCause {} + private static class DamageListener { + private static final DecimalFormat decimalFormat = new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.ROOT)); + + private static String format(final OptionalDouble value) { + return DamageListener.format(value.orElse(Double.NaN)); + } + + private static String format(final double value) { + return DamageListener.decimalFormat.format(value); + } + @Listener - private void onAttack(final AttackEntityEvent event, @Root DamageSource damageSource) { + private void onAttackPre(final AttackEntityEvent.Pre event) { + event.addModifierBefore(DamageStepTypes.CRITICAL_HIT, + DamageModifier.builder().type(DOUBLE_CRITICAL).frameModifier((frame) -> frame.pushCause(new CustomCause())) + .damageFunction((step, damage) -> { + step.parent().get().skip(); + return damage * 2; + }).build()); + event.addModifierAfter(DOUBLE_CRITICAL, + DamageModifier.builder().type(DOUBLE_DOUBLE_CRITICAL).damageFunction((step, damage) -> damage * 2).build()); + } + + @Listener + private void onDamagePre(final DamageCalculationEvent.Pre event, @Root final DamageSource damageSource) { + final Component eventName = event instanceof AttackEntityEvent ? + text("AttackEntityEvent", NamedTextColor.RED) : text("DamageEntityEvent", NamedTextColor.BLUE); + final Audience audience = Sponge.server(); - audience.sendMessage(Component.text("------------AttackEntityEvent------------")); - audience.sendMessage(Component.text().content("entity: ").append(event.entity().displayName().get()).build()); - audience.sendMessage(Component.text("damage type: " + damageSource.type().key(RegistryTypes.DAMAGE_TYPE))); - audience.sendMessage(Component.text("damage: " + event.originalDamage())); - audience.sendMessage(Component.text("modifiers:")); - for (final DamageFunction f : event.originalFunctions()) { - final DamageModifier modifier = f.modifier(); - final Tuple tuple = event.originalModifierDamage(modifier); - audience.sendMessage(Component.text(" " + ResourceKey.resolve(modifier.group()).value() + "/" + modifier.type().key(RegistryTypes.DAMAGE_MODIFIER_TYPE).value() + ": " + tuple.first() + " -> " + tuple.second())); - } - audience.sendMessage(Component.text("final damage: " + event.originalFinalDamage())); - audience.sendMessage(Component.text("-----------------------------------------")); + audience.sendMessage(text().content("-------------").append(eventName, text(".Pre", NamedTextColor.YELLOW), text("---------------"))); + audience.sendMessage(text().content(damageSource.type().key(RegistryTypes.DAMAGE_TYPE).value()) + .color(NamedTextColor.GOLD).append(text(" → ", NamedTextColor.WHITE), event.entity().displayName().get())); + audience.sendMessage(text("base damage: " + format(event.baseDamage()))); + audience.sendMessage(text("-----------------------------------------------")); } @Listener - private void onDamage(final DamageEntityEvent event, @Root DamageSource damageSource) { + private void onDamagePost(final DamageCalculationEvent.Post event, @Root final DamageSource damageSource) { + final Component eventName = event instanceof AttackEntityEvent ? + text("AttackEntityEvent", NamedTextColor.RED) : text("DamageEntityEvent", NamedTextColor.BLUE); + final Audience audience = Sponge.server(); - audience.sendMessage(Component.text("------------DamageEntityEvent------------")); - audience.sendMessage(Component.text().content("entity: ").append(event.entity().displayName().get()).build()); - audience.sendMessage(Component.text("damage type: " + damageSource.type().key(RegistryTypes.DAMAGE_TYPE))); - audience.sendMessage(Component.text("damage: " + event.originalDamage())); - audience.sendMessage(Component.text("modifiers:")); - for (final DamageFunction f : event.originalFunctions()) { - final DamageModifier modifier = f.modifier(); - final Tuple tuple = event.originalModifierDamage(modifier); - audience.sendMessage(Component.text(" " + ResourceKey.resolve(modifier.group()).value() + "/" + modifier.type().key(RegistryTypes.DAMAGE_MODIFIER_TYPE).value() + ": " + tuple.first() + " -> " + tuple.second())); + audience.sendMessage(text().content("-------------").append(eventName, text(".Post", NamedTextColor.GREEN), text("--------------"))); + audience.sendMessage(text().content(damageSource.type().key(RegistryTypes.DAMAGE_TYPE).value()) + .color(NamedTextColor.GOLD).append(text(" → ", NamedTextColor.WHITE), event.entity().displayName().get())); + audience.sendMessage(text("base damage: " + format(event.baseDamage()))); + audience.sendMessage(text("steps:")); + for (final DamageStep step : event.history().rootSteps()) { + audience.sendMessage(formatStep(step)); + } + audience.sendMessage(text("final damage: " + format(event.finalDamage()))); + audience.sendMessage(text("-----------------------------------------------")); + } + + private static Component formatStep(final DamageStep step) { + final List components = new ArrayList<>(); + components.add(Component.text(format(step.damageBeforeChildren()))); + formatStep(step, components); + return Component.join(JoinConfiguration.separator(Component.text(" → ", NamedTextColor.GRAY)), components); + } + + private static void formatStep(final DamageStep step, final List components) { + for (final DamageStep child : step.childrenBefore()) { + formatStep(child, components); + } + + final List causeClasses = new ArrayList<>(); + for (final Object obj : step.cause().all()) { + causeClasses.add(obj.getClass().getSimpleName()); + } + + components.add(Component.text() + .content(step.type().findKey(RegistryTypes.DAMAGE_STEP_TYPE).map(Key::value).orElse("?")) + .color(step.parent().isEmpty() ? NamedTextColor.AQUA : NamedTextColor.YELLOW) + .decoration(TextDecoration.STRIKETHROUGH, step.isSkipped()) + .hoverEvent(HoverEvent.showText(Component.text(String.join(" ", causeClasses)))) + .build()); + + components.add(Component.text(format(step.damageAfterSelf()))); + + for (final DamageStep child : step.childrenAfter()) { + formatStep(child, components); } - audience.sendMessage(Component.text("final damage: " + event.originalFinalDamage())); - audience.sendMessage(Component.text("-----------------------------------------")); } } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java deleted file mode 100644 index ccb7d33c84a..00000000000 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.vanilla.mixin.core.world.entity; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.TamableAnimal; -import net.minecraft.world.entity.animal.Wolf; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Coerce; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.ModifyConstant; -import org.spongepowered.asm.mixin.injection.Redirect; - - -@Mixin(value = LivingEntity.class, priority = 900) -public abstract class LivingEntityMixin_Attack_Impl { - - @SuppressWarnings("InvalidInjectorMethodSignature") - @ModifyConstant(method = "resolvePlayerResponsibleForDamage", constant = @Constant(classValue = Wolf.class, ordinal = 0)) - private Class attackImpl$onWolfCast(final Object entity, final Class wolf) { - return TamableAnimal.class; - } - - @Redirect(method = "resolvePlayerResponsibleForDamage", - at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;isTame()Z")) - private boolean attackImpl$onWolfIsTame(@Coerce final Object instance) { - return ((TamableAnimal)instance).isTame(); - } - - @Redirect(method = "resolvePlayerResponsibleForDamage", - at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwner()Lnet/minecraft/world/entity/LivingEntity;")) - private LivingEntity attackImpl$onWolfGetOwner(@Coerce final Object instance) { - return ((TamableAnimal)instance).getOwner(); - } - - /** - * Prevents {@link ServerPlayer#awardStat} from running before event - */ - @Redirect(method = "getDamageAfterMagicAbsorb", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V")) - public void attackImpl$onAwardStatDamageResist(final ServerPlayer instance, final ResourceLocation resourceLocation, final int i) { - // do nothing - } - - -} diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java new file mode 100644 index 00000000000..e50181c6f12 --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java @@ -0,0 +1,113 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.world.entity; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.animal.Wolf; +import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; +import org.spongepowered.common.item.util.ItemStackUtil; + +@Mixin(value = LivingEntity.class, priority = 900) +public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageBridge { + + @ModifyExpressionValue(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isDamageSourceBlocked(Lnet/minecraft/world/damagesource/DamageSource;)Z")) + private boolean damage$modifyBeforeAndAfterShield(final boolean original) { + if (!original) { + return false; + } + + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return true; + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(((LivingEntity) (Object) this).getUseItem())); + step.applyChildrenBefore((float) tracker.preEvent().baseDamage()); + step.applyChildrenAfter(0); + return !step.isSkipped(); + } + + @ModifyVariable(method = "hurtServer", ordinal = 2, at = @At("STORE"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V") + )) + private float damage$setBlockedDamage(final float damage) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return damage; + } + final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); + return step == null ? damage : (float) Math.max(step.damageBeforeSelf().getAsDouble(), 0); + } + + @ModifyVariable(method = "hurtServer", at = @At("STORE"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;") + )) + private boolean damage$setBlockedFlag(final boolean blocked) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return blocked; + } + final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); + return step == null ? blocked : step.damageAfterChildren().getAsDouble() <= 0; + } + + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) + private float damage$firePostEvent_Living(final float damage) { + return this.damage$firePostEvent(damage); + } + + @SuppressWarnings("InvalidInjectorMethodSignature") + @ModifyConstant(method = "resolvePlayerResponsibleForDamage", constant = @Constant(classValue = Wolf.class, ordinal = 0)) + private Class damage$onWolfCast(final Object entity, final Class wolf) { + return TamableAnimal.class; + } + + @Redirect(method = "resolvePlayerResponsibleForDamage", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;isTame()Z")) + private boolean damage$onWolfIsTame(@Coerce final Object instance) { + return ((TamableAnimal) instance).isTame(); + } + + @Redirect(method = "resolvePlayerResponsibleForDamage", at = @At(value = "INVOKE" , target = "Lnet/minecraft/world/entity/animal/Wolf;getOwner()Lnet/minecraft/world/entity/LivingEntity;")) + private LivingEntity damage$onWolfGetOwner(@Coerce final Object instance) { + return ((TamableAnimal) instance).getOwner(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Attack_Impl.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java similarity index 62% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Attack_Impl.java rename to vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java index fb7aceaf7b3..26e6c1fb227 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Attack_Impl.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java @@ -22,29 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.player; +package org.spongepowered.vanilla.mixin.core.world.entity.player; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin_Attack_Impl; +import org.spongepowered.vanilla.mixin.core.world.entity.LivingEntityMixin_Vanilla_Damage; -// Forge and Vanilla -@Mixin(value = Player.class, priority = 900) -public abstract class PlayerMixin_Shared_Attack_Impl extends LivingEntityMixin_Attack_Impl { +@Mixin(Player.class) +public abstract class PlayerMixin_Vanilla_Damage extends LivingEntityMixin_Vanilla_Damage { - /** - * Set absorbed damage after calling {@link Player#setAbsorptionAmount} in which we called the event - */ - @ModifyVariable(method = "actuallyHurt", ordinal = 2, - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V")), - at = @At(value = "STORE", ordinal = 0)) - public float attackImpl$setAbsorbed(final float value) { - if (this.attackImpl$actuallyHurtResult.event().isCancelled()) { - return 0; - } - return this.attackImpl$actuallyHurtResult.damageAbsorbed().orElse(0f); + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) + private float damage$firePostEvent_Player(final float damage) { + return this.damage$firePostEvent(damage); } } diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 01d3e67384b..d2775112b79 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -32,12 +32,12 @@ "tags.TagLoaderMixin_Vanilla", "world.entity.EntityMixin_Vanilla", "world.entity.EntityTypeMixin_Vanilla", - "world.entity.LivingEntityMixin_Attack_Impl", + "world.entity.LivingEntityMixin_Vanilla_Damage", "world.entity.LivingEntityMixin_Vanilla", "world.entity.ai.attributes.DefaultAttributesMixin", "world.entity.animal.SnowGolemMixin_Vanilla", "world.entity.item.ItemEntityMixin_Vanilla", - "world.entity.player.PlayerMixin_Vanilla_Attack_Impl", + "world.entity.player.PlayerMixin_Vanilla_Damage", "world.entity.vehicle.AbstractBoatMixin_Vanilla", "world.level.ServerExplosionMixin_Vanilla", "world.level.block.FireBlockMixin_Vanilla", diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json index b322779182e..e23ba17fbba 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json @@ -5,8 +5,8 @@ "priority": 1301, "mixins": [ "server.level.ServerEntityMixin_Shared", - "world.entity.LivingEntityMixin_Shared_Attack_Impl", - "world.entity.player.PlayerMixin_Shared_Attack_Impl", + "world.entity.LivingEntityMixin_Shared_Damage", + "world.entity.player.PlayerMixin_Shared_Damage", "world.entity.projectile.FishingHookMixin_Shared" ], "overwrites": { From fb76cfc452ac28c3d7b4d9b8aa1ea838915fe4a1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 19 Apr 2025 17:40:34 -0700 Subject: [PATCH 249/586] feat(forge): update MinecraftForge to 1.21.5 - Updated MinecraftForge version to 1.21.5-55.0.6 - Introduced a mixin for NamespacedWrapper to address registry hierarchy changes from MinecraftForge - Refined scope of damage steps in LivingEntity for Forge --- forge/build.gradle.kts | 2 +- forge/gradle.properties | 4 +- .../NamespacedWrapperMixin_Forge.java | 49 ++++++++ .../LivingEntityMixin_Forge_Damage.java | 42 ++++++- .../resources/mixins.spongeforge.core.json | 1 + gradle/verification-metadata.xml | 109 ++++++++++++++++++ .../mixin/core/core/MappedRegistryMixin.java | 7 +- .../entity/LivingEntityMixin_Damage.java | 2 +- 8 files changed, 203 insertions(+), 13 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 1571df4fe5e..acde6bd0b25 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -220,7 +220,7 @@ AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { - mappings("official", "1.21.4") + mappings("official", "1.21.5") accessTransformers.from(atFile) reobf = false diff --git a/forge/gradle.properties b/forge/gradle.properties index 41a103e96f6..e0d40b2027b 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=54.0.12 -loom.platform=forge -fabric.loom.dontRemap=true +forgeVersion=55.0.6 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java new file mode 100644 index 00000000000..425381d7cfb --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.minecraftforge.registries; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.core.MappedRegistryAccessor; + +/** + * Due to the Accessor being intrinsically implemented on top of MappedRegistry, the + * extended NamespacedWrapper class redefines frozen as a private field, leaving the + * original accessor to be useless. To fix registry issues, we therefore re-implement + * our accessor interface explicitly for registry purposes. + * + * @author gabizou - Minecraft 1.21.5 MinecraftForge 55.0.6 + * @param + */ +@Mixin(targets = "net/minecraftforge/registries/NamespacedWrapper") +public abstract class NamespacedWrapperMixin_Forge implements MappedRegistryAccessor { + + @Shadow private boolean frozen; + + @Override + public boolean accessor$frozen() { + return this.frozen; + } +} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java index 78d36540f89..7fe503766e6 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java @@ -26,11 +26,14 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; import net.minecraftforge.event.entity.living.ShieldBlockEvent; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyArg; @@ -44,6 +47,10 @@ @Mixin(LivingEntity.class) public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBridge { + //@formatter:off + @Shadow public abstract ItemStack shadow$getUseItem(); + //@formatter:on + @ModifyConstant(method = "actuallyHurt", constant = @Constant(floatValue = 0), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingHurt(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"))) @@ -51,21 +58,44 @@ public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBri return Float.NaN; } - @WrapOperation(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/ForgeEventFactory;onShieldBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)Lnet/minecraftforge/event/entity/living/ShieldBlockEvent;")) - private ShieldBlockEvent damage$modifyBeforeAndAfterShield(final LivingEntity self, final DamageSource source, final float originalDamage, final Operation operation) { + @WrapOperation(method = "hurtServer", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F" + )) + private float damage$initiateBlockingStep( + final LivingEntity self, final ServerLevel level, final DamageSource source, final float originalDamage, + final Operation original) { final SpongeDamageTracker tracker = this.damage$tracker(); if (tracker == null) { - return operation.call(self, source, originalDamage); + return original.call(self, level, source, originalDamage); } - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(self.getUseItem())); + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(this.shadow$getUseItem())); float damage = (float) step.applyChildrenBefore(originalDamage); + return original.call(self, level, source, damage); + } + + + @WrapOperation(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/ForgeEventFactory;onShieldBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/item/ItemStack;)Lnet/minecraftforge/event/entity/living/ShieldBlockEvent;")) + private ShieldBlockEvent damage$modifyBeforeAndAfterShield( + final LivingEntity self, final DamageSource source, final float originalDamage, final ItemStack stack, + final Operation operation + ) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return operation.call(self, source, originalDamage, stack); + } + final var step = tracker.currentStep(DamageStepTypes.SHIELD); + if (step == null) { + return operation.call(self, source, originalDamage, stack); + } + float damage = (float) step.damageBeforeSelf().getAsDouble(); final ShieldBlockEvent event; if (step.isSkipped()) { - event = new ShieldBlockEvent(self, source, damage); + event = new ShieldBlockEvent(self, source, damage, stack); event.setCanceled(true); } else { - event = operation.call(self, source, damage); + event = operation.call(self, source, damage, stack); if (!event.isCanceled()) { damage -= event.getBlockedDamage(); } diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 7aae2731cc6..51b614af6cc 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -18,6 +18,7 @@ "minecraftforge.internal.BrandingControlMixin_Forge", "minecraftforge.registries.ForgeRegistryMixin_Forge", "minecraftforge.registries.GameDataMixin_Forge", + "minecraftforge.registries.NamespacedWrapperMixin_Forge", "minecraftforge.registries.RegistryManagerMixin_Forge", "network.ConnectionMixin_Forge", "network.protocol.common.ClientboundCustomPayloadPacketMixin_Forge", diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a5adacbcd80..86a4e42c5c1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -176,6 +176,14 @@ + + + + + + + + @@ -230,6 +238,14 @@ + + + + + + + + @@ -3555,6 +3571,14 @@ + + + + + + + + @@ -3771,6 +3795,14 @@ + + + + + + + + @@ -3787,6 +3819,14 @@ + + + + + + + + @@ -3908,6 +3948,14 @@ + + + + + + + + @@ -4010,6 +4058,14 @@ + + + + + + + + @@ -4112,6 +4168,14 @@ + + + + + + + + @@ -4383,6 +4447,14 @@ + + + + + + + + @@ -4493,6 +4565,14 @@ + + + + + + + + @@ -4603,6 +4683,14 @@ + + + + + + + + @@ -4668,6 +4756,14 @@ + + + + + + + + @@ -6238,6 +6334,11 @@ + + + + + @@ -6272,6 +6373,14 @@ + + + + + + + + diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java index 12730ddf63d..c6ad60f3d62 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java @@ -46,6 +46,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.accessor.core.MappedRegistryAccessor; import org.spongepowered.common.accessor.resources.ResourceKeyAccessor; import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.core.RegistryBridge; @@ -165,8 +166,10 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa @Inject(method = "freeze", at = @At(value = "FIELD", target = "Lnet/minecraft/core/MappedRegistry;frozen:Z", opcode = Opcodes.PUTFIELD)) private void impl$onFreeze(final CallbackInfoReturnable> cir) { this.impl$dependencies.forEach(t -> { - if (!this.impl$registryHolder.findRegistry(t) - .map(r -> ((MappedRegistryMixin) r).frozen) + final Optional> registry = this.impl$registryHolder.findRegistry(t); + final var accessor = registry.map(r -> ((MappedRegistryAccessor) r)); + final var isFrozen = accessor.map(MappedRegistryAccessor::accessor$frozen); + if (!isFrozen .orElse(false)) { throw new ValueNotFoundException(String.format("Dependency %s was not found!", t)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index 013847be5c6..e7e24b46748 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -106,7 +106,7 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li return damage; } final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); - return step == null ? damage : (float) step.damageAfterChildren().getAsDouble(); + return step == null ? damage : (float) step.damageAfterChildren().orElseGet(() -> step.applyChildrenAfter(damage)); } @ModifyVariable(method = "hurtServer", at = @At("LOAD"), argsOnly = true, slice = @Slice( From 382e2262d1e20f986fa8ceae34161574699c036e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 26 Mar 2025 13:39:23 -0700 Subject: [PATCH 250/586] feat(neo): update NeoForge to 1.21.5-21.5.47-beta - Updates Gradle to 8.11.1 - Improve changes for damage event handling with the three platforms - Improve Registry loader handling between the three platforms --- build-logic/build.gradle | 2 +- .../RegistryDataLoaderMixin_Forge.java | 81 +++++++++ .../resources/mixins.spongeforge.core.json | 1 + gradle/verification-metadata.xml | 172 ++++++++++++++++++ gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 2 +- neoforge/gradle.properties | 2 +- .../RegistryDataLoaderMixin_Neo.java | 80 ++++++++ .../entity/LivingEntityMixin_Neo_Damage.java | 47 ++++- .../resources/mixins.spongeneo.core.json | 93 +++++----- .../resources/RegistryDataLoaderMixin.java | 45 ----- .../entity/LivingEntityMixin_Damage.java | 5 - .../LivingEntityMixin_Shared_Damage.java | 9 + .../RegistryDataLoaderMixin_Vanilla.java | 80 ++++++++ .../resources/mixins.spongevanilla.core.json | 1 + 15 files changed, 517 insertions(+), 107 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java diff --git a/build-logic/build.gradle b/build-logic/build.gradle index 00d4c56f993..52dd96d905b 100644 --- a/build-logic/build.gradle +++ b/build-logic/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation(libs.accessWidener) // arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies - api("dev.architectury:architectury-loom:1.7.423") + api("dev.architectury:architectury-loom:1.10.430") } indraSpotlessLicenser { diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java new file mode 100644 index 00000000000..443940799f2 --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java @@ -0,0 +1,81 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.util.DependencySorter; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Mixin(RegistryDataLoader.class) +public class RegistryDataLoaderMixin_Forge { + + + @SuppressWarnings({"rawtypes", "unchecked"}) + @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", + at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) + private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + // TODO: Remote layer + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + instance.stream() + .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) + .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + .forEach((k, v) -> { + ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + lifecycle.processServerRegistries(k, v.stream() + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); + }); + + List> loaders = new ArrayList<>(instance.size()); + dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); + + original.call(Collections.unmodifiableList(loaders), consumer); + } +} diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 51b614af6cc..1c0b3e43166 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -23,6 +23,7 @@ "network.ConnectionMixin_Forge", "network.protocol.common.ClientboundCustomPayloadPacketMixin_Forge", "network.protocol.common.ServerboundCustomPayloadPacketMixin_Forge", + "resources.RegistryDataLoaderMixin_Forge", "server.BootstrapMixin_Forge", "server.MinecraftServerMixin_Forge", "server.commands.SpreadPlayersCommandMixin_Forge", diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 86a4e42c5c1..19f89b6b126 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1458,6 +1458,9 @@ + + + @@ -1622,6 +1625,9 @@ + + + @@ -2041,6 +2047,14 @@ + + + + + + + + @@ -2833,6 +2847,14 @@ + + + + + + + + @@ -2881,6 +2903,22 @@ + + + + + + + + + + + + + + + + @@ -5052,6 +5090,14 @@ + + + + + + + + @@ -5196,6 +5242,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5228,6 +5302,14 @@ + + + + + + + + @@ -5260,6 +5342,14 @@ + + + + + + + + @@ -5268,6 +5358,14 @@ + + + + + + + + @@ -5308,6 +5406,22 @@ + + + + + + + + + + + + + + + + @@ -5348,6 +5462,22 @@ + + + + + + + + + + + + + + + + @@ -7004,6 +7134,11 @@ + + + + + @@ -7033,6 +7168,22 @@ + + + + + + + + + + + + + + + + @@ -7041,6 +7192,14 @@ + + + + + + + + @@ -7065,6 +7224,14 @@ + + + + + + + + @@ -7086,6 +7253,11 @@ + + + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8a1f6b97f47..22286c90de3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=89d4e70e4e84e2d2dfbb63e4daa53e21b25017cc70c37e4eea31ee51fb15098a +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a42690..b740cf13397 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index e3c2fd2274f..0a36e66219b 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.4.93-beta +neoForgeVersion=21.5.47-beta loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java new file mode 100644 index 00000000000..1c92a7a560a --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.util.DependencySorter; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Mixin(RegistryDataLoader.class) +public class RegistryDataLoaderMixin_Neo { + + @SuppressWarnings({"rawtypes", "unchecked"}) + @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;Z)Lnet/minecraft/core/RegistryAccess$Frozen;", + at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) + private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + // TODO: Remote layer + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + instance.stream() + .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) + .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + .forEach((k, v) -> { + ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + lifecycle.processServerRegistries(k, v.stream() + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); + }); + + List> loaders = new ArrayList<>(instance.size()); + dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); + + original.call(Collections.unmodifiableList(loaders), consumer); + } +} diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java index c9b309cc362..cf73385cfdb 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java @@ -27,15 +27,20 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.common.damagesource.DamageContainer; import net.neoforged.neoforge.event.entity.living.LivingShieldBlockEvent; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @@ -48,6 +53,11 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg @Shadow protected Stack damageContainers; + @Shadow public abstract ItemStack shadow$getUseItem(); + + // Note, this is actually already defined in LivingEntityMixin_Damage + private boolean damage$inventoryChanged; + @Override public float damage$getContainerDamage(final float damage) { return this.damageContainers.peek().getNewDamage(); @@ -58,12 +68,37 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg this.damageContainers.peek().setNewDamage(damage); } + @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;FI)V")) + private void damage$onHurtShield(final CallbackInfoReturnable cir) { + this.damage$inventoryChanged = true; + } + + @WrapOperation(method = "hurtServer", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F" + )) + private float damage$initiateBlockingStep( + final LivingEntity self, final ServerLevel level, final DamageSource source, final float originalDamage, + final Operation original) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return original.call(self, level, source, originalDamage); + } + + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(this.shadow$getUseItem())); + float damage = (float) step.applyChildrenBefore(originalDamage); + return original.call(self, level, source, damage); + } + @SuppressWarnings("UnstableApiUsage") - @WrapOperation(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onDamageBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;Z)Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;")) - private LivingShieldBlockEvent damage$modifyBeforeAndAfterShield(final LivingEntity self, final DamageContainer container, final boolean blocked, final Operation operation) { + @WrapOperation(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onDamageBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;FZ)Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;")) + private LivingShieldBlockEvent damage$modifyBeforeAndAfterShield( + final LivingEntity self, final DamageContainer container, final float originalBlockedDamage, + final boolean blocked, final Operation operation + ) { final SpongeDamageTracker tracker = this.damage$tracker(); if (tracker == null || !blocked) { // don't capture when vanilla wouldn't block - return operation.call(self, container, false); + return operation.call(self, container, originalBlockedDamage, false); } final float originalDamage = container.getNewDamage(); @@ -72,10 +107,10 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg container.setNewDamage(damage); final LivingShieldBlockEvent event; if (step.isSkipped()) { - event = new LivingShieldBlockEvent(self, container, true); + event = new LivingShieldBlockEvent(self, container, damage, true); event.setBlocked(true); } else { - event = operation.call(self, container, true); + event = operation.call(self, container, damage, true); container.setBlockedDamage(event); damage = container.getNewDamage(); } @@ -83,7 +118,7 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg return event; } - @WrapWithCondition(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setBlockedDamage(Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;)V")) + @WrapWithCondition(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setBlockedDamage(Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;)V")) private boolean damage$cancelSetBlockedDamage(final DamageContainer container, final LivingShieldBlockEvent event) { // We already did it above return false; diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index 135ad8490aa..f61741a8226 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -1,48 +1,49 @@ { - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.neoforge.mixin.core", - "priority": 1301, - "mixins": [ - "api.event.EventMixin_Neo", - "api.event.block.ChangeBlockEvent_AllMixin_Neo", - "api.event.entity.ChangeEntityWorldEvent_PreMixin_Neo", - "api.event.entity.ChangeEventWorldEvent_PostMixin_Neo", - "neoforge.event.entity.item.ItemTossEventMixin_Neo", - "commands.CommandsMixin_Neo", - "neoforge.NeoForgeMixin_Neo", - "neoforge.event.entity.EntityTravelToDimensionEventMixin_Neo", - "neoforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Neo", - "neoforge.event.world.BlockEvent_BreakEventMixin_Neo", - "neoforge.event.world.BlockEventMixin_Neo", - "neoforge.internal.BrandingControlMixin_Neo", - "neoforge.registries.GameDataMixin_Neo", - "neoforge.registries.RegistryManagerMixin_Neo", - "network.ConnectionMixin_Neo", - "server.BootstrapMixin_Neo", - "server.MinecraftServerMixin_Neo", - "server.commands.SpreadPlayersCommandMixin_Neo", - "server.level.ServerEntityMixin_Neo", - "server.level.ServerPlayerMixin_Neo", - "server.network.ServerGamePacketListenerImplMixin_Neo", - "tags.TagLoaderMixin_NeoForge", - "world.entity.EntityMixin_Neo", - "world.entity.LivingEntityMixin_Neo", - "world.entity.LivingEntityMixin_Neo_Damage", - "world.entity.animal.SnowGolemMixin_Neo", - "world.entity.item.ItemEntityMixin_Neo", - "world.entity.player.PlayerMixin_Neo_Damage", - "world.entity.projectile.FishingHookMixin_Neo", - "world.entity.vehicle.AbstractBoatMixin_Neo", - "world.level.ServerExplosionMixin_NeoForge", - "world.level.block.FireBlockMixin_Neo", - "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" - ], - "client": [ - "client.MinecraftMixin_Neo", - "client.main.MainMixin_Neo" - ], - "server": [ - "server.MainMixin_Neo" - ] + "required": true, + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.neoforge.mixin.core", + "priority": 1301, + "mixins": [ + "api.event.EventMixin_Neo", + "api.event.block.ChangeBlockEvent_AllMixin_Neo", + "api.event.entity.ChangeEntityWorldEvent_PreMixin_Neo", + "api.event.entity.ChangeEventWorldEvent_PostMixin_Neo", + "commands.CommandsMixin_Neo", + "neoforge.NeoForgeMixin_Neo", + "neoforge.event.entity.EntityTravelToDimensionEventMixin_Neo", + "neoforge.event.entity.item.ItemTossEventMixin_Neo", + "neoforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Neo", + "neoforge.event.world.BlockEvent_BreakEventMixin_Neo", + "neoforge.event.world.BlockEventMixin_Neo", + "neoforge.internal.BrandingControlMixin_Neo", + "neoforge.registries.GameDataMixin_Neo", + "neoforge.registries.RegistryManagerMixin_Neo", + "network.ConnectionMixin_Neo", + "resources.RegistryDataLoaderMixin_Neo", + "server.BootstrapMixin_Neo", + "server.MinecraftServerMixin_Neo", + "server.commands.SpreadPlayersCommandMixin_Neo", + "server.level.ServerEntityMixin_Neo", + "server.level.ServerPlayerMixin_Neo", + "server.network.ServerGamePacketListenerImplMixin_Neo", + "tags.TagLoaderMixin_NeoForge", + "world.entity.EntityMixin_Neo", + "world.entity.LivingEntityMixin_Neo", + "world.entity.LivingEntityMixin_Neo_Damage", + "world.entity.animal.SnowGolemMixin_Neo", + "world.entity.item.ItemEntityMixin_Neo", + "world.entity.player.PlayerMixin_Neo_Damage", + "world.entity.projectile.FishingHookMixin_Neo", + "world.entity.vehicle.AbstractBoatMixin_Neo", + "world.level.ServerExplosionMixin_NeoForge", + "world.level.block.FireBlockMixin_Neo", + "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" + ], + "client": [ + "client.MinecraftMixin_Neo", + "client.main.MainMixin_Neo" + ], + "server": [ + "server.MainMixin_Neo" + ] } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index 4eda0dd3ca2..85e36189f3a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -24,11 +24,8 @@ */ package org.spongepowered.common.mixin.core.resources; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.serialization.Decoder; import net.minecraft.core.RegistrationInfo; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.ChatType; @@ -38,30 +35,13 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.DependencySorter; import org.spongepowered.api.adventure.ChatTypes; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.api.registry.RegistryRoots; -import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; -import org.spongepowered.common.bridge.core.WritableRegistryBridge; -import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.launch.Lifecycle; -import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; -import org.spongepowered.common.registry.SpongeRegistryHolder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; @Mixin(RegistryDataLoader.class) public class RegistryDataLoaderMixin { @@ -83,29 +63,4 @@ public class RegistryDataLoaderMixin { } } - @SuppressWarnings({"rawtypes", "unchecked"}) - @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", - at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) - private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { - // TODO: Remote layer - final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); - final Lifecycle lifecycle = Launch.instance().lifecycle(); - instance.stream() - .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) - .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) - .forEach((k, v) -> { - ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); - lifecycle.processServerRegistries(k, v.stream() - .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! - .map(l -> (Registry) l.accessor$registry())); - v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), - new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); - }); - - List> loaders = new ArrayList<>(instance.size()); - dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); - - original.call(Collections.unmodifiableList(loaders), consumer); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index e7e24b46748..3eb9f78511c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -91,11 +91,6 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li } } - @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) - private void damage$onHurtShield(final CallbackInfoReturnable cir) { - this.damage$inventoryChanged = true; - } - @ModifyVariable(method = "hurtServer", argsOnly = true, at = @At("STORE"), index = 3, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F"), to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;") diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java index 206e6a53ee4..dda88f63a09 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java @@ -31,8 +31,10 @@ import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @@ -40,6 +42,13 @@ @Mixin(value = LivingEntity.class, priority = 900) public abstract class LivingEntityMixin_Shared_Damage implements TrackedDamageBridge { + private boolean damage$inventoryChanged = false; + + @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) + private void damage$onHurtShield(final CallbackInfoReturnable cir) { + this.damage$inventoryChanged = true; + } + @ModifyVariable(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I"), argsOnly = true) private float damage$setBaseDamage(final float damage) { final SpongeDamageTracker tracker = this.damage$tracker(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java new file mode 100644 index 00000000000..f60f5dc5c3c --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.util.DependencySorter; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Mixin(RegistryDataLoader.class) +public class RegistryDataLoaderMixin_Vanilla { + + @SuppressWarnings({"rawtypes", "unchecked"}) + @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", + at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) + private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + // TODO: Remote layer + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + instance.stream() + .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) + .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + .forEach((k, v) -> { + ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + lifecycle.processServerRegistries(k, v.stream() + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); + }); + + List> loaders = new ArrayList<>(instance.size()); + dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); + + original.call(Collections.unmodifiableList(loaders), consumer); + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index d2775112b79..7599c381005 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -23,6 +23,7 @@ "network.protocol.common.ClientboundCustomPayloadPacketMixin_Vanilla", "network.protocol.common.ServerboundCustomPayloadPacketMixin_Vanilla", "registries.BuiltInRegistriesMixin_Vanilla", + "resources.RegistryDataLoaderMixin_Vanilla", "server.BootstrapMixin_Vanilla", "server.MinecraftServerMixin_Vanilla", "server.commands.SpreadPlayersCommandMixin_Vanilla", From 57df1185705aefa9122bba5516f5cfc47ca2c9fc Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 19 Apr 2025 19:39:38 -0700 Subject: [PATCH 251/586] chore(gradle): update verification metadata --- .editorconfig | 5 ++++- gradle/verification-metadata.xml | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 9443384d4f0..ea5ecdce71a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,4 +13,7 @@ tab_width = 4 indent_size = 2 [*.yaml] -indent_size = 2 \ No newline at end of file +indent_size = 2 + +[verification-metadata.xml] +indent_size = 3 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 19f89b6b126..c56bc8b84bb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2815,6 +2815,14 @@ + + + + + + + + @@ -5042,6 +5050,14 @@ + + + + + + + + From 880bdb4d2adbcab1058390073d6e67fd485ceb30 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 20 Apr 2025 12:04:59 -0700 Subject: [PATCH 252/586] feat(minecraft): update to 25w16a Follows most of the API additions. SpongeVanilla's client ui is definitely broken for the plugins screen. I'm unsure of the damage injections, something to look at fixing likely in api-15 as well. Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../vanilla/generator/Context.java | 2 +- gradle.properties | 2 +- .../org/spongepowered/common/SpongeCommon.java | 4 ++-- .../common/SpongeMinecraftVersion.java | 2 +- .../schematic/SchematicUpdater1_to_2.java | 2 +- .../block/state/BlockStateDataProvider.java | 1 + .../provider/entity/AreaEffectCloudData.java | 2 +- .../tracking/phase/packet/PacketPhase.java | 4 ---- .../world/schematic/SchematicTranslator.java | 4 ++-- .../world/server/SpongeWorldTypeBuilder.java | 2 ++ ...xin_API.java => FlyingAnimalMixin_API.java} | 6 +++--- .../world/entity/monster/GhastMixin_API.java | 5 +++-- .../world/entity/monster/PhantomMixin_API.java | 5 +++-- src/mixins/resources/mixins.sponge.api.json | 2 +- .../vanilla/client/gui/widget/ScrollPanel.java | 8 ++++---- .../LivingEntityMixin_Vanilla_Damage.java | 18 +++++++++--------- 17 files changed, 36 insertions(+), 35 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/{FlyingMobMixin_API.java => FlyingAnimalMixin_API.java} (90%) diff --git a/SpongeAPI b/SpongeAPI index 52792007710..faf25d0f6ca 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 527920077105384acc911b58116c2d3240297b17 +Subproject commit faf25d0f6ca8f9fdf490fafea2c7b91f3e25e322 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java index a31b37a5a04..e47330f862f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java @@ -67,7 +67,7 @@ public final class Context { } public String gameVersion() { - return SharedConstants.getCurrentVersion().getName(); + return SharedConstants.getCurrentVersion().name(); } public RegistryAccess registries() { diff --git a/gradle.properties b/gradle.properties index 0c56afda37b..0167ea0643d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.5 +minecraftVersion=25w16a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/SpongeCommon.java b/src/main/java/org/spongepowered/common/SpongeCommon.java index c91b1b648e0..1825c57adfe 100644 --- a/src/main/java/org/spongepowered/common/SpongeCommon.java +++ b/src/main/java/org/spongepowered/common/SpongeCommon.java @@ -52,8 +52,8 @@ public final class SpongeCommon { private static final Logger LOGGER = LogManager.getLogger(Launch.instance().id()); private static final SpongeMinecraftVersion MINECRAFT_VERSION = new SpongeMinecraftVersion( - SharedConstants.getCurrentVersion().getName(), - SharedConstants.getCurrentVersion().getProtocolVersion() + SharedConstants.getCurrentVersion().name(), + SharedConstants.getCurrentVersion().protocolVersion() ); @Inject private @Nullable static SpongeGame game; diff --git a/src/main/java/org/spongepowered/common/SpongeMinecraftVersion.java b/src/main/java/org/spongepowered/common/SpongeMinecraftVersion.java index 7c85fd6941e..ec212009f1c 100644 --- a/src/main/java/org/spongepowered/common/SpongeMinecraftVersion.java +++ b/src/main/java/org/spongepowered/common/SpongeMinecraftVersion.java @@ -57,7 +57,7 @@ public boolean isLegacy() { @Override public OptionalInt dataVersion() { - return OptionalInt.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion()); + return OptionalInt.of(SharedConstants.getCurrentVersion().dataVersion().version()); } @Override diff --git a/src/main/java/org/spongepowered/common/data/persistence/schematic/SchematicUpdater1_to_2.java b/src/main/java/org/spongepowered/common/data/persistence/schematic/SchematicUpdater1_to_2.java index 83a32b34bb1..ba136624eb0 100644 --- a/src/main/java/org/spongepowered/common/data/persistence/schematic/SchematicUpdater1_to_2.java +++ b/src/main/java/org/spongepowered/common/data/persistence/schematic/SchematicUpdater1_to_2.java @@ -46,7 +46,7 @@ public int outputVersion() { @Override public DataView update(final DataView content) { content.set(Constants.Sponge.Schematic.VERSION, 2); - content.set(Constants.Sponge.Schematic.DATA_VERSION, SharedConstants.getCurrentVersion().getDataVersion().getVersion()); + content.set(Constants.Sponge.Schematic.DATA_VERSION, SharedConstants.getCurrentVersion().dataVersion().version()); content.getViewList(Constants.Sponge.Schematic.Versions.V1_TILE_ENTITY_DATA).ifPresent(tiles -> { tiles.forEach(tile -> { // Remove unnecessary version information. diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index 6449fab5911..924648252de 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -79,6 +79,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DOUBLE_BLOCK_HALF, BlockStateProperties.DOUBLE_BLOCK_HALF); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DOWN, BlockStateProperties.DOWN); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRAG, BlockStateProperties.DRAG); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIED_GHAST_HYDRATION_LEVELS, BlockStateProperties.DRIED_GHAST_HYDRATION_LEVELS); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIPSTONE_THICKNESS, BlockStateProperties.DRIPSTONE_THICKNESS); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DUSTED, BlockStateProperties.DUSTED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.EAST, BlockStateProperties.EAST); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java index 95ec7d9b635..d465f36a1fc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java @@ -64,7 +64,7 @@ public static void register(final DataProviderRegistrator registrator) { }) .create(Keys.PARTICLE_EFFECT) .get(h -> SpongeParticleHelper.spongeParticleOptions(h.getParticle())) - .set((h, v) -> h.setParticle(SpongeParticleHelper.vanillaParticleOptions(v))) + .set((h, v) -> h.setCustomParticle(SpongeParticleHelper.vanillaParticleOptions(v))) .create(Keys.RADIUS) .get(h -> (double) h.getRadius()) .set((h, v) -> h.setRadius(v.floatValue())) diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java index 75ee68ad551..85c685de2a4 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java @@ -121,8 +121,6 @@ public static final class General { static final IPhaseState INVALID = new InvalidPacketState(); static final IPhaseState START_RIDING_JUMP = new BasicPacketState(); static final IPhaseState ANIMATION = new AnimationPacketState(); - static final IPhaseState PRESS_SHIFT_KEY = new BasicPacketState(); - static final IPhaseState RELEASE_SHIFT_KEY = new BasicPacketState(); static final IPhaseState START_SPRINTING = new BasicPacketState(); static final IPhaseState STOP_SPRINTING = new BasicPacketState(); static final IPhaseState STOP_SLEEPING = new StopSleepingPacketState(); @@ -336,8 +334,6 @@ private void setupPacketToStateMapping() { } private static final ImmutableMap>> PLAYER_ACTION_MAPPINGS = ImmutableMap.>>builder() - .put(ServerboundPlayerCommandPacket.Action.PRESS_SHIFT_KEY, PacketPhase.General.PRESS_SHIFT_KEY) - .put(ServerboundPlayerCommandPacket.Action.RELEASE_SHIFT_KEY, PacketPhase.General.RELEASE_SHIFT_KEY) .put(ServerboundPlayerCommandPacket.Action.STOP_SLEEPING, PacketPhase.General.STOP_SLEEPING) .put(ServerboundPlayerCommandPacket.Action.START_SPRINTING, PacketPhase.General.START_SPRINTING) .put(ServerboundPlayerCommandPacket.Action.STOP_SPRINTING, PacketPhase.General.STOP_SPRINTING) diff --git a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java index cc781ad9926..1a2eb6b61bc 100644 --- a/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java +++ b/src/main/java/org/spongepowered/common/world/schematic/SchematicTranslator.java @@ -128,7 +128,7 @@ public Schematic translate(final DataView unprocessed) throws InvalidDataExcepti final int dataVersion = schematicView.getInt(Constants.Sponge.Schematic.DATA_VERSION).get(); // DataFixer will be able to upgrade entity and tile entity data if and only if we're running a valid server and // the data version is outdated. - final boolean needsFixers = dataVersion < SharedConstants.getCurrentVersion().getDataVersion().getVersion() && SchematicTranslator.VANILLA_FIXER != null; + final boolean needsFixers = dataVersion < SharedConstants.getCurrentVersion().dataVersion().version() && SchematicTranslator.VANILLA_FIXER != null; final DataView updatedView; @@ -420,7 +420,7 @@ public DataView addTo(final Schematic schematic, final DataView data) { data.set(Constants.Sponge.Schematic.LENGTH, (short) length); data.set(Constants.Sponge.Schematic.VERSION, Constants.Sponge.Schematic.CURRENT_VERSION); - data.set(Constants.Sponge.Schematic.DATA_VERSION, SharedConstants.getCurrentVersion().getDataVersion().getVersion()); + data.set(Constants.Sponge.Schematic.DATA_VERSION, SharedConstants.getCurrentVersion().dataVersion().version()); for (final DataQuery metaKey : schematic.metadata().keys(false)) { data.set(Constants.Sponge.Schematic.METADATA.then(metaKey), schematic.metadata().get(metaKey).get()); } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index e531e249561..1049649ed1d 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -45,6 +45,7 @@ import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; +import java.util.Optional; import java.util.OptionalLong; public final class SpongeWorldTypeBuilder implements WorldType.Builder { @@ -113,6 +114,7 @@ public WorldType.Builder from(final WorldType type) { (TagKey) (Object) infiniburn, (ResourceLocation) (Object) effect.key(), ambientLighting, + Optional.empty(), new DimensionType.MonsterSettings(piglinSafe, hasRaids, monsterSpawnLightTest, monsterSpawnBlockLightLimit)); if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { bridge.bridge$decorateData(spongeData); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingMobMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingMobMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java index eb413d88e1f..3c61c8a2d3a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingMobMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity; -import net.minecraft.world.entity.FlyingMob; +import net.minecraft.world.entity.animal.FlyingAnimal; import org.spongepowered.api.entity.Aerial; import org.spongepowered.asm.mixin.Mixin; -@Mixin(FlyingMob.class) -public abstract class FlyingMobMixin_API extends MobMixin_API implements Aerial { +@Mixin(FlyingAnimal.class) +public interface FlyingAnimalMixin_API extends Aerial { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java index 1889b3331da..2af05c40941 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java @@ -26,9 +26,10 @@ import org.spongepowered.api.entity.living.monster.Ghast; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingMobMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingAnimalMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; @Mixin(net.minecraft.world.entity.monster.Ghast.class) -public abstract class GhastMixin_API extends FlyingMobMixin_API implements Ghast { +public abstract class GhastMixin_API extends MobMixin_API implements Ghast { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java index 0c9d98220b7..3f36775585d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java @@ -28,12 +28,13 @@ import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.monster.Phantom; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingMobMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingAnimalMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; import java.util.Set; @Mixin(net.minecraft.world.entity.monster.Phantom.class) -public abstract class PhantomMixin_API extends FlyingMobMixin_API implements Phantom { +public abstract class PhantomMixin_API extends MobMixin_API implements Phantom { @Override protected Set> api$getVanillaValues() { diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index a37c8facf54..1f00c2f534d 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -103,7 +103,7 @@ "minecraft.world.entity.EntityMixin_API", "minecraft.world.entity.EntityTypeMixin_API", "minecraft.world.entity.ExperienceOrbMixin_API", - "minecraft.world.entity.FlyingMobMixin_API", + "minecraft.world.entity.FlyingAnimalMixin_API", "minecraft.world.entity.GlowSquidMixin_API", "minecraft.world.entity.HumanoidArmMixin_API", "minecraft.world.entity.InteractionMixin_API", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index b63f267d356..825f57e7162 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -183,12 +183,12 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, final Tesselator tess = Tesselator.getInstance(); final double scale = this.client.getWindow().getGuiScale(); - RenderSystem.enableScissor((int) (this.left * scale), (int) (this.client.getWindow().getHeight() - (this.bottom * scale)), (int) (this.width * scale), - (int) (this.height * scale)); +// RenderSystem.enableScissor((int) (this.left * scale), (int) (this.client.getWindow().getHeight() - (this.bottom * scale)), (int) (this.width * scale), +// (int) (this.height * scale)); // TODO fix me RenderSystem.setShader(GameRenderer::getPositionTexColorShader); // RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); +// RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); final float texScale = 32.0F; BufferBuilder worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); worldr.addVertex(this.left, this.bottom, 0.0f).setUv(this.left / texScale, (this.bottom + (int) this.scrollDistance) / texScale) @@ -250,7 +250,7 @@ public void render(final GuiGraphics stack, final int mouseX, final int mouseY, // RenderSystem.enableTexture(); // RenderSystem.disableBlend(); - RenderSystem.disableScissor(); +// RenderSystem.disableScissor(); } @Override diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java index 2963a454eff..f68eb4432d6 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java @@ -46,21 +46,21 @@ @Mixin(value = LivingEntity.class, priority = 900) public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageBridge { - @ModifyExpressionValue(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isInvulnerableTo(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)Z")) - private boolean damage$modifyBeforeAndAfterShield(final boolean original) { - if (!original) { - return false; - } - + @ModifyExpressionValue(method = "hurtServer", at = @At(value = "CONSTANT", args = "floatValue=0.0"), + slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F") + )) + private float damage$modifyBeforeAndAfterShield(final float original) { final SpongeDamageTracker tracker = this.damage$tracker(); if (tracker == null) { - return true; + return original; } - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(((LivingEntity) (Object) this).getUseItem())); + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(((LivingEntity) (Object) this).getItemBlockingWith())); step.applyChildrenBefore((float) tracker.preEvent().baseDamage()); step.applyChildrenAfter(0); - return !step.isSkipped(); + return !step.isSkipped() ? 0.0F : (float) step.damageAfterChildren().getAsDouble(); } @ModifyVariable(method = "applyItemBlocking", at = @At("STORE"), index = 9, slice = @Slice( From 52c8128335a1357ee09b9436511ef177d72ad7c8 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 21 Apr 2025 15:24:45 +0200 Subject: [PATCH 253/586] Update shield damage step impl for 1.21.5 --- .../LivingEntityMixin_Forge_Damage.java | 55 --------------- .../entity/LivingEntityMixin_Neo_Damage.java | 68 ------------------- .../entity/LivingEntityMixin_Damage.java | 51 ++++++++++++-- .../LivingEntityMixin_Shared_Damage.java | 9 --- .../LivingEntityMixin_Vanilla_Damage.java | 54 --------------- 5 files changed, 45 insertions(+), 192 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java index 7fe503766e6..3e983729e50 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java @@ -24,14 +24,8 @@ */ package org.spongepowered.forge.mixin.core.world.entity; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.event.entity.living.ShieldBlockEvent; -import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -40,9 +34,6 @@ import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; -import org.spongepowered.common.item.util.ItemStackUtil; @Mixin(LivingEntity.class) public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBridge { @@ -58,52 +49,6 @@ public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBri return Float.NaN; } - @WrapOperation(method = "hurtServer", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F" - )) - private float damage$initiateBlockingStep( - final LivingEntity self, final ServerLevel level, final DamageSource source, final float originalDamage, - final Operation original) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return original.call(self, level, source, originalDamage); - } - - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(this.shadow$getUseItem())); - float damage = (float) step.applyChildrenBefore(originalDamage); - return original.call(self, level, source, damage); - } - - - @WrapOperation(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/ForgeEventFactory;onShieldBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/item/ItemStack;)Lnet/minecraftforge/event/entity/living/ShieldBlockEvent;")) - private ShieldBlockEvent damage$modifyBeforeAndAfterShield( - final LivingEntity self, final DamageSource source, final float originalDamage, final ItemStack stack, - final Operation operation - ) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return operation.call(self, source, originalDamage, stack); - } - final var step = tracker.currentStep(DamageStepTypes.SHIELD); - if (step == null) { - return operation.call(self, source, originalDamage, stack); - } - float damage = (float) step.damageBeforeSelf().getAsDouble(); - final ShieldBlockEvent event; - if (step.isSkipped()) { - event = new ShieldBlockEvent(self, source, damage, stack); - event.setCanceled(true); - } else { - event = operation.call(self, source, damage, stack); - if (!event.isCanceled()) { - damage -= event.getBlockedDamage(); - } - } - step.applyChildrenAfter(damage); - return event; - } - @ModifyArg(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingDamage(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F")) private float damage$firePostEvent_Living(final float damage) { return this.damage$firePostEvent(damage); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java index cf73385cfdb..52f9056e52b 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java @@ -25,26 +25,17 @@ package org.spongepowered.neoforge.mixin.core.world.entity; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.common.damagesource.DamageContainer; -import net.neoforged.neoforge.event.entity.living.LivingShieldBlockEvent; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; -import org.spongepowered.common.item.util.ItemStackUtil; import java.util.Stack; @@ -55,9 +46,6 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg @Shadow public abstract ItemStack shadow$getUseItem(); - // Note, this is actually already defined in LivingEntityMixin_Damage - private boolean damage$inventoryChanged; - @Override public float damage$getContainerDamage(final float damage) { return this.damageContainers.peek().getNewDamage(); @@ -68,62 +56,6 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg this.damageContainers.peek().setNewDamage(damage); } - @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;FI)V")) - private void damage$onHurtShield(final CallbackInfoReturnable cir) { - this.damage$inventoryChanged = true; - } - - @WrapOperation(method = "hurtServer", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F" - )) - private float damage$initiateBlockingStep( - final LivingEntity self, final ServerLevel level, final DamageSource source, final float originalDamage, - final Operation original) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return original.call(self, level, source, originalDamage); - } - - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(this.shadow$getUseItem())); - float damage = (float) step.applyChildrenBefore(originalDamage); - return original.call(self, level, source, damage); - } - - @SuppressWarnings("UnstableApiUsage") - @WrapOperation(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/CommonHooks;onDamageBlock(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;FZ)Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;")) - private LivingShieldBlockEvent damage$modifyBeforeAndAfterShield( - final LivingEntity self, final DamageContainer container, final float originalBlockedDamage, - final boolean blocked, final Operation operation - ) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null || !blocked) { // don't capture when vanilla wouldn't block - return operation.call(self, container, originalBlockedDamage, false); - } - - final float originalDamage = container.getNewDamage(); - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(self.getUseItem())); - float damage = (float) step.applyChildrenBefore(originalDamage); - container.setNewDamage(damage); - final LivingShieldBlockEvent event; - if (step.isSkipped()) { - event = new LivingShieldBlockEvent(self, container, damage, true); - event.setBlocked(true); - } else { - event = operation.call(self, container, damage, true); - container.setBlockedDamage(event); - damage = container.getNewDamage(); - } - step.applyChildrenAfter(damage); - return event; - } - - @WrapWithCondition(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/common/damagesource/DamageContainer;setBlockedDamage(Lnet/neoforged/neoforge/event/entity/living/LivingShieldBlockEvent;)V")) - private boolean damage$cancelSetBlockedDamage(final DamageContainer container, final LivingShieldBlockEvent event) { - // We already did it above - return false; - } - @ModifyVariable(method = "actuallyHurt", ordinal = 1, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/neoforged/neoforge/common/CommonHooks;onLivingDamagePre(Lnet/minecraft/world/entity/LivingEntity;Lnet/neoforged/neoforge/common/damagesource/DamageContainer;)F")) private float damage$modifyBeforeAbsorption(final float damage) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index 3eb9f78511c..605942854f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -27,6 +27,8 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Cancellable; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; @@ -57,6 +59,7 @@ import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; +import org.spongepowered.common.item.util.ItemStackUtil; import java.util.Deque; import java.util.LinkedList; @@ -91,17 +94,53 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li } } - @ModifyVariable(method = "hurtServer", argsOnly = true, at = @At("STORE"), index = 3, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;") + @ModifyVariable(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;resolveBlockedDamage(Lnet/minecraft/world/damagesource/DamageSource;FD)F"), argsOnly = true) + private float damage$modifyBeforeShield(final float originalDamage, @Local final ItemStack stack, @Cancellable final CallbackInfoReturnable cir) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return originalDamage; + } + final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(stack)); + final float inputDamage = (float) step.applyChildrenBefore(originalDamage); + if (step.isSkipped()) { + final float outputDamage = (float) step.applyChildrenAfter(inputDamage); + cir.setReturnValue(originalDamage - outputDamage); + } + return inputDamage; + } + + @Inject(method = "applyItemBlocking", at = @At("RETURN"), cancellable = true, slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;resolveBlockedDamage(Lnet/minecraft/world/damagesource/DamageSource;FD)F") )) - private float damage$setDamageAfterShield(final float damage) { + private void damage$modifyAfterShield(final ServerLevel level, final DamageSource source, float damage, final CallbackInfoReturnable cir) { final SpongeDamageTracker tracker = this.damage$tracker(); if (tracker == null) { - return damage; + return; } final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); - return step == null ? damage : (float) step.damageAfterChildren().orElseGet(() -> step.applyChildrenAfter(damage)); + if (step == null) { + return; + } + damage = (float) step.applyChildrenAfter(damage - cir.getReturnValueF()); + cir.setReturnValue((float) step.damageBeforeChildren().getAsDouble() - damage); + } + + @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) + private void damage$onHurtShield(final CallbackInfoReturnable cir) { + this.damage$inventoryChanged = true; + } + + @ModifyVariable(method = "hurtServer", at = @At("STORE"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F"), + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;")) + ) + private boolean damage$setBlockedFlag(final boolean blocked) { + final SpongeDamageTracker tracker = this.damage$tracker(); + if (tracker == null) { + return blocked; + } + final SpongeDamageStep step = tracker.lastStep(DamageStepTypes.SHIELD); + return step == null ? blocked : step.damageAfterSelf().getAsDouble() < step.damageBeforeSelf().getAsDouble(); } @ModifyVariable(method = "hurtServer", at = @At("LOAD"), argsOnly = true, slice = @Slice( diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java index dda88f63a09..206e6a53ee4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java @@ -31,10 +31,8 @@ import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; @@ -42,13 +40,6 @@ @Mixin(value = LivingEntity.class, priority = 900) public abstract class LivingEntityMixin_Shared_Damage implements TrackedDamageBridge { - private boolean damage$inventoryChanged = false; - - @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) - private void damage$onHurtShield(final CallbackInfoReturnable cir) { - this.damage$inventoryChanged = true; - } - @ModifyVariable(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I"), argsOnly = true) private float damage$setBaseDamage(final float damage) { final SpongeDamageTracker tracker = this.damage$tracker(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java index 2963a454eff..e62415ed374 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java @@ -24,12 +24,10 @@ */ package org.spongepowered.vanilla.mixin.core.world.entity; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.animal.wolf.Wolf; -import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Coerce; @@ -39,62 +37,10 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; -import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; -import org.spongepowered.common.item.util.ItemStackUtil; @Mixin(value = LivingEntity.class, priority = 900) public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageBridge { - @ModifyExpressionValue(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isInvulnerableTo(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)Z")) - private boolean damage$modifyBeforeAndAfterShield(final boolean original) { - if (!original) { - return false; - } - - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return true; - } - - final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(((LivingEntity) (Object) this).getUseItem())); - step.applyChildrenBefore((float) tracker.preEvent().baseDamage()); - step.applyChildrenAfter(0); - return !step.isSkipped(); - } - - @ModifyVariable(method = "applyItemBlocking", at = @At("STORE"), index = 9, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;resolveBlockedDamage(Lnet/minecraft/world/damagesource/DamageSource;FD)F"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V") - )) - private float damage$setBlockedDamage(final float damage) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return damage; - } - final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); - return step == null ? damage : (float) Math.max(step.damageBeforeSelf().getAsDouble(), 0); - } - - @ModifyVariable(method = "hurtServer", - at = @At("STORE"), - slice = @Slice( - from = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F" - ), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;") - ) - ) - private boolean damage$setBlockedFlag(final boolean blocked) { - final SpongeDamageTracker tracker = this.damage$tracker(); - if (tracker == null) { - return blocked; - } - final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.SHIELD); - return step == null ? blocked : step.damageAfterChildren().getAsDouble() <= 0; - } - @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) From 8c3045826be9bc9a9bfbe3ef478d39224476f62f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 21 Apr 2025 16:27:28 +0200 Subject: [PATCH 254/586] Fix shield injection on NeoForge --- .../mixin/core/world/entity/LivingEntityMixin_Damage.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index 605942854f1..13d69e638b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -125,7 +125,11 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li cir.setReturnValue((float) step.damageBeforeChildren().getAsDouble() - damage); } - @Inject(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V")) + @SuppressWarnings("MixinAnnotationTarget") + @Inject(method = "applyItemBlocking", at = { + @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V"), // Vanilla and Forge + @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;FI)V") // Neo + }) private void damage$onHurtShield(final CallbackInfoReturnable cir) { this.damage$inventoryChanged = true; } From 31cbd93bd3747a80ffa9f70b0ddb2e4893dceaa3 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 10 May 2025 17:41:32 -0700 Subject: [PATCH 255/586] feat!(minecraft): update to 25w17a Mainly additions/changes from the previous snapshot. See: https://minecraft.wiki/w/Java_Edition_25w17a --- SpongeAPI | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index faf25d0f6ca..3762c5eb472 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit faf25d0f6ca8f9fdf490fafea2c7b91f3e25e322 +Subproject commit 3762c5eb4725052705efdab2ffa9791368a7d66e diff --git a/gradle.properties b/gradle.properties index 0167ea0643d..5ef612ec76d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w16a +minecraftVersion=25w17a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 77bc6706eb1fb09e3a6f3e4d815d68d9d19d3fcb Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 10 May 2025 17:42:40 -0700 Subject: [PATCH 256/586] chore(lint): apply linting fixes --- .../mixin/api/minecraft/world/entity/monster/GhastMixin_API.java | 1 - .../api/minecraft/world/entity/monster/PhantomMixin_API.java | 1 - .../org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java | 1 - 3 files changed, 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java index 2af05c40941..c05d9c3ee35 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/GhastMixin_API.java @@ -26,7 +26,6 @@ import org.spongepowered.api.entity.living.monster.Ghast; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingAnimalMixin_API; import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; @Mixin(net.minecraft.world.entity.monster.Ghast.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java index 3f36775585d..718e9a5327a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PhantomMixin_API.java @@ -28,7 +28,6 @@ import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.monster.Phantom; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.FlyingAnimalMixin_API; import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; import java.util.Set; diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 825f57e7162..7fa79ba1be8 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -24,7 +24,6 @@ */ package org.spongepowered.vanilla.client.gui.widget; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.Tesselator; From 56d9a817104e7980e9e0960e7ecf8f377ad12b32 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 10 May 2025 22:07:42 -0700 Subject: [PATCH 257/586] feat(minecraft): update to 25w18a Notable changes: - ArmorStands have proper accessors - TrialSpawnerData has a "component" for all the configs - Gson component serialization apparently is inlined.. will need to verify that Adventure's components still will function - All read/write to Compounds is now routed through interfaces ValueInput/Output. - This requires further thought for how Sponge serializes its custom data, we will need to update the overall implementation to better support these interfaces moving forward. --- gradle.properties | 2 +- .../entity/decoration/ArmorStandAccessor.java | 9 ---- .../trialspawner/TrialSpawnerAccessor.java | 5 +- .../TrialSpawnerDataAccessor.java | 4 +- .../common/block/SpongeBlockSnapshot.java | 5 +- .../entity/SpongeBlockEntityArchetype.java | 5 +- .../entity/TrialSpawnerDataProvider.java | 41 ++++++++------- .../data/provider/entity/ArmorStandData.java | 16 +++--- .../entity/SpongeEntityArchetypeBuilder.java | 9 ++-- .../common/entity/SpongeEntitySnapshot.java | 5 +- .../entity/SpongeEntitySnapshotBuilder.java | 13 +++-- .../entity/living/human/HumanEntity.java | 21 ++++---- .../common/entity/player/SpongeUserData.java | 35 ++++++++----- .../entity/player/SpongeUserInventory.java | 51 ++++++++++--------- .../EntityPerformingDropsTransaction.java | 8 +-- .../world/SpawnEntityTransaction.java | 6 ++- .../packet/SpongeBasicPacketChannel.java | 1 + .../spongepowered/common/util/Constants.java | 8 +++ .../storage/SpongePlayerDataManager.java | 13 +++-- .../world/volume/VolumeStreamUtils.java | 16 ++++-- .../minecraft/map/MapDecorationMixin_API.java | 23 ++++++++- .../world/entity/EntityMixin_API.java | 24 +++++---- .../minecraft/world/level/LevelMixin_API.java | 13 +++-- .../TrialSpawnerBlockEntityMixin_API.java | 8 +-- .../StructureTemplateMixin_API.java | 6 ++- .../chat/Component_SerializerMixin.java | 15 +++--- .../core/server/players/PlayerListMixin.java | 18 ++++--- .../mixin/core/world/entity/EntityMixin.java | 24 ++++++--- .../mixin/core/world/level/LevelMixin.java | 9 +++- .../level/block/entity/BlockEntityMixin.java | 31 ++++++++--- .../level/storage/PlayerDataStorageMixin.java | 6 +-- 31 files changed, 283 insertions(+), 167 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5ef612ec76d..05f3bb7dabf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w17a +minecraftVersion=25w18a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java index a44016eaaa9..f3909b42155 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/ArmorStandAccessor.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.accessor.world.entity.decoration; -import net.minecraft.core.Rotations; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import org.spongepowered.asm.mixin.Mixin; @@ -38,14 +37,6 @@ public interface ArmorStandAccessor { @Accessor("disabledSlots") void accessor$disabledSlots(final int disabledSlots); - @Accessor("leftArmPose") Rotations accessor$leftArmPose(); - - @Accessor("rightArmPose") Rotations accessor$rightArmPose(); - - @Accessor("leftLegPose") Rotations accessor$leftLegPose(); - - @Accessor("rightLegPose") Rotations accessor$rightLegPose(); - @Invoker("isDisabled") boolean invoker$isDisabled(final EquipmentSlot slot); @Invoker("setSmall") void invoker$setSmall(final boolean small); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java index 82c6ff5adfa..e9c04f3bb7a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerAccessor.java @@ -24,9 +24,7 @@ */ package org.spongepowered.common.accessor.world.level.block.entity.trialspawner; -import net.minecraft.core.Holder; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner; -import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; @@ -34,6 +32,5 @@ @Mixin(TrialSpawner.class) public interface TrialSpawnerAccessor { - @Mutable @Accessor("normalConfig") void accessor$normalConfig(Holder normalConfig); - @Mutable @Accessor("ominousConfig") void accessor$ominousConfig(Holder ominousConfig); + @Mutable @Accessor("config") void accessor$config(TrialSpawner.FullConfig normalConfig); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerDataAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerDataAccessor.java index f5de3ae6590..fa5e807d684 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerDataAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/trialspawner/TrialSpawnerDataAccessor.java @@ -25,7 +25,7 @@ package org.spongepowered.common.accessor.world.level.block.entity.trialspawner; import net.minecraft.world.level.SpawnData; -import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerData; +import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerStateData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -33,7 +33,7 @@ import java.util.Set; import java.util.UUID; -@Mixin(TrialSpawnerData.class) +@Mixin(TrialSpawnerStateData.class) public interface TrialSpawnerDataAccessor { @Accessor("nextSpawnData") Optional accessor$nextSpawnData(); diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index ccce158b495..b619c9f57d0 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -29,8 +29,10 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.storage.TagValueInput; import org.apache.logging.log4j.Level; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; @@ -200,7 +202,8 @@ public boolean restore(final boolean force, final BlockChangeFlag flag) { @Nullable BlockEntity te = world.getBlockEntity(pos); if (te != null) { te.setBlockState((net.minecraft.world.level.block.state.BlockState) this.blockState); - te.loadWithComponents(this.compound, world.registryAccess()); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, world.registryAccess(), this.compound); + te.loadWithComponents(input); } else { // Because, some mods will "unintentionally" only obey some of the rules but not all. // In cases like this, we need to directly just say "fuck it" and deserialize from the compound directly. diff --git a/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java b/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java index 08aaf25943d..e9b60d40af3 100644 --- a/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/block/entity/SpongeBlockEntityArchetype.java @@ -28,8 +28,10 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.TagValueInput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.block.BlockState; @@ -114,7 +116,8 @@ public Optional apply(final ServerLocation location) { compound.putInt(Constants.TileEntity.Y_POS, blockpos.getY()); compound.putInt(Constants.TileEntity.Z_POS, blockpos.getZ()); tileEntity.setBlockState((net.minecraft.world.level.block.state.BlockState) currentState); - tileEntity.loadWithComponents(compound, minecraftWorld.registryAccess()); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, minecraftWorld.registryAccess(), compound); + tileEntity.loadWithComponents(input); return Optional.of((org.spongepowered.api.block.entity.BlockEntity) tileEntity); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java index 1c383d849e4..b5c03f3d7cf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/TrialSpawnerDataProvider.java @@ -26,6 +26,7 @@ import net.minecraft.core.Holder; import net.minecraft.world.level.block.entity.TrialSpawnerBlockEntity; +import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerConfig; import org.spongepowered.api.data.Keys; import org.spongepowered.common.accessor.world.level.block.entity.trialspawner.TrialSpawnerAccessor; @@ -46,54 +47,56 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(TrialSpawnerBlockEntity.class) .create(Keys.MAX_NEARBY_ENTITIES) - .get(h -> h.getTrialSpawner().getConfig().calculateTargetSimultaneousMobs(h.getTrialSpawner().getData().countAdditionalPlayers(h.getBlockPos()))) + .get(h -> h.getTrialSpawner().activeConfig().calculateTargetSimultaneousMobs(h.getTrialSpawner().getStateData().countAdditionalPlayers(h.getBlockPos()))) .create(Keys.NEXT_ENTITY_TO_SPAWN) - .get(h -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getData()).accessor$nextSpawnData().map(EntityUtil::toArchetype).orElse(null)) - .set((h, v) -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getData()).accessor$nextSpawnData(Optional.of(EntityUtil.toSpawnData(v)))) - .delete(h -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getData()).accessor$nextSpawnData(Optional.empty())) + .get(h -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getStateData()).accessor$nextSpawnData().map(EntityUtil::toArchetype).orElse(null)) + .set((h, v) -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getStateData()).accessor$nextSpawnData(Optional.of(EntityUtil.toSpawnData(v)))) + .delete(h -> ((TrialSpawnerDataAccessor) h.getTrialSpawner().getStateData()).accessor$nextSpawnData(Optional.empty())) .create(Keys.REMAINING_SPAWN_DELAY) - .get(h -> new SpongeTicks(((TrialSpawnerDataAccessor) h.getTrialSpawner().getData()).accessor$nextMobSpawnsAt() - h.getLevel().getGameTime())) + .get(h -> new SpongeTicks(((TrialSpawnerDataAccessor) h.getTrialSpawner().getStateData()).accessor$nextMobSpawnsAt() - h.getLevel().getGameTime())) .setAnd((h, v) -> { if (v.isInfinite()) { return false; } - ((TrialSpawnerDataAccessor) h.getTrialSpawner().getData()).accessor$nextMobSpawnsAt(h.getLevel().getGameTime() + v.ticks()); + ((TrialSpawnerDataAccessor) h.getTrialSpawner().getStateData()).accessor$nextMobSpawnsAt(h.getLevel().getGameTime() + v.ticks()); return true; }) .create(Keys.SPAWN_RANGE) - .get(h -> (double) h.getTrialSpawner().getConfig().spawnRange()) + .get(h -> (double) h.getTrialSpawner().activeConfig().spawnRange()) .set((h, v) -> { - final var normalConfig = h.getTrialSpawner().getNormalConfig(); - final var ominousConfig = h.getTrialSpawner().getOminousConfig(); + final var trialSpawner = h.getTrialSpawner(); + final var normalConfig = trialSpawner.normalConfig(); + final var ominousConfig = trialSpawner.ominousConfig(); final var newNormalConfig = new TrialSpawnerConfig(v.intValue(), normalConfig.totalMobs(), normalConfig.simultaneousMobs(), normalConfig.totalMobsAddedPerPlayer(), normalConfig.simultaneousMobsAddedPerPlayer(), normalConfig.ticksBetweenSpawn(), normalConfig.spawnPotentialsDefinition(), normalConfig.lootTablesToEject(), normalConfig.itemsToDropWhenOminous()); final var newOminiousConfig = new TrialSpawnerConfig(v.intValue(), ominousConfig.totalMobs(), ominousConfig.simultaneousMobs(), ominousConfig.totalMobsAddedPerPlayer(), ominousConfig.simultaneousMobsAddedPerPlayer(), ominousConfig.ticksBetweenSpawn(), ominousConfig.spawnPotentialsDefinition(), ominousConfig.lootTablesToEject(), ominousConfig.itemsToDropWhenOminous()); - final var accessor = (TrialSpawnerAccessor) (Object) h.getTrialSpawner(); - accessor.accessor$normalConfig(Holder.direct(newNormalConfig)); - accessor.accessor$ominousConfig(Holder.direct(newOminiousConfig)); + final var accessor = (TrialSpawnerAccessor) (Object) trialSpawner; + final var full = new TrialSpawner.FullConfig(Holder.direct(newNormalConfig), Holder.direct(newOminiousConfig), trialSpawner.getTargetCooldownLength(), trialSpawner.getRequiredPlayerRange()); + accessor.accessor$config(full); }) // TODO totalMobs // TODO simultaneousMobs // TODO totalMobsAddedPerPlayer // TODO simultaneousMobsAddedPerPlayer .create(Keys.MAX_SPAWN_DELAY) - .get(h -> new SpongeTicks(h.getTrialSpawner().getConfig().ticksBetweenSpawn())) + .get(h -> new SpongeTicks(h.getTrialSpawner().activeConfig().ticksBetweenSpawn())) // TODO set ticksBetweenSpawn .create(Keys.MIN_SPAWN_DELAY) - .get(h -> new SpongeTicks(h.getTrialSpawner().getConfig().ticksBetweenSpawn())) + .get(h -> new SpongeTicks(h.getTrialSpawner().activeConfig().ticksBetweenSpawn())) .create(Keys.SPAWNABLE_ENTITIES) - .get(h -> EntityUtil.toWeightedArchetypes(h.getTrialSpawner().getConfig().spawnPotentialsDefinition())) + .get(h -> EntityUtil.toWeightedArchetypes(h.getTrialSpawner().activeConfig().spawnPotentialsDefinition())) .set((h, v) -> { final var spawnPotentials = EntityUtil.toSpawnPotentials(v); - final var normalConfig = h.getTrialSpawner().getNormalConfig(); - final var ominousConfig = h.getTrialSpawner().getOminousConfig(); + final var trialSpawner = h.getTrialSpawner(); + final var normalConfig = h.getTrialSpawner().normalConfig(); + final var ominousConfig = h.getTrialSpawner().ominousConfig(); final var newNormalConfig = new TrialSpawnerConfig(normalConfig.spawnRange(), normalConfig.totalMobs(), normalConfig.simultaneousMobs(), normalConfig.totalMobsAddedPerPlayer(), normalConfig.simultaneousMobsAddedPerPlayer(), normalConfig.ticksBetweenSpawn(), spawnPotentials, normalConfig.lootTablesToEject(), normalConfig.itemsToDropWhenOminous()); final var newOminiousConfig = new TrialSpawnerConfig(ominousConfig.spawnRange(), ominousConfig.totalMobs(), ominousConfig.simultaneousMobs(), ominousConfig.totalMobsAddedPerPlayer(), ominousConfig.simultaneousMobsAddedPerPlayer(), ominousConfig.ticksBetweenSpawn(), spawnPotentials, ominousConfig.lootTablesToEject(), ominousConfig.itemsToDropWhenOminous()); final var accessor = (TrialSpawnerAccessor) (Object) h.getTrialSpawner(); - accessor.accessor$normalConfig(Holder.direct(newNormalConfig)); - accessor.accessor$ominousConfig(Holder.direct(newOminiousConfig)); + final var full = new TrialSpawner.FullConfig(Holder.direct(newNormalConfig), Holder.direct(newOminiousConfig), trialSpawner.getTargetCooldownLength(), trialSpawner.getRequiredPlayerRange()); + accessor.accessor$config(full); }); // TODO lootTablesToEject // TODO itemsToDropWhenOminous diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java index 03356948e4d..f948e7b8071 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java @@ -60,10 +60,10 @@ public static void register(final DataProviderRegistrator registrator) { final Map values = new HashMap<>(); values.put(BodyParts.HEAD.get(), VecHelper.toVector3d(h.getHeadPose())); values.put(BodyParts.CHEST.get(), VecHelper.toVector3d(h.getBodyPose())); - values.put(BodyParts.LEFT_ARM.get(), VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$leftArmPose())); - values.put(BodyParts.RIGHT_ARM.get(), VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$rightArmPose())); - values.put(BodyParts.LEFT_LEG.get(), VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$leftLegPose())); - values.put(BodyParts.RIGHT_LEG.get(), VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$rightLegPose())); + values.put(BodyParts.LEFT_ARM.get(), VecHelper.toVector3d(h.getLeftArmPose())); + values.put(BodyParts.RIGHT_ARM.get(), VecHelper.toVector3d(h.getRightArmPose())); + values.put(BodyParts.LEFT_LEG.get(), VecHelper.toVector3d(h.getLeftLegPose())); + values.put(BodyParts.RIGHT_LEG.get(), VecHelper.toVector3d(h.getRightLegPose())); return values; }) .set((h, v) -> { @@ -167,16 +167,16 @@ public static void register(final DataProviderRegistrator registrator) { ((ArmorStandAccessor) h).accessor$disabledSlots(disabledSlots); }) .create(Keys.LEFT_ARM_ROTATION) - .get(h -> VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$leftArmPose())) + .get(h -> VecHelper.toVector3d(h.getLeftArmPose())) .set((h, v) -> h.setLeftArmPose(VecHelper.toRotation(v))) .create(Keys.LEFT_LEG_ROTATION) - .get(h -> VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$leftLegPose())) + .get(h -> VecHelper.toVector3d(h.getLeftLegPose())) .set((h, v) -> h.setLeftLegPose(VecHelper.toRotation(v))) .create(Keys.RIGHT_ARM_ROTATION) - .get(h -> VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$rightArmPose())) + .get(h -> VecHelper.toVector3d(h.getRightArmPose())) .set((h, v) -> h.setRightArmPose(VecHelper.toRotation(v))) .create(Keys.RIGHT_LEG_ROTATION) - .get(h -> VecHelper.toVector3d(((ArmorStandAccessor) h).accessor$rightLegPose())) + .get(h -> VecHelper.toVector3d(h.getRightLegPose())) .set((h, v) -> h.setRightLegPose(VecHelper.toRotation(v))); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetypeBuilder.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetypeBuilder.java index 2f7d81e7e69..f6f91e0f9a4 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetypeBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetypeBuilder.java @@ -25,6 +25,8 @@ package org.spongepowered.common.entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -135,13 +137,14 @@ public EntityArchetype.Builder from(final Entity entity) { throw new IllegalArgumentException("Attempting to archetype a non-serializable entity: " + entity); } this.entityType = entityType; - final CompoundTag compound = new CompoundTag(); net.minecraft.world.entity.Entity mcEntity = (net.minecraft.world.entity.Entity) entity; + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, mcEntity.level().registryAccess()); if (entityType == SpongeEntityTypes.HUMAN) { - mcEntity.saveWithoutId(compound); + mcEntity.saveWithoutId(output); } else { - mcEntity.saveAsPassenger(compound); + mcEntity.saveAsPassenger(output); } + final CompoundTag compound = output.buildResult(); this.position = new Vector3d(mcEntity.getX(), mcEntity.getY(), mcEntity.getZ()); SpongeEntityArchetypeBuilder.stripCompound(compound); this.position = entity.position(); diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshot.java b/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshot.java index 8c658540cfa..43237b8b407 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshot.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshot.java @@ -25,6 +25,8 @@ package org.spongepowered.common.entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.storage.TagValueInput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -229,7 +231,8 @@ public Optional restore() { if (newEntity != null) { final net.minecraft.world.entity.Entity nmsEntity = (net.minecraft.world.entity.Entity) newEntity; if (this.compound != null) { - nmsEntity.load(this.compound); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, nmsEntity.level().registryAccess(), this.compound); + nmsEntity.load(input); } final boolean spawnResult = world.get().spawnEntity((Entity) nmsEntity); diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshotBuilder.java b/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshotBuilder.java index 9d8ae3d7715..71ded7a91c7 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshotBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntitySnapshotBuilder.java @@ -25,6 +25,8 @@ package org.spongepowered.common.entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -118,8 +120,10 @@ public SpongeEntitySnapshotBuilder from(final Entity entity) { this.entityType = entity.type(); this.uniqueId = entity.uniqueId(); this.manipulator = ((SpongeDataHolderBridge) entity).bridge$getManipulator().copy(); - this.compound = new CompoundTag(); - ((net.minecraft.world.entity.Entity) entity).saveWithoutId(this.compound); + final var mcEntity = (net.minecraft.world.entity.Entity) entity; + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, mcEntity.level().registryAccess()); + mcEntity.saveWithoutId(output); + this.compound = output.buildResult(); return this; } @@ -166,8 +170,9 @@ public SpongeEntitySnapshotBuilder from(final net.minecraft.world.entity.Entity this.rotation = transform.rotation(); this.scale = transform.scale(); this.manipulator = DataManipulator.mutableOf((Entity) minecraftEntity); - this.compound = new CompoundTag(); - minecraftEntity.saveWithoutId(this.compound); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, minecraftEntity.level().registryAccess()); + minecraftEntity.saveWithoutId(output); + this.compound = output.buildResult(); return this; } diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 66398d33327..e96f11ea028 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -70,6 +70,8 @@ import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import org.checkerframework.checker.nullness.qual.Nullable; @@ -188,23 +190,20 @@ public void setCustomName(final net.minecraft.network.chat.@Nullable Component n } @Override - public void readAdditionalSaveData(final CompoundTag tag) { + public void readAdditionalSaveData(final ValueInput tag) { super.readAdditionalSaveData(tag); - if (tag.contains("profile")) { - ResolvableProfile.CODEC - .parse(NbtOps.INSTANCE, tag.get("profile")) - .resultOrPartial($$0x -> SpongeCommon.logger().error("Failed to load profile from player head: {}", $$0x)) - .ifPresent(profile -> this.fakeProfile = profile); - - this.setUUID(this.fakeProfile.id().get()); - } + tag.read("profile", ResolvableProfile.CODEC) + .ifPresent(profile -> { + this.fakeProfile = profile; + this.setUUID(this.fakeProfile.id().get()); + }); } @Override - public void addAdditionalSaveData(final CompoundTag tag) { + public void addAdditionalSaveData(final ValueOutput tag) { super.addAdditionalSaveData(tag); final DataResult result = ResolvableProfile.CODEC.encodeStart(NbtOps.INSTANCE, this.fakeProfile); - result.ifSuccess(gameProfile -> tag.put("profile", gameProfile)); + result.ifSuccess(gameProfile -> tag.storeNullable("profile", ResolvableProfile.CODEC, this.fakeProfile)); } @Override diff --git a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java index 8efb348b388..67a1857b79c 100644 --- a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java +++ b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java @@ -29,17 +29,20 @@ import com.mojang.authlib.GameProfile; import net.minecraft.core.Rotations; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.util.datafix.DataFixers; +import net.minecraft.world.ItemStackWithSlot; import net.minecraft.world.inventory.PlayerEnderChestContainer; import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -201,8 +204,9 @@ public DataHolder.Mutable getDataHolder(final boolean markDirty) { private UserInventory loadInventory() { if (this.inventory == null) { this.inventory = new SpongeUserInventory(this); - final ListTag listNBT = this.compound.getListOrEmpty(Constants.Entity.Player.INVENTORY); - this.inventory.readList(listNBT); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, SpongeCommon.scopedHolder(), this.compound); + final var inventoryInput = input.listOrEmpty(Constants.Entity.Player.INVENTORY, ItemStackWithSlot.CODEC); + this.inventory.readList(inventoryInput); this.compound.getInt(Constants.Entity.Player.SELECTED_ITEM_SLOT) .ifPresent(slotId -> this.inventory.currentItem = slotId); } @@ -213,8 +217,9 @@ private SpongeUserData loadEnderInventory() { if (this.enderChest == null) { this.enderChest = new SpongeUserInventoryEnderchest(this); if (this.compound.contains(Constants.Entity.Player.ENDERCHEST_INVENTORY)) { - final ListTag nbttaglist1 = this.compound.getListOrEmpty(Constants.Entity.Player.ENDERCHEST_INVENTORY); - this.enderChest.fromTag(nbttaglist1, SpongeCommon.server().registryAccess()); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, SpongeCommon.scopedHolder(), this.compound); + final var enderChestItems = input.listOrEmpty(Constants.Entity.Player.ENDERCHEST_INVENTORY, ItemStackWithSlot.CODEC); + this.enderChest.fromSlots(enderChestItems); } } return this; @@ -228,7 +233,7 @@ public void readCompound(final CompoundTag compound) { .ifPresent(key -> this.worldKey = (ResourceKey) (Object) key); final var rotation = compound.read(Constants.Entity.ENTITY_ROTATION, Rotations.CODEC).orElse(new Rotations(0, 0, 0)); - final var position = compound.read(Constants.Entity.ENTITY_POSITION, Constants.Entity.ROTATIONS_CODEC).orElse(Vector3f.ZERO); + final var position = compound.read(Constants.Entity.ENTITY_POSITION, Constants.Entity.ENTITY_POSITION_CODEC).orElse(Vector3d.ZERO); this.x = position.x(); this.y = position.y(); this.z = position.z(); @@ -241,18 +246,22 @@ public void readCompound(final CompoundTag compound) { } public void writeCompound(final CompoundTag compound) { - - compound.putString(Constants.Sponge.World.WORLD_KEY, this.worldKey.formatted()); + final var holder = SpongeCommon.scopedHolder(); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, holder); + output.putString(Constants.Sponge.World.WORLD_KEY, this.worldKey.formatted()); this.loadInventory(); this.loadEnderInventory(); - compound.put(Constants.Entity.Player.INVENTORY, this.inventory.writeList(new ListTag())); - compound.put(Constants.Entity.Player.ENDERCHEST_INVENTORY, this.enderChest.createTag(SpongeCommon.server().registryAccess())); - compound.putInt(Constants.Entity.Player.SELECTED_ITEM_SLOT, this.inventory.currentItem); + final var inventory = output.list(Constants.Entity.Player.INVENTORY, ItemStackWithSlot.CODEC); + this.inventory.writeList(inventory); + final var enderChestInventory = output.list(Constants.Entity.Player.ENDERCHEST_INVENTORY, ItemStackWithSlot.CODEC); + this.enderChest.storeAsSlots(enderChestInventory); - compound.put(Constants.Entity.ENTITY_POSITION, Constants.NBT.newDoubleNBTList(this.x, this.y, this.z)); - compound.put(Constants.Entity.ENTITY_ROTATION, Constants.NBT.newFloatNBTList(this.yaw, this.pitch)); + output.putInt(Constants.Entity.Player.SELECTED_ITEM_SLOT, this.inventory.currentItem); + output.store(Constants.Entity.ENTITY_POSITION, Constants.Entity.ENTITY_POSITION_CODEC, new Vector3d(this.x, this.y, this.z)); + output.store(Constants.Entity.ENTITY_ROTATION, Constants.Entity.ROTATIONS_CODEC, new Vector3f(this.yaw, this.pitch, 0)); + compound.merge(output.buildResult()); if (DataUtil.syncDataToTag(this)) { compound.merge(this.data$getCompound()); diff --git a/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java b/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java index c2181f78502..fa199c1b852 100644 --- a/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java +++ b/src/main/java/org/spongepowered/common/entity/player/SpongeUserInventory.java @@ -26,12 +26,14 @@ import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; +import net.minecraft.world.ItemStackWithSlot; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.spongepowered.common.SpongeCommon; import java.util.Arrays; @@ -134,56 +136,55 @@ public void setItem(int index, final ItemStack stack) { * Writes the inventory out as a list of compound tags. This is where the slot indices are used (+100 for armor, +80 * for crafting). */ - public ListTag writeList(final ListTag nbtTagListIn) { + public void writeList(final ValueOutput.TypedOutputList nbtTagListIn) { for (int i = 0; i < this.mainInventory.size(); ++i) { - if (!this.mainInventory.get(i).isEmpty()) { - final CompoundTag nbttagcompound = new CompoundTag(); - nbttagcompound.putByte("Slot", (byte) i); - nbtTagListIn.add(this.mainInventory.get(i).save(SpongeCommon.server().registryAccess(), nbttagcompound)); + final var stack = this.mainInventory.get(i); + if (!stack.isEmpty()) { + final var slottedItem = new ItemStackWithSlot(i, stack); + nbtTagListIn.add(slottedItem); } } for (int j = 0; j < this.armorInventory.size(); ++j) { - if (!this.armorInventory.get(j).isEmpty()) { + final var armorItem = this.armorInventory.get(j); + if (!armorItem.isEmpty()) { final CompoundTag nbttagcompound1 = new CompoundTag(); nbttagcompound1.putByte("Slot", (byte) (j + 100)); - nbtTagListIn.add(this.armorInventory.get(j).save(SpongeCommon.server().registryAccess(), nbttagcompound1)); + final var slottedItem = new ItemStackWithSlot(j + 100, armorItem); + nbtTagListIn.add(slottedItem); } } for (int k = 0; k < this.offHandInventory.size(); ++k) { - if (!this.offHandInventory.get(k).isEmpty()) { + final var offhandItem = this.offHandInventory.get(k); + if (!offhandItem.isEmpty()) { final CompoundTag nbttagcompound2 = new CompoundTag(); nbttagcompound2.putByte("Slot", (byte) (k + 150)); - nbtTagListIn.add(this.offHandInventory.get(k).save(SpongeCommon.server().registryAccess(), nbttagcompound2)); + nbtTagListIn.add(new ItemStackWithSlot(k + 150, offhandItem)); } } this.dirty = false; - - return nbtTagListIn; } /** * Reads from the given tag list and fills the slots in the inventory with the correct items. */ - public void readList(final ListTag nbtTagListIn) { + public void readList(final ValueInput.TypedInputList nbtTagListIn) { this.mainInventory.clear(); this.armorInventory.clear(); this.offHandInventory.clear(); - for (int i = 0; i < nbtTagListIn.size(); i++) { - CompoundTag slotTag = nbtTagListIn.getCompoundOrEmpty(i); - int j = slotTag.getByteOr("Slot", (byte)0) & 255; - ItemStack itemstack = ItemStack.parse(SpongeCommon.server().registryAccess(), slotTag).orElse(ItemStack.EMPTY); - if (!itemstack.isEmpty()) { - if (j >= 0 && j < this.mainInventory.size()) { - this.mainInventory.set(j, itemstack); - } else if (j >= 100 && j < this.armorInventory.size() + 100) { - this.armorInventory.set(j - 100, itemstack); - } else if (j >= 150 && j < this.offHandInventory.size() + 150) { - this.offHandInventory.set(j - 150, itemstack); - } + for (final var input : nbtTagListIn) { + final var slot = input.slot(); + if (slot >= 0 && slot < this.mainInventory.size()) { + this.mainInventory.set(slot, input.stack()); + } else if (slot >= 100 && slot < this.armorInventory.size() + 100) { + this.armorInventory.set(slot - 100, input.stack()); + } else if (slot >= 150 && slot < this.offHandInventory.size() + 150) { + this.offHandInventory.set(slot - 150, input.stack()); + } else { + SpongeCommon.logger().warn("Skipping Slot {} as it does not exist in the inventory", slot); } } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/EntityPerformingDropsTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/EntityPerformingDropsTransaction.java index 99af9107277..e5218686581 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/EntityPerformingDropsTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/EntityPerformingDropsTransaction.java @@ -27,10 +27,12 @@ import com.google.common.collect.ImmutableList; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.damagesource.CombatEntry; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -71,9 +73,9 @@ protected void captureState() { final Entity entity = this.destroyingEntity; this.worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier((ServerLevel) entity.level(), "ServerLevel"); - final CompoundTag tag = new CompoundTag(); - entity.saveWithoutId(tag); - this.entityTag = tag; + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, entity.level().registryAccess()); + entity.saveWithoutId(output); + this.entityTag = output.buildResult(); final @Nullable DamageSource lastAttacker; if (entity instanceof LivingEntity) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/SpawnEntityTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/SpawnEntityTransaction.java index b053b9de402..e3f3435ade0 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/SpawnEntityTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/world/SpawnEntityTransaction.java @@ -27,7 +27,9 @@ import com.google.common.collect.ImmutableList; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -91,7 +93,9 @@ public SpawnEntityTransaction( @Override protected void captureState() { super.captureState(); - this.entityTag = this.entityToSpawn.saveWithoutId(new CompoundTag()); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, this.worldSupplier.get().registryAccess()); + this.entityToSpawn.saveWithoutId(output); + this.entityTag = output.buildResult(); } @Override diff --git a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java index b941acfe6e6..88e3b5db59e 100644 --- a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java @@ -180,6 +180,7 @@ public CompletableFuture sendTo(final EngineConnection connection, final P } } + @SuppressWarnings("deprecated") @Override public CompletableFuture sendToServer(final RequestPacket packet) { throw new UnsupportedOperationException( diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index db3dbb7b1f8..5349e93abb8 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -72,6 +72,7 @@ import org.spongepowered.api.entity.living.player.gamemode.GameModes; import org.spongepowered.api.util.Axis; import org.spongepowered.api.util.Direction; +import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3f; import org.spongepowered.math.vector.Vector3i; @@ -147,6 +148,7 @@ public static final class V2 { * {@link org.spongepowered.api.data.persistence.DataStore} based data */ public static final class V3 { + public static final String SPONGE_TAG_KEY = "sponge-data"; public static final DataQuery SPONGE_DATA_ROOT = DataQuery.of("sponge-data"); public static final DataQuery CONTENT_VERSION = DataQuery.of("version"); public static final DataQuery CONTENT = DataQuery.of("content"); @@ -740,6 +742,12 @@ public static final class Entity { // These are used by Minecraft's internals for entity spawning public static final String ENTITY_TYPE_ID = "id"; public static final String ENTITY_POSITION = "Pos"; + public static final Codec ENTITY_POSITION_CODEC = Codec.DOUBLE.listOf() + .comapFlatMap( + rawList -> Util.fixedSize(rawList, 3) + .map(list -> new Vector3d(list.get(0), list.get(1), list.get(2))), + vec -> List.of(vec.x(), vec.y(), vec.z()) + ); public static final String ENTITY_DIMENSION = "Dimension"; public static final String ENTITY_ROTATION = "Rotation"; public static final Codec ROTATIONS_CODEC = Codec.FLOAT diff --git a/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java b/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java index 7202b5871de..f3e86cdcbef 100644 --- a/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java +++ b/src/main/java/org/spongepowered/common/world/storage/SpongePlayerDataManager.java @@ -28,6 +28,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; +import net.minecraft.world.level.storage.ValueInput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Server; import org.spongepowered.api.data.Keys; @@ -52,20 +53,22 @@ public SpongePlayerDataManager(final Server server) { this.playersDirectory = ((SpongeWorldManager) this.server.worldManager()).getDefaultWorldDirectory().resolve("data").resolve(SpongePlayerDataManager.SPONGE_DATA); } - public void readLegacyPlayerData(final ServerPlayer playerEntity, final CompoundTag compound, @Nullable Instant creation) { + public void readLegacyPlayerData(final ServerPlayer playerEntity, final ValueInput compound, @Nullable Instant creation) { if (creation == null) { creation = Instant.now(); } Instant lastPlayed = creation; // first try to migrate bukkit join data stuff - if (compound.contains(Constants.Bukkit.BUKKIT)) { - final CompoundTag bukkitCompound = compound.getCompoundOrEmpty(Constants.Bukkit.BUKKIT); + final var bukkit = compound.child(Constants.Bukkit.BUKKIT); + if (bukkit.isPresent()) { + final var bukkitCompound = bukkit.get(); creation = Instant.ofEpochMilli(bukkitCompound.getLongOr(Constants.Bukkit.BUKKIT_FIRST_PLAYED, 0)); lastPlayed = Instant.ofEpochMilli(bukkitCompound.getLongOr(Constants.Bukkit.BUKKIT_LAST_PLAYED, 0)); } // migrate canary join data - if (compound.contains(Constants.Canary.ROOT)) { - final CompoundTag canaryCompound = compound.getCompoundOrEmpty(Constants.Canary.ROOT); + final var canary = compound.child(Constants.Canary.ROOT); + if (canary.isPresent()) { + final var canaryCompound = canary.get(); creation = Instant.ofEpochMilli(canaryCompound.getLongOr(Constants.Canary.FIRST_JOINED, 0)); lastPlayed = Instant.ofEpochMilli(canaryCompound.getLongOr(Constants.Canary.LAST_JOINED, 0)); } diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index acd61727b3a..68857b61851 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -32,6 +32,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.util.Tuple; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; @@ -49,6 +50,8 @@ import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.entity.EntitySection; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -241,8 +244,9 @@ public static BiConsumer getOrCloneEnti final Level level ) { return shouldCarbonCopy ? (pos, entity) -> { - final CompoundTag nbt = new CompoundTag(); - entity.save(nbt); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, level.registryAccess()); + entity.saveWithoutId(output); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, level.registryAccess(), output.buildResult()); final net.minecraft.world.entity.@Nullable Entity cloned = entity.getType().create(level, EntitySpawnReason.COMMAND); Objects.requireNonNull( cloned, @@ -250,7 +254,7 @@ public static BiConsumer getOrCloneEnti "EntityType[%s] creates a null Entity!", net.minecraft.world.entity.EntityType.getKey(entity.getType()) ) - ).load(nbt); + ).load(input); backingVolume.spawnEntity((org.spongepowered.api.entity.Entity) cloned); } : (pos, tile) -> { }; @@ -261,14 +265,16 @@ public static BiConsumer { - final CompoundTag nbt = tile.saveWithFullMetadata(tile.getLevel().registryAccess()); // TODO NPE possible? + final var registryAccess = tile.getLevel().registryAccess(); + final CompoundTag nbt = tile.saveWithFullMetadata(registryAccess); final BlockState state = tile.getBlockState(); final net.minecraft.world.level.block.entity.@Nullable BlockEntity cloned = tile.getType().create(pos, state); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, registryAccess, nbt); Objects.requireNonNull( cloned, () -> String.format( "TileEntityType[%s] creates a null TileEntity!", BlockEntityType.getKey(tile.getType())) - ).loadWithComponents(nbt, tile.getLevel().registryAccess()); // TODO NPE possible? + ).loadWithComponents(input); if (level != null) { ((BlockEntityAccessor) cloned).accessor$level(level); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/map/MapDecorationMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/map/MapDecorationMixin_API.java index e1a76fb46eb..c0710819bb3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/map/MapDecorationMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/map/MapDecorationMixin_API.java @@ -24,9 +24,15 @@ */ package org.spongepowered.common.mixin.api.minecraft.map; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.mojang.serialization.JsonOps; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.world.level.saveddata.maps.MapDecoration; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.map.decoration.MapDecorationType; @@ -35,6 +41,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.storage.MapDecorationBridge; import org.spongepowered.common.map.decoration.orientation.SpongeMapDecorationOrientation; @@ -56,6 +63,15 @@ public abstract class MapDecorationMixin_API implements org.spongepowered.api.ma @Shadow @Final private Optional name; // @formatter:on + @Unique + private static final Gson impl$gson = impl$gson(); + + @Unique + private static Gson impl$gson() { + final GsonBuilder builder = new GsonBuilder().disableHtmlEscaping(); + GsonComponentSerializer.gson().populator().apply(builder); + return builder.create(); + } @Override public MapDecorationType type() { @@ -106,7 +122,12 @@ public DataContainer toContainer() { .set(Constants.Map.DECORATION_X, this.x) .set(Constants.Map.DECORATION_Y, this.y) .set(Constants.Map.DECORATION_ROTATION, (byte) MapUtil.normalizeDecorationOrientation(this.rot)); - this.name.ifPresent(component -> data.set(Constants.Map.NAME, Component.Serializer.toJson(component, SpongeCommon.server().registryAccess()))); + this.name.ifPresent(component -> { + final var json = ComponentSerialization.CODEC + .encodeStart(SpongeCommon.scopedHolder().createSerializationContext(JsonOps.INSTANCE), component) + .getOrThrow(JsonParseException::new); + data.set(Constants.Map.NAME, impl$gson.toJson(json)); + }); return data; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index 52e72093668..8b5af7f1b05 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -29,17 +29,20 @@ import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.Relative; import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; @@ -105,7 +108,7 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.En @Shadow public abstract void shadow$setRemoved(Entity.RemovalReason var1); @Shadow public abstract void shadow$discard(); @Shadow public abstract void shadow$lookAt(EntityAnchorArgument.Anchor param0, Vec3 param1); - @Shadow public abstract CompoundTag shadow$saveWithoutId(CompoundTag $$0); + @Shadow public abstract void shadow$saveWithoutId(ValueOutput $$0); @Shadow public abstract Level shadow$level(); @Shadow public abstract Vec3 shadow$position(); // @formatter:on @@ -268,10 +271,10 @@ public int contentVersion() { @Override public DataContainer toContainer() { final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - final CompoundTag compound = new CompoundTag(); - compound.putString("id", entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()).toString()); - this.shadow$saveWithoutId(compound); - final DataContainer unsafeNbt = NBTTranslator.INSTANCE.translateFrom(compound); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, this.level.registryAccess()); + output.store("id", net.minecraft.world.entity.EntityType.CODEC, this.type); + this.shadow$saveWithoutId(output); + final DataContainer unsafeNbt = NBTTranslator.INSTANCE.translateFrom(output.buildResult()); final DataContainer container = DataContainer.createNew() .set(Queries.CONTENT_VERSION, this.contentVersion()) .set(Constants.Entity.CLASS, this.getClass().getName()) @@ -303,10 +306,11 @@ public org.spongepowered.api.entity.Entity copy() { } try { final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - final CompoundTag compound = new CompoundTag(); - compound.putString("id", entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()).toString()); - this.shadow$saveWithoutId(compound); - final Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, this.shadow$getCommandSenderWorld(), EntitySpawnReason.COMMAND, + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, this.level.registryAccess()); + output.putString("id", entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()).toString()); + this.shadow$saveWithoutId(output); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, this.level.registryAccess(), output.buildResult()); + final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(input, this.shadow$getCommandSenderWorld(), EntitySpawnReason.COMMAND, (createdEntity) -> { createdEntity.setUUID(UUID.randomUUID()); return createdEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 446756cfa4f..09146a1a2ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -26,10 +26,11 @@ import net.kyori.adventure.sound.Sound; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.util.ProblemReporter; import net.minecraft.util.Tuple; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.Level; @@ -43,6 +44,8 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.level.storage.LevelData; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.entity.BlockEntity; @@ -119,10 +122,12 @@ public abstract class LevelMixin_API, L extends Location entityTypeTest, net.minecraft.world.phys.AABB param1, @Nullable Predicate param2); + @Shadow public abstract RegistryAccess shadow$registryAccess(); // @formatter:on + private Context api$context; private RegistryHolderLogic api$registryHolder; protected @MonotonicNonNull SpongeChunkLayout api$chunkLayout; @@ -282,8 +287,9 @@ public void addBlockEntity(final int x, final int y, final int z, final BlockEnt // BlockEntity stores its location, as well as it being mutable and stuff, so just setting what we've given here // would cause unexpected bugs. final net.minecraft.world.level.block.entity.BlockEntity mcOriginalBlockEntity = (net.minecraft.world.level.block.entity.BlockEntity) Objects.requireNonNull(blockEntity, "blockEntity"); + final var output = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, this.shadow$registryAccess()); // Save the nbt so we can copy it, specifically wout the metadata of x,y,z coordinates - final CompoundTag tag = mcOriginalBlockEntity.saveWithId(mcOriginalBlockEntity.getLevel().registryAccess()); + mcOriginalBlockEntity.saveWithId(output); // Ensure that where we are placing this blockentity is the right blockstate, so that minecraft will actually accept it. this.world().setBlock(x, y, z, (org.spongepowered.api.block.BlockState) mcOriginalBlockEntity.getBlockState()); @@ -292,7 +298,8 @@ public void addBlockEntity(final int x, final int y, final int z, final BlockEnt .orElseThrow(() -> new IllegalStateException("Failed to create Block Entity at " + this.location(Vector3i.from(x, y, z)))); // Load the data into it. - mcNewBlockEntity.loadWithComponents(tag, mcOriginalBlockEntity.getLevel().registryAccess()); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, this.shadow$registryAccess(), output.buildResult()); + mcNewBlockEntity.loadWithComponents(input); // Finally, inform minecraft about our actions. this.shadow$setBlockEntity(mcNewBlockEntity); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java index d7d08227976..f8972753682 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java @@ -45,13 +45,13 @@ public void spawnImmediately(final boolean force) { } final var thisLevel = (ServerLevel) this.level; final var spawner = this.getTrialSpawner(); - final var spawnerData = (TrialSpawnerDataAccessor) spawner.getData(); - final var spawnerConfig = spawner.getConfig(); + final var spawnerData = (TrialSpawnerDataAccessor) spawner.getStateData(); + final var spawnerConfig = spawner.activeConfig(); - final var additionalPlayers = spawner.getData().countAdditionalPlayers(this.worldPosition); + final var additionalPlayers = spawner.getStateData().countAdditionalPlayers(this.worldPosition); final var nextSpawnAt = spawnerData.accessor$nextMobSpawnsAt(); spawnerData.accessor$nextMobSpawnsAt(0); - if (force || spawner.getData().isReadyToSpawnNextMob(thisLevel, spawnerConfig, additionalPlayers)) { + if (force || spawner.getStateData().isReadyToSpawnNextMob(thisLevel, spawnerConfig, additionalPlayers)) { // See TrialSpawnerState#tickAndGetNext spawner.spawnMob(thisLevel, this.worldPosition).ifPresent(spawned -> { spawnerData.accessor$currentMobs().add(spawned); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_API.java index 8bbfb8d251c..32e581416bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_API.java @@ -27,10 +27,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.storage.TagValueInput; import net.minecraft.world.phys.Vec3; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.block.BlockType; @@ -53,6 +55,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeArchetypeVolumeDataHolder; import org.spongepowered.common.data.persistence.NBTTranslator; import org.spongepowered.common.util.VecHelper; @@ -196,7 +199,8 @@ public VolumeStream blockEntityArchetypeS // TODO caching? private Stream api$buildEntityArchetypeList() { return this.entityInfoList.stream().map(info -> { - final Optional> by = EntityType.by(info.nbt); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, SpongeCommon.scopedHolder(), info.nbt); + final Optional> by = EntityType.by(input); if (by.isPresent()) { final DataContainer data = NBTTranslator.INSTANCE.translateFrom(info.nbt); final EntityArchetype archetype = EntityArchetype.builder().type((org.spongepowered.api.entity.EntityType) by.get()).entityData(data).build(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java index e7fa9067481..97824574f4a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java @@ -25,19 +25,20 @@ package org.spongepowered.common.mixin.core.network.chat; import com.google.gson.GsonBuilder; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin(net.minecraft.network.chat.Component.Serializer.class) +@Mixin(targets = "net/minecraft/network/codec/ByteBufCodecs$34") public abstract class Component_SerializerMixin { // inject into the anonymous function to build a gson instance - @Redirect(method = "", at = @At(value = "INVOKE", target = "com/google/gson/GsonBuilder.disableHtmlEscaping()Lcom/google/gson/GsonBuilder;", remap = false), remap = false) - private static GsonBuilder impl$injectAdventureGson(final GsonBuilder gson) { - gson.disableHtmlEscaping(); - GsonComponentSerializer.gson().populator().apply(gson); - return gson; + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "com/google/gson/GsonBuilder.disableHtmlEscaping()Lcom/google/gson/GsonBuilder;", remap = false), remap = false) + private static GsonBuilder impl$injectAdventureGson(GsonBuilder instance, Operation original) { + original.call(instance); + GsonComponentSerializer.gson().populator().apply(instance); + return instance; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index b306086991d..439f0ed7ae4 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -32,7 +32,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.Connection; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.MutableComponent; @@ -51,12 +50,14 @@ import net.minecraft.server.players.PlayerList; import net.minecraft.server.players.UserBanList; import net.minecraft.server.players.UserWhiteList; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.BorderChangeListener; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.level.storage.PlayerDataStorage; +import net.minecraft.world.level.storage.ValueInput; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.slf4j.Logger; @@ -152,7 +153,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Shadow @Final private PlayerDataStorage playerIo; @Shadow public abstract MinecraftServer shadow$getServer(); - @Shadow public abstract Optional shadow$load(final net.minecraft.server.level.ServerPlayer $$0); + @Shadow public abstract Optional shadow$load(final net.minecraft.server.level.ServerPlayer $$0, final ProblemReporter $$1); @Shadow public abstract boolean shadow$canBypassPlayerLimit(com.mojang.authlib.GameProfile param0); @Shadow protected abstract boolean shadow$verifyChatTrusted(final PlayerChatMessage $$0); @Shadow protected abstract void shadow$broadcastChatMessage(final PlayerChatMessage $$0, final Predicate $$1, @@ -249,11 +250,14 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/players/PlayerList;load(Lnet/minecraft/server/level/ServerPlayer;)Ljava/util/Optional;" + target = "Lnet/minecraft/server/players/PlayerList;load(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/util/ProblemReporter;)Ljava/util/Optional;" ) ) - private Optional impl$setPlayerDataForNewPlayers(final PlayerList playerList, final net.minecraft.server.level.ServerPlayer playerIn) { - final Optional compound = this.shadow$load(playerIn); + private Optional impl$setPlayerDataForNewPlayers( + final PlayerList playerList, final net.minecraft.server.level.ServerPlayer playerIn, + final ProblemReporter problemReporter + ) { + final Optional compound = this.shadow$load(playerIn, problemReporter); if (compound.isEmpty()) { final Instant now = Instant.now(); ((ServerPlayer) playerIn).offer(Keys.FIRST_DATE_JOINED, now); @@ -480,10 +484,10 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Redirect(method = "load", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;load(Lnet/minecraft/nbt/CompoundTag;)V" + target = "Lnet/minecraft/server/level/ServerPlayer;load(Lnet/minecraft/world/level/storage/ValueInput;)V" ) ) - private void impl$setSpongePlayerDataForSinglePlayer(final net.minecraft.server.level.ServerPlayer entity, final CompoundTag compound) { + private void impl$setSpongePlayerDataForSinglePlayer(final net.minecraft.server.level.ServerPlayer entity, final ValueInput compound) { entity.load(compound); if (((ServerPlayer) entity).get(Keys.FIRST_DATE_JOINED).isEmpty()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index e2dc0df2ed2..34d28462f2f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -54,6 +54,7 @@ import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -62,6 +63,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; @@ -184,7 +188,6 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract boolean shadow$onGround(); @Shadow @Nullable protected abstract String shadow$getEncodeId(); @Shadow @javax.annotation.Nullable public PortalProcessor portalProcess; - @Shadow public abstract boolean save(final CompoundTag $$0); @Shadow public abstract Level level(); // @formatter:on @@ -939,16 +942,25 @@ public void stopRiding() { } @Inject(method = "saveWithoutId", at = @At("RETURN")) - private void impl$WriteSpongeDataToCompound(final CompoundTag compound, final CallbackInfoReturnable ci) { - if (DataUtil.syncDataToTag(this)) { - compound.merge(this.data$getCompound()); + private void impl$WriteSpongeDataToCompound(final ValueOutput out, final CallbackInfo ci) { + if (out instanceof TagValueOutput tag) { + if (DataUtil.syncDataToTag(this)) { + // TODO - technically this shouldn't be used but we can access the build result + // here, ideally we may have to consider migrating the existing data serialization + // process to the new "style". + tag.buildResult().merge(this.data$getCompound()); + } } } @Inject(method = "load", at = @At("RETURN")) - private void impl$ReadSpongeDataFromCompound(final CompoundTag compound, final CallbackInfo ci) { + private void impl$ReadSpongeDataFromCompound(final ValueInput input, final CallbackInfo ci) { // TODO If we are in Forge data is already present - this.data$setCompound(compound); // For vanilla we set the incoming nbt + final var spongeData = input.read(Constants.Sponge.Data.V3.SPONGE_TAG_KEY, CustomData.CODEC); + if (spongeData.isEmpty()) { + return; + } + this.data$setCompound(spongeData.get().copyTag()); // For vanilla we set the incoming nbt // Deserialize custom data... DataUtil.syncTagToData(this); this.data$setCompound(null); // done reading diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index f511876a32c..48764abb719 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -27,9 +27,11 @@ import com.mojang.serialization.Dynamic; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; +import net.minecraft.util.ProblemReporter; import net.minecraft.util.RandomSource; import net.minecraft.util.datafix.DataFixers; import net.minecraft.util.datafix.fixes.References; @@ -52,6 +54,7 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.storage.LevelData; +import net.minecraft.world.level.storage.TagValueInput; import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.phys.AABB; import org.checkerframework.checker.nullness.qual.NonNull; @@ -107,10 +110,12 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { @Shadow public abstract boolean shadow$isRaining(); @Shadow public abstract net.minecraft.world.level.block.entity.@Nullable BlockEntity shadow$getBlockEntity(BlockPos p_175625_1_); @Shadow public abstract WorldBorder shadow$getWorldBorder(); + @Shadow public abstract RegistryAccess shadow$registryAccess(); //@Shadow protected abstract void shadow$postGameEventInRadius(@javax.annotation.Nullable net.minecraft.world.entity.Entity $$0, GameEvent $$1, BlockPos $$2, int $$3); // @formatter on + @Override public boolean bridge$isFake() { return this.isClientSide(); @@ -168,7 +173,9 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { final var e = ((net.minecraft.world.entity.Entity) createdEntity); // mimicing Entity#restoreFrom dataFixed.remove("Dimension"); - e.load((CompoundTag) dataFixed.getValue()); + final var tag = (CompoundTag) dataFixed.getValue(); + final var input = TagValueInput.create(ProblemReporter.DISCARDING, this.shadow$registryAccess(), tag); + e.load(input); // position needs a reset e.snapTo(proposedPosition.x(), proposedPosition.y(), proposedPosition.z()); }); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BlockEntityMixin.java index 0241fb2ec9c..9a8039c4793 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BlockEntityMixin.java @@ -25,11 +25,16 @@ package org.spongepowered.common.mixin.core.world.level.block.entity; import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.world.server.ServerWorld; @@ -44,16 +49,17 @@ import org.spongepowered.common.data.DataUtil; import org.spongepowered.common.data.provider.nbt.NBTDataType; import org.spongepowered.common.data.provider.nbt.NBTDataTypes; +import org.spongepowered.common.util.Constants; import java.util.StringJoiner; -@Mixin(net.minecraft.world.level.block.entity.BlockEntity.class) +@Mixin(BlockEntity.class) public abstract class BlockEntityMixin implements BlockEntityBridge, DataCompoundHolder { //@formatter:off @Shadow @Final private BlockEntityType type; @Shadow @Nullable private BlockState blockState; - @Shadow protected net.minecraft.world.level.Level level; + @Shadow protected Level level; @Shadow @Final protected BlockPos worldPosition; @Shadow public abstract BlockPos shadow$getBlockPos(); @@ -79,16 +85,25 @@ public abstract class BlockEntityMixin implements BlockEntityBridge, DataCompoun } @Inject(method = "saveMetadata", at = @At("RETURN")) - private void impl$writeSpongeData(final CompoundTag $$0, final CallbackInfo ci) { - if (DataUtil.syncDataToTag(this)) { - $$0.merge(this.data$getCompound()); + private void impl$writeSpongeData(final ValueOutput out, final CallbackInfo ci) { + if (out instanceof TagValueOutput tag) { + if (DataUtil.syncDataToTag(this)) { + // TODO - technically this shouldn't be used but we can access the build result + // here, ideally we may have to consider migrating the existing data serialization + // process to the new "style". + tag.buildResult().merge(this.data$getCompound()); + } } } @Inject(method = "loadWithComponents", at = @At("RETURN")) - private void impl$readSpongeData(final CompoundTag compound, HolderLookup.Provider $$1, final CallbackInfo ci) { + private void impl$readSpongeData(final ValueInput input, final CallbackInfo ci) { // TODO If we are in Forge data is already present - this.data$setCompound(compound); // For vanilla we set the incoming nbt + final var spongeData = input.read(Constants.Sponge.Data.V3.SPONGE_TAG_KEY, CustomData.CODEC); + if (spongeData.isEmpty()) { + return; + } + this.data$setCompound(spongeData.get().copyTag()); // For vanilla we set the incoming nbt // Deserialize custom data... DataUtil.syncTagToData(this); this.data$setCompound(null); // done reading diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java index 449b00f5283..a44d4984345 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.level.storage; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.storage.PlayerDataStorage; +import net.minecraft.world.level.storage.ValueInput; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.asm.mixin.Final; @@ -53,8 +53,8 @@ public abstract class PlayerDataStorageMixin { @Shadow @Final private File playerDir; // @formatter:on - @Redirect(method = "lambda$load$1", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;load(Lnet/minecraft/nbt/CompoundTag;)V")) - private void impl$readSpongePlayerData(final Player playerEntity, final CompoundTag compound) throws IOException { + @Redirect(method = "lambda$load$1", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;load(Lnet/minecraft/world/level/storage/ValueInput;)V")) + private void impl$readSpongePlayerData(final Player playerEntity, final ValueInput compound) throws IOException { playerEntity.load(compound); if (((ServerPlayer) playerEntity).get(Keys.FIRST_DATE_JOINED).isEmpty()) { final Path file = new File(this.playerDir, playerEntity.getStringUUID() + ".dat").toPath(); From 85d14d4abc6c8ea9133f5288d75fa2d236d7ed5a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 11 May 2025 10:16:02 -0700 Subject: [PATCH 258/586] feat(minecraft): update to 25w19a Notable changes: - EntityReferences abound, they're resolvable within the scope of a world that is being asked - Method rename for ServerPlayer.serverLevel() -> level(). See: https://minecraft.wiki/w/Java_Edition_25w19a --- SpongeAPI | 2 +- gradle.properties | 2 +- .../world/entity/animal/AnimalAccessor.java | 7 ++-- .../world/entity/item/PrimedTntAccessor.java | 3 +- .../entity/projectile/ProjectileAccessor.java | 37 ------------------- .../projectile/ShulkerBulletAccessor.java | 5 ++- .../entity/ConduitBlockEntityAccessor.java | 5 ++- .../resources/mixins.sponge.accessors.json | 1 - .../server/level/ServerPlayerBridge.java | 2 +- .../provider/block/entity/ConduitData.java | 21 +++++++++-- .../data/provider/entity/AnimalData.java | 5 ++- .../provider/entity/ServerPlayerData.java | 8 ++-- .../provider/entity/ShulkerBulletData.java | 12 +++++- .../common/data/provider/entity/TNTData.java | 3 +- .../inventory/InventoryEventFactory.java | 2 +- .../inventory/ContainerBasedTransaction.java | 2 +- .../inventory/CraftingPreviewTransaction.java | 2 +- .../phase/packet/PacketPhaseUtil.java | 2 +- .../player/AttackEntityPacketState.java | 9 ++--- .../player/InteractEntityPacketState.java | 6 +-- .../server/level/ServerPlayerMixin_API.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 18 ++++----- .../ServerGamePacketListenerImplMixin.java | 4 +- .../core/server/players/PlayerListMixin.java | 12 +++--- .../entity/projectile/EyeOfEnderMixin.java | 12 +++--- .../entity/projectile/ProjectileMixin.java | 8 ++-- .../entity/projectile/WitherSkullMixin.java | 3 +- .../level/ServerPlayerMixin_Inventory.java | 16 ++++---- .../ServerPlayerMixin_Shared_Inventory.java | 6 +-- ...GamePacketListenerImplMixin_Inventory.java | 14 +++---- ...erGamePacketListenerImplMixin_Tracker.java | 2 +- .../players/PlayerListMixin_Tracker.java | 4 +- .../entity/item/PrimedTntMixin_Tracker.java | 7 ++-- .../level/ServerPlayerMixin_Vanilla.java | 4 +- 34 files changed, 119 insertions(+), 131 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ProjectileAccessor.java diff --git a/SpongeAPI b/SpongeAPI index 3762c5eb472..7ec9a87f889 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3762c5eb4725052705efdab2ffa9791368a7d66e +Subproject commit 7ec9a87f889f0f4331438d5faa72b08a3026d873 diff --git a/gradle.properties b/gradle.properties index 05f3bb7dabf..a65167f004a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w18a +minecraftVersion=25w19a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/AnimalAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/AnimalAccessor.java index 2eeacc7a4ef..0e9cc08ac3d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/AnimalAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/AnimalAccessor.java @@ -24,17 +24,18 @@ */ package org.spongepowered.common.accessor.world.entity.animal; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.animal.Animal; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.UUID; @Mixin(Animal.class) public interface AnimalAccessor { - @Accessor("loveCause") UUID accessor$loveCause(); + @Accessor("loveCause") EntityReference accessor$loveCause(); - @Accessor("loveCause") void accessor$loveCause(final UUID loveCause); + @Accessor("loveCause") void accessor$loveCause(final EntityReference loveCause); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/item/PrimedTntAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/item/PrimedTntAccessor.java index 83b6c34bb07..ffc5a212e4f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/item/PrimedTntAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/item/PrimedTntAccessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.accessor.world.entity.item; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; import org.spongepowered.asm.mixin.Mixin; @@ -32,6 +33,6 @@ @Mixin(PrimedTnt.class) public interface PrimedTntAccessor { - @Accessor("owner") void accessor$owner(final LivingEntity owner); + @Accessor("owner") void accessor$owner(final EntityReference owner); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ProjectileAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ProjectileAccessor.java deleted file mode 100644 index 92ee000e10e..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ProjectileAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.entity.projectile; - -import net.minecraft.world.entity.projectile.Projectile; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.UUID; - -@Mixin(Projectile.class) -public interface ProjectileAccessor { - - @Accessor("ownerUUID") UUID accessor$ownerUUID(); -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ShulkerBulletAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ShulkerBulletAccessor.java index 0ef473a6dca..d607c02d1f4 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ShulkerBulletAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ShulkerBulletAccessor.java @@ -26,6 +26,7 @@ import net.minecraft.core.Direction; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.projectile.ShulkerBullet; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -34,9 +35,9 @@ @Mixin(ShulkerBullet.class) public interface ShulkerBulletAccessor { - @Accessor("finalTarget") Entity accessor$finalTarget(); + @Accessor("finalTarget") EntityReference accessor$finalTarget(); - @Accessor("finalTarget") void accessor$finalTarget(final Entity finalTarget); + @Accessor("finalTarget") void accessor$finalTarget(final EntityReference finalTarget); @Accessor("currentMoveDirection") @Nullable Direction accessor$currentMoveDirection(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/ConduitBlockEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/ConduitBlockEntityAccessor.java index 0846872d3af..ef9914cd4a3 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/ConduitBlockEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/ConduitBlockEntityAccessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.accessor.world.level.block.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.block.entity.ConduitBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; @@ -33,8 +34,8 @@ @Mixin(ConduitBlockEntity.class) public interface ConduitBlockEntityAccessor { - @Accessor("destroyTarget") @Nullable LivingEntity accessor$destroyTarget(); + @Accessor("destroyTarget") @Nullable EntityReference accessor$destroyTarget(); - @Accessor("destroyTarget") void accessor$setDestroyTarget(@Nullable LivingEntity target); + @Accessor("destroyTarget") void accessor$setDestroyTarget(@Nullable EntityReference target); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 364f69ba05c..312cc1ee549 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -127,7 +127,6 @@ "world.entity.projectile.EyeOfEnderAccessor", "world.entity.projectile.FireworkRocketEntityAccessor", "world.entity.projectile.FishingHookAccessor", - "world.entity.projectile.ProjectileAccessor", "world.entity.projectile.ShulkerBulletAccessor", "world.entity.raid.RaidAccessor", "world.entity.raid.RaiderAccessor", diff --git a/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java index 89fa19c7ce8..3eec12cdcab 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/level/ServerPlayerBridge.java @@ -102,7 +102,7 @@ public interface ServerPlayerBridge extends ServerPlayerEntityHealthScaleBridge isFlat, ((ServerPlayer) this).getLastDeathLocation(), ((ServerPlayer) this).getPortalCooldown(), - ((ServerPlayer) this).serverLevel().getSeaLevel() + ((ServerPlayer) this).level().getSeaLevel() ), dataToKeepMask)); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java index f07798b4bc5..ac5b47ea0ac 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java @@ -24,7 +24,11 @@ */ package org.spongepowered.common.data.provider.block.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.ConduitBlockEntity; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.Entity; import org.spongepowered.common.accessor.world.level.block.entity.ConduitBlockEntityAccessor; @@ -39,7 +43,18 @@ public static void register(final DataProviderRegistrator registrator) { //@formatter:off registrator.asMutable(ConduitBlockEntityAccessor.class) .create(Keys.TARGET_ENTITY) - .get(c -> (Entity) c.accessor$destroyTarget()) + .get(c -> { + final var conduit = (ConduitBlockEntity) c; + final @Nullable EntityReference target = c.accessor$destroyTarget(); + if (target == null) { + return null; + } + final @Nullable Level level = conduit.getLevel(); + if (level == null) { + return null; + } + return (Entity) target.getEntity(level, LivingEntity.class); + }) .deleteAnd(c -> { if (c.accessor$destroyTarget() == null) { return false; @@ -48,10 +63,10 @@ public static void register(final DataProviderRegistrator registrator) { return true; }) .setAnd((c, e) -> { - if (!(e instanceof LivingEntity)) { + if (!(e instanceof LivingEntity le)) { return false; } - c.accessor$setDestroyTarget((LivingEntity) e); + c.accessor$setDestroyTarget(new EntityReference<>(le)); return true; }); //@formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java index 23bc7a9e74d..62866334dcc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; import org.spongepowered.api.data.Keys; import org.spongepowered.common.accessor.world.entity.animal.AnimalAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -38,8 +39,8 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(AnimalAccessor.class) .create(Keys.BREEDER) - .get(AnimalAccessor::accessor$loveCause) - .set(AnimalAccessor::accessor$loveCause); + .get(a -> a.accessor$loveCause().getUUID()) + .set(((animalAccessor, uuid) -> animalAccessor.accessor$loveCause(new EntityReference<>(uuid)))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 1d238384131..5263916c19f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -133,20 +133,20 @@ private static void resendProfile(final ServerPlayer h) { // should work without this on ServerSideConnectionEvent.Login if (h.level().getEntity(h.getId()) == h && !h.isRemoved()) { // Remove Entity - h.serverLevel().getChunkSource().removeEntity(h); + h.level().getChunkSource().removeEntity(h); // Remove from TabList h.getServer().getPlayerList().broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(h.getUUID()))); // Add back to TabList h.getServer().getPlayerList().broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(h))); // Add Entity - h.serverLevel().getChunkSource().addEntity(h); + h.level().getChunkSource().addEntity(h); // Reconnect local player - final var commonSpawnInfo = h.createCommonSpawnInfo(h.serverLevel()); + final var commonSpawnInfo = h.createCommonSpawnInfo(h.level()); h.connection.send(new ClientboundRespawnPacket(commonSpawnInfo, (byte) 0)); // tp - just in case h.connection.teleport(h.getX(), h.getY(), h.getZ(), h.getYRot(), h.getXRot()); // resend remaining player data... (see ServerPlayer#changeDimension) - h.connection.send(new ClientboundChangeDifficultyPacket(h.serverLevel().getLevelData().getDifficulty(), h.serverLevel().getLevelData().isDifficultyLocked())); + h.connection.send(new ClientboundChangeDifficultyPacket(h.level().getLevelData().getDifficulty(), h.level().getLevelData().isDifficultyLocked())); h.connection.send(new ClientboundPlayerAbilitiesPacket(h.getAbilities())); final PlayerList playerList = h.getServer().getPlayerList(); playerList.sendAllPlayerInfo(h); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java index 48785ff85dd..1f4fedc565a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.projectile.ShulkerBullet; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.util.Direction; @@ -44,8 +46,14 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.accessor$currentMoveDirection() == null ? Direction.NONE : Constants.DirectionFunctions.getFor(h.accessor$currentMoveDirection())) .set((h, v) -> h.accessor$currentMoveDirection(Constants.DirectionFunctions.getFor(v))) .create(Keys.TARGET_ENTITY) - .get(h -> (Entity) h.accessor$finalTarget()) - .set((h, v) -> h.accessor$finalTarget((net.minecraft.world.entity.Entity) v)); + .get(h -> { + final var target = h.accessor$finalTarget(); + if (target == null || ((ShulkerBullet) h).level() == null) { + return null; + } + return (Entity) target.getEntity(((ShulkerBullet) h).level(), net.minecraft.world.entity.Entity.class); + }) + .set((h, v) -> h.accessor$finalTarget(new EntityReference<>((net.minecraft.world.entity.Entity) v))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java index cac00f141a5..3136f6d8903 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; import org.spongepowered.api.block.BlockState; @@ -43,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(PrimedTnt.class) .create(Keys.DETONATOR) .get(h -> (Living) h.getOwner()) - .set((h, v) -> ((PrimedTntAccessor) h).accessor$owner((LivingEntity) v)) + .set((h, v) -> ((PrimedTntAccessor) h).accessor$owner(new EntityReference<>((LivingEntity) v))) .create(Keys.BLOCK_STATE) .get(h -> (BlockState) h.getBlockState()) .set((h, v) -> h.setBlockState((net.minecraft.world.level.block.state.BlockState) v)); diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index ffc7b0f198c..4c02f7f3f8b 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -230,7 +230,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player, final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(menu.getCarried()); final Transaction cursorTransaction = new Transaction<>(ItemStackSnapshot.empty(), newCursor); final InteractContainerEvent.Open event = - SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getWorldInstance(player.serverLevel()).currentCause(), + SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getWorldInstance(player.level()).currentCause(), (org.spongepowered.api.item.inventory.Container) player.containerMenu, cursorTransaction); SpongeCommon.post(event); if (event.isCancelled()) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java index 0dd6d67cd58..3afcf2c413a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java @@ -288,7 +288,7 @@ private void handleCraftingPreview(final Player player, final ClickContainerEven // TODO push event to cause? // TODO prevent event when there is no preview? final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), event.transactions()); - final var recipe = sp.serverLevel().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); + final var recipe = sp.level().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); final CraftItemEvent.Preview previewEvent = SpongeEventFactory.createCraftItemEventPreview(event.cause(), (Container) this.menu, this.craftingInventory, event.cursorTransaction(), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), event.transactions()); SpongeCommon.post(previewEvent); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java index f244054dca7..7b488255d1d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java @@ -76,7 +76,7 @@ Optional createInventoryEvent(final List s } final ItemStackSnapshot cursor = ItemStackUtil.snapshotOf(this.player.containerMenu.getCarried()); final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), slotTransactions); - final var recipe = sp.serverLevel().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftSlots.asCraftInput(), this.player.level()); + final var recipe = sp.level().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftSlots.asCraftInput(), this.player.level()); final CraftItemEvent.Preview event = SpongeEventFactory.createCraftItemEventPreview(currentCause, ContainerUtil.fromNative(this.menu), this.craftingInventory, new Transaction<>(cursor, cursor), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index eb890959bf3..4ad24719405 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -258,7 +258,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n } else { final IPhaseState> packetState = PacketPhase.getInstance().getStateForPacket(packetIn); // At the very least make an unknown packet state case. - final PacketContext context = packetState.createPhaseContext(PhaseTracker.getWorldInstance(packetPlayer.serverLevel())); + final PacketContext context = packetState.createPhaseContext(PhaseTracker.getWorldInstance(packetPlayer.level())); context.source(packetPlayer) .packetPlayer(packetPlayer) .packet(packetIn); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java index ff50d7dc6b1..ec7bc34185d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java @@ -26,7 +26,6 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.LivingEntity; @@ -54,7 +53,7 @@ public final class AttackEntityPacketState extends BasicPacketState { frame.addContext(EventContextKeys.USED_ITEM, ctx.getItemUsedSnapshot()); final ServerboundInteractPacket useEntityPacket = ctx.getPacket(); final ServerPlayer player = ctx.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.serverLevel()); + final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); if (entity != null) { // hand is not populated if we don't have an entity in scope that caused this. frame.addContext(EventContextKeys.USED_HAND, ctx.getHandUsed()); @@ -73,7 +72,7 @@ public boolean isPacketIgnored(final Packet packetIn, final ServerPlayer pack final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packetIn; // There are cases where a player is interacting with an entity that // doesn't exist on the server. - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget((ServerLevel) packetPlayer.level()); + final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(packetPlayer.level()); return entity == null; } @@ -89,7 +88,7 @@ public Supplier getSpawnTypeForTransaction( ) { final ServerboundInteractPacket useEntityPacket = context.getPacket(); final ServerPlayer player = context.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.serverLevel()); + final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); if (entity != null && (entity.isRemoved() || entity instanceof LivingEntity && ((LivingEntity) entity).isDeadOrDying())) { return entityToSpawn instanceof ExperienceOrb ? SpawnTypes.EXPERIENCE : SpawnTypes.DROPPED_ITEM; } @@ -104,7 +103,7 @@ public void unwind(final BasicPacketContext context) { if (!TrackingUtil.processBlockCaptures(context)) { final ServerboundInteractPacket useEntityPacket = context.getPacket(); final ServerPlayer player = context.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.serverLevel()); + final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); if (entity instanceof Entity) { ((Entity) entity).offer(Keys.NOTIFIER, player.getUUID()); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java index a4c42910665..50e3268b092 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java @@ -47,14 +47,14 @@ public final class InteractEntityPacketState extends BasicPacketState { public boolean isPacketIgnored(final Packet packetIn, final ServerPlayer packetPlayer) { final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packetIn; // There are cases where a player is interacting with an entity that doesn't exist on the server. - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(packetPlayer.serverLevel()); + final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(packetPlayer.level()); return entity == null; } @Override public void populateContext(final ServerPlayer player, final Packet packet, final BasicPacketContext context) { final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packet; - final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.serverLevel()); + final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.level()); if (entity != null) { final ServerboundInteractPacket_InteractionActionAccessor accessor = (ServerboundInteractPacket_InteractionActionAccessor) ((ServerboundInteractPacketAccessor) useEntityPacket).accessor$action(); final ItemStack stack = ItemStackUtil.cloneDefensive(player.getItemInHand(accessor.accessor$hand())); @@ -72,7 +72,7 @@ public void unwind(final BasicPacketContext phaseContext) { final ServerPlayer player = phaseContext.getPacketPlayer(); final ServerboundInteractPacket useEntityPacket = phaseContext.getPacket(); - final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.serverLevel()); + final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.level()); if (entity == null) { // Something happened? return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java index 88d561a5167..a52290e1163 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java @@ -106,7 +106,7 @@ public abstract class ServerPlayerMixin_API extends PlayerMixin_API implements S @Shadow @Final private PlayerAdvancements advancements; @Shadow public ServerGamePacketListenerImpl connection; - @Shadow public abstract net.minecraft.server.level.ServerLevel shadow$serverLevel(); + @Shadow public abstract net.minecraft.server.level.@NonNull ServerLevel shadow$level(); @Shadow public abstract void shadow$sendSystemMessage(final net.minecraft.network.chat.Component $$0); // @formatter:on @@ -119,7 +119,7 @@ public abstract class ServerPlayerMixin_API extends PlayerMixin_API implements S @Override public ServerWorld world() { - return (ServerWorld) this.shadow$serverLevel(); + return (ServerWorld) this.shadow$level(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 6dad8add329..6e754a253ee 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -175,7 +175,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Shadow private float lastSentHealth; @Shadow private int lastSentFood; - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); @Shadow protected abstract void shadow$triggerDimensionChangeTriggers(ServerLevel serverworld); @Shadow public abstract void shadow$doCloseContainer(); @Shadow public abstract boolean shadow$setGameMode(GameType param0); @@ -325,7 +325,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Override public boolean bridge$keepInventory() { - return Objects.requireNonNullElseGet(this.impl$keepInventory, () -> this.shadow$serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)); + return Objects.requireNonNullElseGet(this.impl$keepInventory, () -> this.shadow$level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)); } @Override @@ -461,7 +461,7 @@ public boolean teleportTo(final ServerLevel world, } final var originalNewLevel = originalTransition.newLevel(); - final var oldLevel = this.shadow$serverLevel(); + final var oldLevel = this.shadow$level(); // SpongeStart final var transition = this.impl$fireDimensionTransitionEvents(originalTransition, thisPlayer); @@ -533,10 +533,10 @@ public boolean teleportTo(final ServerLevel world, final net.minecraft.server.level.ServerPlayer thisPlayer ) { var transition = originalTransition; - var isDimensionChange = transition.newLevel() != thisPlayer.serverLevel(); + var isDimensionChange = transition.newLevel() != thisPlayer.level(); if (!this.impl$moveEventsFired) { - final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(thisPlayer.serverLevel()); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(thisPlayer.level()); final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange() .player(); final boolean hasMovementContext = phaseTracker.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); @@ -570,7 +570,7 @@ public boolean teleportTo(final ServerLevel world, } } - final var reposition = this.bridge$fireRepositionEvent((ServerWorld) thisPlayer.serverLevel(), (ServerWorld) transition.newLevel(), originalDest); + final var reposition = this.bridge$fireRepositionEvent((ServerWorld) thisPlayer.level(), (ServerWorld) transition.newLevel(), originalDest); if (reposition.isCancelled()) { return null; // we did not move yet so just return } @@ -959,7 +959,7 @@ public void sendMessage(final OutgoingChatMessage $$0, final boolean $$1, final */ @Overwrite private boolean isPvpAllowed() { - return ((ServerWorld) this.shadow$serverLevel()).properties().pvp(); + return ((ServerWorld) this.shadow$level()).properties().pvp(); } /** @@ -987,11 +987,11 @@ private boolean isPvpAllowed() { if (playerRespawnDestination == null) { SpongeCommon.logger().warn("The player '{}' respawn location was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", player.getGameProfile().getName()); - playerRespawnDestination = player.server.overworld(); + playerRespawnDestination = player.getServer().overworld(); } final RespawnPlayerEvent.SelectWorld event = SpongeEventFactory.createRespawnPlayerEventSelectWorld(PhaseTracker.getInstance().currentCause(), - (ServerWorld) playerRespawnDestination, (ServerWorld) player.serverLevel(), (ServerWorld) playerRespawnDestination, (ServerPlayer) player); + (ServerWorld) playerRespawnDestination, (ServerWorld) player.level(), (ServerWorld) playerRespawnDestination, (ServerPlayer) player); SpongeCommon.post(event); this.impl$respawnLevel = (ServerLevel) event.destinationWorld(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index ae99dc0f340..6c60e4f30cd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -397,7 +397,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack if (ShouldFire.INTERACT_ITEM_EVENT_PRIMARY) { final Vec3 startPos = this.player.getEyePosition(1); final Vec3 endPos = startPos.add(this.player.getLookAngle().scale(5d)); // TODO hook for blockReachDistance? - final HitResult result = this.player.serverLevel().clip(new ClipContext(startPos, endPos, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); + final HitResult result = this.player.level().clip(new ClipContext(startPos, endPos, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); if (result.getType() == HitResult.Type.MISS) { final ItemStack heldItem = this.player.getItemInHand(hand); SpongeCommonEventFactory.callInteractItemEventPrimary(this.player, heldItem, hand); @@ -445,7 +445,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack return; // prevents Mismatch in destroy block pos warning } } - final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.player.serverLevel()); + final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.player.level()); try (final CauseStackManager.StackFrame frame = tracker.pushCauseFrame(); final PhaseContext context = PlayerPhase.State.PLAYER_INTERACT.createPhaseContext(tracker) .creator(this.player.getUUID()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 439f0ed7ae4..c92827a40e2 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -344,7 +344,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { private void impl$onInitPlayer_printPlayerWorldInJoinFeedback(final org.slf4j.Logger logger, final String s, final Object[] objects, final Connection conn, final net.minecraft.server.level.ServerPlayer player) { logger.info("{}[{}] logged in to world '{}' with entity id {} at ({}, {}, {})", player.getName().getString(), player, - ((ServerWorld)player.serverLevel()).key(), player.getId(), player.getX(), player.getY(), player.getZ()); + ((ServerWorld)player.level()).key(), player.getId(), player.getX(), player.getY(), player.getZ()); } @Redirect(method = "placeNewPlayer", @@ -386,13 +386,13 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Redirect(method = "placeNewPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/server/players/PlayerList;viewDistance:I")) private int impl$usePerWorldViewDistance(final PlayerList self, final Connection co, final net.minecraft.server.level.ServerPlayer player, final CommonListenerCookie cookie) { - return ((ServerLevelDataBridge) player.serverLevel().getLevelData()).bridge$viewDistance().orElse(self.getViewDistance()); + return ((ServerLevelDataBridge) player.level().getLevelData()).bridge$viewDistance().orElse(self.getViewDistance()); } @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getCustomBossEvents()Lnet/minecraft/server/bossevents/CustomBossEvents;")) private CustomBossEvents impl$getPerWorldBossBarManager( final MinecraftServer minecraftServer, final Connection netManager, final net.minecraft.server.level.ServerPlayer playerIn) { - return ((ServerLevelBridge) playerIn.serverLevel()).bridge$getBossBarManager(); + return ((ServerLevelBridge) playerIn.level()).bridge$getBossBarManager(); } @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;updateEntireScoreboard(Lnet/minecraft/server/ServerScoreboard;Lnet/minecraft/server/level/ServerPlayer;)V")) @@ -449,7 +449,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ((ServerPlayerBridge) mcPlayer).bridge$setConnectionMessageToSend(null); - final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(mcPlayer.serverLevel()); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(mcPlayer.level()); final PhaseContext context = phaseTracker.getPhaseContext(); phaseTracker.pushCause(event); final TransactionalCaptureSupplier transactor = context.getTransactor(); @@ -461,7 +461,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Redirect(method = "remove", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getCustomBossEvents()Lnet/minecraft/server/bossevents/CustomBossEvents;")) private CustomBossEvents impl$getPerWorldBossBarManager(final MinecraftServer minecraftServer, final net.minecraft.server.level.ServerPlayer playerIn) { - return ((ServerLevelBridge) playerIn.serverLevel()).bridge$getBossBarManager(); + return ((ServerLevelBridge) playerIn.level()).bridge$getBossBarManager(); } @Inject(method = "remove", at = @At("HEAD")) @@ -557,7 +557,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { private void impl$callRespawnPlayerPostEvent(final net.minecraft.server.level.ServerPlayer player, final boolean $$1, final Entity.RemovalReason $$2, final CallbackInfoReturnable cir, final @Local TeleportTransition dimensionTransition) { final ServerPlayer recreatedPlayer = (ServerPlayer) cir.getReturnValue(); - final ServerWorld originalWorld = (ServerWorld) player.serverLevel(); + final ServerWorld originalWorld = (ServerWorld) player.level(); final RespawnPlayerEvent.Post event = SpongeEventFactory.createRespawnPlayerEventPost(PhaseTracker.getInstance().currentCause(), recreatedPlayer.world(), originalWorld, (ServerWorld) dimensionTransition.newLevel(), recreatedPlayer); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java index bf3c3ba5950..214776a127a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity.projectile; import net.minecraft.world.entity.projectile.EyeOfEnder; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -32,27 +33,24 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.LocationTargetingBridge; import org.spongepowered.common.mixin.core.world.entity.EntityMixin; +import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; @Mixin(EyeOfEnder.class) public abstract class EyeOfEnderMixin extends EntityMixin implements LocationTargetingBridge { // @formatter:off - @Shadow private double tx; - @Shadow private double ty; - @Shadow private double tz; + @Shadow private Vec3 target; // @formatter:on @Override public Vector3d bridge$getTargetedPosition() { - return new Vector3d(this.tx, this.ty, this.tz); + return VecHelper.toVector3d(this.target); } @Override public void bridge$setTargetedPosition(final Vector3d vec) { - this.tx = vec.x(); - this.ty = vec.y(); - this.tz = vec.z(); + this.target = VecHelper.toVanillaVector3d(vec); } @Inject( diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java index 528084809f8..eac9e4edf8d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity.projectile; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.projectile.ProjectileDeflection; import net.minecraft.world.phys.HitResult; @@ -48,13 +49,12 @@ public abstract class ProjectileMixin extends EntityMixin { // @formatter:off - @Shadow protected abstract void shadow$onHit(HitResult result); - @Shadow public abstract void shadow$setOwner(@Nullable Entity p_212361_1_); @Shadow public abstract @Nullable Entity shadow$getOwner(); @Shadow protected abstract ProjectileDeflection shadow$hitTargetOrDeflectSelf(HitResult result); - @Shadow protected abstract void onHit(HitResult result); + @Shadow @Nullable protected EntityReference owner; // @formatter:on + private ProjectileSource impl$projectileSource = UnknownProjectileSource.UNKNOWN; protected ProjectileSource impl$getProjectileSource() { @@ -68,7 +68,7 @@ public abstract class ProjectileMixin extends EntityMixin { return this.impl$projectileSource; } - @Inject(method = "setOwner", at = @At("RETURN")) + @Inject(method = "setOwner(Lnet/minecraft/world/entity/Entity;)V", at = @At("RETURN")) private void impl$assignProjectileSource(final @Nullable Entity owner, final CallbackInfo ci) { this.impl$projectileSource = owner == null ? UnknownProjectileSource.UNKNOWN : (EntityProjectileSource) owner; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java index 2d5f2c81f2a..5a93b6709a6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java @@ -36,7 +36,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.accessor.world.entity.projectile.ProjectileAccessor; import org.spongepowered.common.bridge.explosives.ExplosiveBridge; import org.spongepowered.common.bridge.world.entity.projectile.WitherSkullBridge; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -59,7 +58,7 @@ public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin im if (this.impl$damageSet) { return this.impl$damage; } - if (((ProjectileAccessor) this).accessor$ownerUUID() != null) { + if (this.owner != null) { return Constants.Entity.WitherSkull.DEFAULT_WITHER_CREATED_SKULL_DAMAGE; } return Constants.Entity.WitherSkull.DEFAULT_NO_SOURCE_SKULL_DAMAGE; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 08d448e0be5..5251c8a80d8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -95,7 +95,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Nullable private EffectTransactor inventory$effectTransactor = null; @Nullable private Object inventory$menuProvider; - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // @formatter:on // Ignore @@ -107,7 +107,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void inventory$wrapSetSlotWithTransaction(EquipmentSlot slot, ItemStack item, Operation original) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final PlayerInventoryTransaction.EventCreator eventCreator = context.getState() instanceof SwapHandItemsState ? PlayerInventoryTransaction.EventCreator.SWAP_HAND : PlayerInventoryTransaction.EventCreator.STANDARD; @@ -123,7 +123,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Inject(method = "drop(Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;removeFromSelected(Z)Lnet/minecraft/world/item/ItemStack;")) protected void impl$beforeRemoveItem(final boolean param0, final CallbackInfoReturnable cir) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); this.inventory$effectTransactor = transactor.logDropFromPlayerInventory((ServerPlayer) (Object) this, param0); } @@ -147,7 +147,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory entity.playerTouch(player); return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); try (final EffectTransactor ignored = context.getTransactor().logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { entity.playerTouch(player); this.inventoryMenu.broadcastChanges(); // capture @@ -162,7 +162,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void inventory$onUpdateUsingItem(final LivingEntity thisPlayer) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect((ServerPlayer) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD)) { this.shadow$completeUsingItem(); @@ -181,7 +181,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory ) ) private void impl$afterOpenHorseInventory(final AbstractHorse $$0, final Container $$1, final CallbackInfo ci) { - PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() + PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext() .getTransactor() .logContainerSet((ServerPlayer) (Object) this); } @@ -251,7 +251,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @WrapMethod(method = "doCloseContainer") private void impl$onPreDoCloseContainer(final Operation original) { - final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$serverLevel()); + final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$level()); final ItemStackSnapshot resultingCursor = ItemStackUtil.snapshotOf(this.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(resultingCursor, resultingCursor); final InteractContainerEvent.Close event = SpongeEventFactory.createInteractContainerEventClosePre( @@ -286,7 +286,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @WrapOperation(method = "doCloseContainer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;removed(Lnet/minecraft/world/entity/player/Player;)V")) private void impl$onDoCloseContainerCaptureRemoval(final AbstractContainerMenu instance, final Player player, final Operation original) { - final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$serverLevel()); + final PhaseTracker tracker = PhaseTracker.getWorldInstance(this.shadow$level()); final PhaseContext<@NonNull ?> context = tracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCloseInventory(context, player)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java index 3009ea343da..54964203714 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java @@ -55,7 +55,7 @@ public abstract class ServerPlayerMixin_Shared_Inventory extends PlayerMixin_Inventory { // @formatter:off - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // @formatter:on @Nullable private Object inventory$menuProvider; @@ -74,7 +74,7 @@ protected ServerPlayerMixin_Shared_Inventory(final EntityType param0, final L ) ) private void impl$afterOpenMenu(final CallbackInfoReturnable cir) { - PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); + PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); } @Inject(method = "openMenu", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initMenu(Lnet/minecraft/world/inventory/AbstractContainerMenu;)V")) @@ -100,7 +100,7 @@ protected ServerPlayerMixin_Shared_Inventory(final EntityType param0, final L final MenuProvider menuProvider, final int containerCounter, final net.minecraft.world.entity.player.Inventory inventory, final Player player, final Operation original, final @Cancellable CallbackInfoReturnable cir ) { - final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); try (final EffectTransactor ignored = context.getTransactor().logOpenInventory((ServerPlayer) (Object) this)) { final AbstractContainerMenu menu = original.call(menuProvider, containerCounter, inventory, player); context.containerLocation().ifPresent(((ContainerBridge) menu)::bridge$setOpenLocation); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index 596f426f381..f905b0dfa25 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -66,7 +66,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/InventoryMenu;broadcastChanges()V")) private void impl$onBroadcastCreativeActionResult(final InventoryMenu inventoryMenu, final ServerboundSetCreativeModeSlotPacket packetIn) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final ItemStack itemstack = packetIn.itemStack(); @@ -79,7 +79,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Lnet/minecraft/world/item/ItemStack;Z)Lnet/minecraft/world/entity/item/ItemEntity;")) private ItemEntity impl$onBroadcastCreativeActionResult(final ServerPlayer serverPlayer, final ItemStack stack, final boolean param1) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCreativeClickContainer(-1, ItemStackUtil.snapshotOf(stack), this.player)) { return serverPlayer.drop(stack, param1); @@ -92,7 +92,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;stopUsingItem()V")) ) private void impl$onHandleSetCarriedItem(final ServerboundSetCarriedItemPacket packet, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final int slotIdx = packet.getSlot(); transactor.logPlayerCarriedItem(this.player, slotIdx); @@ -101,7 +101,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleContainerClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;sendAllDataToRemote()V")) private void impl$onSpectatorClick(final AbstractContainerMenu menu, final ServerboundContainerClickPacket packet) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.slotNum(), packet.buttonNum(), packet.clickType(), this.player @@ -120,7 +120,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItem(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) private InteractionResult impl$onHandleUseItem(final ServerPlayerGameMode serverPlayerGameMode, final ServerPlayer param0, final Level param1, final ItemStack param2, final InteractionHand param3) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logSecondaryInteractItemTransaction(param0, param2)) { final var pipeline = ((TrackedWorldBridge) param1).bridge$startItemInteractionUseChange(param1, param0, param3, param2); @@ -131,7 +131,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleRenameItem(Lnet/minecraft/network/protocol/game/ServerboundRenameItemPacket;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AnvilMenu;setItemName(Ljava/lang/String;)Z")) private boolean impl$onHandleRenameItem(final AnvilMenu menu, final String name) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final var ignored = transactor.logIgnoredInventory(this.player.containerMenu)) { return menu.setItemName(name); @@ -141,7 +141,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Inject(method = "handleSelectTrade", at = @At("RETURN")) private void impl$onHandleSelectTrade(final ServerboundSelectTradePacket param0, final CallbackInfo ci) { if (this.player.containerMenu instanceof MerchantMenu) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logSelectTrade(this.player, param0.getItem()); this.player.containerMenu.broadcastChanges(); // capture diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java index 2fb2e423001..1d3906024cb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java @@ -61,7 +61,7 @@ public abstract class ServerGamePacketListenerImplMixin_Tracker { player.doTick(); return; } - try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.getWorldInstance(this.player.serverLevel())).source(player)) { + try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.getWorldInstance(this.player.level())).source(player)) { context.buildAndSwitch(); PhaseTracker.LOGGER.trace(TrackingUtil.PLAYER_TICK, () -> "Wrapping Player Tick: " + player.toString()); player.doTick(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java index 06b0b047334..72fc7596a76 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java @@ -57,7 +57,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onPlaceNewPlayerInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.level())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } @@ -66,7 +66,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onRespawnInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.level())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/item/PrimedTntMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/item/PrimedTntMixin_Tracker.java index 235de221041..aa658f8de06 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/item/PrimedTntMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/item/PrimedTntMixin_Tracker.java @@ -38,12 +38,13 @@ @Mixin(PrimedTnt.class) public abstract class PrimedTntMixin_Tracker extends EntityMixin_Tracker { - @Shadow @Nullable private LivingEntity owner; + @Shadow @Nullable public abstract LivingEntity shadow$getOwner(); @Override protected void tracker$populateDeathContextIfNeeded(final CauseStackManager.StackFrame frame, final EntityTickContext context) { - if (this.owner != null) { - frame.addContext(EventContextKeys.IGNITER, (Living) this.owner); + final var owner = this.shadow$getOwner(); + if (owner != null) { + frame.addContext(EventContextKeys.IGNITER, (Living) owner); } super.tracker$populateDeathContextIfNeeded(frame, context); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java index d1bd9c40e2b..a99e11732f0 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java @@ -41,13 +41,13 @@ public abstract class ServerPlayerMixin_Vanilla extends LivingEntityMixin_Vanilla implements ServerPlayerBridge { // @formatter:off - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // @formatter:on // override from LivingEntityMixin_Vanilla @Override protected void vanilla$onElytraUse(final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { From 82bee140cb660eff5da113d879aaa0fe36be5c39 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 29 May 2025 21:14:05 +0200 Subject: [PATCH 259/586] Replace arch-loom with ModDevGradle --- build-logic/build.gradle | 3 - gradle/libs.versions.toml | 1 + gradle/verification-metadata.xml | 72 +++++++++ neoforge/build.gradle.kts | 142 +++++++++--------- .../moddiscovery/SpongeNeoModLocator.java | 28 +++- .../src/lang/resources/META-INF/MANIFEST.MF | 2 + 6 files changed, 176 insertions(+), 72 deletions(-) create mode 100644 neoforge/src/lang/resources/META-INF/MANIFEST.MF diff --git a/build-logic/build.gradle b/build-logic/build.gradle index 00d4c56f993..f52ba83013a 100644 --- a/build-logic/build.gradle +++ b/build-logic/build.gradle @@ -15,9 +15,6 @@ dependencies { implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:${apiLibs.versions.ideaExt.get()}") implementation(libs.at) implementation(libs.accessWidener) - - // arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies - api("dev.architectury:architectury-loom:1.7.423") } indraSpotlessLicenser { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ac0d6ac03ee..4e82f7eae06 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -78,3 +78,4 @@ indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = " shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } +modDevGradle = { id = "net.neoforged.moddev", version = "2.0.78" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 91ccb5aa1d7..7d3f3c01b8b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1934,6 +1934,14 @@ + + + + + + + + @@ -2284,6 +2292,14 @@ + + + + + + + + @@ -4032,6 +4048,9 @@ + + + @@ -4193,6 +4212,14 @@ + + + + + + + + @@ -4287,6 +4314,19 @@ + + + + + + + + + + + + + @@ -4347,6 +4387,9 @@ + + + @@ -4381,6 +4424,14 @@ + + + + + + + + @@ -4509,6 +4560,19 @@ + + + + + + + + + + + + + @@ -5992,6 +6056,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 594dc81c86c..fd3c7e36ecb 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,12 +1,15 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.neoforged.moddevgradle.dsl.NeoForgeExtension +import org.spongepowered.gradle.impl.AWToAT buildscript { repositories { maven("https://repo.spongepowered.org/repository/maven-public") { name = "sponge" } - maven("https://maven.architectury.dev/") + maven("https://maven.neoforged.net/releases/") { + name = "neoforge" + } } } @@ -14,7 +17,7 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("dev.architectury.loom") + alias(libs.plugins.modDevGradle) } val commonProject = parent!! @@ -41,6 +44,7 @@ repositories { } // SpongeNeo libraries +val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") val serviceLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceLibraries") val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") @@ -49,26 +53,21 @@ val gameManagedLibrariesConfig: NamedDomainObjectProvider = confi val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") -configurations.named("forgeRuntimeLibrary") { - extendsFrom(serviceLibrariesConfig.get()) -} - // ModLauncher layers +val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { + extendsFrom(bootLibrariesConfig.get()) +} val serviceLayerConfig: NamedDomainObjectProvider = configurations.register("serviceLayer") { + extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) - extendsFrom(configurations.getByName("forgeDependencies")) } val langLayerConfig: NamedDomainObjectProvider = configurations.register("langLayer") { - extendsFrom(configurations.getByName("forgeDependencies")) + extendsFrom(bootLayerConfig.get()) } val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) - - afterEvaluate { - extendsFrom(configurations.getByName("minecraftNamedCompile")) - } } // SpongeCommon source sets @@ -151,40 +150,68 @@ configurations.configureEach { } } -extensions.configure(LoomGradleExtensionAPI::class) { - silentMojangMappingsLicense() - accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) +val awFiles: Set = files(main.get().resources, forgeMain.resources).filter { it.name.endsWith(".accesswidener") }.files +val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile +AWToAT.convert(awFiles, atFile) + +val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations + +extensions.configure(NeoForgeExtension::class) { + version = neoForgeVersion + accessTransformers.from(atFile) + + runs { + configureEach { + // jvmArgument("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath - mixin { - useLegacyMixinAp.set(false) + programArguments.addAll(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) + + disableIdeRun() // Source sets are broken + } + + create("client") { + client() + } + + create("server") { + server() + programArgument("--nogui") + } } mods { - named("main") { + create("applaunch") { + sourceSet(forgeAppLaunch) + sourceSet(applaunch.get()) + } + + create("lang") { + sourceSet(forgeLang) + } + + create("main") { + sourceSet(forgeMain) sourceSet(forgeMixins) sourceSet(forgeAccessors) sourceSet(forgeLaunch) - sourceSet(main.get(), commonProject) - sourceSet(mixins.get(), commonProject) - sourceSet(accessors.get(), commonProject) - sourceSet(launch.get(), commonProject) + sourceSet(main.get()) + sourceSet(mixins.get()) + sourceSet(accessors.get()) + sourceSet(launch.get()) + } - configuration(gameManagedLibrariesConfig.get()) - configuration(gameShadedLibrariesConfig.get()) + testPluginsProject?.also { + create("testplugins") { + sourceSet(it.sourceSets.getByName("main")) + } } } } -dependencies { - "minecraft"("com.mojang:minecraft:${minecraftVersion}") - "neoForge"("net.neoforged:neoforge:$neoForgeVersion") - "mappings"(loom.layered { - officialMojangMappings { - nameSyntheticMembers = true - } - }) +bootLibrariesConfig.get().extendsFrom(configurations.getByName("modDevCompileDependencies")) +dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) service(project(transformersProject.path)) { @@ -213,14 +240,24 @@ dependencies { val gameShadedLibraries = gameShadedLibrariesConfig.name gameShadedLibraries("org.spongepowered:spongeapi:$apiVersion") { isTransitive = false } - afterEvaluate { - spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), configurations.getByName("forgeDependencies"), serviceShadedLibrariesConfig.get()) - spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) + spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), bootLayerConfig.get(), serviceShadedLibrariesConfig.get()) + spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) +} - "forgeRuntimeLibrary"(files(tasks.named("forgeServicesJar"), tasks.named("forgeLangJar"))) +// Put libs in game layer +extensions.configure(NeoForgeExtension::class) { + val gameLibs: MutableList = mutableListOf() + gameLibs.addAll(gameManagedLibrariesConfig.get()) + gameLibs.addAll(gameShadedLibrariesConfig.get()) + val resourcesEnv = gameLibs.joinToString(File.pathSeparator) + runs.configureEach { + jvmArgument("-Dsponge.resources=" + resourcesEnv) } } +// Put libs in boot layer +configurations.getByName("additionalRuntimeClasspath").extendsFrom(serviceShadedLibrariesConfig.get()) + val forgeManifest = java.manifest { attributes( "Specification-Title" to "SpongeNeo", @@ -235,8 +272,6 @@ val forgeManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } -val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations - tasks { jar { manifest.from(forgeManifest) @@ -287,35 +322,6 @@ tasks { duplicatesStrategy = DuplicatesStrategy.WARN } - afterEvaluate { - withType(net.fabricmc.loom.task.AbstractRunTask::class) { - // Tip: don't set classpath here, it is ignored by bootstrap-launcher - // Add boot jars into forgeRuntimeLibrary instead - - testPluginsProject?.also { - val testPluginsOutput = it.sourceSets.getByName("main").output - val dirs: MutableList = mutableListOf() - dirs.add(testPluginsOutput.resourcesDir!!) - dirs.addAll(testPluginsOutput.classesDirs) - environment["SPONGE_PLUGINS"] = dirs.joinToString("&") - - dependsOn(it.tasks.classes) - } - - argumentProviders += CommandLineArgumentProvider { - mixinConfigs.asSequence() - .flatMap { sequenceOf("--mixin.config", it) } - .toList() - } - - // jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath - - sourceSets.forEach { - dependsOn(it.classesTaskName) - } - } - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") forgeAppLaunch.resources.srcDir(installerResources) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java index 487cc56d630..6b9920bb342 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java @@ -25,11 +25,15 @@ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; import com.google.common.collect.ImmutableMap; +import cpw.mods.jarhandling.JarContents; +import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.Launcher; import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.ILaunchContext; import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; +import net.neoforged.neoforgespi.locating.IModFile; import net.neoforged.neoforgespi.locating.IModFileCandidateLocator; import net.neoforged.neoforgespi.locating.IncompatibleFileReporting; import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; @@ -37,6 +41,7 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.neoforge.applaunch.plugin.NeoForgePluginPlatform; +import java.io.File; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; @@ -57,11 +62,32 @@ public SpongeNeoModLocator() { @Override public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) { + final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); + if (!FMLEnvironment.production) { + final String resourcesProp = System.getProperty("sponge.resources"); + if (resourcesProp != null) { + for (final String entry : resourcesProp.split(File.pathSeparator)) { + if (entry.isBlank()) { + continue; + } + + final JarContents jarContents = JarContents.of(Stream.of(entry.split("&")).map(Path::of).toList()); + IModFile modFile = null; + try { + // attempt to load as mod or plugin + modFile = pipeline.readModFile(jarContents, attributes); + } catch (Exception ignored) {} + if (modFile == null) { + // fallback to game library + modFile = IModFile.create(SecureJar.from(jarContents), JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes); + } + pipeline.addModFile(modFile); + } + } return; } - final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); try { URL rootJar = SpongeNeoModLocator.class.getProtectionDomain().getCodeSource().getLocation(); FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar diff --git a/neoforge/src/lang/resources/META-INF/MANIFEST.MF b/neoforge/src/lang/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..c93f76cce69 --- /dev/null +++ b/neoforge/src/lang/resources/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Automatic-Module-Name: spongeneo.lang +FMLModType: LIBRARY From 1cfe27e082ddfe94700e4512e9b8f154a89820cb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 30 May 2025 21:24:54 +0200 Subject: [PATCH 260/586] Fix standard input for gradle runs --- forge/build.gradle.kts | 8 ++++++++ neoforge/build.gradle.kts | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 9e2859ae474..206ca8cf729 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,5 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import net.minecraftforge.gradle.common.util.RunConfig import net.minecraftforge.gradle.userdev.UserDevExtension +import org.gradle.api.tasks.JavaExec import org.gradle.internal.DefaultTaskExecutionRequest import org.spongepowered.gradle.impl.AWToAT import org.spongepowered.gradle.impl.IdeHelper @@ -271,6 +273,12 @@ val forgeManifest = java.manifest { } tasks { + withType(JavaExec::class) { + if (group == RunConfig.RUNS_GROUP) { + standardInput = System.`in` + } + } + jar { manifest.from(forgeManifest) } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index fd3c7e36ecb..9cf301e9b1c 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,5 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.neoforged.moddevgradle.dsl.NeoForgeExtension +import net.neoforged.moddevgradle.internal.RunGameTask import org.spongepowered.gradle.impl.AWToAT buildscript { @@ -273,6 +274,10 @@ val forgeManifest = java.manifest { } tasks { + withType(RunGameTask::class) { + standardInput = System.`in` + } + jar { manifest.from(forgeManifest) } From caa5c4b5ad65ea5d5b20168f87f1b3ce4ec24c86 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 30 May 2025 22:28:26 +0200 Subject: [PATCH 261/586] Cleanup gradle source sets and tasks --- build.gradle.kts | 6 +- forge/build.gradle.kts | 210 ++++++++++++++++---------------- neoforge/build.gradle.kts | 243 ++++++++++++++++++-------------------- vanilla/build.gradle.kts | 191 ++++++++++++++---------------- 4 files changed, 306 insertions(+), 344 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3806f8b32c4..8f170578682 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,6 @@ plugins { alias(libs.plugins.versions) } -val commonProject = project val apiVersion: String by project val apiJavaTarget: String by project val minecraftVersion: String by project @@ -384,22 +383,27 @@ tasks { jar { manifest.from(commonManifest) } + val mixinsJar by registering(Jar::class) { + group = "build" archiveClassifier.set("mixins") manifest.from(commonManifest) from(mixins.map { it.output }) } val accessorsJar by registering(Jar::class) { + group = "build" archiveClassifier.set("accessors") manifest.from(commonManifest) from(accessors.map { it.output }) } val launchJar by registering(Jar::class) { + group = "build" archiveClassifier.set("launch") manifest.from(commonManifest) from(launch.map { it.output }) } val applaunchJar by registering(Jar::class) { + group = "build" archiveClassifier.set("applaunch") manifest.from(commonManifest) from(applaunch.map { it.output }) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 206ca8cf729..f13e98ee9cf 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -44,50 +44,49 @@ repositories { } // SpongeForge libraries -val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") { +val bootLibrariesConfig = configurations.register("bootLibraries") { // Ideally we would filter minecraft itself and only keep its dependencies for this layer, // but I couldn't find a way to do it without breaking ForgeGradle. extendsFrom(configurations.minecraft.get()) } -val serviceLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceLibraries") -val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") +val serviceLibrariesConfig = configurations.register("serviceLibraries") +val gameLibrariesConfig = configurations.register("gameLibraries") -val gameManagedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameManagedLibraries") +val gameManagedLibrariesConfig = configurations.register("gameManagedLibraries") -val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") -val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") +val serviceShadedLibrariesConfig = configurations.register("serviceShadedLibraries") +val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") -val productionExcludedLibrariesConfig: NamedDomainObjectProvider = configurations.register("productionExcludedLibraries") +val productionExcludedLibrariesConfig = configurations.register("productionExcludedLibraries") // ModLauncher layers -val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { +val bootLayerConfig = configurations.register("bootLayer") { extendsFrom(bootLibrariesConfig.get()) } -val serviceLayerConfig: NamedDomainObjectProvider = configurations.register("serviceLayer") { +val serviceLayerConfig = configurations.register("serviceLayer") { extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) } -val langLayerConfig: NamedDomainObjectProvider = configurations.register("langLayer") { +val langLayerConfig = configurations.register("langLayer") { extendsFrom(bootLayerConfig.get()) } -val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { +val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) } // SpongeCommon source sets -val launchConfig: NamedDomainObjectProvider = commonProject.configurations.named("launch") -val accessors: NamedDomainObjectProvider = commonProject.sourceSets.named("accessors") -val launch: NamedDomainObjectProvider = commonProject.sourceSets.named("launch") -val applaunch: NamedDomainObjectProvider = commonProject.sourceSets.named("applaunch") -val mixins: NamedDomainObjectProvider = commonProject.sourceSets.named("mixins") -val main: NamedDomainObjectProvider = commonProject.sourceSets.named("main") +val commonAccessors = commonProject.sourceSets.named("accessors") +val commonLaunch = commonProject.sourceSets.named("launch") +val commonAppLaunch = commonProject.sourceSets.named("applaunch") +val commonMixins = commonProject.sourceSets.named("mixins") +val commonMain = commonProject.sourceSets.named("main") // SpongeForge source sets // Service layer -val forgeAppLaunch by sourceSets.register("applaunch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) +val appLaunch by sourceSets.register("applaunch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(serviceLayerConfig.get()) @@ -95,63 +94,63 @@ val forgeAppLaunch by sourceSets.register("applaunch") { } // Lang layer -val forgeLang by sourceSets.register("lang") { +val lang by sourceSets.register("lang") { configurations.named(implementationConfigurationName) { extendsFrom(langLayerConfig.get()) } } // Game layer -val forgeLaunch by sourceSets.register("launch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) +val launch by sourceSets.register("launch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeAccessors by sourceSets.register("accessors") { - spongeImpl.addDependencyToImplementation(accessors.get(), this) +val accessors by sourceSets.register("accessors") { + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeMixins by sourceSets.register("mixins") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(mixins.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) - spongeImpl.addDependencyToImplementation(forgeLaunch, this) - spongeImpl.addDependencyToImplementation(forgeAccessors, this) +val mixins by sourceSets.register("mixins") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMixins.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeMain by sourceSets.named("main") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) - spongeImpl.addDependencyToImplementation(forgeLaunch, this) - spongeImpl.addDependencyToImplementation(forgeAccessors, this) +val main by sourceSets.named("main") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) - spongeImpl.addDependencyToImplementation(this, forgeMixins) + spongeImpl.addDependencyToImplementation(this, mixins) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } // The rest of the project because we want everything in the initial classpath - spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) - spongeImpl.addDependencyToRuntimeOnly(forgeMixins, this) - spongeImpl.addDependencyToRuntimeOnly(forgeLang, this) + spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) + spongeImpl.addDependencyToRuntimeOnly(mixins, this) + spongeImpl.addDependencyToRuntimeOnly(lang, this) } configurations.configureEach { @@ -215,7 +214,7 @@ dependencies { } } -val awFiles: Set = files(main.get().resources, forgeMain.resources).filter { it.name.endsWith(".accesswidener") }.files +val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile AWToAT.convert(awFiles, atFile) @@ -272,6 +271,29 @@ val forgeManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } +sourceSets { + main { + blossom.resources { + property("apiVersion", apiVersion) + property("version", version.toString()) + property("description", description.toString()) + property("forgeVersion", forgeVersion) + } + } + + configureEach { + val sourceSet = this + if (sourceSet.name != "main") { + tasks.register(sourceSet.name + "Jar", Jar::class.java) { + group = "build" + archiveClassifier.set(sourceSet.name) + manifest.from(forgeManifest) + from(sourceSet.output) + } + } + } +} + tasks { withType(JavaExec::class) { if (group == RunConfig.RUNS_GROUP) { @@ -282,40 +304,16 @@ tasks { jar { manifest.from(forgeManifest) } - val forgeAppLaunchJar by registering(Jar::class) { - archiveClassifier.set("applaunch") - manifest.from(forgeManifest) - from(forgeAppLaunch.output) - } - val forgeLaunchJar by registering(Jar::class) { - archiveClassifier.set("launch") - manifest.from(forgeManifest) - from(forgeLaunch.output) - } - val forgeAccessorsJar by registering(Jar::class) { - archiveClassifier.set("accessors") - manifest.from(forgeManifest) - from(forgeAccessors.output) - } - val forgeMixinsJar by registering(Jar::class) { - archiveClassifier.set("mixins") - manifest.from(forgeManifest) - from(forgeMixins.output) - } - val forgeLangJar by registering(Jar::class) { - archiveClassifier.set("lang") - manifest { - from(forgeManifest) - attributes( - "Automatic-Module-Name" to "spongeforge.lang", - "FMLModType" to "LANGPROVIDER" - ) - } - from(forgeLang.output) + + val langJar by existing(Jar::class) { + manifest.attributes( + "Automatic-Module-Name" to "spongeforge.lang", + "FMLModType" to "LANGPROVIDER" + ) } val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") - forgeAppLaunch.resources.srcDir(installerResources) + appLaunch.resources.srcDir(installerResources) val emitDependencies by registering(org.spongepowered.gradle.impl.OutputDependenciesToJson::class) { group = "sponge" @@ -325,11 +323,12 @@ tasks { outputFile.set(installerResources.map { it.file("sponge-libraries.json") }) } - named(forgeAppLaunch.processResourcesTaskName).configure { + + named(appLaunch.processResourcesTaskName) { dependsOn(emitDependencies) } - val forgeServicesShadowJar by register("servicesShadowJar", ShadowJar::class) { + val servicesShadowJar by register("servicesShadowJar", ShadowJar::class) { group = "shadow" archiveClassifier.set("services") @@ -345,8 +344,8 @@ tasks { ) } - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(forgeAppLaunch.output) + from(commonAppLaunch.map { it.output }) + from(appLaunch.output) // Make sure to relocate access widener so that we don't conflict with other coremods relocate("net.fabricmc.accesswidener", "org.spongepowered.forge.libs.accesswidener") @@ -360,37 +359,37 @@ tasks { configurations = listOf(gameShadedLibrariesConfig.get()) manifest { + from(forgeManifest) attributes( "Access-Widener" to "common.accesswidener", "Superclass-Transformer" to "common.superclasschange,forge.superclasschange", "MixinConfigs" to mixinConfigs.joinToString(",") ) - from(forgeManifest) } - from(commonProject.sourceSets.main.map { it.output }) - from(commonProject.sourceSets.named("mixins").map {it.output }) - from(commonProject.sourceSets.named("accessors").map {it.output }) - from(commonProject.sourceSets.named("launch").map {it.output }) + from(commonMain.map { it.output }) + from(commonMixins.map { it.output }) + from(commonAccessors.map { it.output }) + from(commonLaunch.map { it.output }) - from(forgeLaunch.output) - from(forgeAccessors.output) - from(forgeMixins.output) + from(launch.output) + from(accessors.output) + from(mixins.output) } val universalJar = register("universalJar", Jar::class) { group = "build" archiveClassifier.set("universal") - manifest.from(forgeServicesShadowJar.manifest) + manifest.from(servicesShadowJar.manifest) - from(forgeServicesShadowJar.archiveFile.map { zipTree(it) }) + from(servicesShadowJar.archiveFile.map { zipTree(it) }) into("jars") { from(shadowJar) rename("spongeforge-(.*)-mod.jar", "spongeforge-mod.jar") - from(forgeLangJar) + from(langJar) rename("spongeforge-(.*)-lang.jar", "spongeforge-lang.jar") } } @@ -406,17 +405,6 @@ if (IdeHelper.isIdeaSync()) { } } -sourceSets { - main { - blossom.resources { - property("apiVersion", apiVersion) - property("version", version.toString()) - property("description", description.toString()) - property("forgeVersion", forgeVersion) - } - } -} - publishing { publications { register("sponge", MavenPublication::class) { @@ -425,19 +413,19 @@ publishing { artifact(tasks["jar"]) artifact(tasks["sourcesJar"]) - artifact(tasks["forgeLangJar"]) + artifact(tasks["langJar"]) artifact(tasks["langSourcesJar"]) - artifact(tasks["forgeMixinsJar"]) + artifact(tasks["mixinsJar"]) artifact(tasks["mixinsSourcesJar"]) - artifact(tasks["forgeAccessorsJar"]) + artifact(tasks["accessorsJar"]) artifact(tasks["accessorsSourcesJar"]) - artifact(tasks["forgeLaunchJar"]) + artifact(tasks["launchJar"]) artifact(tasks["launchSourcesJar"]) - artifact(tasks["forgeAppLaunchJar"]) + artifact(tasks["applaunchJar"]) artifact(tasks["applaunchSourcesJar"]) pom { diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 9cf301e9b1c..a1e52797906 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -45,44 +45,43 @@ repositories { } // SpongeNeo libraries -val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") -val serviceLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceLibraries") -val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") +val bootLibrariesConfig = configurations.register("bootLibraries") +val serviceLibrariesConfig = configurations.register("serviceLibraries") +val gameLibrariesConfig = configurations.register("gameLibraries") -val gameManagedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameManagedLibraries") +val gameManagedLibrariesConfig = configurations.register("gameManagedLibraries") -val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") -val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") +val serviceShadedLibrariesConfig = configurations.register("serviceShadedLibraries") +val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") // ModLauncher layers -val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { +val bootLayerConfig = configurations.register("bootLayer") { extendsFrom(bootLibrariesConfig.get()) } -val serviceLayerConfig: NamedDomainObjectProvider = configurations.register("serviceLayer") { +val serviceLayerConfig = configurations.register("serviceLayer") { extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) } -val langLayerConfig: NamedDomainObjectProvider = configurations.register("langLayer") { +val langLayerConfig = configurations.register("langLayer") { extendsFrom(bootLayerConfig.get()) } -val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { +val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) } // SpongeCommon source sets -val launchConfig: NamedDomainObjectProvider = commonProject.configurations.named("launch") -val accessors: NamedDomainObjectProvider = commonProject.sourceSets.named("accessors") -val launch: NamedDomainObjectProvider = commonProject.sourceSets.named("launch") -val applaunch: NamedDomainObjectProvider = commonProject.sourceSets.named("applaunch") -val mixins: NamedDomainObjectProvider = commonProject.sourceSets.named("mixins") -val main: NamedDomainObjectProvider = commonProject.sourceSets.named("main") +val commonAccessors = commonProject.sourceSets.named("accessors") +val commonLaunch = commonProject.sourceSets.named("launch") +val commonAppLaunch = commonProject.sourceSets.named("applaunch") +val commonMixins = commonProject.sourceSets.named("mixins") +val commonMain = commonProject.sourceSets.named("main") // SpongeNeo source sets // Service layer -val forgeAppLaunch by sourceSets.register("applaunch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) +val appLaunch by sourceSets.register("applaunch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(serviceLayerConfig.get()) @@ -90,54 +89,54 @@ val forgeAppLaunch by sourceSets.register("applaunch") { } // Lang layer -val forgeLang by sourceSets.register("lang") { +val lang by sourceSets.register("lang") { configurations.named(implementationConfigurationName) { extendsFrom(langLayerConfig.get()) } } // Game layer -val forgeLaunch by sourceSets.register("launch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) +val launch by sourceSets.register("launch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeAccessors by sourceSets.register("accessors") { - spongeImpl.addDependencyToImplementation(accessors.get(), this) +val accessors by sourceSets.register("accessors") { + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeMixins by sourceSets.register("mixins") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(mixins.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) - spongeImpl.addDependencyToImplementation(forgeLaunch, this) - spongeImpl.addDependencyToImplementation(forgeAccessors, this) +val mixins by sourceSets.register("mixins") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMixins.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val forgeMain by sourceSets.named("main") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(forgeAppLaunch, this) - spongeImpl.addDependencyToImplementation(forgeLaunch, this) - spongeImpl.addDependencyToImplementation(forgeAccessors, this) +val main by sourceSets.named("main") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) - spongeImpl.addDependencyToImplementation(this, forgeMixins) + spongeImpl.addDependencyToImplementation(this, mixins) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) @@ -151,7 +150,7 @@ configurations.configureEach { } } -val awFiles: Set = files(main.get().resources, forgeMain.resources).filter { it.name.endsWith(".accesswidener") }.files +val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile AWToAT.convert(awFiles, atFile) @@ -182,24 +181,24 @@ extensions.configure(NeoForgeExtension::class) { mods { create("applaunch") { - sourceSet(forgeAppLaunch) - sourceSet(applaunch.get()) + sourceSet(appLaunch) + sourceSet(commonAppLaunch.get()) } create("lang") { - sourceSet(forgeLang) + sourceSet(lang) } create("main") { - sourceSet(forgeMain) - sourceSet(forgeMixins) - sourceSet(forgeAccessors) - sourceSet(forgeLaunch) - - sourceSet(main.get()) - sourceSet(mixins.get()) - sourceSet(accessors.get()) - sourceSet(launch.get()) + sourceSet(main) + sourceSet(mixins) + sourceSet(accessors) + sourceSet(launch) + + sourceSet(commonMain.get()) + sourceSet(commonMixins.get()) + sourceSet(commonAccessors.get()) + sourceSet(commonLaunch.get()) } testPluginsProject?.also { @@ -259,7 +258,7 @@ extensions.configure(NeoForgeExtension::class) { // Put libs in boot layer configurations.getByName("additionalRuntimeClasspath").extendsFrom(serviceShadedLibrariesConfig.get()) -val forgeManifest = java.manifest { +val neoManifest = java.manifest { attributes( "Specification-Title" to "SpongeNeo", "Specification-Vendor" to "SpongePowered", @@ -273,62 +272,62 @@ val forgeManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } +sourceSets { + main { + blossom.resources { + property("apiVersion", apiVersion) + property("version", version.toString()) + property("description", description.toString()) + property("neoForgeVersion", neoForgeVersion) + } + } + + configureEach { + val sourceSet = this + if (sourceSet.name != "main") { + tasks.register(sourceSet.name + "Jar", Jar::class.java) { + group = "build" + archiveClassifier.set(sourceSet.name) + manifest.from(neoManifest) + from(sourceSet.output) + } + } + } +} + tasks { withType(RunGameTask::class) { standardInput = System.`in` } jar { - manifest.from(forgeManifest) - } - val forgeAppLaunchJar by registering(Jar::class) { - archiveClassifier.set("applaunch") - manifest.from(forgeManifest) - from(forgeAppLaunch.output) - } - val forgeLaunchJar by registering(Jar::class) { - archiveClassifier.set("launch") - manifest.from(forgeManifest) - from(forgeLaunch.output) - } - val forgeAccessorsJar by registering(Jar::class) { - archiveClassifier.set("accessors") - manifest.from(forgeManifest) - from(forgeAccessors.output) - } - val forgeMixinsJar by registering(Jar::class) { - archiveClassifier.set("mixins") - manifest.from(forgeManifest) - from(forgeMixins.output) + manifest.from(neoManifest) } - val forgeLangJar by registering(Jar::class) { - archiveClassifier.set("lang") - manifest { - from(forgeManifest) - attributes( - "Automatic-Module-Name" to "spongeneo.lang", - "FMLModType" to "LIBRARY" - ) - } - from(forgeLang.output) + + val langJar by existing(Jar::class) { + manifest.attributes( + "Automatic-Module-Name" to "spongeneo.lang", + "FMLModType" to "LIBRARY" + ) } - val forgeServicesJar by registering(Jar::class) { + val servicesJar by registering(Jar::class) { + group = "build" archiveClassifier.set("services") manifest { - from(forgeManifest) + from(neoManifest) attributes("Automatic-Module-Name" to "spongeneo.services") } - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(forgeAppLaunch.output) + from(commonAppLaunch.map { it.output }) + from(appLaunch.output) duplicatesStrategy = DuplicatesStrategy.WARN } val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") - forgeAppLaunch.resources.srcDir(installerResources) + appLaunch.resources.srcDir(installerResources) val emitDependencies by registering(org.spongepowered.gradle.impl.OutputDependenciesToJson::class) { group = "sponge" @@ -337,11 +336,12 @@ tasks { outputFile.set(installerResources.map { it.file("sponge-libraries.json") }) } - named(forgeAppLaunch.processResourcesTaskName).configure { + + named(appLaunch.processResourcesTaskName) { dependsOn(emitDependencies) } - val forgeServicesShadowJar by register("servicesShadowJar", ShadowJar::class) { + val servicesShadowJar by register("servicesShadowJar", ShadowJar::class) { group = "shadow" archiveClassifier.set("services") @@ -350,15 +350,15 @@ tasks { exclude("META-INF/INDEX.LIST", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", "**/module-info.class") manifest { - from(forgeManifest) + from(neoManifest) attributes( "Automatic-Module-Name" to "spongeneo.services", "Multi-Release" to true ) } - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(forgeAppLaunch.output) + from(commonAppLaunch.map { it.output }) + from(appLaunch.output) // Make sure to relocate access widener so that we don't conflict with other coremods relocate("net.fabricmc.accesswidener", "org.spongepowered.neoforge.libs.accesswidener") @@ -372,38 +372,38 @@ tasks { configurations = listOf(gameShadedLibrariesConfig.get()) manifest { + from(neoManifest) attributes( "Access-Widener" to "common.accesswidener", "Superclass-Transformer" to "common.superclasschange,neoforge.superclasschange", "MixinConfigs" to mixinConfigs.joinToString(",") ) - from(forgeManifest) } - from(commonProject.sourceSets.main.map { it.output }) - from(commonProject.sourceSets.named("mixins").map {it.output }) - from(commonProject.sourceSets.named("accessors").map {it.output }) - from(commonProject.sourceSets.named("launch").map {it.output }) + from(commonMain.map { it.output }) + from(commonMixins.map { it.output }) + from(commonAccessors.map { it.output }) + from(commonLaunch.map { it.output }) - from(forgeLaunch.output) - from(forgeAccessors.output) - from(forgeMixins.output) + from(launch.output) + from(accessors.output) + from(mixins.output) } val universalJar = register("universalJar", Jar::class) { group = "build" archiveClassifier.set("universal") - manifest.from(forgeServicesShadowJar.manifest) + manifest.from(servicesShadowJar.manifest) - from(forgeServicesShadowJar.archiveFile.map { zipTree(it) }) - mustRunAfter(forgeServicesJar) + from(servicesShadowJar.archiveFile.map { zipTree(it) }) + mustRunAfter(servicesJar) into("jars") { from(shadowJar) rename("spongeneo-(.*)-mod.jar", "spongeneo-mod.jar") - from(forgeLangJar) + from(langJar) rename("spongeneo-(.*)-lang.jar", "spongeneo-lang.jar") } } @@ -413,17 +413,6 @@ tasks { } } -sourceSets { - main { - blossom.resources { - property("apiVersion", apiVersion) - property("version", version.toString()) - property("description", description.toString()) - property("neoForgeVersion", neoForgeVersion) - } - } -} - publishing { publications { register("sponge", MavenPublication::class) { @@ -432,19 +421,19 @@ publishing { artifact(tasks["jar"]) artifact(tasks["sourcesJar"]) - artifact(tasks["forgeLangJar"]) + artifact(tasks["langJar"]) artifact(tasks["langSourcesJar"]) - artifact(tasks["forgeMixinsJar"]) + artifact(tasks["mixinsJar"]) artifact(tasks["mixinsSourcesJar"]) - artifact(tasks["forgeAccessorsJar"]) + artifact(tasks["accessorsJar"]) artifact(tasks["accessorsSourcesJar"]) - artifact(tasks["forgeLaunchJar"]) + artifact(tasks["launchJar"]) artifact(tasks["launchSourcesJar"]) - artifact(tasks["forgeAppLaunchJar"]) + artifact(tasks["applaunchJar"]) artifact(tasks["applaunchSourcesJar"]) pom { diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 1be3d88d12b..f9f7d821b8e 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -25,46 +25,46 @@ description = "The SpongeAPI implementation for Vanilla Minecraft" version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion) // SpongeVanilla libraries -val installerLibrariesConfig: NamedDomainObjectProvider = configurations.register("installerLibraries") -val initLibrariesConfig: NamedDomainObjectProvider = configurations.register("initLibraries") // JVM initial classpath -val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") -val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") { +val installerLibrariesConfig = configurations.register("installerLibraries") +val initLibrariesConfig = configurations.register("initLibraries") // JVM initial classpath +val bootLibrariesConfig = configurations.register("bootLibraries") +val gameLibrariesConfig = configurations.register("gameLibraries") { extendsFrom(configurations.minecraft.get()) } -val gameManagedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameManagedLibraries") +val gameManagedLibrariesConfig = configurations.register("gameManagedLibraries") -val bootShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootShadedLibraries") -val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") +val bootShadedLibrariesConfig = configurations.register("bootShadedLibraries") +val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") // ModLauncher layers -val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { +val bootLayerConfig = configurations.register("bootLayer") { extendsFrom(initLibrariesConfig.get()) extendsFrom(bootLibrariesConfig.get()) } -val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { +val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(bootLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) } // SpongeCommon source sets -val accessors: NamedDomainObjectProvider = commonProject.sourceSets.named("accessors") -val launch: NamedDomainObjectProvider = commonProject.sourceSets.named("launch") -val applaunch: NamedDomainObjectProvider = commonProject.sourceSets.named("applaunch") -val mixins: NamedDomainObjectProvider = commonProject.sourceSets.named("mixins") -val main: NamedDomainObjectProvider = commonProject.sourceSets.named("main") +val commonAccessors = commonProject.sourceSets.named("accessors") +val commonLaunch = commonProject.sourceSets.named("launch") +val commonAppLaunch = commonProject.sourceSets.named("applaunch") +val commonMixins = commonProject.sourceSets.named("mixins") +val commonMain = commonProject.sourceSets.named("main") // SpongeVanilla source sets // Prod launch -val vanillaInstaller by sourceSets.register("installer") { +val installer by sourceSets.register("installer") { configurations.named(implementationConfigurationName) { extendsFrom(installerLibrariesConfig.get()) } } // Boot layer -val vanillaAppLaunch by sourceSets.register("applaunch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) +val appLaunch by sourceSets.register("applaunch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(bootLayerConfig.get()) @@ -72,63 +72,63 @@ val vanillaAppLaunch by sourceSets.register("applaunch") { } // Game layer -val vanillaLaunch by sourceSets.register("launch") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(vanillaAppLaunch, this) +val launch by sourceSets.register("launch") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val vanillaAccessors by sourceSets.register("accessors") { - spongeImpl.addDependencyToImplementation(accessors.get(), this) +val accessors by sourceSets.register("accessors") { + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val vanillaMixins by sourceSets.register("mixins") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(mixins.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(vanillaAppLaunch, this) - spongeImpl.addDependencyToImplementation(vanillaLaunch, this) - spongeImpl.addDependencyToImplementation(vanillaAccessors, this) +val mixins by sourceSets.register("mixins") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMixins.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } } -val vanillaMain by sourceSets.named("main") { - spongeImpl.addDependencyToImplementation(applaunch.get(), this) - spongeImpl.addDependencyToImplementation(launch.get(), this) - spongeImpl.addDependencyToImplementation(accessors.get(), this) - spongeImpl.addDependencyToImplementation(main.get(), this) - spongeImpl.addDependencyToImplementation(vanillaAppLaunch, this) - spongeImpl.addDependencyToImplementation(vanillaLaunch, this) - spongeImpl.addDependencyToImplementation(vanillaAccessors, this) +val main by sourceSets.named("main") { + spongeImpl.addDependencyToImplementation(commonAppLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonLaunch.get(), this) + spongeImpl.addDependencyToImplementation(commonAccessors.get(), this) + spongeImpl.addDependencyToImplementation(commonMain.get(), this) + spongeImpl.addDependencyToImplementation(appLaunch, this) + spongeImpl.addDependencyToImplementation(launch, this) + spongeImpl.addDependencyToImplementation(accessors, this) - spongeImpl.addDependencyToImplementation(this, vanillaMixins) + spongeImpl.addDependencyToImplementation(this, mixins) configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } // The rest of the project because we want everything in the initial classpath - spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) - spongeImpl.addDependencyToRuntimeOnly(vanillaMixins, this) + spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) + spongeImpl.addDependencyToRuntimeOnly(mixins, this) } val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations minecraft { - accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) - accessWideners(vanillaMain.resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(commonMain.get().resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(main.resources.filter { it.name.endsWith(".accesswidener") }) } configurations.configureEach { @@ -321,59 +321,46 @@ val vanillaManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } -vanillaAppLaunch.apply { +appLaunch.apply { blossom.resources { property("minecraftVersion", minecraftVersion) } } -vanillaLaunch.apply { +launch.apply { blossom.resources { property("apiVersion", apiVersion) property("minecraftVersion", minecraftVersion) property("version", version.toString()) } } -vanillaInstaller.apply { +installer.apply { blossom.javaSources { property("minecraftVersion", minecraftVersion) } } +sourceSets.configureEach { + val sourceSet = this + if (sourceSet.name != "main") { + tasks.register(sourceSet.name + "Jar", Jar::class.java) { + group = "build" + archiveClassifier.set(sourceSet.name) + manifest.from(vanillaManifest) + from(sourceSet.output) + } + } +} + tasks { jar { manifest.from(vanillaManifest) } - val vanillaInstallerJar by registering(Jar::class) { - archiveClassifier.set("installer") - manifest{ - from(vanillaManifest) - attributes( - "Main-Class" to "org.spongepowered.vanilla.installer.InstallerMain", - "Multi-Release" to true - ) - } - from(vanillaInstaller.output) - } - val vanillaAppLaunchJar by registering(Jar::class) { - archiveClassifier.set("applaunch") - manifest.from(vanillaManifest) - from(vanillaAppLaunch.output) - } - val vanillaLaunchJar by registering(Jar::class) { - archiveClassifier.set("launch") - manifest.from(vanillaManifest) - from(vanillaLaunch.output) - } - val vanillaAccessorsJar by registering(Jar::class) { - archiveClassifier.set("accessors") - manifest.from(vanillaManifest) - from(vanillaAccessors.output) - } - val vanillaMixinsJar by registering(Jar::class) { - archiveClassifier.set("mixins") - manifest.from(vanillaManifest) - from(vanillaMixins.output) + val installerJar by existing(Jar::class) { + manifest.attributes( + "Main-Class" to "org.spongepowered.vanilla.installer.InstallerMain", + "Multi-Release" to true + ) } val integrationTest by registering { @@ -382,7 +369,7 @@ tasks { } val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") - vanillaInstaller.resources.srcDir(installerResources) + installer.resources.srcDir(installerResources) val emitDependencies by registering(org.spongepowered.gradle.impl.OutputDependenciesToJson::class) { group = "sponge" @@ -393,11 +380,12 @@ tasks { outputFile.set(installerResources.map { it.file("sponge-libraries.json") }) } - named(vanillaInstaller.processResourcesTaskName).configure { + + named(installer.processResourcesTaskName) { dependsOn(emitDependencies) } - val vanillaBootShadowJar by register("bootShadowJar", ShadowJar::class) { + val bootShadowJar by register("bootShadowJar", ShadowJar::class) { group = "shadow" archiveClassifier.set("boot") @@ -409,8 +397,8 @@ tasks { attributes("Automatic-Module-Name" to "spongevanilla.boot") } - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(vanillaAppLaunch.output) + from(commonAppLaunch.map { it.output }) + from(appLaunch.output) } val installerShadowJar by register("installerShadowJar", ShadowJar::class) { @@ -433,7 +421,7 @@ tasks { attributes(mapOf("Implementation-Version" to libs.versions.asm.get()), "org/objectweb/asm/") } - from(vanillaInstaller.output) + from(installer.output) } shadowJar { @@ -453,14 +441,14 @@ tasks { ) } - from(commonProject.sourceSets.main.map { it.output }) - from(commonProject.sourceSets.named("mixins").map { it.output }) - from(commonProject.sourceSets.named("accessors").map { it.output }) - from(commonProject.sourceSets.named("launch").map { it.output }) + from(commonMain.map { it.output }) + from(commonMixins.map { it.output }) + from(commonAccessors.map { it.output }) + from(commonLaunch.map { it.output }) - from(vanillaLaunch.output) - from(vanillaAccessors.output) - from(vanillaMixins.output) + from(launch.output) + from(accessors.output) + from(mixins.output) } val universalJar = register("universalJar", Jar::class) { @@ -475,7 +463,7 @@ tasks { from(shadowJar) rename("spongevanilla-(.*)-mod.jar", "spongevanilla-mod.jar") - from(vanillaBootShadowJar) + from(bootShadowJar) rename("spongevanilla-(.*)-boot.jar", "spongevanilla-boot.jar") } } @@ -485,13 +473,6 @@ tasks { } } -val universalJar by tasks.existing -val vanillaInstallerJar by tasks.existing -val vanillaAppLaunchJar by tasks.existing -val vanillaLaunchJar by tasks.existing -val vanillaAccessorsJar by tasks.existing -val vanillaMixinsJar by tasks.existing - publishing { publications { register("sponge", MavenPublication::class) { @@ -500,19 +481,19 @@ publishing { artifact(tasks["jar"]) artifact(tasks["sourcesJar"]) - artifact(tasks["vanillaInstallerJar"]) + artifact(tasks["installerJar"]) artifact(tasks["installerSourcesJar"]) - artifact(tasks["vanillaMixinsJar"]) + artifact(tasks["mixinsJar"]) artifact(tasks["mixinsSourcesJar"]) - artifact(tasks["vanillaAccessorsJar"]) + artifact(tasks["accessorsJar"]) artifact(tasks["accessorsSourcesJar"]) - artifact(tasks["vanillaLaunchJar"]) + artifact(tasks["launchJar"]) artifact(tasks["launchSourcesJar"]) - artifact(tasks["vanillaAppLaunchJar"]) + artifact(tasks["applaunchJar"]) artifact(tasks["applaunchSourcesJar"]) pom { From 262419e4a29fabe0aff9efc50485f45fcf2cc55a Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 30 May 2025 22:51:49 +0200 Subject: [PATCH 262/586] Remove unused servicesJar task in Neo --- neoforge/build.gradle.kts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index a1e52797906..f051af7bb4c 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -311,21 +311,6 @@ tasks { ) } - val servicesJar by registering(Jar::class) { - group = "build" - archiveClassifier.set("services") - - manifest { - from(neoManifest) - attributes("Automatic-Module-Name" to "spongeneo.services") - } - - from(commonAppLaunch.map { it.output }) - from(appLaunch.output) - - duplicatesStrategy = DuplicatesStrategy.WARN - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") appLaunch.resources.srcDir(installerResources) @@ -397,7 +382,6 @@ tasks { manifest.from(servicesShadowJar.manifest) from(servicesShadowJar.archiveFile.map { zipTree(it) }) - mustRunAfter(servicesJar) into("jars") { from(shadowJar) From 8e871a0e5af17d14e164cd47654b62b1fccf00f0 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 1 Jun 2025 10:53:26 +0200 Subject: [PATCH 263/586] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8b4f130ad84..bae04d28747 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.1](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.1&queryOpt=%3Aversion%3D1.21.1*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.1*) +[![SpongeVanilla 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.1](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.1&queryOpt=%3Aversion%3D1.21.1*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.1*) +[![SpongeForge 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.1](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.1&queryOpt=%3Aversion%3D1.21.1*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.1*) +[![SpongeNeo 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) ## Prerequisites @@ -42,7 +42,7 @@ The following steps will ensure your project is cloned properly. ## Setup **Note**: Sponge uses [Gradle] as its build system. The repo includes the Gradle wrapper that will automatically download the correct Gradle -version. Local installations of Gradle may work (as long as they are using Gradle 8.7+) but are untested. To execute the Gradle wrapper, run the +version. Local installations of Gradle may work (as long as they are using Gradle 8.8+) but are untested. To execute the Gradle wrapper, run the `./gradlew` script on Unix systems or only `gradlew` on Windows systems. To have browsable sources for use in-IDE, run `./gradlew :decompile`. This command will need to be re-ran after any change to From 7218e301aad3d0647f1ce15d1c844a62ce4355d0 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 1 Jun 2025 11:01:30 +0200 Subject: [PATCH 264/586] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bae04d28747..7792d8e116a 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) +[![SpongeVanilla 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) +[![SpongeForge 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.3](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.3&queryOpt=%3Aversion%3D1.21.3*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.3*) +[![SpongeNeo 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) ## Prerequisites From 0d22278ce1a0642081c898a7cee642a66ebe4f1b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 1 Jun 2025 11:14:45 +0200 Subject: [PATCH 265/586] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7792d8e116a..64e71435119 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) +[![SpongeVanilla 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) +[![SpongeForge 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.4](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.4&queryOpt=%3Aversion%3D1.21.4*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.4*) +[![SpongeNeo 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) ## Prerequisites @@ -42,7 +42,7 @@ The following steps will ensure your project is cloned properly. ## Setup **Note**: Sponge uses [Gradle] as its build system. The repo includes the Gradle wrapper that will automatically download the correct Gradle -version. Local installations of Gradle may work (as long as they are using Gradle 8.8+) but are untested. To execute the Gradle wrapper, run the +version. Local installations of Gradle may work (as long as they are using Gradle 8.11.1+) but are untested. To execute the Gradle wrapper, run the `./gradlew` script on Unix systems or only `gradlew` on Windows systems. To have browsable sources for use in-IDE, run `./gradlew :decompile`. This command will need to be re-ran after any change to From 6e06ee8d0357c7295f6eefe3c49d3a9ebdbc35a3 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 1 Jun 2025 11:30:15 +0200 Subject: [PATCH 266/586] Fix passenger injection --- .../core/server/level/ServerEntityMixin.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java index def4340c8e0..06ce9970562 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java @@ -24,7 +24,8 @@ */ package org.spongepowered.common.mixin.core.server.level; -import com.llamalad7.mixinextras.injector.ModifyReceiver; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.network.protocol.Packet; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerEntity; @@ -40,7 +41,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor; import org.spongepowered.common.bridge.data.VanishableBridge; @@ -59,8 +59,6 @@ public abstract class ServerEntityMixin { // @formatter:off @Shadow @Final private Entity entity; @Shadow @Final @Mutable private Consumer> broadcast; - - @Shadow protected abstract void shadow$broadcastAndSend(Packet arg); // @formatter:on /** @@ -139,16 +137,15 @@ public abstract class ServerEntityMixin { return packed; } - @ModifyReceiver(method = "sendChanges", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), - slice = @Slice( - from = @At(value = "NEW", target = "(Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/network/protocol/game/ClientboundSetPassengersPacket;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerEntity;removedPassengers(Ljava/util/List;Ljava/util/List;)Ljava/util/stream/Stream;"))) - private Consumer> impl$sendSetPassengersToSelf(final Consumer> instance, final T packet) { + @WrapOperation(method = "sendChanges", at = @At(value = "INVOKE", target = "Ljava/util/function/BiConsumer;accept(Ljava/lang/Object;Ljava/lang/Object;)V")) + private void impl$sendSetPassengersToSelf(final BiConsumer instance, final Object packet, final Object ignored, final Operation original) { // When passengers are removed from a player entity, the target // is the player itself, and we need to synchronize it to them. // In vanilla, it is not possible to ride player entities // so we never end up hitting this code path. - // noinspection Convert2MethodRef https://github.com/SpongePowered/Mixin/issues/406 - return p -> this.shadow$broadcastAndSend(p); + original.call(instance, packet, ignored); + if (this.entity instanceof final ServerPlayer player) { + player.connection.send((Packet) packet); + } } } From db4e24e409bd2162468f27c4308fc269b5729079 Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 3 Jun 2025 01:02:52 +0300 Subject: [PATCH 267/586] Fix HIDE_CAN_DESTROY & HIDE_CAN_PLACE Vanilla no longer permits empty collection --- .../item/stack/HideFlagsItemStackData.java | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java index 5938e51050d..0e257fc5380 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; import net.minecraft.util.Unit; import net.minecraft.world.item.AdventureModePredicate; @@ -38,8 +38,6 @@ import org.spongepowered.common.accessor.world.item.enchantment.ItemEnchantmentsAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; -import java.util.Collections; -import java.util.List; public final class HideFlagsItemStackData { @@ -54,17 +52,13 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY).showInTooltip()) .set((h, v) -> h.update(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY, p -> new ItemAttributeModifiers(p.modifiers(), !v))) .create(Keys.HIDE_CAN_DESTROY) - .get(h -> h.has(DataComponents.CAN_BREAK) && !h.get(DataComponents.CAN_BREAK).showInTooltip()) - .set((h, v) -> h.set(DataComponents.CAN_BREAK, HideFlagsItemStackData.newAdventureModePredicate(h, !v))) + .get(h -> !h.get(DataComponents.CAN_BREAK).showInTooltip()) + .set((h, v) -> h.set(DataComponents.CAN_BREAK, HideFlagsItemStackData.newAdventureModePredicate(h, DataComponents.CAN_BREAK, !v))) + .supports(h -> h.has(DataComponents.CAN_BREAK)) .create(Keys.HIDE_CAN_PLACE) - .get(h -> { - final var predicate = h.get(DataComponents.CAN_BREAK); - if (predicate == null) { - return false; - } - return !predicate.showInTooltip(); - }) - .set((h, v) -> h.set(DataComponents.CAN_PLACE_ON, HideFlagsItemStackData.newAdventureModePredicate(h, !v))) + .get(h -> !h.get(DataComponents.CAN_PLACE_ON).showInTooltip()) + .set((h, v) -> h.set(DataComponents.CAN_PLACE_ON, HideFlagsItemStackData.newAdventureModePredicate(h, DataComponents.CAN_PLACE_ON, !v))) + .supports(h -> h.has(DataComponents.CAN_PLACE_ON)) .create(Keys.HIDE_ENCHANTMENTS) .get(h -> ((ItemEnchantmentsAccessor)h.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY)).accessor$showInTooltip()) .set((h, v) -> h.set(DataComponents.ENCHANTMENTS, HideFlagsItemStackData.newItemEnchantments(h, !v))) @@ -92,12 +86,8 @@ public static void register(final DataProviderRegistrator registrator) { // @formatter:on @NotNull - private static AdventureModePredicate newAdventureModePredicate(final ItemStack h, final boolean showInTooltip) { - if (h.has(DataComponents.CAN_BREAK)) { - final List $$0 = ((AdventureModePredicateAccessor) h.get(DataComponents.CAN_BREAK)).accessor$predicates(); - return new AdventureModePredicate($$0, showInTooltip); - } - return new AdventureModePredicate(Collections.emptyList(), showInTooltip); + private static AdventureModePredicate newAdventureModePredicate(final ItemStack h, final DataComponentType old, final boolean showInTooltip) { + return new AdventureModePredicate(((AdventureModePredicateAccessor) h.get(old)).accessor$predicates(), showInTooltip); } @NotNull From 9b5d285ec547572d4847eaaae501686c206d3e31 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 5 Jun 2025 22:06:16 +0200 Subject: [PATCH 268/586] Backport Forge registries fix from fb76cfc4 --- .../NamespacedWrapperMixin_Forge.java | 49 +++++++++++++++++++ .../resources/mixins.spongeforge.core.json | 1 + .../mixin/core/core/MappedRegistryMixin.java | 5 +- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java new file mode 100644 index 00000000000..0a2d34bd4a5 --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/NamespacedWrapperMixin_Forge.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.minecraftforge.registries; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.core.MappedRegistryAccessor; + +/** + * Due to the Accessor being intrinsically implemented on top of MappedRegistry, the + * extended NamespacedWrapper class redefines frozen as a private field, leaving the + * original accessor to be useless. To fix registry issues, we therefore re-implement + * our accessor interface explicitly for registry purposes. + * + * @author gabizou + * @param + */ +@Mixin(targets = "net/minecraftforge/registries/NamespacedWrapper") +public abstract class NamespacedWrapperMixin_Forge implements MappedRegistryAccessor { + + @Shadow private boolean frozen; + + @Override + public boolean accessor$frozen() { + return this.frozen; + } +} diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 7aae2731cc6..51b614af6cc 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -18,6 +18,7 @@ "minecraftforge.internal.BrandingControlMixin_Forge", "minecraftforge.registries.ForgeRegistryMixin_Forge", "minecraftforge.registries.GameDataMixin_Forge", + "minecraftforge.registries.NamespacedWrapperMixin_Forge", "minecraftforge.registries.RegistryManagerMixin_Forge", "network.ConnectionMixin_Forge", "network.protocol.common.ClientboundCustomPayloadPacketMixin_Forge", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java index 12730ddf63d..5a1e8c58bf0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java @@ -46,6 +46,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.accessor.core.MappedRegistryAccessor; import org.spongepowered.common.accessor.resources.ResourceKeyAccessor; import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.core.RegistryBridge; @@ -166,7 +167,7 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa private void impl$onFreeze(final CallbackInfoReturnable> cir) { this.impl$dependencies.forEach(t -> { if (!this.impl$registryHolder.findRegistry(t) - .map(r -> ((MappedRegistryMixin) r).frozen) + .map(r -> ((MappedRegistryAccessor) r).accessor$frozen()) .orElse(false)) { throw new ValueNotFoundException(String.format("Dependency %s was not found!", t)); } @@ -183,7 +184,7 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa @Override public void bridge$addDependencies(final Supplier> supplier, final RegistryType... dependencies) { if (Arrays.stream(dependencies).allMatch(d -> this.impl$registryHolder.findRegistry(d) - .map(r -> ((MappedRegistryMixin) r).frozen) + .map(r -> ((MappedRegistryAccessor) r).accessor$frozen()) .orElse(false))) { this.impl$appendRegister(supplier); return; From 707c2aff4fae0c62d71e431489418e1b5a7fd33b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 5 Jun 2025 22:31:52 +0200 Subject: [PATCH 269/586] Update MinecraftForge to 54.1.3 and NeoForge to 21.4.137 --- forge/gradle.properties | 2 +- gradle/verification-metadata.xml | 139 +++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 3 files changed, 141 insertions(+), 2 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 41a103e96f6..cea524b7f55 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=54.0.12 +forgeVersion=54.1.3 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f587a6773ea..83fbcaaccd1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -176,6 +176,14 @@ + + + + + + + + @@ -230,6 +238,14 @@ + + + + + + + + @@ -3467,6 +3483,14 @@ + + + + + + + + @@ -3683,6 +3707,14 @@ + + + + + + + + @@ -3699,6 +3731,14 @@ + + + + + + + + @@ -3820,6 +3860,14 @@ + + + + + + + + @@ -3922,6 +3970,14 @@ + + + + + + + + @@ -4024,6 +4080,14 @@ + + + + + + + + @@ -4295,6 +4359,14 @@ + + + + + + + + @@ -4405,6 +4477,14 @@ + + + + + + + + @@ -4515,6 +4595,14 @@ + + + + + + + + @@ -4580,6 +4668,14 @@ + + + + + + + + @@ -5016,6 +5112,20 @@ + + + + + + + + + + + + + + @@ -5151,6 +5261,14 @@ + + + + + + + + @@ -5191,6 +5309,14 @@ + + + + + + + + @@ -6206,6 +6332,11 @@ + + + + + @@ -6240,6 +6371,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index e3c2fd2274f..e17171736e2 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.4.93-beta +neoForgeVersion=21.4.137 loom.platform=neoforge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file From aaece712b9b13e20f1e9a51c5c73374e5c8b4118 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 5 Jun 2025 23:01:45 +0200 Subject: [PATCH 270/586] Remove loom leftovers --- .gitignore | 4 ++-- forge/build.gradle.kts | 6 ++++-- forge/gradle.properties | 4 +--- gradle.properties | 2 +- gradle/verification-metadata.xml | 3 --- neoforge/build.gradle.kts | 5 +---- neoforge/gradle.properties | 4 +--- settings.gradle.kts | 6 ++++-- vanilla/gradle.properties | 2 +- 9 files changed, 15 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 5c96c5ecdf8..edd432c7e7a 100644 --- a/.gitignore +++ b/.gitignore @@ -75,10 +75,10 @@ nb-configuration.xml /.apt_generated/ *.launch /.nb-gradle/ +/.vscode/ + # We need to exclude the copied files. buildSrc/src/api -# forge-loom always generates this for some reason... -/.vscode/ # This is to optionally enable testplugins in development. # the test plugins themselves can be committed as examples. diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index f13e98ee9cf..738df209ca9 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -8,10 +8,12 @@ import org.spongepowered.gradle.impl.IdeHelper buildscript { repositories { - maven("https://repo.spongepowered.org/repository/maven-public") { + maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } - maven("https://maven.minecraftforge.net/") + maven("https://maven.minecraftforge.net/") { + name = "forge" + } } } diff --git a/forge/gradle.properties b/forge/gradle.properties index b8469f277ea..a875efde344 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -3,6 +3,4 @@ implementation=Forge description=The SpongeAPI implementation for MinecraftForge forgeVersion=53.0.37 -loom.platform=forge -fabric.loom.dontRemap=true -mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file +mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index 150a7604d2b..d13d6d5d70e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m org.gradle.parallel=true -org.gradle.caching=false \ No newline at end of file +org.gradle.caching=false diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7d3f3c01b8b..ce3cf75c00e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4,7 +4,6 @@ true false - @@ -27,8 +26,6 @@ - - diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index f051af7bb4c..6588563ff1e 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -5,7 +5,7 @@ import org.spongepowered.gradle.impl.AWToAT buildscript { repositories { - maven("https://repo.spongepowered.org/repository/maven-public") { + maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } maven("https://maven.neoforged.net/releases/") { @@ -39,9 +39,6 @@ repositories { maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } - maven("https://maven.neoforged.net/releases/") { - name = "neoforge" - } } // SpongeNeo libraries diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 7be93de69a7..043459a6938 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -3,6 +3,4 @@ implementation=NeoForge description=The SpongeAPI implementation for NeoForge neoForgeVersion=21.3.58 -loom.platform=neoforge -fabric.loom.dontRemap=true -mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json \ No newline at end of file +mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/settings.gradle.kts b/settings.gradle.kts index 6202443c650..f03b0eb07b8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,9 @@ pluginManagement { maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } - maven("https://maven.architectury.dev/") + maven("https://maven.architectury.dev/") { + name = "architectury" + } } val vanillaGradleVersion = "0.2.1-20241107.194040-91" plugins { @@ -27,7 +29,7 @@ plugins { } dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) // needed for arch-loom, unfortunately + repositoriesMode = RepositoriesMode.PREFER_PROJECT // needed for ForgeGradle, unfortunately repositories { maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" diff --git a/vanilla/gradle.properties b/vanilla/gradle.properties index e34373dcd39..80fb2390f88 100644 --- a/vanilla/gradle.properties +++ b/vanilla/gradle.properties @@ -2,4 +2,4 @@ name=SpongeVanilla implementation=Vanilla description=The SpongeAPI implementation for Vanilla Minecraft -mixinConfigs=mixins.spongevanilla.accessors.json,mixins.spongevanilla.api.json,mixins.spongevanilla.core.json,mixins.spongevanilla.core.shared.json,mixins.spongevanilla.inventory.json,mixins.spongevanilla.inventory.shared.json,mixins.spongevanilla.tracker.json \ No newline at end of file +mixinConfigs=mixins.spongevanilla.accessors.json,mixins.spongevanilla.api.json,mixins.spongevanilla.core.json,mixins.spongevanilla.core.shared.json,mixins.spongevanilla.inventory.json,mixins.spongevanilla.inventory.shared.json,mixins.spongevanilla.tracker.json From bb0561990c4edea483e91c29dfc6d39bafdb8040 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 5 Jun 2025 23:41:40 +0200 Subject: [PATCH 271/586] Update MinecraftForge to 55.0.22 and NeoForge to 21.5.75 --- forge/gradle.properties | 2 +- gradle/verification-metadata.xml | 142 +++++++++++++++++++------------ neoforge/gradle.properties | 2 +- 3 files changed, 88 insertions(+), 58 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 0c079d0e356..606c020189e 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=55.0.6 +forgeVersion=55.0.22 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 401376bd36a..b61a27c04aa 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -181,14 +181,6 @@ - - - - - - - - @@ -208,6 +200,14 @@ + + + + + + + + @@ -251,14 +251,6 @@ - - - - - - - - @@ -278,6 +270,14 @@ + + + + + + + + @@ -3654,14 +3654,6 @@ - - - - - - - - @@ -3886,14 +3878,6 @@ - - - - - - - - @@ -3918,14 +3902,6 @@ - - - - - - - - @@ -4055,6 +4031,14 @@ + + + + + + + + @@ -4165,14 +4149,6 @@ - - - - - - - - @@ -4181,6 +4157,22 @@ + + + + + + + + + + + + + + + + @@ -4291,6 +4283,14 @@ + + + + + + + + @@ -4578,6 +4578,14 @@ + + + + + + + + @@ -4704,6 +4712,14 @@ + + + + + + + + @@ -4830,6 +4846,14 @@ + + + + + + + + @@ -5444,6 +5468,20 @@ + + + + + + + + + + + + + + @@ -6722,14 +6760,6 @@ - - - - - - - - diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index c130de572ae..8700d76c8d4 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.5.47-beta +neoForgeVersion=21.5.75 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 4e82ec47e2ae4690129067b773e351c8ebc68e66 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 13:05:16 -0700 Subject: [PATCH 272/586] feat(minecraft): update to 25w20a Notable Changes: - CommandsMixin needs a re-examination. It appears suggestion providers are moved to a different section, for now sponge commands do not get sent over to the client, but they still function on the server side. See: https://minecraft.wiki/w/Java_Edition_25w20a --- SpongeAPI | 2 +- gradle.properties | 2 +- .../data/provider/entity/WitherData.java | 2 +- .../common/event/tracking/PhaseTracker.java | 2 +- .../common/hooks/EventHooks.java | 2 +- .../world/biome/SpongeBiomeBuilder.java | 2 +- .../ambient/SpongeSoundConfigFactory.java | 2 +- .../SuggestionProviders_WrapperMixin_API.java | 2 +- .../server/level/ServerPlayerMixin_API.java | 2 +- .../api/minecraft/sounds/MusicMixin_API.java | 15 +- .../world/entity/EntityMixin_API.java | 7 +- .../mixin/core/commands/CommandsMixin.java | 342 +++++++++--------- .../server/commands/TeleportCommandMixin.java | 4 +- .../block/entity/SignBlockEntityMixin.java | 11 +- .../core/commands/CommandsMixin_Vanilla.java | 67 ++-- .../selector/EntitySelectorMixin_Vanilla.java | 20 +- 16 files changed, 243 insertions(+), 241 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 7ec9a87f889..a7a3f062111 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 7ec9a87f889f0f4331438d5faa72b08a3026d873 +Subproject commit a7a3f062111befd90329c32e14bf9229cb99f1bd diff --git a/gradle.properties b/gradle.properties index a65167f004a..c14e8071860 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w19a +minecraftVersion=25w20a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/WitherData.java b/src/main/java/org/spongepowered/common/data/provider/entity/WitherData.java index c61d2c863f0..c4eb1e8e689 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/WitherData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/WitherData.java @@ -45,7 +45,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(WitherBoss.class) .create(Keys.WITHER_TARGETS) .get(h -> Stream.of(h.getAlternativeTarget(0), h.getAlternativeTarget(1), h.getAlternativeTarget(2)) - .map(id -> h.getCommandSenderWorld().getEntity(id)) + .map(id -> h.level().getEntity(id)) // TODO filter null? .filter(Objects::nonNull) .map(org.spongepowered.api.entity.Entity.class::cast) .collect(Collectors.toList()) diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 93c253d7d14..d8d8ad95af5 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -292,7 +292,7 @@ public void init() { frame.addContext(EventContextKeys.SPAWN_TYPE, SpongeSpawnTypes.FORCED); for (final Entity entity : entities) { // At this point, we don't care what the causes are... - entity.getCommandSenderWorld().addFreshEntity(entity); + entity.level().addFreshEntity(entity); } } diff --git a/src/main/java/org/spongepowered/common/hooks/EventHooks.java b/src/main/java/org/spongepowered/common/hooks/EventHooks.java index af90ddb14a9..87c42715caf 100644 --- a/src/main/java/org/spongepowered/common/hooks/EventHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/EventHooks.java @@ -41,7 +41,7 @@ public interface EventHooks { default ChangeEntityWorldEvent.Pre callChangeEntityWorldEventPre(final Entity entity, final ServerLevel toWorld) { final ChangeEntityWorldEvent.Pre event = SpongeEventFactory.createChangeEntityWorldEventPre(PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.getCommandSenderWorld(), + (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.level(), (org.spongepowered.api.world.server.ServerWorld) toWorld, (org.spongepowered.api.world.server.ServerWorld) toWorld); SpongeCommon.post(event); return event; diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java index 6c4fa2c966b..d7729837bc5 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java @@ -129,7 +129,7 @@ public Biome build() { ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) m)); additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) s)); - backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) m)); + backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) (Object) m)); final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() .creatureGenerationProbability(spawnChance.floatValue()); diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java index 286d309f889..99964b0f271 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java @@ -46,6 +46,6 @@ public SoundConfig.Additional ofAdditional(final SoundType sound, final double t @Override public SoundConfig.BackgroundMusic ofBackroundMusic(final SoundType sound, final int minDelay, final int maxDelay, final boolean replacesCurrent) { - return (SoundConfig.BackgroundMusic) new Music(Holder.direct((SoundEvent) (Object) sound), minDelay, maxDelay, replacesCurrent); + return (SoundConfig.BackgroundMusic) (Object) new Music(Holder.direct((SoundEvent) (Object) sound), minDelay, maxDelay, replacesCurrent); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/synchronization/SuggestionProviders_WrapperMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/synchronization/SuggestionProviders_WrapperMixin_API.java index 98070be4dbe..9f6f6135387 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/synchronization/SuggestionProviders_WrapperMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/synchronization/SuggestionProviders_WrapperMixin_API.java @@ -41,7 +41,7 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -@Mixin(targets = "net/minecraft/commands/synchronization/SuggestionProviders$Wrapper") +@Mixin(targets = "net/minecraft/commands/synchronization/SuggestionProviders$RegisteredSuggestion") public abstract class SuggestionProviders_WrapperMixin_API implements CommandCompletionProvider { // @formatter:off diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java index a52290e1163..926dea4c5ef 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java @@ -289,7 +289,7 @@ public Optional setWorldBorder(final @Nullable WorldBorder border) this.connection.send(new ClientboundInitializeBorderPacket(mutableWorldBorder)); } else { // unset the border if null ((ServerPlayerBridge) this).bridge$replaceWorldBorder(null); - this.connection.send(new ClientboundInitializeBorderPacket(this.shadow$getCommandSenderWorld().getWorldBorder())); + this.connection.send(new ClientboundInitializeBorderPacket(this.shadow$level().getWorldBorder())); } return toSet; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java index 55c04b7c5d3..c865d062e76 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java @@ -30,10 +30,14 @@ import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(Music.class) +@Implements(@Interface(iface = SoundConfig.BackgroundMusic.class, prefix = "api$", remap = Interface.Remap.NONE)) public abstract class MusicMixin_API implements SoundConfig.BackgroundMusic { // @formatter:off @@ -48,18 +52,17 @@ public SoundType sound() { return (SoundType) (Object) this.event.value(); } - @Override - public int minDelay() { + @Intrinsic + public int api$minDelay() { return this.minDelay; } - @Override - public int maxDelay() { + @Intrinsic + public int api$maxDelay() { return this.maxDelay; } - @Override - public boolean replacesCurrent() { + public boolean api$replacesCurrent() { return this.replaceCurrentMusic; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index 8b5af7f1b05..60500f0005b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -30,7 +30,6 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.ProblemReporter; @@ -98,8 +97,6 @@ public abstract class EntityMixin_API implements org.spongepowered.api.entity.En @Shadow public abstract double shadow$getX(); @Shadow public abstract double shadow$getY(); @Shadow public abstract double shadow$getZ(); - @Shadow public abstract Level shadow$getCommandSenderWorld(); - @Shadow @Nullable public abstract MinecraftServer shadow$getServer(); @Shadow public abstract boolean shadow$isRemoved(); @Shadow public abstract UUID shadow$getUUID(); @Shadow public abstract boolean shadow$hurtOrSimulate(DamageSource source, float amount); @@ -135,7 +132,7 @@ public boolean setPosition(final Vector3d position) { @Override public ServerLocation location() { - return ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) this.shadow$getCommandSenderWorld(), this.position()); + return ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) this.shadow$level(), this.position()); } @Override @@ -310,7 +307,7 @@ public org.spongepowered.api.entity.Entity copy() { output.putString("id", entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()).toString()); this.shadow$saveWithoutId(output); final var input = TagValueInput.create(ProblemReporter.DISCARDING, this.level.registryAccess(), output.buildResult()); - final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(input, this.shadow$getCommandSenderWorld(), EntitySpawnReason.COMMAND, + final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(input, this.shadow$level(), EntitySpawnReason.COMMAND, (createdEntity) -> { createdEntity.setUUID(UUID.randomUUID()); return createdEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 49ef9cb8abf..c868d91b891 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -30,14 +30,12 @@ import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; -import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.synchronization.SuggestionProviders; import net.minecraft.server.commands.AdvancementCommands; -import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.registry.RegistryHolder; @@ -51,7 +49,6 @@ import org.spongepowered.common.bridge.commands.CommandsBridge; import org.spongepowered.common.bridge.commands.arguments.CompletionsArgumentTypeBridge; import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; -import org.spongepowered.common.command.brigadier.dispatcher.SpongeNodePermissionCache; import org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode; import org.spongepowered.common.command.brigadier.tree.SpongeNode; import org.spongepowered.common.command.brigadier.tree.SuggestionArgumentNode; @@ -60,35 +57,34 @@ import org.spongepowered.common.launch.Launch; import org.spongepowered.common.util.CommandUtil; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Map; -import java.util.WeakHashMap; @Mixin(Commands.class) public abstract class CommandsMixin implements CommandsBridge { // @formatter:off - @Shadow private void shadow$fillUsableCommands(final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { + @Shadow private static void shadow$fillUsableCommands( + final CommandNode rootCommandSource, + final CommandNode rootSuggestion, + final S source, + final Map, CommandNode> commandNodeToSuggestionNode + ) { throw new AssertionError("This shouldn't be callable"); } // @formatter:on private CauseStackManager.@MonotonicNonNull StackFrame impl$initFrame = null; - private final WeakHashMap, List>>> impl$playerNodeCache = - new WeakHashMap<>(); +// @Unique +// private static final WeakHashMap, List>>> impl$playerNodeCache = +// new WeakHashMap<>(); private @MonotonicNonNull SpongeCommandManager impl$commandManager; // We prepare our own dispatcher and commands manager, to redirect registrations to our system @Redirect(method = "", at = @At( - value = "NEW", - args = "class=com/mojang/brigadier/CommandDispatcher", - remap = false + value = "NEW", + args = "class=com/mojang/brigadier/CommandDispatcher", + remap = false )) private CommandDispatcher impl$useSpongeDispatcher(final Commands.CommandSelection $$0, final CommandBuildContext $$1) { if (!Launch.instance().pluginManager().isReady()) { @@ -101,7 +97,7 @@ public abstract class CommandsMixin implements CommandsBridge { } @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/commands/AdvancementCommands;register(Lcom/mojang/brigadier/CommandDispatcher;)V")) + target = "Lnet/minecraft/server/commands/AdvancementCommands;register(Lcom/mojang/brigadier/CommandDispatcher;)V")) private void impl$setupStackFrameOnInit(final CommandDispatcher dispatcher) { if (Launch.instance().pluginManager().isReady()) { this.impl$initFrame = PhaseTracker.getInstance().pushCauseFrame(); @@ -123,35 +119,36 @@ public abstract class CommandsMixin implements CommandsBridge { * Hides nodes that we have marked as "hidden" */ @Redirect(method = "fillUsableCommands", - slice = @Slice( - from = @At("HEAD"), - to = @At(value = "INVOKE", remap = false, target = "Ljava/util/Iterator;hasNext()Z") - ), - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;getChildren()Ljava/util/Collection;", remap = false)) - private Collection> impl$handleHiddenChildrenAndEnsureUnsortedLoop(final CommandNode commandNode) { - return this.impl$getChildrenFromNode(commandNode); + slice = @Slice( + from = @At("HEAD"), + to = @At(value = "INVOKE", remap = false, target = "Ljava/util/Iterator;hasNext()Z") + ), + at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;getChildren()Ljava/util/Collection;", remap = false)) + private static Collection> impl$handleHiddenChildrenAndEnsureUnsortedLoop(final CommandNode commandNode) { + return CommandsMixin.impl$getChildrenFromNode(commandNode); } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/tree/CommandNode;createBuilder()Lcom/mojang/brigadier/builder/ArgumentBuilder;", - remap = false)) - private ArgumentBuilder impl$createArgumentBuilder( - final CommandNode commandNode, - final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { + at = @At(value = "INVOKE", + target = "Lcom/mojang/brigadier/tree/CommandNode;createBuilder()Lcom/mojang/brigadier/builder/ArgumentBuilder;", + remap = false)) + private static ArgumentBuilder impl$createArgumentBuilder( + final CommandNode commandNode, + final CommandNode rootCommandSource, + final CommandNode rootSuggestion, + final S source, + final Map, CommandNode> commandNodeToSuggestionNode + ) { if (commandNode instanceof SpongeArgumentCommandNode node) { - return node.createBuilderForSuggestions(rootSuggestion, commandNodeToSuggestionNode); + return node.createBuilderForSuggestions((CommandNode) rootSuggestion, (Map) commandNodeToSuggestionNode); } if (commandNode instanceof ArgumentCommandNode acn && acn.getType() instanceof CompletionsArgumentTypeBridge catb) { final RequiredArgumentBuilder builder = RequiredArgumentBuilder.argument(acn.getName(), catb.bridge$clientSideCompletionType()); builder.executes(acn.getCommand()) - .forward(acn.getRedirect(), acn.getRedirectModifier(), acn.isFork()) - .requires(acn.getRequirement()); + .forward(acn.getRedirect(), acn.getRedirectModifier(), acn.isFork()) + .requires(acn.getRequirement()); if (!CommandUtil.checkForCustomSuggestions(rootSuggestion)) { builder.suggests((SuggestionProvider) SuggestionProviders.ASK_SERVER); } @@ -160,141 +157,152 @@ public abstract class CommandsMixin implements CommandsBridge { return commandNode.createBuilder(); } - @SuppressWarnings("unchecked") - @Redirect(method = "fillUsableCommands", at = - @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) - private V impl$preventPutIntoMapIfNodeIsComplex(final Map map, - final K key, - final V value, - final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { - if (!map.containsKey(key)) { - // done here because this check is applicable - final ServerPlayer e = (ServerPlayer) source.getEntity(); - final Map, List>> playerNodes = this.impl$playerNodeCache.get(e); - if (!playerNodes.containsKey(key)) { - final List> children = new ArrayList<>(); - children.add((CommandNode) value); - playerNodes.put((CommandNode) key, children); - } - - // If the current root suggestion has already got a custom suggestion and this node has a custom suggestion, - // we need to swap it out. - if (value instanceof ArgumentCommandNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions((ArgumentCommandNode) value)); - } else { - rootSuggestion.addChild((CommandNode) value); - } - return map.put(key, value); - } - return null; // it's ignored anyway. - } + // TODO - 25w20a changes +// @SuppressWarnings("unchecked") +// @Redirect(method = "fillUsableCommands", at = +// @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) +// private static V impl$preventPutIntoMapIfNodeIsComplex( +// final Map map, +// final K key, +// final V value, +// final CommandNode rootCommandSource, +// final CommandNode rootSuggestion, +// final S source, +// final Map, CommandNode> commandNodeToSuggestionNode +// ) { +// if (!map.containsKey(key)) { +// if (!(source instanceof CommandSourceStack css)) { +// return map.put(key, value); +// } +// // done here because this check is applicable +// final ServerPlayer e = (ServerPlayer) css.getEntity(); +// final Map, List>> playerNodes = CommandsMixin.impl$playerNodeCache.get(e); +// if (!playerNodes.containsKey(key)) { +// final List> children = new ArrayList<>(); +// children.add((CommandNode) value); +// playerNodes.put((CommandNode) key, children); +// } +// +// // If the current root suggestion has already got a custom suggestion and this node has a custom suggestion, +// // we need to swap it out. +// if (value instanceof ArgumentCommandNode argNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { +// rootSuggestion.addChild(CommandsMixin.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode)); +// } else { +// rootSuggestion.addChild((CommandNode) value); +// } +// return map.put(key, value); +// } +// return null; // it's ignored anyway. +// } @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/tree/CommandNode;addChild(Lcom/mojang/brigadier/tree/CommandNode;)V", - remap = false)) - private void impl$preventAddChild(final CommandNode root, final CommandNode newChild) { + at = @At(value = "INVOKE", + target = "Lcom/mojang/brigadier/tree/CommandNode;addChild(Lcom/mojang/brigadier/tree/CommandNode;)V", + remap = false)) + private static void impl$preventAddChild(final CommandNode root, final CommandNode newChild) { // no-op, we did this above. } - @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;canUse(Ljava/lang/Object;)Z", remap = false)) - private boolean impl$testPermissionAndPreventRecalculationWhenSendingNodes( - final CommandNode commandNode, - final Object source, - final CommandNode rootCommandNode, - final CommandNode rootSuggestion, - final CommandSourceStack sourceButTyped, - final Map, CommandNode> commandNodeToSuggestionNode - ) { - final ServerPlayer e = (ServerPlayer) sourceButTyped.getEntity(); - final Map, List>> playerNodes = this.impl$playerNodeCache.get(e); - final List> existingNodes = playerNodes.get(commandNode); - if (existingNodes != null) { - if (!existingNodes.isEmpty()) { - boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - for (final CommandNode node : existingNodes) { - // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug - // in the client where it'll send more than one custom suggestion request - which is fine, except - // the client will then ignore all but one of them. This is a problem because we then end up with - // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, - // meaning thenRun(...) does not run, which is how displaying the suggestions works... - // - // Because we don't control the client, we have to work around it here. - if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode) { - final ArgumentCommandNode argNode = (ArgumentCommandNode) node; - if (argNode.getCustomSuggestions() != null) { - // Rebuild the node without the custom suggestions. - rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode)); - continue; - } - } else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode) node).getCustomSuggestions() != null) { - hasCustomSuggestionsAlready = true; // no more custom suggestions - } - rootSuggestion.addChild(node); - } - } - // If empty, we have a node won't resolve (even if not complex), so we ignore it. - return false; - // If we have already processed this node and it appears in the suggestion node list, prevent a potentially costly - // canUse check as we know we can already use it. - } else if (!commandNodeToSuggestionNode.containsKey(commandNode) && !SpongeNodePermissionCache.canUse( - rootCommandNode instanceof RootCommandNode, this.impl$commandManager.getDispatcher(), commandNode, sourceButTyped)) { - playerNodes.put(commandNode, Collections.emptyList()); - return false; - } - - if (commandNode instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode) commandNode).isComplex()) { - final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - final CommandNode finalCommandNode = ((SpongeArgumentCommandNode) commandNode).getComplexSuggestions( - rootSuggestion, - commandNodeToSuggestionNode, - playerNodes, - !hasCustomSuggestionsAlready - ); - if (!this.impl$getChildrenFromNode(commandNode).isEmpty()) { - this.shadow$fillUsableCommands(commandNode, finalCommandNode, sourceButTyped, commandNodeToSuggestionNode); - } - return false; - } - - // Normal node, handle it normally. We don't add to the playerNodeCache - the commandNodeToSuggestionNode map handles this. - return true; - } - - @Redirect(method = "fillUsableCommands", at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;suggests(Lcom/mojang/brigadier/suggestion/SuggestionProvider;)Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;", remap = false)) - private RequiredArgumentBuilder impl$dontAskServerIfSiblingAlreadyDoes( - final RequiredArgumentBuilder requiredArgumentBuilder, - final SuggestionProvider provider, - final CommandNode rootCommandNode, - final CommandNode rootSuggestion, - final CommandSourceStack sourceButTyped, - final Map, CommandNode> commandNodeToSuggestionNode - ) { - // From above. - // - // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug - // in the client where it'll send more than one custom suggestion request - which is fine, except - // the client will then ignore all but one of them. This is a problem because we then end up with - // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, - // meaning thenRun(...) does not run, which is how displaying the suggestions works... - // - // Because we don't control the client, we have to work around it here. - if (provider != SuggestionProviders.ASK_SERVER || !CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - requiredArgumentBuilder.suggests(provider); - } - return requiredArgumentBuilder; - } + // TODO - 25w20a changes +// @Redirect(method = "fillUsableCommands", +// at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;canUse(Ljava/lang/Object;)Z", remap = false)) +// private static boolean impl$testPermissionAndPreventRecalculationWhenSendingNodes( +// final CommandNode commandNode, +// final S source, +// final CommandNode rootCommandNode, +// final CommandNode rootSuggestion, +// final S fillSource, +// final Map, CommandNode> commandNodeToSuggestionNode +// ) { +// if (!(source instanceof CommandSourceStack css)) { +// return commandNode.canUse(source); +// } +// final ServerPlayer e = (ServerPlayer) css.getEntity(); +// final Map, List>> playerNodes = CommandsMixin.impl$playerNodeCache.get(e); +// final List> existingNodes = playerNodes.get(commandNode); +// if (existingNodes != null) { +// if (!existingNodes.isEmpty()) { +// boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); +// for (final CommandNode node : existingNodes) { +// // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug +// // in the client where it'll send more than one custom suggestion request - which is fine, except +// // the client will then ignore all but one of them. This is a problem because we then end up with +// // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, +// // meaning thenRun(...) does not run, which is how displaying the suggestions works... +// // +// // Because we don't control the client, we have to work around it here. +// if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode argNode) { +// if (argNode.getCustomSuggestions() != null) { +// // Rebuild the node without the custom suggestions. +// rootSuggestion.addChild(CommandsMixin.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode)); +// continue; +// } +// } else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode) node).getCustomSuggestions() != null) { +// hasCustomSuggestionsAlready = true; // no more custom suggestions +// } +// rootSuggestion.addChild(node); +// } +// } +// // If empty, we have a node won't resolve (even if not complex), so we ignore it. +// return false; +// // If we have already processed this node and it appears in the suggestion node list, prevent a potentially costly +// // canUse check as we know we can already use it. +// } +// final CommandNode castedNode = (CommandNode) commandNode; +// if (!commandNodeToSuggestionNode.containsKey(commandNode) && !SpongeNodePermissionCache.canUse( +// rootCommandNode instanceof RootCommandNode, CommandsMixin.impl$commandManager.getDispatcher(), castedNode, css)) { +// playerNodes.put(castedNode, Collections.emptyList()); +// return false; +// } +// +// if (commandNode instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode) commandNode).isComplex()) { +// final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); +// final CommandNode finalCommandNode = ((SpongeArgumentCommandNode) commandNode).getComplexSuggestions( +// rootSuggestion, +// commandNodeToSuggestionNode, +// playerNodes, +// !hasCustomSuggestionsAlready +// ); +// if (!CommandsMixin.impl$getChildrenFromNode(castedNode).isEmpty()) { +// CommandsMixin.shadow$fillUsableCommands(castedNode, finalCommandNode, css, commandNodeToSuggestionNode); +// } +// return false; +// } +// +// // Normal node, handle it normally. We don't add to the playerNodeCache - the commandNodeToSuggestionNode map handles this. +// return true; +// } +// +// @Redirect(method = "fillUsableCommands", at = @At(value = "INVOKE", +// target = "Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;suggests(Lcom/mojang/brigadier/suggestion/SuggestionProvider;)Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;", remap = false)) +// private static RequiredArgumentBuilder impl$dontAskServerIfSiblingAlreadyDoes( +// final RequiredArgumentBuilder requiredArgumentBuilder, +// final SuggestionProvider provider, +// final CommandNode rootCommandNode, +// final CommandNode rootSuggestion, +// final CommandSourceStack sourceButTyped, +// final Map, CommandNode> commandNodeToSuggestionNode +// ) { +// // From above. +// // +// // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug +// // in the client where it'll send more than one custom suggestion request - which is fine, except +// // the client will then ignore all but one of them. This is a problem because we then end up with +// // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, +// // meaning thenRun(...) does not run, which is how displaying the suggestions works... +// // +// // Because we don't control the client, we have to work around it here. +// if (provider != SuggestionProviders.ASK_SERVER || !CommandUtil.checkForCustomSuggestions(rootSuggestion)) { +// requiredArgumentBuilder.suggests(provider); +// } +// return requiredArgumentBuilder; +// } @SuppressWarnings("unchecked") @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/builder/ArgumentBuilder;build()Lcom/mojang/brigadier/tree/CommandNode;", remap = false)) - private CommandNode impl$createSpongeArgumentNode(final ArgumentBuilder argumentBuilder) { + at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/builder/ArgumentBuilder;build()Lcom/mojang/brigadier/tree/CommandNode;", remap = false)) + private static CommandNode impl$createSpongeArgumentNode(final ArgumentBuilder argumentBuilder) { if (argumentBuilder instanceof RequiredArgumentBuilder) { return new SuggestionArgumentNode<>((RequiredArgumentBuilder) argumentBuilder); } @@ -306,7 +314,7 @@ public abstract class CommandsMixin implements CommandsBridge { return this.impl$commandManager; } - private Collection> impl$getChildrenFromNode(final CommandNode parentNode) { + private static Collection> impl$getChildrenFromNode(final CommandNode parentNode) { final Collection> nodes; if (parentNode instanceof SpongeNode) { nodes = ((SpongeNode) parentNode).getChildrenForSuggestions(); @@ -316,8 +324,10 @@ public abstract class CommandsMixin implements CommandsBridge { return nodes; } - private ArgumentCommandNode impl$cloneArgumentCommandNodeWithoutSuggestions(final ArgumentCommandNode toClone) { - final RequiredArgumentBuilder builder = toClone.createBuilder(); + private static ArgumentCommandNode impl$cloneArgumentCommandNodeWithoutSuggestions( + final ArgumentCommandNode toClone + ) { + final RequiredArgumentBuilder builder = toClone.createBuilder(); builder.suggests(null); for (final CommandNode node : toClone.getChildren()) { builder.then(node); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index 3a9547f8f8d..b8b9f5f8845 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -146,7 +146,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - final ServerLevel fromWorld = (ServerLevel) entityIn.getCommandSenderWorld(); + final ServerLevel fromWorld = (ServerLevel) entityIn.level(); final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(entityIn, worldIn); @@ -157,7 +157,7 @@ private static void performTeleport(CommandSourceStack source, Entity entityIn, final ChangeEntityWorldEvent.Reposition posEvent = SpongeEventFactory.createChangeEntityWorldEventReposition(frame.currentCause(), (org.spongepowered.api.entity.Entity) entityIn, - (org.spongepowered.api.world.server.ServerWorld) entityIn.getCommandSenderWorld(), + (org.spongepowered.api.world.server.ServerWorld) entityIn.level(), VecHelper.toVector3d(entityIn.position()), new Vector3d(x, y, z), preEvent.originalDestinationWorld(), new Vector3d(x, y, z), preEvent.destinationWorld()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/SignBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/SignBlockEntityMixin.java index 39e5760bd6c..44cd67bf139 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/SignBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/SignBlockEntityMixin.java @@ -26,9 +26,9 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.SignBlockEntity; import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.PermissionService; @@ -41,8 +41,8 @@ @Mixin(SignBlockEntity.class) public abstract class SignBlockEntityMixin extends BlockEntityMixin implements SubjectBridge, CommandSourceProviderBridge { - // @formatter:off - @Shadow private static CommandSourceStack shadow$createCommandSourceStack(final Player $$0, final Level $$1, final BlockPos $$2) { + // @formatter:offs + @Shadow private static CommandSourceStack shadow$createCommandSourceStack(final Player $$0, final ServerLevel $$1, final BlockPos $$2) { throw new UnsupportedOperationException("Shadowed createCommandSourceStack"); } // @formatter:on @@ -59,7 +59,10 @@ public abstract class SignBlockEntityMixin extends BlockEntityMixin implements S @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return SignBlockEntityMixin.shadow$createCommandSourceStack(cause.first(ServerPlayer.class).orElse(null), this.level, this.worldPosition); + if (!(this.level instanceof ServerLevel serverLevel)) { + throw new UnsupportedOperationException("cannot use a command source on a non-server level"); + } + return SignBlockEntityMixin.shadow$createCommandSourceStack(cause.first(ServerPlayer.class).orElse(null), serverLevel, this.worldPosition); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java index 1ea7a5f049a..694a82f6832 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java @@ -29,19 +29,11 @@ import net.minecraft.commands.Commands; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.server.level.ServerPlayer; -import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.service.permission.Subject; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; import org.spongepowered.common.command.manager.SpongeCommandManager; -import org.spongepowered.common.event.tracking.PhaseTracker; -import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -50,10 +42,10 @@ public abstract class CommandsMixin_Vanilla { // @formatter:off - @Shadow private void shadow$fillUsableCommands(final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { + @Shadow private static void shadow$fillUsableCommands(final CommandNode rootCommandSource, + final CommandNode rootSuggestion, + final S source, + final Map, CommandNode> commandNodeToSuggestionNode) { throw new AssertionError("This shouldn't be callable"); } // @formatter:on @@ -62,29 +54,30 @@ public abstract class CommandsMixin_Vanilla { private WeakHashMap, List>>> impl$playerNodeCache; private SpongeCommandManager impl$commandManager; - @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Lnet/minecraft/commands/CommandSourceStack;Ljava/util/Map;)V")) - private void impl$addNonBrigSuggestions( - final Commands commands, - final CommandNode p_197052_1_, - final CommandNode p_197052_2_, - final CommandSourceStack p_197052_3_, - final Map, CommandNode> p_197052_4_, - final ServerPlayer playerEntity) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(playerEntity); - frame.addContext(EventContextKeys.SUBJECT, (Subject) playerEntity); - final CommandCause sourceToUse = ((CommandSourceStackBridge) p_197052_3_).bridge$withCurrentCause(); - try { - this.impl$playerNodeCache.put(playerEntity, new IdentityHashMap<>()); - // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(p_197052_4_); - this.shadow$fillUsableCommands(p_197052_1_, p_197052_2_, (CommandSourceStack) sourceToUse, idMap); - } finally { - this.impl$playerNodeCache.remove(playerEntity); - } - for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { - p_197052_2_.addChild(node); - } - } - } + // TODO - 25w20a changes +// @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Lnet/minecraft/commands/CommandSourceStack;Ljava/util/Map;)V")) +// private void impl$addNonBrigSuggestions( +// final Commands commands, +// final CommandNode p_197052_1_, +// final CommandNode p_197052_2_, +// final CommandSourceStack p_197052_3_, +// final Map, CommandNode> p_197052_4_, +// final ServerPlayer playerEntity) { +// try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { +// frame.pushCause(playerEntity); +// frame.addContext(EventContextKeys.SUBJECT, (Subject) playerEntity); +// final CommandCause sourceToUse = ((CommandSourceStackBridge) p_197052_3_).bridge$withCurrentCause(); +// try { +// this.impl$playerNodeCache.put(playerEntity, new IdentityHashMap<>()); +// // We use this because the redirects should be a 1:1 mapping (which is what this map is for). +// final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(p_197052_4_); +// this.shadow$fillUsableCommands(p_197052_1_, p_197052_2_, (CommandSourceStack) sourceToUse, idMap); +// } finally { +// this.impl$playerNodeCache.remove(playerEntity); +// } +// for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { +// p_197052_2_.addChild(node); +// } +// } +// } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/arguments/selector/EntitySelectorMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/arguments/selector/EntitySelectorMixin_Vanilla.java index 1228d58f96b..3f693e13c4d 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/arguments/selector/EntitySelectorMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/arguments/selector/EntitySelectorMixin_Vanilla.java @@ -24,22 +24,18 @@ */ package org.spongepowered.vanilla.mixin.core.commands.arguments.selector; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.selector.EntitySelector; -import net.minecraft.commands.arguments.selector.EntitySelectorParser; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; @Mixin(EntitySelector.class) public abstract class EntitySelectorMixin_Vanilla { - @WrapOperation(method = "checkPermissions", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/CommandSourceStack;hasPermission(I)Z")) - private boolean vanilla$onCheckSelectorPermission(final CommandSourceStack instance, final int $$0, final Operation original) { - if (EntitySelectorParser.allowSelectors(instance)) { - return true; - } - return original.call(instance, $$0); - } + // TODO - 25w20a changes +// @WrapOperation(method = "checkPermissions", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/CommandSourceStack;hasPermission(I)Z")) +// private boolean vanilla$onCheckSelectorPermission(final CommandSourceStack instance, final int $$0, final Operation original) { +// if (EntitySelectorParser.allowSelectors(instance)) { +// return true; +// } +// return original.call(instance, $$0); +// } } From df7b2d6a55e85fef53ffe24ed3ebfb66105b1c25 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 13:20:29 -0700 Subject: [PATCH 273/586] feat(minecraft): update to 25w21a Small changes to leash sound registered names. See: https://minecraft.wiki/w/Java_Edition_25w21a --- SpongeAPI | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index a7a3f062111..b09d5dcb1e6 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a7a3f062111befd90329c32e14bf9229cb99f1bd +Subproject commit b09d5dcb1e6f1111f0809686938b34d5f86a0bef diff --git a/gradle.properties b/gradle.properties index 91783ede9c3..ecf20181fba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w20a +minecraftVersion=25w21a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 2c3df4ec75e70288c52ae55f9d8c579028c5c878 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 14:01:50 -0700 Subject: [PATCH 274/586] feat(minecraft): update to 1.21.6-pre1 Notable Changes: - Mojang removed further customization of packet sending, so Sponge's handling of custom packets ought to be the same, but it's otherwise untested. See: https://minecraft.wiki/w/Java_Edition_1.21.6_Pre-Release_1 --- gradle.properties | 2 +- .../common/network/channel/PacketSender.java | 14 +++++++-- .../mixin/core/client/MinecraftMixin.java | 4 +-- .../mixin/core/network/ConnectionMixin.java | 11 +++---- .../chat/Component_SerializerMixin.java | 2 +- .../ServerCommonPacketListenerImplMixin.java | 2 +- ...rConfigurationPacketListenerImplMixin.java | 2 +- .../entity/LivingEntityMixin_Damage.java | 2 +- .../projectile/ProjectileUtilMixin.java | 2 +- .../core/network/ConnectionMixin_Vanilla.java | 30 ++++++++++++++----- 10 files changed, 49 insertions(+), 22 deletions(-) diff --git a/gradle.properties b/gradle.properties index ecf20181fba..487fcca2b53 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w21a +minecraftVersion=1.21.6-pre1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/network/channel/PacketSender.java b/src/main/java/org/spongepowered/common/network/channel/PacketSender.java index ffa5b9a77bc..443cce8512b 100644 --- a/src/main/java/org/spongepowered/common/network/channel/PacketSender.java +++ b/src/main/java/org/spongepowered/common/network/channel/PacketSender.java @@ -24,8 +24,9 @@ */ package org.spongepowered.common.network.channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; import net.minecraft.network.protocol.Packet; import net.minecraft.util.thread.BlockableEventLoop; import org.checkerframework.checker.nullness.qual.Nullable; @@ -59,7 +60,7 @@ public static void sendTo(final EngineConnection connection, final Packet pac }); } - public static final class SpongePacketSendListener implements PacketSendListener { + public static final class SpongePacketSendListener implements ChannelFutureListener { private final BlockableEventLoop executor; private final Consumer<@Nullable Throwable> listener; @@ -71,6 +72,15 @@ public SpongePacketSendListener(final EngineConnectionSide this.listener.accept(throwable)); } + + @Override + public void operationComplete(ChannelFuture future) { + this.executor.execute(() -> { + if (!future.isSuccess()) { + this.listener.accept(future.cause()); + } + }); + } } private PacketSender() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index ce0fb5a032c..dfcb506becc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -112,8 +112,8 @@ public MinecraftMixin(String param0) { this.singleplayerServer = null; } - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("TAIL")) - private void impl$nullServerRefAndPhaseTracker(Screen screenIn, CallbackInfo ci) { + @Inject(method = "disconnect", at = @At("TAIL")) + private void impl$nullServerRefAndPhaseTracker(Screen screenIn, boolean keepResourcePacks, CallbackInfo ci) { ((MinecraftBridge) this).bridge$setTemporaryIntegratedServer(null); try { PhaseTracker.getServerInstanceExplicitly().setThread(null); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/ConnectionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/ConnectionMixin.java index fbb419193ce..5ad56e567f6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/ConnectionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/ConnectionMixin.java @@ -27,12 +27,12 @@ import com.google.common.collect.Sets; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.local.LocalAddress; import net.minecraft.network.Connection; import net.minecraft.network.PacketListener; -import net.minecraft.network.PacketSendListener; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; @@ -163,10 +163,11 @@ public abstract class ConnectionMixin extends SimpleChannelInboundHandler $$0, final @Nullable PacketSendListener $$1, final boolean $$2) { + private boolean impl$onQueue(final Queue> instance, final E consumer, + final Packet $$0, final @Nullable ChannelFutureListener $$1, final boolean $$2) { if (this.impl$disconnected) { if ($$1 instanceof final PacketSender.SpongePacketSendListener spongeListener) { spongeListener.accept(new IOException("Connection has been closed.")); @@ -188,7 +189,7 @@ public void accept(final Connection connection) { } }); } else { - result = instance.add(consumer); + result = instance.add((Consumer) consumer); } if (this.impl$disconnected) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java index 97824574f4a..01ce68a2357 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(targets = "net/minecraft/network/codec/ByteBufCodecs$34") +@Mixin(targets = "net/minecraft/network/codec/ByteBufCodecs$35") public abstract class Component_SerializerMixin { // inject into the anonymous function to build a gson instance diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java index e0386d860a9..99aaa23b71f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java @@ -87,7 +87,7 @@ public abstract class ServerCommonPacketListenerImplMixin implements ServerCommo private Map impl$resourcePackCallbacks = new ConcurrentHashMap<>(); @ModifyVariable( - method = "send(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketSendListener;)V", + method = "send(Lnet/minecraft/network/protocol/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("HEAD"), argsOnly = true ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java index fbd2b131e31..a798a21ca54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java @@ -183,7 +183,7 @@ public Type type() { } @Inject(method = "handleConfigurationFinished", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/players/PlayerList;getPlayerForLogin(Lcom/mojang/authlib/GameProfile;Lnet/minecraft/server/level/ClientInformation;)Lnet/minecraft/server/level/ServerPlayer;")) + target = "Lnet/minecraft/server/players/PlayerList;getPlayer(Ljava/util/UUID;)Lnet/minecraft/server/level/ServerPlayer;")) private void impl$sendChannels(final CallbackInfo ci) { ((SpongeChannelManager) SpongeCommon.game().channelManager()).sendChannelRegistrations( ((ConnectionBridge) this.connection).bridge$getEngineConnection()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index 13d69e638b9..2df79d0393f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -128,7 +128,7 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li @SuppressWarnings("MixinAnnotationTarget") @Inject(method = "applyItemBlocking", at = { @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V"), // Vanilla and Forge - @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;FI)V") // Neo + @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V") // Neo }) private void damage$onHurtShield(final CallbackInfoReturnable cir) { this.damage$inventoryChanged = true; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java index 6f786188ad6..19c5a4d75cb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java @@ -78,7 +78,7 @@ public abstract class ProjectileUtilMixin { @Redirect(method = { "getHitResult(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/Entity;Ljava/util/function/Predicate;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/level/Level;FLnet/minecraft/world/level/ClipContext$Block;)Lnet/minecraft/world/phys/HitResult;", - "getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Lnet/minecraft/world/phys/EntityHitResult;" + "getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Lnet/minecraft/world/phys/EntityHitResult;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ProjectileUtil;getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;F)Lnet/minecraft/world/phys/EntityHitResult;")) private static EntityHitResult impl$onGetEntityHitResult(final Level $$0, final Entity $$1, final Vec3 $$2, final Vec3 $$3, final AABB $$4, final Predicate $$5, final float $$6) { if ($$0.isClientSide) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/network/ConnectionMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/network/ConnectionMixin_Vanilla.java index f144a638e63..65aaaba8dd8 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/network/ConnectionMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/network/ConnectionMixin_Vanilla.java @@ -24,22 +24,38 @@ */ package org.spongepowered.vanilla.mixin.core.network; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; +import net.minecraft.network.protocol.Packet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.network.channel.PacketSender; @Mixin(Connection.class) public class ConnectionMixin_Vanilla { - @Inject(method = "lambda$doSendPacket$13", at = @At(value = "INVOKE", target = "Lio/netty/util/concurrent/Future;isSuccess()Z")) - public void impl$onPacketSent(final PacketSendListener listener, final Future future, final CallbackInfo ci) { - if (listener instanceof final PacketSender.SpongePacketSendListener spongeListener) { - spongeListener.accept(future.cause()); + @WrapOperation(method = "doSendPacket", at = @At( + value = "INVOKE", + target = "Lio/netty/channel/ChannelFuture;addListener(Lio/netty/util/concurrent/GenericFutureListener;)Lio/netty/channel/ChannelFuture;", + remap = false + )) + public ChannelFuture impl$onPacketSent( + final ChannelFuture instance, final GenericFutureListener> genericFutureListener, + final Operation original, final Packet packet, + final ChannelFutureListener listener, final boolean abool + ) { + if (listener instanceof PacketSender.SpongePacketSendListener spsl) { + original.call(instance, (ChannelFutureListener) (future) -> { + if (!future.isSuccess()) { + spsl.accept(future.cause()); + } + }); } + return original.call(instance, listener); } } From a0f4a31820eb3553a732fc9597c0f0a4c37073a5 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 14:08:18 -0700 Subject: [PATCH 275/586] feat(minecraft): update to 1.21.6-pre2 See: https://minecraft.wiki/w/Java_Edition_1.21.6_Pre-Release_2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 487fcca2b53..e0c9ffab02a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6-pre1 +minecraftVersion=1.21.6-pre2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From b9a6f0017d62ffd0d79d6f2da12fbefb6047f25d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 14:35:07 -0700 Subject: [PATCH 276/586] feat(adventure): update adventure to 4.21 Notably 4.21 includes component enhancements since 1.21.5 See changes from https://docs.advntr.dev/version-history/adventure.html#release-v4-19-0 https://docs.advntr.dev/version-history/adventure.html#release-v4-20-0 https://docs.advntr.dev/version-history/adventure.html#release-v4-21-0 --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 173 +++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index b09d5dcb1e6..9bc0fc9edc9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b09d5dcb1e6f1111f0809686938b34d5f86a0bef +Subproject commit 9bc0fc9edc9caf957ba1972fa7184bec068374e7 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index b61a27c04aa..178638e4689 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3058,6 +3058,22 @@ + + + + + + + + + + + + + + + + @@ -3082,6 +3098,19 @@ + + + + + + + + + + + + + @@ -3115,6 +3144,22 @@ + + + + + + + + + + + + + + + + @@ -3145,6 +3190,22 @@ + + + + + + + + + + + + + + + + @@ -3178,6 +3239,22 @@ + + + + + + + + + + + + + + + + @@ -3208,6 +3285,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3241,6 +3350,22 @@ + + + + + + + + + + + + + + + + @@ -3274,6 +3399,22 @@ + + + + + + + + + + + + + + + + @@ -3307,6 +3448,22 @@ + + + + + + + + + + + + + + + + @@ -3340,6 +3497,22 @@ + + + + + + + + + + + + + + + + From 88b238bf2f205f1380ea7bd2b723ca57c6a69315 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 14:36:42 -0700 Subject: [PATCH 277/586] feat(minecraft): update minecraft to 1.21.6-pre3 Notable change: - Addition of Sound category that isn't yet represented in Adventure, so we delegate it to Master for now. See https://minecraft.wiki/w/Java_Edition_1.21.6_Pre-Release_3 --- gradle.properties | 2 +- .../org/spongepowered/common/adventure/SpongeAdventure.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e0c9ffab02a..7ee5a7980c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6-pre2 +minecraftVersion=1.21.6-pre3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index b4964468f4c..b09679ab007 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -823,6 +823,8 @@ public static Sound.Source asAdventure(final SoundSource source) { case PLAYERS -> Sound.Source.PLAYER; case AMBIENT -> Sound.Source.AMBIENT; case VOICE -> Sound.Source.VOICE; + // TODO - for now just use master + case UI -> Sound.Source.MASTER; }; } From e32014e227699166dec7ccddc445c1b27dbaeb6c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 14:53:47 -0700 Subject: [PATCH 278/586] chore(deps): update Adventure to 4.21 This minor release adds component enhancements for 1.21.5's components. --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 88 ++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 52792007710..6fc1b4a3472 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 527920077105384acc911b58116c2d3240297b17 +Subproject commit 6fc1b4a34727f19654a49c524e45d54950e214fb diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index b61a27c04aa..b8879031dcb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3058,6 +3058,14 @@ + + + + + + + + @@ -3082,6 +3090,14 @@ + + + + + + + + @@ -3115,6 +3131,14 @@ + + + + + + + + @@ -3145,6 +3169,14 @@ + + + + + + + + @@ -3178,6 +3210,14 @@ + + + + + + + + @@ -3208,6 +3248,22 @@ + + + + + + + + + + + + + + + + @@ -3241,6 +3297,14 @@ + + + + + + + + @@ -3274,6 +3338,14 @@ + + + + + + + + @@ -3307,6 +3379,14 @@ + + + + + + + + @@ -3340,6 +3420,14 @@ + + + + + + + + From 6de367a6117bb456ab199b5db6a1cffedbc11d10 Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Mon, 9 Jun 2025 02:23:35 +0300 Subject: [PATCH 279/586] Implement DefaultedTag (#4206) * implement DefaultedTag * generate tags using DefaultedTag --------- Co-authored-by: aromaa --- SpongeAPI | 2 +- .../vanilla/generator/TagGenerator.java | 4 +- .../vanilla/generator/Types.java | 2 + .../common/bridge/tags/TagBridge.java | 32 +++++++ .../event/lifecycle/RegisterTagEventImpl.java | 32 +++++-- .../common/item/SpongeToolRuleFactory.java | 10 +-- .../common/tag/SpongeDefaultedTag.java | 86 +++++++++++++++++++ .../world/server/SpongeWorldTypeBuilder.java | 4 +- .../api/minecraft/block/BlockMixin_API.java | 20 ----- .../core/MappedRegistryMixin_API.java | 10 +-- .../api/minecraft/tags/TagKeyMixin_API.java | 16 ++++ .../damagesource/DamageTypeMixin_API.java | 22 ----- .../world/entity/EntityTypeMixin_API.java | 21 ----- .../minecraft/world/item/ItemMixin_API.java | 21 ----- .../world/level/biome/BiomeMixin_API.java | 26 ------ .../world/level/material/FluidMixin_API.java | 20 ----- .../common/mixin/api/tag/TaggableMixin.java | 42 +++++++++ .../common/mixin/core/tags/TagKeyMixin.java | 38 ++++++++ src/mixins/resources/mixins.sponge.api.json | 3 +- src/mixins/resources/mixins.sponge.core.json | 1 + .../common/test/stub/block/StubBlock.java | 15 +--- .../test/stub/registry/StubbedRegistry.java | 5 +- .../spongepowered/test/entity/EntityTest.java | 3 +- .../test/projectile/ProjectileTest.java | 2 +- .../org/spongepowered/test/tag/TagTest.java | 14 +-- 25 files changed, 274 insertions(+), 177 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/bridge/tags/TagBridge.java create mode 100644 src/main/java/org/spongepowered/common/tag/SpongeDefaultedTag.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/tag/TaggableMixin.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/tags/TagKeyMixin.java diff --git a/SpongeAPI b/SpongeAPI index 267c5df1e0f..b2e2eb44c4e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 267c5df1e0fe396a0ffc7f7768bb845dff092bfe +Subproject commit b2e2eb44c4e1ae21cbfcf0488976b1ae83ee22a7 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java index 68d9d95b4ed..c1c8c1007fb 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java @@ -79,7 +79,7 @@ public void generate(final Context ctx) throws IOException { clazz.addAnnotation(Types.suppressWarnings("unused")); clazz.addAnnotation(TagGenerator.SCOPE.registryScopeAnnotation()); - final var fieldType = ParameterizedTypeName.get(Types.TAG, this.typeName); + final var fieldType = ParameterizedTypeName.get(Types.DEFAULTED_TAG, this.typeName); final ParameterSpec locationParam = ParameterSpec.builder(Types.RESOURCE_KEY, "key", Modifier.FINAL).build(); final var factoryMethod = MethodSpec.methodBuilder("key") .addModifiers(Modifier.PRIVATE, Modifier.STATIC) @@ -87,7 +87,7 @@ public void generate(final Context ctx) throws IOException { .addParameter(locationParam) .addCode( "return $T.of($T.$L, $N);", - Types.TAG, + Types.DEFAULTED_TAG, Types.REGISTRY_TYPES, this.registryTypeName.toUpperCase(Locale.ROOT), locationParam diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java b/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java index 518cbb2d6da..bc7cf62220b 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java @@ -57,6 +57,8 @@ final class Types { public static final ClassName DEFAULTED_REGISTRY_TYPE = ClassName.get(Context.BASE_PACKAGE + ".registry", "DefaultedRegistryType"); + public static final ClassName DEFAULTED_TAG = ClassName.get(Context.BASE_PACKAGE + ".tag", "DefaultedTag"); + public static final ClassName REGISTRY = ClassName.get(Context.BASE_PACKAGE + ".registry", "Registry"); public static final ClassName REGISTRY_KEY = ClassName.get(Context.BASE_PACKAGE + ".registry", "RegistryKey"); diff --git a/src/main/java/org/spongepowered/common/bridge/tags/TagBridge.java b/src/main/java/org/spongepowered/common/bridge/tags/TagBridge.java new file mode 100644 index 00000000000..332754b65a9 --- /dev/null +++ b/src/main/java/org/spongepowered/common/bridge/tags/TagBridge.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.bridge.tags; + +import net.minecraft.tags.TagKey; + +public interface TagBridge { + + TagKey bridge$asVanillaTag(); +} diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterTagEventImpl.java b/src/main/java/org/spongepowered/common/event/lifecycle/RegisterTagEventImpl.java index bf33e3485fa..1f9e30ecdc9 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/RegisterTagEventImpl.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/RegisterTagEventImpl.java @@ -26,10 +26,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Game; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.lifecycle.RegisterTagEvent; import org.spongepowered.api.registry.DefaultedRegistryReference; -import org.spongepowered.api.registry.RegistryKey; +import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.tag.Tag; import org.spongepowered.common.tag.SpongePluginTag; import org.spongepowered.common.tag.SpongePluginTagModifier; @@ -45,7 +46,7 @@ public final class RegisterTagEventImpl extends AbstractLifecycleEvent implements RegisterTagEvent { - private final Map, SpongePluginTagModifier> tags = new HashMap<>(); + private final Map> tags = new HashMap<>(); public RegisterTagEventImpl(final Cause cause, final Game game) { super(cause, game); @@ -54,13 +55,13 @@ public RegisterTagEventImpl(final Cause cause, final Game game) { @SuppressWarnings("unchecked") @Override public TagStep tag(final Tag tag) { - final SpongePluginTagModifier modifier = this.tags.computeIfAbsent(tag, $ -> new SpongePluginTagModifier<>()); + final SpongePluginTagModifier modifier = this.tags.computeIfAbsent(new TagKey(tag), $ -> new SpongePluginTagModifier<>()); return new TagStepImpl<>((SpongePluginTagModifier) modifier, null); } public SpongePluginTags tags() { return new SpongePluginTags(this.tags.entrySet().stream().collect( - Collectors.groupingBy(e -> e.getKey().registry(), Collectors.toMap(e -> e.getKey().key(), Map.Entry::getValue)))); + Collectors.groupingBy(e -> e.getKey().registry().registryType(), Collectors.toMap(e -> e.getKey().tag(), Map.Entry::getValue)))); } private record TagStepImpl(SpongePluginTagModifier pluginTagModifier, @Nullable SpongePluginTagPredicate predicate) implements TagStep { @@ -84,7 +85,7 @@ public TagStep filterTags(final BiPredicate, DefaultedRegistryReferenc } @Override - public TagStep append(final RegistryKey key) { + public TagStep append(final org.spongepowered.api.registry.RegistryKey key) { this.pluginTagModifier.append(new SpongePluginTag(key.location(), false), this.predicate); return this; } @@ -113,4 +114,25 @@ public TagStep testTags(final BiPredicate, DefaultedRegistryReference< return this; } } + + private record TagKey(RegistryTypeKey registry, ResourceKey tag) + { + public TagKey(final Tag tag) + { + this(new RegistryTypeKey(tag.registry()), tag.key()); + } + } + + private record RegistryTypeKey(ResourceKey registryRoot, ResourceKey registryKey) + { + public RegistryTypeKey(RegistryType registryType) + { + this(registryType.root(), registryType.location()); + } + + public RegistryType registryType() + { + return RegistryType.of(this.registryRoot, this.registryKey); + } + } } diff --git a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java index 5ce79c4d06f..bae8eb40804 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java +++ b/src/main/java/org/spongepowered/common/item/SpongeToolRuleFactory.java @@ -27,13 +27,13 @@ import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.component.Tool; import net.minecraft.world.level.block.Block; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.type.ToolRule; import org.spongepowered.api.tag.Tag; +import org.spongepowered.common.bridge.tags.TagBridge; import java.util.List; import java.util.Optional; @@ -49,7 +49,7 @@ public ToolRule minesAndDrops(final List blocks, final double speed) @Override public ToolRule minesAndDrops(final Tag blockTypeTag, final double speed) { - final var tag = (TagKey) (Object) blockTypeTag; + final var tag = ((TagBridge) blockTypeTag).bridge$asVanillaTag(); final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.minesAndDrops(holderSet, (float) speed); } @@ -63,7 +63,7 @@ public ToolRule deniesDrops(final List blocks) { @Override public ToolRule deniesDrops(final Tag blockTypeTag) { - final var tag = (TagKey) (Object) blockTypeTag; + final var tag = ((TagBridge) blockTypeTag).bridge$asVanillaTag(); final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.deniesDrops(holderSet); } @@ -76,7 +76,7 @@ public ToolRule overrideSpeed(final List blocks, final double speed) @Override public ToolRule overrideSpeed(final Tag blockTypeTag, final double speed) { - final var tag = (TagKey) (Object) blockTypeTag; + final var tag = ((TagBridge) blockTypeTag).bridge$asVanillaTag(); final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) Tool.Rule.overrideSpeed(holderSet, (float) speed); } @@ -91,7 +91,7 @@ public ToolRule forBlocks(final List blocks, @Nullable final Double s @Override public ToolRule forTag(final Tag blockTypeTag, @Nullable final Double speed, @Nullable final Boolean drops) { // See Tool#forTag - final var tag = (TagKey) (Object) blockTypeTag; + final var tag = ((TagBridge) blockTypeTag).bridge$asVanillaTag(); final var holderSet = BuiltInRegistries.BLOCK.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return (ToolRule) (Object) new Tool.Rule(holderSet, Optional.ofNullable(speed).map(Double::floatValue), Optional.ofNullable(drops)); } diff --git a/src/main/java/org/spongepowered/common/tag/SpongeDefaultedTag.java b/src/main/java/org/spongepowered/common/tag/SpongeDefaultedTag.java new file mode 100644 index 00000000000..3ac88b6c515 --- /dev/null +++ b/src/main/java/org/spongepowered/common/tag/SpongeDefaultedTag.java @@ -0,0 +1,86 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.tag; + +import net.minecraft.core.MappedRegistry; +import net.minecraft.tags.TagKey; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.tag.DefaultedTag; +import org.spongepowered.api.tag.Tag; +import org.spongepowered.common.bridge.tags.TagBridge; + +import java.util.Objects; +import java.util.function.Supplier; + +public final class SpongeDefaultedTag implements DefaultedTag, TagBridge { + + private final Supplier defaultHolder; + private final TagKey vanillaTag; + private final Tag spongeTag; + + public SpongeDefaultedTag(final Tag tag, final Supplier defaultHolder) { + this.defaultHolder = Objects.requireNonNull(defaultHolder, "defaultHolder"); + this.vanillaTag = ((TagBridge) tag).bridge$asVanillaTag(); + this.spongeTag = (Tag) (Object) this.vanillaTag; + } + + @Override + public Supplier defaultHolder() { + return this.defaultHolder; + } + + @Override + public RegistryType registry() { + return this.spongeTag.registry(); + } + + @Override + public DefaultedTag asDefaultedTag(final Supplier holder) { + return this.spongeTag.asDefaultedTag(holder); + } + + @Override + public DefaultedTag asScopedTag() { + return this.spongeTag.asScopedTag(); + } + + @Override + public ResourceKey key() { + return this.spongeTag.key(); + } + + @Override + public TagKey bridge$asVanillaTag() { + return this.vanillaTag; + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(final T value) { + return ((MappedRegistry) this.defaultHolder.get().registry(this.registry())).wrapAsHolder(value).is(this.vanillaTag); + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index e531e249561..8774fb0562f 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -25,7 +25,6 @@ package org.spongepowered.common.world.server; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.dimension.DimensionType; @@ -41,6 +40,7 @@ import org.spongepowered.api.util.Range; import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.WorldTypeEffect; +import org.spongepowered.common.bridge.tags.TagBridge; import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; @@ -110,7 +110,7 @@ public WorldType.Builder from(final WorldType type) { hasSkylight, hasCeiling, scorching, natural, coordinateMultiplier, bedsUsable, respawnAnchorsUsable, floor, height, logicalHeight, - (TagKey) (Object) infiniburn, + ((TagBridge) infiniburn).bridge$asVanillaTag(), (ResourceLocation) (Object) effect.key(), ambientLighting, new DimensionType.MonsterSettings(piglinSafe, hasRaids, monsterSpawnLightTest, monsterSpawnBlockLightLimit)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java index a308240cd85..7126ff3910d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/block/BlockMixin_API.java @@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableList; import net.kyori.adventure.text.Component; import net.minecraft.core.Holder; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Block; @@ -35,10 +34,7 @@ import org.spongepowered.api.block.BlockState; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.registry.DefaultedRegistryType; -import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.state.StateProperty; -import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -48,7 +44,6 @@ import java.util.Collection; import java.util.Optional; import java.util.function.Supplier; -import java.util.stream.Collectors; @Mixin(value = Block.class, priority = 999) public abstract class BlockMixin_API extends BlockBehaviourMixin_API implements SpongeImmutableDataHolder { @@ -104,19 +99,4 @@ public boolean isAnyOf(final Supplier... types) { public boolean isAnyOf(final BlockType... types) { return Arrays.stream(types).anyMatch(type -> type == this); } - - @Override - public DefaultedRegistryType registryType() { - return RegistryTypes.BLOCK_TYPE; - } - - @Override - public Collection> tags() { - return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); - } - - @Override - public boolean is(Tag tag) { - return this.builtInRegistryHolder.is((TagKey) (Object) tag); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java index 82f095dcec1..033b74fe337 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java @@ -43,11 +43,10 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.core.RegistryBridge; import org.spongepowered.common.bridge.core.WritableRegistryBridge; +import org.spongepowered.common.bridge.tags.TagBridge; import java.util.Objects; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; @Mixin(MappedRegistry.class) @@ -120,11 +119,10 @@ public V value(final ResourceKey key) { @Override @SuppressWarnings("unchecked") - public Set taggedValues(final Tag tag) { - return this.impl$getTag((TagKey) (Object) tag).stream() + public Stream taggedValues(final Tag tag) { + return this.impl$getTag(((TagBridge) tag).bridge$asVanillaTag()).stream() .flatMap(HolderSet.ListBacked::stream) - .map(h -> (V) h.value()) - .collect(Collectors.toSet()); + .map(h -> (V) h.value()); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java index 073ccb77bf0..d4f3c45fd30 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java @@ -28,11 +28,17 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.api.tag.DefaultedTag; import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.tag.SpongeDefaultedTag; + +import java.util.function.Supplier; @Mixin(TagKey.class) public abstract class TagKeyMixin_API implements Tag { @@ -51,4 +57,14 @@ public RegistryType registry() { public ResourceKey key() { return (ResourceKey) (Object) this.location; } + + @Override + public DefaultedTag asDefaultedTag(final Supplier holder) { + return new SpongeDefaultedTag<>(this, holder); + } + + @Override + public DefaultedTag asScopedTag() { + return new SpongeDefaultedTag<>(this, SpongeCommon::scopedHolder); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java index 2d1e88833ec..c90ee60f58d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/damagesource/DamageTypeMixin_API.java @@ -29,19 +29,13 @@ import org.spongepowered.api.event.cause.entity.damage.DamageEffect; import org.spongepowered.api.event.cause.entity.damage.DamageScaling; import org.spongepowered.api.event.cause.entity.damage.DamageType; -import org.spongepowered.api.registry.DefaultedRegistryType; import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.util.DataPackUtil; -import java.util.Collection; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; @Mixin(value = net.minecraft.world.damagesource.DamageType.class) public abstract class DamageTypeMixin_API implements DamageType { @@ -75,22 +69,6 @@ public DamageEffect effect() { return (DamageEffect) (Object) this.effects; } - @Override - public boolean is(final Tag tag) { - final Set matchingTypes = RegistryTypes.DAMAGE_TYPE.get().taggedValues(tag); - return matchingTypes.contains(this); - } - - @Override - public DefaultedRegistryType registryType() { - return RegistryTypes.DAMAGE_TYPE; - } - - @Override - public Collection> tags() { - return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); - } - @Override public Optional toDataPack(final RegistryHolder registryHolder) { return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.damagesource.DamageType.DIRECT_CODEC, (net.minecraft.world.damagesource.DamageType) (Object) this); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityTypeMixin_API.java index efa78182d6f..391067fbb49 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityTypeMixin_API.java @@ -26,21 +26,15 @@ import net.kyori.adventure.text.Component; import net.minecraft.core.Holder; -import net.minecraft.tags.TagKey; import net.minecraft.world.entity.MobCategory; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.EntityCategory; import org.spongepowered.api.entity.EntityType; -import org.spongepowered.api.registry.DefaultedRegistryType; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.adventure.SpongeAdventure; -import java.util.Collection; -import java.util.stream.Collectors; @Mixin(net.minecraft.world.entity.EntityType.class) public abstract class EntityTypeMixin_API implements EntityType { @@ -81,21 +75,6 @@ public boolean isSummonable() { return this.shadow$canSummon(); } - @Override - public DefaultedRegistryType> registryType() { - return RegistryTypes.ENTITY_TYPE; - } - - @Override - public Collection>> tags() { - return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); - } - - @Override - public boolean is(Tag> tag) { - return this.builtInRegistryHolder.is((TagKey>) (Object) tag); - } - @SuppressWarnings("ConstantConditions") @Override public EntityCategory category() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java index e0e6f7f20c3..2005cabafd4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java @@ -28,25 +28,19 @@ import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponents; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.registry.DefaultedRegistryType; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.data.holder.SpongeImmutableDataHolder; import java.util.Arrays; -import java.util.Collection; import java.util.Optional; import java.util.function.Supplier; -import java.util.stream.Collectors; @Mixin(Item.class) public abstract class ItemMixin_API implements ItemType, SpongeImmutableDataHolder { @@ -94,21 +88,6 @@ public boolean isAnyOf(ItemType... types) { return Arrays.stream(types).anyMatch(type -> type == this); } - @Override - public DefaultedRegistryType registryType() { - return RegistryTypes.ITEM_TYPE; - } - - @Override - public Collection> tags() { - return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); - } - - @Override - public boolean is(Tag tag) { - return this.builtInRegistryHolder.is((TagKey) (Object) tag); - } - @Override public Optional container() { final @Nullable Item craftingRemainingItem = this.craftingRemainingItem; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java index b1583a8f400..93065d9feff 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/BiomeMixin_API.java @@ -24,44 +24,18 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.biome; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.tags.TagKey; import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.registry.DefaultedRegistryType; import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.tag.Tag; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeDataHolder; import org.spongepowered.common.util.DataPackUtil; -import java.util.Collection; import java.util.Optional; @Mixin(net.minecraft.world.level.biome.Biome.class) public abstract class BiomeMixin_API implements Biome, SpongeDataHolder { - @Override - public DefaultedRegistryType registryType() { - return RegistryTypes.BIOME; - } - - @Override - public Collection> tags() { - return this.registryType().get().tags().filter(this::is).toList(); - } - - @Override - public boolean is(final Tag tag) { - final Registry registry = SpongeCommon.vanillaRegistry(Registries.BIOME); - final Holder.Reference holder = registry.createIntrusiveHolder((net.minecraft.world.level.biome.Biome) (Object) this); - return holder.is(((TagKey) (Object) tag)); - } - @Override public Optional toDataPack(final RegistryHolder registryHolder) { return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.level.biome.Biome.DIRECT_CODEC, (net.minecraft.world.level.biome.Biome) (Object) this); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/material/FluidMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/material/FluidMixin_API.java index 6b803a1ba1b..97dcf31b3f6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/material/FluidMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/material/FluidMixin_API.java @@ -26,21 +26,16 @@ import com.google.common.collect.ImmutableList; import net.minecraft.core.Holder; -import net.minecraft.tags.TagKey; import net.minecraft.world.level.material.Fluid; import org.spongepowered.api.fluid.FluidState; import org.spongepowered.api.fluid.FluidType; -import org.spongepowered.api.registry.DefaultedRegistryType; -import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.state.StateProperty; -import org.spongepowered.api.tag.Tag; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.util.Collection; import java.util.Optional; -import java.util.stream.Collectors; @Mixin(Fluid.class) public abstract class FluidMixin_API implements FluidType { @@ -71,19 +66,4 @@ public Collection> stateProperties() { public Optional> findStateProperty(final String name) { return Optional.ofNullable((StateProperty) this.shadow$getStateDefinition().getProperty(name)); } - - @Override - public DefaultedRegistryType registryType() { - return RegistryTypes.FLUID_TYPE; - } - - @Override - public Collection> tags() { - return this.registryType().get().tags().filter(this::is).collect(Collectors.toSet()); - } - - @Override - public boolean is(final Tag tag) { - return this.builtInRegistryHolder.is((TagKey) (Object) tag); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/tag/TaggableMixin.java b/src/mixins/java/org/spongepowered/common/mixin/api/tag/TaggableMixin.java new file mode 100644 index 00000000000..03a59ff253f --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/tag/TaggableMixin.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.tag; + +import net.minecraft.core.MappedRegistry; +import org.spongepowered.api.registry.DefaultedRegistryType; +import org.spongepowered.api.tag.Tag; +import org.spongepowered.api.tag.Taggable; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.stream.Stream; + +@Mixin(value = Taggable.class, remap = false) +public interface TaggableMixin> { + + @SuppressWarnings("unchecked") + default Stream> tags(final DefaultedRegistryType registryType) { + return (Stream>) (Object) ((MappedRegistry) registryType.get()).wrapAsHolder((T) this).tags(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagKeyMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagKeyMixin.java new file mode 100644 index 00000000000..0320278cc14 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagKeyMixin.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.tags; + +import net.minecraft.tags.TagKey; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.bridge.tags.TagBridge; + +@Mixin(TagKey.class) +public abstract class TagKeyMixin implements TagBridge { + + @Override + public TagKey bridge$asVanillaTag() { + return (TagKey) (Object) this; + } +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 6af919666ac..73022a8caef 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -180,7 +180,7 @@ "minecraft.world.entity.animal.TurtleMixin_API", "minecraft.world.entity.animal.WaterAnimalMixin_API", "minecraft.world.entity.animal.WolfMixin_API", - "minecraft.world.entity.animal.WolfVariantMixin_API", + "minecraft.world.entity.animal.WolfVariantMixin_API", "minecraft.world.entity.animal.allay.AllayMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", @@ -508,6 +508,7 @@ "minecraft.world.ticks.ScheduledTickMixin_API", "minecraft.world.ticks.TickPriorityMixin_API", "service.permission.SubjectMixin_API", + "tag.TaggableMixin", "world.LocatableBlockMixin_API" ], "client": [ diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 3474f16504c..37e5a6271dd 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -109,6 +109,7 @@ "server.rcon.thread.QueryThreadGs4Mixin", "server.rcon.thread.RconClientMixin", "service.permission.SubjectMixin", + "tags.TagKeyMixin", "tags.TagLoader_EntryWithSourceMixin", "tags.TagLoaderMixin", "util.ClassInstanceMultiMapMixin", diff --git a/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java b/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java index c4d67ca5f4f..e376dd32df5 100644 --- a/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java +++ b/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java @@ -42,6 +42,7 @@ import java.util.Collections; import java.util.Optional; import java.util.function.Supplier; +import java.util.stream.Stream; public class StubBlock implements SpongeImmutableDataHolder, BlockType { @@ -132,17 +133,7 @@ public Optional> findStateProperty(final String name) { } @Override - public DefaultedRegistryType registryType() { - return null; - } - - @Override - public Collection> tags() { - return Collections.emptyList(); - } - - @Override - public boolean is(Tag tag) { - return false; + public Stream> tags(DefaultedRegistryType registryType) { + return Stream.empty(); } } diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java b/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java index beb7ef193f8..59651a29340 100644 --- a/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java +++ b/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java @@ -35,7 +35,6 @@ import org.spongepowered.common.test.stub.StubKey; import java.util.Optional; -import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; @@ -110,8 +109,8 @@ public V value(final ResourceKey key) { } @Override - public Set taggedValues(final Tag tag) { - return Set.of(); + public Stream taggedValues(final Tag tag) { + return Stream.empty(); } @Override diff --git a/testplugins/src/main/java/org/spongepowered/test/entity/EntityTest.java b/testplugins/src/main/java/org/spongepowered/test/entity/EntityTest.java index e8a0a1c2338..2e4874b7541 100644 --- a/testplugins/src/main/java/org/spongepowered/test/entity/EntityTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/entity/EntityTest.java @@ -37,7 +37,6 @@ import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.data.type.HandTypes; -import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; @@ -101,7 +100,7 @@ public void onRegisterCommand(final RegisterCommandEvent event) { }) .build(), "testload"); final Parameter.Value> entityTypeParam = - Parameter.registryElement(new TypeToken>() {}, RegistryTypes.ENTITY_TYPE, "minecraft").key("entityType").build(); + Parameter.registryElement(new TypeToken>() {}, RegistryTypes.ENTITY_TYPE, "minecraft").key("entityType").build(); event.register(this.plugin, Command.builder() .addChild(Command.builder() .addParameter(entityTypeParam) diff --git a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java index 1f70e0e6626..c1a27c51c61 100644 --- a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java @@ -79,7 +79,7 @@ public void enable(final CommandContext ctx) { private void registerCommand(final RegisterCommandEvent event) { final Parameter.Value> entityTypeParameter = Parameter.registryElement( - new TypeToken>() {}, + new TypeToken>() {}, (ctx) -> Sponge.game(), RegistryTypes.ENTITY_TYPE, "minecraft", diff --git a/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java b/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java index 950584de7ff..bf61e68731c 100644 --- a/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/tag/TagTest.java @@ -144,7 +144,7 @@ private void registerCommands(final RegisterCommandEvent .executor(ctx -> { final BlockType blockType = TagTest.raytraceBlock(ctx).blockState().type(); final Audience audience = ctx.cause().audience(); - TagTest.sendTags(audience, blockType); + TagTest.sendTags(audience, blockType, RegistryTypes.BLOCK_TYPE); return CommandResult.success(); }) .build(); @@ -153,7 +153,7 @@ private void registerCommands(final RegisterCommandEvent .executor(ctx -> { final ItemType itemType = TagTest.requireItemInHand(ctx); final Audience audience = ctx.cause().audience(); - TagTest.sendTags(audience, itemType); + TagTest.sendTags(audience, itemType, RegistryTypes.ITEM_TYPE); return CommandResult.success(); }) .build(); @@ -162,7 +162,7 @@ private void registerCommands(final RegisterCommandEvent .executor(ctx -> { final EntityType entityType = TagTest.raytraceEntity(ctx); final Audience audience = ctx.cause().audience(); - TagTest.sendTags(audience, entityType); + TagTest.sendTags(audience, entityType, RegistryTypes.ENTITY_TYPE); return CommandResult.success(); }) .build(); @@ -171,7 +171,7 @@ private void registerCommands(final RegisterCommandEvent .executor(ctx -> { final FluidType fluidType = TagTest.raytraceBlock(ctx).blockState().fluidState().type(); final Audience audience = ctx.cause().audience(); - TagTest.sendTags(audience, fluidType); + TagTest.sendTags(audience, fluidType, RegistryTypes.FLUID_TYPE); return CommandResult.success(); }) .build(); @@ -295,9 +295,9 @@ private static ItemType requireItemInHand(final CommandContext ctx) throws Comma return heldItem.type(); } - private static > void sendTags(final Audience audience, final T taggable) { - final Collection> tags = taggable.tags(); - final String taggableKey = taggable.registryType().get().valueKey(taggable).toString(); + private static > void sendTags(final Audience audience, final T taggable, final DefaultedRegistryType registry) { + final Collection> tags = taggable.tags(registry).toList(); + final String taggableKey = taggable.key(registry).toString(); if (tags.isEmpty()) { audience.sendMessage(Component.text(taggableKey + " has no tags", NamedTextColor.RED)); return; From 898528d48a3a4bafd175ba4bb62a1f46bf93997b Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 9 Jun 2025 02:32:29 +0300 Subject: [PATCH 280/586] Fix typo EnchantmenTypeTags -> EnchantmentTypeTags --- SpongeAPI | 2 +- .../spongepowered/vanilla/generator/world/TagRegistries.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index b2e2eb44c4e..1ac37848903 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b2e2eb44c4e1ae21cbfcf0488976b1ae83ee22a7 +Subproject commit 1ac37848903fc356c7a47b0c4445e458c5de10ac diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java index 02340f3ea7b..635f9efdb62 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java @@ -77,7 +77,7 @@ public static List tagRegistries(final Context context) { Registries.ENCHANTMENT, context.relativeClass("item.enchantment", "EnchantmentType"), "tag", - "EnchantmenTypeTags" + "EnchantmentTypeTags" ), new TagGenerator( From 393642d9173e9c8e2d586033b025040195dc40c4 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 9 Jun 2025 02:42:04 +0300 Subject: [PATCH 281/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 1ac37848903..a490075071b 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 1ac37848903fc356c7a47b0c4445e458c5de10ac +Subproject commit a490075071b22f7b6a51d92ed1dda84cae796ca5 From a80282eb4e9da8ff4ed2c3344e2a71ea71ecfe8e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 9 Jun 2025 10:21:54 +0200 Subject: [PATCH 282/586] Remove fillUsableCommands injections and fix suggestions on modded platforms --- .../core/commands/CommandsMixin_Forge.java | 43 ++-- .../core/commands/CommandsMixin_Neo.java | 44 ++-- .../SpongeSuggestionTreeResolver.java | 187 ++++++++++++++ .../mixin/core/commands/CommandsMixin.java | 241 +----------------- .../core/commands/CommandsMixin_Vanilla.java | 46 ++-- 5 files changed, 238 insertions(+), 323 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java index 9fca1ca0145..dab0090da5f 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java @@ -33,7 +33,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.server.command.CommandHelper; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -43,18 +42,16 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; import org.spongepowered.common.command.manager.SpongeCommandManager; +import org.spongepowered.common.command.resolver.SpongeSuggestionTreeResolver; import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.IdentityHashMap; -import java.util.List; import java.util.Map; -import java.util.WeakHashMap; import java.util.function.Function; @Mixin(Commands.class) public abstract class CommandsMixin_Forge { - private WeakHashMap, List>>> impl$playerNodeCache; private SpongeCommandManager impl$commandManager; // The event fired by Forge is fired in ForgeCommandManager at the appropriate time. @@ -64,38 +61,30 @@ public abstract class CommandsMixin_Forge { return false; } - @SuppressWarnings("unchecked") - @Redirect(method = "sendCommands", at = @At( - value = "INVOKE", - target = "Lnet/minecraftforge/server/command/CommandHelper;mergeCommandNode(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Ljava/util/Map;Ljava/lang/Object;Lcom/mojang/brigadier/Command;Ljava/util/function/Function;)V", - remap = false - )) + @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/server/command/CommandHelper;mergeCommandNode(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Ljava/util/Map;Ljava/lang/Object;Lcom/mojang/brigadier/Command;Ljava/util/function/Function;)V")) private void impl$addNonBrigSuggestions( - final CommandNode sourceChild, - final CommandNode sourceNode, - final Map, CommandNode> resultNode, - final S sourceToResult, - final Command canUse, - final Function, SuggestionProvider> execute, + final CommandNode rootCommandNode, + final CommandNode rootSuggestion, + final Map, CommandNode> commandToSuggestion, + final S source, + final Command execute, + final Function, SuggestionProvider> commandToSuggestionFunction, final ServerPlayer player ) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(player); frame.addContext(EventContextKeys.SUBJECT, (Subject) player); - final CommandCause sourceToUse = ((CommandSourceStackBridge) sourceToResult).bridge$withCurrentCause(); - try { - this.impl$playerNodeCache.put(player, new IdentityHashMap<>()); - // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(resultNode); - CommandHelper.mergeCommandNode(sourceChild, sourceNode, idMap, sourceToResult, canUse, execute); - } finally { - this.impl$playerNodeCache.remove(player); - } + final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); + + // We use this because the redirects should be a 1:1 mapping (which is what this map is for). + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); + new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) + .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { - sourceNode.addChild((CommandNode) node); + rootSuggestion.addChild((CommandNode) node); } } } - } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java index 66494dedaaf..7ad771cefc5 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java @@ -33,7 +33,6 @@ import net.minecraft.server.level.ServerPlayer; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.server.command.CommandHelper; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -43,21 +42,19 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; import org.spongepowered.common.command.manager.SpongeCommandManager; +import org.spongepowered.common.command.resolver.SpongeSuggestionTreeResolver; import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.IdentityHashMap; -import java.util.List; import java.util.Map; -import java.util.WeakHashMap; import java.util.function.Function; @Mixin(Commands.class) public abstract class CommandsMixin_Neo { - private WeakHashMap, List>>> impl$playerNodeCache; private SpongeCommandManager impl$commandManager; - // The event fired by Forge is fired in ForgeCommandManager at the appropriate time. + // The event fired by Neo is fired in NeoCommandManager at the appropriate time. @Redirect(method = "performCommand", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;")) private Event neo$redirectToSpongeCommandManager(IEventBus instance, Event event) { @@ -65,36 +62,29 @@ public abstract class CommandsMixin_Neo { } @SuppressWarnings("unchecked") - @Redirect(method = "sendCommands", at = @At( - value = "INVOKE", - target = "Lnet/neoforged/neoforge/server/command/CommandHelper;mergeCommandNode(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Ljava/util/Map;Ljava/lang/Object;Lcom/mojang/brigadier/Command;Ljava/util/function/Function;)V", - remap = false - )) + @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/server/command/CommandHelper;mergeCommandNode(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Ljava/util/Map;Ljava/lang/Object;Lcom/mojang/brigadier/Command;Ljava/util/function/Function;)V")) private void impl$addNonBrigSuggestions( - final CommandNode sourceChild, - final CommandNode sourceNode, - final Map, CommandNode> resultNode, - final S sourceToResult, - final Command canUse, - final Function, SuggestionProvider> execute, + final CommandNode rootCommandNode, + final CommandNode rootSuggestion, + final Map, CommandNode> commandToSuggestion, + final S source, + final Command execute, + final Function, SuggestionProvider> commandToSuggestionFunction, final ServerPlayer player ) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(player); frame.addContext(EventContextKeys.SUBJECT, (Subject) player); - final CommandCause sourceToUse = ((CommandSourceStackBridge) sourceToResult).bridge$withCurrentCause(); - try { - this.impl$playerNodeCache.put(player, new IdentityHashMap<>()); - // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(resultNode); - CommandHelper.mergeCommandNode(sourceChild, sourceNode, idMap, sourceToResult, canUse, execute); - } finally { - this.impl$playerNodeCache.remove(player); - } + final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); + + // We use this because the redirects should be a 1:1 mapping (which is what this map is for). + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); + new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) + .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { - sourceNode.addChild((CommandNode) node); + rootSuggestion.addChild((CommandNode) node); } } } - } diff --git a/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java b/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java new file mode 100644 index 00000000000..0d4de845df5 --- /dev/null +++ b/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java @@ -0,0 +1,187 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.command.resolver; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.tree.ArgumentCommandNode; +import com.mojang.brigadier.tree.CommandNode; +import com.mojang.brigadier.tree.RootCommandNode; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.synchronization.SuggestionProviders; +import org.spongepowered.common.bridge.commands.arguments.CompletionsArgumentTypeBridge; +import org.spongepowered.common.command.brigadier.dispatcher.SpongeNodePermissionCache; +import org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode; +import org.spongepowered.common.command.brigadier.tree.SpongeNode; +import org.spongepowered.common.command.brigadier.tree.SuggestionArgumentNode; +import org.spongepowered.common.command.manager.SpongeCommandManager; +import org.spongepowered.common.util.CommandUtil; + +import java.util.*; + +public record SpongeSuggestionTreeResolver( + CommandSourceStack source, + Map, CommandNode> commandToSuggestion, + Map, List>> playerNodes, + SpongeCommandManager commandManager +) { + + /** + * Replacement of Commands#fillUsableCommands. + * There is no need to split this into injections to be compatible with mods because modded platforms never call fillUsableCommands. + * Instead, they redirect fillUsableCommands to their own method, like we do. + */ + public void fillSuggestions(final CommandNode rootCommandNode, final CommandNode rootSuggestion) { + for (final CommandNode commandNode : SpongeSuggestionTreeResolver.getChildren(rootCommandNode)) { + final List> existingNodes = this.playerNodes.get(commandNode); + if (existingNodes != null) { + if (!existingNodes.isEmpty()) { + boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); + for (final CommandNode node : existingNodes) { + // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug + // in the client where it'll send more than one custom suggestion request - which is fine, except + // the client will then ignore all but one of them. This is a problem because we then end up with + // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, + // meaning thenRun(...) does not run, which is how displaying the suggestions works... + // + // Because we don't control the client, we have to work around it here. + if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode argNode) { + if (argNode.getCustomSuggestions() != null) { + // Rebuild the node without the custom suggestions. + rootSuggestion.addChild(SpongeSuggestionTreeResolver.cloneArgumentWithoutSuggestions(argNode)); + continue; + } + } else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode) node).getCustomSuggestions() != null) { + hasCustomSuggestionsAlready = true; // no more custom suggestions + } + rootSuggestion.addChild(node); + } + } + // If empty, we have a node that won't resolve (even if not complex), so we ignore it. + continue; + // If we have already processed this node, and it appears in the suggestion node list, prevent a potentially costly + // canUse check as we know we can already use it. + } + + if (!this.commandToSuggestion.containsKey(commandNode) && !SpongeNodePermissionCache.canUse( + rootCommandNode instanceof RootCommandNode, this.commandManager.getDispatcher(), commandNode, this.source)) { + this.playerNodes.put(commandNode, Collections.emptyList()); + continue; + } + + if (commandNode instanceof SpongeArgumentCommandNode spongeCommandNode && spongeCommandNode.isComplex()) { + final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); + final CommandNode finalCommandNode = spongeCommandNode.getComplexSuggestions(rootSuggestion, this.commandToSuggestion, this.playerNodes, !hasCustomSuggestionsAlready); + if (!SpongeSuggestionTreeResolver.getChildren(commandNode).isEmpty()) { + this.fillSuggestions(commandNode, finalCommandNode); + } + continue; + } + + ArgumentBuilder builder; + if (commandNode instanceof SpongeArgumentCommandNode node) { + builder = node.createBuilderForSuggestions(rootSuggestion, this.commandToSuggestion); + } else if (commandNode instanceof ArgumentCommandNode argNode && argNode.getType() instanceof CompletionsArgumentTypeBridge argType) { + final RequiredArgumentBuilder r = RequiredArgumentBuilder.argument(argNode.getName(), argType.bridge$clientSideCompletionType()); + r.executes(argNode.getCommand()) + .forward(argNode.getRedirect(), argNode.getRedirectModifier(), argNode.isFork()) + .requires(argNode.getRequirement()); + if (!CommandUtil.checkForCustomSuggestions(rootSuggestion)) { + r.suggests(SuggestionProviders.ASK_SERVER); + } + builder = r; + } else { + builder = (ArgumentBuilder) commandNode.createBuilder(); + } + + builder.requires(src -> true); + if (builder.getCommand() != null) { + builder.executes(src -> 0); + } + + if (builder instanceof RequiredArgumentBuilder r && r.getSuggestionsProvider() != null) { + r.suggests(SuggestionProviders.safelySwap(r.getSuggestionsProvider())); + + // From above. + // + // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug + // in the client where it'll send more than one custom suggestion request - which is fine, except + // the client will then ignore all but one of them. This is a problem because we then end up with + // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, + // meaning thenRun(...) does not run, which is how displaying the suggestions works... + // + // Because we don't control the client, we have to work around it here. + if (r.getSuggestionsProvider() == SuggestionProviders.ASK_SERVER && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { + r.suggests(null); + } + } + + if (builder.getRedirect() != null) { + builder.redirect(this.commandToSuggestion.get(builder.getRedirect())); + } + + final CommandNode suggestion = builder instanceof RequiredArgumentBuilder r ? new SuggestionArgumentNode(r) : builder.build(); + + if (!this.commandToSuggestion.containsKey(commandNode)) { + // done here because this check is applicable + if (!this.playerNodes.containsKey(commandNode)) { + final List> children = new ArrayList<>(); + children.add(suggestion); + this.playerNodes.put(commandNode, children); + } + + // If the current root suggestion has already got a custom suggestion and this node has a custom suggestion, + // we need to swap it out. + if (commandNode instanceof ArgumentCommandNode argNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { + rootSuggestion.addChild(SpongeSuggestionTreeResolver.cloneArgumentWithoutSuggestions(argNode)); + } else { + rootSuggestion.addChild(suggestion); + } + this.commandToSuggestion.put(commandNode, suggestion); + } + + if (!commandNode.getChildren().isEmpty()) { + this.fillSuggestions(commandNode, suggestion); + } + } + } + + private static Collection> getChildren(final CommandNode node) { + if (node instanceof SpongeNode) { + return ((SpongeNode) node).getChildrenForSuggestions(); + } + return node.getChildren(); + } + + private static ArgumentCommandNode cloneArgumentWithoutSuggestions(final ArgumentCommandNode toClone) { + final RequiredArgumentBuilder builder = toClone.createBuilder(); + builder.suggests(null); + for (final CommandNode node : toClone.getChildren()) { + builder.then(node); + } + return new SuggestionArgumentNode<>(builder); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 49ef9cb8abf..7e74cbc682e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -25,63 +25,28 @@ package org.spongepowered.common.mixin.core.commands; import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.suggestion.SuggestionProvider; -import com.mojang.brigadier.tree.ArgumentCommandNode; -import com.mojang.brigadier.tree.CommandNode; -import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.SharedSuggestionProvider; -import net.minecraft.commands.synchronization.SuggestionProviders; import net.minecraft.server.commands.AdvancementCommands; -import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.commands.CommandsBridge; -import org.spongepowered.common.bridge.commands.arguments.CompletionsArgumentTypeBridge; import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; -import org.spongepowered.common.command.brigadier.dispatcher.SpongeNodePermissionCache; -import org.spongepowered.common.command.brigadier.tree.SpongeArgumentCommandNode; -import org.spongepowered.common.command.brigadier.tree.SpongeNode; -import org.spongepowered.common.command.brigadier.tree.SuggestionArgumentNode; import org.spongepowered.common.command.manager.SpongeCommandManager; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.util.CommandUtil; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; @Mixin(Commands.class) public abstract class CommandsMixin implements CommandsBridge { - // @formatter:off - @Shadow private void shadow$fillUsableCommands(final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { - throw new AssertionError("This shouldn't be callable"); - } - // @formatter:on - private CauseStackManager.@MonotonicNonNull StackFrame impl$initFrame = null; - private final WeakHashMap, List>>> impl$playerNodeCache = - new WeakHashMap<>(); private @MonotonicNonNull SpongeCommandManager impl$commandManager; // We prepare our own dispatcher and commands manager, to redirect registrations to our system @@ -90,12 +55,12 @@ public abstract class CommandsMixin implements CommandsBridge { args = "class=com/mojang/brigadier/CommandDispatcher", remap = false )) - private CommandDispatcher impl$useSpongeDispatcher(final Commands.CommandSelection $$0, final CommandBuildContext $$1) { + private CommandDispatcher impl$useSpongeDispatcher(final Commands.CommandSelection selection, final CommandBuildContext context) { if (!Launch.instance().pluginManager().isReady()) { return new CommandDispatcher<>(); } final SpongeCommandManager manager = Launch.instance().lifecycle().platformInjector().getInstance(SpongeCommandManager.class); - manager.init((RegistryHolder) $$1); + manager.init((RegistryHolder) context); this.impl$commandManager = manager; return new DelegatingCommandDispatcher(manager.getBrigadierRegistrar()); } @@ -119,210 +84,8 @@ public abstract class CommandsMixin implements CommandsBridge { } } - /* - * Hides nodes that we have marked as "hidden" - */ - @Redirect(method = "fillUsableCommands", - slice = @Slice( - from = @At("HEAD"), - to = @At(value = "INVOKE", remap = false, target = "Ljava/util/Iterator;hasNext()Z") - ), - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;getChildren()Ljava/util/Collection;", remap = false)) - private Collection> impl$handleHiddenChildrenAndEnsureUnsortedLoop(final CommandNode commandNode) { - return this.impl$getChildrenFromNode(commandNode); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/tree/CommandNode;createBuilder()Lcom/mojang/brigadier/builder/ArgumentBuilder;", - remap = false)) - private ArgumentBuilder impl$createArgumentBuilder( - final CommandNode commandNode, - final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { - if (commandNode instanceof SpongeArgumentCommandNode node) { - return node.createBuilderForSuggestions(rootSuggestion, commandNodeToSuggestionNode); - } - - if (commandNode instanceof ArgumentCommandNode acn && acn.getType() instanceof CompletionsArgumentTypeBridge catb) { - final RequiredArgumentBuilder builder = RequiredArgumentBuilder.argument(acn.getName(), catb.bridge$clientSideCompletionType()); - builder.executes(acn.getCommand()) - .forward(acn.getRedirect(), acn.getRedirectModifier(), acn.isFork()) - .requires(acn.getRequirement()); - if (!CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - builder.suggests((SuggestionProvider) SuggestionProviders.ASK_SERVER); - } - return builder; - } - return commandNode.createBuilder(); - } - - @SuppressWarnings("unchecked") - @Redirect(method = "fillUsableCommands", at = - @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) - private V impl$preventPutIntoMapIfNodeIsComplex(final Map map, - final K key, - final V value, - final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { - if (!map.containsKey(key)) { - // done here because this check is applicable - final ServerPlayer e = (ServerPlayer) source.getEntity(); - final Map, List>> playerNodes = this.impl$playerNodeCache.get(e); - if (!playerNodes.containsKey(key)) { - final List> children = new ArrayList<>(); - children.add((CommandNode) value); - playerNodes.put((CommandNode) key, children); - } - - // If the current root suggestion has already got a custom suggestion and this node has a custom suggestion, - // we need to swap it out. - if (value instanceof ArgumentCommandNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions((ArgumentCommandNode) value)); - } else { - rootSuggestion.addChild((CommandNode) value); - } - return map.put(key, value); - } - return null; // it's ignored anyway. - } - - @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/tree/CommandNode;addChild(Lcom/mojang/brigadier/tree/CommandNode;)V", - remap = false)) - private void impl$preventAddChild(final CommandNode root, final CommandNode newChild) { - // no-op, we did this above. - } - - @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/tree/CommandNode;canUse(Ljava/lang/Object;)Z", remap = false)) - private boolean impl$testPermissionAndPreventRecalculationWhenSendingNodes( - final CommandNode commandNode, - final Object source, - final CommandNode rootCommandNode, - final CommandNode rootSuggestion, - final CommandSourceStack sourceButTyped, - final Map, CommandNode> commandNodeToSuggestionNode - ) { - final ServerPlayer e = (ServerPlayer) sourceButTyped.getEntity(); - final Map, List>> playerNodes = this.impl$playerNodeCache.get(e); - final List> existingNodes = playerNodes.get(commandNode); - if (existingNodes != null) { - if (!existingNodes.isEmpty()) { - boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - for (final CommandNode node : existingNodes) { - // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug - // in the client where it'll send more than one custom suggestion request - which is fine, except - // the client will then ignore all but one of them. This is a problem because we then end up with - // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, - // meaning thenRun(...) does not run, which is how displaying the suggestions works... - // - // Because we don't control the client, we have to work around it here. - if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode) { - final ArgumentCommandNode argNode = (ArgumentCommandNode) node; - if (argNode.getCustomSuggestions() != null) { - // Rebuild the node without the custom suggestions. - rootSuggestion.addChild(this.impl$cloneArgumentCommandNodeWithoutSuggestions(argNode)); - continue; - } - } else if (node instanceof ArgumentCommandNode && ((ArgumentCommandNode) node).getCustomSuggestions() != null) { - hasCustomSuggestionsAlready = true; // no more custom suggestions - } - rootSuggestion.addChild(node); - } - } - // If empty, we have a node won't resolve (even if not complex), so we ignore it. - return false; - // If we have already processed this node and it appears in the suggestion node list, prevent a potentially costly - // canUse check as we know we can already use it. - } else if (!commandNodeToSuggestionNode.containsKey(commandNode) && !SpongeNodePermissionCache.canUse( - rootCommandNode instanceof RootCommandNode, this.impl$commandManager.getDispatcher(), commandNode, sourceButTyped)) { - playerNodes.put(commandNode, Collections.emptyList()); - return false; - } - - if (commandNode instanceof SpongeArgumentCommandNode && ((SpongeArgumentCommandNode) commandNode).isComplex()) { - final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - final CommandNode finalCommandNode = ((SpongeArgumentCommandNode) commandNode).getComplexSuggestions( - rootSuggestion, - commandNodeToSuggestionNode, - playerNodes, - !hasCustomSuggestionsAlready - ); - if (!this.impl$getChildrenFromNode(commandNode).isEmpty()) { - this.shadow$fillUsableCommands(commandNode, finalCommandNode, sourceButTyped, commandNodeToSuggestionNode); - } - return false; - } - - // Normal node, handle it normally. We don't add to the playerNodeCache - the commandNodeToSuggestionNode map handles this. - return true; - } - - @Redirect(method = "fillUsableCommands", at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;suggests(Lcom/mojang/brigadier/suggestion/SuggestionProvider;)Lcom/mojang/brigadier/builder/RequiredArgumentBuilder;", remap = false)) - private RequiredArgumentBuilder impl$dontAskServerIfSiblingAlreadyDoes( - final RequiredArgumentBuilder requiredArgumentBuilder, - final SuggestionProvider provider, - final CommandNode rootCommandNode, - final CommandNode rootSuggestion, - final CommandSourceStack sourceButTyped, - final Map, CommandNode> commandNodeToSuggestionNode - ) { - // From above. - // - // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug - // in the client where it'll send more than one custom suggestion request - which is fine, except - // the client will then ignore all but one of them. This is a problem because we then end up with - // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, - // meaning thenRun(...) does not run, which is how displaying the suggestions works... - // - // Because we don't control the client, we have to work around it here. - if (provider != SuggestionProviders.ASK_SERVER || !CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - requiredArgumentBuilder.suggests(provider); - } - return requiredArgumentBuilder; - } - - - @SuppressWarnings("unchecked") - @Redirect(method = "fillUsableCommands", - at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/builder/ArgumentBuilder;build()Lcom/mojang/brigadier/tree/CommandNode;", remap = false)) - private CommandNode impl$createSpongeArgumentNode(final ArgumentBuilder argumentBuilder) { - if (argumentBuilder instanceof RequiredArgumentBuilder) { - return new SuggestionArgumentNode<>((RequiredArgumentBuilder) argumentBuilder); - } - return argumentBuilder.build(); - } - @Override public SpongeCommandManager bridge$commandManager() { return this.impl$commandManager; } - - private Collection> impl$getChildrenFromNode(final CommandNode parentNode) { - final Collection> nodes; - if (parentNode instanceof SpongeNode) { - nodes = ((SpongeNode) parentNode).getChildrenForSuggestions(); - } else { - nodes = parentNode.getChildren(); - } - return nodes; - } - - private ArgumentCommandNode impl$cloneArgumentCommandNodeWithoutSuggestions(final ArgumentCommandNode toClone) { - final RequiredArgumentBuilder builder = toClone.createBuilder(); - builder.suggests(null); - for (final CommandNode node : toClone.getChildren()) { - builder.then(node); - } - return new SuggestionArgumentNode<>(builder); - } - } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java index 1ea7a5f049a..b3fb1590986 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java @@ -34,56 +34,42 @@ import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.service.permission.Subject; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; import org.spongepowered.common.command.manager.SpongeCommandManager; +import org.spongepowered.common.command.resolver.SpongeSuggestionTreeResolver; import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.IdentityHashMap; -import java.util.List; import java.util.Map; -import java.util.WeakHashMap; @Mixin(Commands.class) public abstract class CommandsMixin_Vanilla { - // @formatter:off - @Shadow private void shadow$fillUsableCommands(final CommandNode rootCommandSource, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandNodeToSuggestionNode) { - throw new AssertionError("This shouldn't be callable"); - } - // @formatter:on - - private CauseStackManager.StackFrame impl$initFrame = null; - private WeakHashMap, List>>> impl$playerNodeCache; private SpongeCommandManager impl$commandManager; @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Lnet/minecraft/commands/CommandSourceStack;Ljava/util/Map;)V")) private void impl$addNonBrigSuggestions( - final Commands commands, - final CommandNode p_197052_1_, - final CommandNode p_197052_2_, - final CommandSourceStack p_197052_3_, - final Map, CommandNode> p_197052_4_, - final ServerPlayer playerEntity) { + final Commands self, + final CommandNode rootCommandNode, + final CommandNode rootSuggestion, + final CommandSourceStack source, + final Map, CommandNode> commandToSuggestion, + final ServerPlayer playerEntity + ) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(playerEntity); frame.addContext(EventContextKeys.SUBJECT, (Subject) playerEntity); - final CommandCause sourceToUse = ((CommandSourceStackBridge) p_197052_3_).bridge$withCurrentCause(); - try { - this.impl$playerNodeCache.put(playerEntity, new IdentityHashMap<>()); - // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(p_197052_4_); - this.shadow$fillUsableCommands(p_197052_1_, p_197052_2_, (CommandSourceStack) sourceToUse, idMap); - } finally { - this.impl$playerNodeCache.remove(playerEntity); - } + final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); + + // We use this because the redirects should be a 1:1 mapping (which is what this map is for). + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(commandToSuggestion); + new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) + .fillSuggestions(rootCommandNode, rootSuggestion); + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { - p_197052_2_.addChild(node); + rootSuggestion.addChild(node); } } } From cfd1a515037e41f17edd53e51fcca9db64711005 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 9 Jun 2025 11:01:57 +0200 Subject: [PATCH 283/586] Update command suggestions --- .../ComplexSuggestionNodeProvider.java | 8 +-- .../ForcedRedirectArgumentSuggestionNode.java | 14 ++-- .../ForcedRedirectLiteralCommandNode.java | 10 +-- .../brigadier/tree/ForcedRedirectNode.java | 4 +- .../tree/SpongeArgumentCommandNode.java | 35 +++++----- .../tree/SuggestionArgumentNode.java | 6 +- .../command/manager/SpongeCommandManager.java | 13 ++-- .../SpongeServerLocationValueParameter.java | 19 +++-- .../tree/builder/AbstractCommandTreeNode.java | 18 ++--- .../tree/builder/ArgumentCommandTreeNode.java | 6 +- .../tree/builder/LiteralCommandTreeNode.java | 6 +- .../tree/builder/RootCommandTreeNode.java | 12 ++-- .../SpongeSuggestionTreeResolver.java | 69 ++++++++----------- .../core/commands/CommandsMixin_Vanilla.java | 25 +++---- 14 files changed, 115 insertions(+), 130 deletions(-) diff --git a/src/main/java/org/spongepowered/common/command/brigadier/argument/ComplexSuggestionNodeProvider.java b/src/main/java/org/spongepowered/common/command/brigadier/argument/ComplexSuggestionNodeProvider.java index 1b95a1ef1cf..9701e86ae54 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/argument/ComplexSuggestionNodeProvider.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/argument/ComplexSuggestionNodeProvider.java @@ -25,7 +25,7 @@ package org.spongepowered.common.command.brigadier.argument; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import java.util.List; import java.util.function.Consumer; @@ -39,8 +39,8 @@ public interface ComplexSuggestionNodeProvider { /** * Creates the nodes. */ - CommandNode createSuggestions(final CommandNode rootNode, final String key, final boolean isTerminal, - final Consumer>> commandNodeListConsumer, - final Consumer> mapInsertionConsumer, boolean allowCustomSuggestionsOnTheFirstElement); + CommandNode createSuggestions(final CommandNode rootNode, final String key, final boolean isTerminal, + final Consumer>> commandNodeListConsumer, + final Consumer> mapInsertionConsumer, boolean allowCustomSuggestionsOnTheFirstElement); } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectArgumentSuggestionNode.java b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectArgumentSuggestionNode.java index 1fdd097beda..96c28f88332 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectArgumentSuggestionNode.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectArgumentSuggestionNode.java @@ -29,29 +29,29 @@ import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Objects; -public final class ForcedRedirectArgumentSuggestionNode extends ArgumentCommandNode implements ForcedRedirectNode { +public final class ForcedRedirectArgumentSuggestionNode extends ArgumentCommandNode implements ForcedRedirectNode { - private @Nullable CommandNode forcedRedirect = null; + private @Nullable CommandNode forcedRedirect = null; public ForcedRedirectArgumentSuggestionNode(final String name, final ArgumentType type, - final Command command, - final SuggestionProvider customSuggestions) { + final Command command, + final SuggestionProvider customSuggestions) { super(name, type, command, isp -> true, null, null, false, customSuggestions); } @Override - public void setForcedRedirect(final @Nullable CommandNode redirect) { + public void setForcedRedirect(final @Nullable CommandNode redirect) { this.forcedRedirect = redirect; } @Override - public CommandNode getRedirect() { + public CommandNode getRedirect() { return this.forcedRedirect; } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectLiteralCommandNode.java b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectLiteralCommandNode.java index 4dc8aca8025..28a7275c199 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectLiteralCommandNode.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectLiteralCommandNode.java @@ -26,25 +26,25 @@ import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.command.registrar.tree.builder.AbstractCommandTreeNode; -public final class ForcedRedirectLiteralCommandNode extends LiteralCommandNode implements ForcedRedirectNode { +public final class ForcedRedirectLiteralCommandNode extends LiteralCommandNode implements ForcedRedirectNode { - private @Nullable CommandNode forcedRedirect = null; + private @Nullable CommandNode forcedRedirect = null; public ForcedRedirectLiteralCommandNode(final String literal, final boolean executable) { super(literal, executable ? AbstractCommandTreeNode.EXECUTABLE : null, c -> true, null, null, false); } @Override - public void setForcedRedirect(final CommandNode node) { + public void setForcedRedirect(final CommandNode node) { this.forcedRedirect = node; } @Override - public CommandNode getRedirect() { + public CommandNode getRedirect() { return this.forcedRedirect; } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectNode.java b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectNode.java index 2b33dada2a0..4822fc2b895 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectNode.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/tree/ForcedRedirectNode.java @@ -25,9 +25,9 @@ package org.spongepowered.common.command.brigadier.tree; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; public interface ForcedRedirectNode { - void setForcedRedirect(CommandNode node); + void setForcedRedirect(CommandNode node); } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/tree/SpongeArgumentCommandNode.java b/src/main/java/org/spongepowered/common/command/brigadier/tree/SpongeArgumentCommandNode.java index dcfb75114fc..8532aede6d4 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/tree/SpongeArgumentCommandNode.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/tree/SpongeArgumentCommandNode.java @@ -42,7 +42,6 @@ import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.synchronization.SuggestionProviders; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.command.CommandCompletion; @@ -144,10 +143,10 @@ public final boolean isComplex() { return this.isComplexSuggestions; } - public final CommandNode getComplexSuggestions( - final CommandNode rootSuggestionNode, - final Map, CommandNode> commandNodeToSuggestionNode, - final Map, List>> commandNodeListMap, + public final CommandNode getComplexSuggestions( + final CommandNode rootSuggestionNode, + final Map, CommandNode> commandNodeToSuggestionNode, + final Map, List>> commandNodeListMap, final boolean allowCustomSuggestionsOnTheFirstElement) { if (!this.isComplexSuggestions) { throw new IllegalStateException("The parser is not a ComplexSuggestionNodeParser"); @@ -176,17 +175,17 @@ private ArgumentType switchTypeIfRequired(final ArgumentType type) { } @SuppressWarnings({"unchecked", "rawtypes"}) - public final ArgumentBuilder createBuilderForSuggestions( - final CommandNode rootSuggestionNode, - final Map, CommandNode> commandNodeToSuggestionNode + public final ArgumentBuilder createBuilderForSuggestions( + final CommandNode rootSuggestionNode, + final Map, CommandNode> commandNodeToSuggestionNode ) { ArgumentType type = this.switchTypeIfRequired(this.getType()); - CommandNode previousNode = rootSuggestionNode; + CommandNode previousNode = rootSuggestionNode; if (!this.parser.getClientCompletionArgumentType().isEmpty()) { // create multiple entries, return the last one final boolean forceCustomSuggestions; final Collection> types = this.parser.getClientCompletionArgumentType().stream() - .filter(Objects::nonNull).collect(Collectors.toList()); + .filter(Objects::nonNull).toList(); if (types.size() > 1) { forceCustomSuggestions = false; // handled in here final Iterator> clientCompletionTypeIterator = this.parser.getClientCompletionArgumentType().iterator(); @@ -197,13 +196,13 @@ private ArgumentType switchTypeIfRequired(final ArgumentType type) { final boolean forceCustomSuggestionsInner = type != this.getType() && !CommandUtil.checkForCustomSuggestions(previousNode); if (clientCompletionTypeIterator.hasNext()) { // create node - final RequiredArgumentBuilder arg = RequiredArgumentBuilder.argument(this.getName(), type); + final RequiredArgumentBuilder arg = RequiredArgumentBuilder.argument(this.getName(), type); arg.requires(x -> true); // if the first node is forced to be custom suggestions or is a string argument type, send the completions. if (forceCustomSuggestionsInner || isFirst && type instanceof StringArgumentType) { - arg.suggests(SuggestionProviders.ASK_SERVER); + arg.suggests((SuggestionProvider) SuggestionProviders.ASK_SERVER); } - final CommandNode built = arg.build(); + final CommandNode built = arg.build(); previousNode.addChild(built); previousNode = built; if (isFirst) { @@ -218,17 +217,17 @@ private ArgumentType switchTypeIfRequired(final ArgumentType type) { forceCustomSuggestions = type != originalType; } - final RequiredArgumentBuilder toReturn = RequiredArgumentBuilder.argument(this.getUsageTextForClient(), type); + final RequiredArgumentBuilder toReturn = RequiredArgumentBuilder.argument(this.getUsageTextForClient(), type); if (this.getCommand() != null) { toReturn.executes(x -> 0); } if (this.modifier != null || forceCustomSuggestions && !CommandUtil.checkForCustomSuggestions(previousNode)) { - toReturn.suggests(SuggestionProviders.ASK_SERVER); + toReturn.suggests((SuggestionProvider) SuggestionProviders.ASK_SERVER); } else if (this.getCustomSuggestions() != null) { - toReturn.suggests((SuggestionProvider) this.getCustomSuggestions()); + toReturn.suggests(this.getCustomSuggestions()); } if (this.getRedirect() != null) { - toReturn.forward((CommandNode) this.getRedirect(), (RedirectModifier) this.getRedirectModifier(), this.isFork()); + toReturn.forward(this.getRedirect(), this.getRedirectModifier(), this.isFork()); } return toReturn; } @@ -249,7 +248,7 @@ private ArgumentType switchTypeIfRequired(final ArgumentType type) { if (this.getCommand() != null) { builder.executes(this.getCommand()); } - return (ArgumentBuilder) builder; + return builder; } public final ArgumentParser getParser() { diff --git a/src/main/java/org/spongepowered/common/command/brigadier/tree/SuggestionArgumentNode.java b/src/main/java/org/spongepowered/common/command/brigadier/tree/SuggestionArgumentNode.java index b401d83c2eb..78e40dba443 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/tree/SuggestionArgumentNode.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/tree/SuggestionArgumentNode.java @@ -26,14 +26,14 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.tree.ArgumentCommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import java.util.Objects; // Used to differentiate between custom suggestions -public final class SuggestionArgumentNode extends ArgumentCommandNode { +public final class SuggestionArgumentNode extends ArgumentCommandNode { - public SuggestionArgumentNode(final RequiredArgumentBuilder builder) { + public SuggestionArgumentNode(final RequiredArgumentBuilder builder) { super(builder.getName(), builder.getType(), builder.getCommand(), diff --git a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java index 7da55029477..e10e9bd297c 100644 --- a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java +++ b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandManager.java @@ -46,7 +46,6 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.util.ComponentMessageThrowable; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.Level; import org.checkerframework.checker.nullness.qual.NonNull; @@ -497,22 +496,22 @@ private void registerInternalCommands(final CommandRegistrar regi CallbackCommand.NAME); } - public Collection> getNonBrigadierSuggestions(final CommandCause cause) { - final List> suggestions = new ArrayList<>(); + public Collection> getNonBrigadierSuggestions(final CommandCause cause) { + final List> suggestions = new ArrayList<>(); for (final Map.Entry entry : this.mappingToSuggestionNodes.entrySet()) { final SpongeCommandMapping mapping = entry.getKey(); // create tree from primary mapping - final CommandNode node = entry.getValue() + final CommandNode node = entry.getValue() .createArgumentTree(cause, LiteralArgumentBuilder.literal(mapping.primaryAlias())); if (node != null) { - final Command executableCommand = node.getCommand(); - final CommandNode toRedirectTo = node.getRedirect() == null ? node : node.getRedirect(); + final Command executableCommand = node.getCommand(); + final CommandNode toRedirectTo = node.getRedirect() == null ? node : node.getRedirect(); suggestions.add(node); for (final String alias : mapping.allAliases()) { if (!alias.equals(mapping.primaryAlias())) { - suggestions.add(LiteralArgumentBuilder.literal(alias) + suggestions.add(LiteralArgumentBuilder.literal(alias) .executes(executableCommand).redirect(toRedirectTo).build()); } } diff --git a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java index b95d8e5ef7c..d17fddc79b0 100644 --- a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java +++ b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java @@ -32,7 +32,6 @@ import com.mojang.brigadier.tree.CommandNode; import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.arguments.coordinates.Coordinates; import net.minecraft.commands.arguments.coordinates.Vec3Argument; import net.minecraft.resources.ResourceLocation; @@ -92,7 +91,7 @@ private Stream complete(final String currentInput) { serverWorld = SpongeCommon.game().server().worldManager() .world(resourceLocation) .orElseThrow(() -> reader.createException( - Component.text("Could not get world with key \"" + resourceLocation.toString() + "\""))); + Component.text("Could not get world with key \"" + resourceLocation + "\""))); } catch (final ArgumentParseException e) { final Optional location = cause.location(); if (location.isPresent()) { @@ -122,13 +121,13 @@ public List> getClientCompletionArgumentType() { } @Override - public CommandNode createSuggestions(final CommandNode rootNode, final String key, + public CommandNode createSuggestions(final CommandNode rootNode, final String key, final boolean isTerminal, - final Consumer>> firstNodes, - final Consumer> redirectionNodes, + final Consumer>> firstNodes, + final Consumer> redirectionNodes, final boolean allowCustomSuggestionsOnTheFirstElement) { - final RequiredArgumentBuilder firstNode = + final RequiredArgumentBuilder firstNode = RequiredArgumentBuilder.argument(key, Constants.Command.RESOURCE_LOCATION_TYPE); if (allowCustomSuggestionsOnTheFirstElement) { firstNode.suggests((context, builder) -> { @@ -136,18 +135,18 @@ public CommandNode createSuggestions(final CommandNode return builder.buildFuture(); }); } - final RequiredArgumentBuilder secondNode = + final RequiredArgumentBuilder secondNode = RequiredArgumentBuilder.argument(key + "_pos", Vec3Argument.vec3()); if (isTerminal) { secondNode.executes(x -> 1); } - final CommandNode second = secondNode.build(); + final CommandNode second = secondNode.build(); firstNode.then(second); - final CommandNode first = firstNode.build(); + final CommandNode first = firstNode.build(); redirectionNodes.accept(second); rootNode.addChild(first); rootNode.addChild(second); - final List> nodesToAttach = new ArrayList<>(); + final List> nodesToAttach = new ArrayList<>(); nodesToAttach.add(first); nodesToAttach.add(second); firstNodes.accept(nodesToAttach); diff --git a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/AbstractCommandTreeNode.java b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/AbstractCommandTreeNode.java index bf04f67d1c2..6679e8a3aa6 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/AbstractCommandTreeNode.java +++ b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/AbstractCommandTreeNode.java @@ -28,7 +28,7 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.synchronization.SuggestionProviders; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -42,10 +42,10 @@ import java.util.Objects; import java.util.function.Predicate; -public abstract class AbstractCommandTreeNode, O extends CommandNode> +public abstract class AbstractCommandTreeNode, O extends CommandNode> implements CommandTreeNode<@NonNull T> { - public final static Command EXECUTABLE = isp -> 1; + public final static Command EXECUTABLE = isp -> 1; private @Nullable CommandTreeNode redirect = null; private @Nullable Map> children = null; @@ -125,8 +125,8 @@ public boolean isExecutable() { } @SuppressWarnings("unchecked") - public SuggestionProvider suggestionProvider() { - return (SuggestionProvider) this.completionProvider; + public SuggestionProvider suggestionProvider() { + return (SuggestionProvider) this.completionProvider; } public @Nullable CommandTreeNode<@NonNull ?> getRedirect() { @@ -137,14 +137,14 @@ public SuggestionProvider suggestionProvider() { protected final void addChildNodesToTree( final CommandCause cause, - final CommandNode node, - final Map, CommandNode> nodeToSuggestionProvider, + final CommandNode node, + final Map, CommandNode> nodeToSuggestionProvider, final Map> redirectsToApply) { this.getChildren().forEach((key, value) -> { if (value.requirement.test(cause)) { - final CommandNode providerCommandNode = + final CommandNode providerCommandNode = nodeToSuggestionProvider.computeIfAbsent(value, k -> { - final CommandNode ret = k.createElement(key); + final CommandNode ret = k.createElement(key); if (k.redirect instanceof AbstractCommandTreeNode && ret instanceof ForcedRedirectNode) { redirectsToApply.put((ForcedRedirectNode) ret, (AbstractCommandTreeNode) k.redirect); } else { diff --git a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/ArgumentCommandTreeNode.java b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/ArgumentCommandTreeNode.java index 5f6bb1bb49f..894bdfd5504 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/ArgumentCommandTreeNode.java +++ b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/ArgumentCommandTreeNode.java @@ -26,13 +26,13 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.command.registrar.tree.CommandTreeNodeType; import org.spongepowered.common.command.brigadier.tree.ForcedRedirectArgumentSuggestionNode; public abstract class ArgumentCommandTreeNode> - extends AbstractCommandTreeNode> { + extends AbstractCommandTreeNode> { private final CommandTreeNodeType parameterType; @@ -41,7 +41,7 @@ public ArgumentCommandTreeNode(final CommandTreeNodeType parameterType) { } @Override - protected CommandNode createElement(final String nodeKey) { + protected CommandNode createElement(final String nodeKey) { return new ForcedRedirectArgumentSuggestionNode<>( nodeKey, this.getArgumentType(), diff --git a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/LiteralCommandTreeNode.java b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/LiteralCommandTreeNode.java index fb51e482799..aa6a2098464 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/LiteralCommandTreeNode.java +++ b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/LiteralCommandTreeNode.java @@ -25,15 +25,15 @@ package org.spongepowered.common.command.registrar.tree.builder; import com.mojang.brigadier.tree.LiteralCommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.common.command.brigadier.tree.ForcedRedirectLiteralCommandNode; -public final class LiteralCommandTreeNode extends AbstractCommandTreeNode> +public final class LiteralCommandTreeNode extends AbstractCommandTreeNode> implements CommandTreeNode.Basic { @Override - protected LiteralCommandNode createElement(final String nodeKey) { + protected LiteralCommandNode createElement(final String nodeKey) { return new ForcedRedirectLiteralCommandNode( nodeKey, this.isExecutable() diff --git a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/RootCommandTreeNode.java b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/RootCommandTreeNode.java index 215d2eeaa53..398d74796fd 100644 --- a/src/main/java/org/spongepowered/common/command/registrar/tree/builder/RootCommandTreeNode.java +++ b/src/main/java/org/spongepowered/common/command/registrar/tree/builder/RootCommandTreeNode.java @@ -28,7 +28,7 @@ import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.RootCommandNode; -import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.CommandSourceStack; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.command.registrar.tree.CommandTreeNode; @@ -38,12 +38,12 @@ import java.util.LinkedHashMap; import java.util.Map; -public final class RootCommandTreeNode extends AbstractCommandTreeNode> +public final class RootCommandTreeNode extends AbstractCommandTreeNode> implements CommandTreeNode.Root { - public @Nullable CommandNode createArgumentTree(final CommandCause cause, final LiteralArgumentBuilder rootBuilder) { + public @Nullable CommandNode createArgumentTree(final CommandCause cause, final LiteralArgumentBuilder rootBuilder) { if (this.getRequirement().test(cause)) { - final Map, CommandNode> nodeToSuggestionProvider = new IdentityHashMap<>(); + final Map, CommandNode> nodeToSuggestionProvider = new IdentityHashMap<>(); // this is going to be iterated only. final Map> redirectsToApply = new LinkedHashMap<>(); @@ -51,7 +51,7 @@ public final class RootCommandTreeNode extends AbstractCommandTreeNode 1); } - final LiteralCommandNode rootNode = rootBuilder.build(); + final LiteralCommandNode rootNode = rootBuilder.build(); this.addChildNodesToTree( cause, rootNode, @@ -67,7 +67,7 @@ public final class RootCommandTreeNode extends AbstractCommandTreeNode createElement(final String nodeKey) { + protected RootCommandNode createElement(final String nodeKey) { // node key is ignored. return new RootCommandNode<>(); } diff --git a/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java b/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java index 0d4de845df5..585e52eef63 100644 --- a/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java +++ b/src/main/java/org/spongepowered/common/command/resolver/SpongeSuggestionTreeResolver.java @@ -26,11 +26,11 @@ import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.synchronization.SuggestionProviders; import org.spongepowered.common.bridge.commands.arguments.CompletionsArgumentTypeBridge; import org.spongepowered.common.command.brigadier.dispatcher.SpongeNodePermissionCache; @@ -44,8 +44,8 @@ public record SpongeSuggestionTreeResolver( CommandSourceStack source, - Map, CommandNode> commandToSuggestion, - Map, List>> playerNodes, + Map, CommandNode> commandToSuggestion, + Map, List>> playerNodes, SpongeCommandManager commandManager ) { @@ -54,13 +54,13 @@ public record SpongeSuggestionTreeResolver( * There is no need to split this into injections to be compatible with mods because modded platforms never call fillUsableCommands. * Instead, they redirect fillUsableCommands to their own method, like we do. */ - public void fillSuggestions(final CommandNode rootCommandNode, final CommandNode rootSuggestion) { + public void fillSuggestions(final CommandNode rootCommandNode, final CommandNode rootSuggestion) { for (final CommandNode commandNode : SpongeSuggestionTreeResolver.getChildren(rootCommandNode)) { - final List> existingNodes = this.playerNodes.get(commandNode); + final List> existingNodes = this.playerNodes.get(commandNode); if (existingNodes != null) { if (!existingNodes.isEmpty()) { boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - for (final CommandNode node : existingNodes) { + for (final CommandNode node : existingNodes) { // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug // in the client where it'll send more than one custom suggestion request - which is fine, except // the client will then ignore all but one of them. This is a problem because we then end up with @@ -68,7 +68,7 @@ public void fillSuggestions(final CommandNode rootCommandNod // meaning thenRun(...) does not run, which is how displaying the suggestions works... // // Because we don't control the client, we have to work around it here. - if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode argNode) { + if (hasCustomSuggestionsAlready && node instanceof ArgumentCommandNode argNode) { if (argNode.getCustomSuggestions() != null) { // Rebuild the node without the custom suggestions. rootSuggestion.addChild(SpongeSuggestionTreeResolver.cloneArgumentWithoutSuggestions(argNode)); @@ -94,68 +94,59 @@ public void fillSuggestions(final CommandNode rootCommandNod if (commandNode instanceof SpongeArgumentCommandNode spongeCommandNode && spongeCommandNode.isComplex()) { final boolean hasCustomSuggestionsAlready = CommandUtil.checkForCustomSuggestions(rootSuggestion); - final CommandNode finalCommandNode = spongeCommandNode.getComplexSuggestions(rootSuggestion, this.commandToSuggestion, this.playerNodes, !hasCustomSuggestionsAlready); + final CommandNode finalCommandNode = spongeCommandNode.getComplexSuggestions(rootSuggestion, this.commandToSuggestion, this.playerNodes, !hasCustomSuggestionsAlready); if (!SpongeSuggestionTreeResolver.getChildren(commandNode).isEmpty()) { this.fillSuggestions(commandNode, finalCommandNode); } continue; } - ArgumentBuilder builder; + ArgumentBuilder builder; if (commandNode instanceof SpongeArgumentCommandNode node) { builder = node.createBuilderForSuggestions(rootSuggestion, this.commandToSuggestion); - } else if (commandNode instanceof ArgumentCommandNode argNode && argNode.getType() instanceof CompletionsArgumentTypeBridge argType) { - final RequiredArgumentBuilder r = RequiredArgumentBuilder.argument(argNode.getName(), argType.bridge$clientSideCompletionType()); + } else if (commandNode instanceof ArgumentCommandNode argNode && argNode.getType() instanceof CompletionsArgumentTypeBridge argType) { + final RequiredArgumentBuilder r = RequiredArgumentBuilder.argument(argNode.getName(), argType.bridge$clientSideCompletionType()); r.executes(argNode.getCommand()) .forward(argNode.getRedirect(), argNode.getRedirectModifier(), argNode.isFork()) .requires(argNode.getRequirement()); if (!CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - r.suggests(SuggestionProviders.ASK_SERVER); + r.suggests((SuggestionProvider) SuggestionProviders.ASK_SERVER); } builder = r; } else { - builder = (ArgumentBuilder) commandNode.createBuilder(); + builder = commandNode.createBuilder(); } - builder.requires(src -> true); - if (builder.getCommand() != null) { - builder.executes(src -> 0); - } - - if (builder instanceof RequiredArgumentBuilder r && r.getSuggestionsProvider() != null) { - r.suggests(SuggestionProviders.safelySwap(r.getSuggestionsProvider())); - - // From above. - // - // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug - // in the client where it'll send more than one custom suggestion request - which is fine, except - // the client will then ignore all but one of them. This is a problem because we then end up with - // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, - // meaning thenRun(...) does not run, which is how displaying the suggestions works... - // - // Because we don't control the client, we have to work around it here. - if (r.getSuggestionsProvider() == SuggestionProviders.ASK_SERVER && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { - r.suggests(null); - } + // From above. + // + // If we have custom suggestions, we need to limit it to one node, otherwise we trigger a bug + // in the client where it'll send more than one custom suggestion request - which is fine, except + // the client will then ignore all but one of them. This is a problem because we then end up with + // no suggestions - CompletableFuture.allOf(...) will contain an exception if a future is cancelled, + // meaning thenRun(...) does not run, which is how displaying the suggestions works... + // + // Because we don't control the client, we have to work around it here. + if (builder instanceof RequiredArgumentBuilder r && r.getSuggestionsProvider() == SuggestionProviders.ASK_SERVER && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { + r.suggests(null); } if (builder.getRedirect() != null) { builder.redirect(this.commandToSuggestion.get(builder.getRedirect())); } - final CommandNode suggestion = builder instanceof RequiredArgumentBuilder r ? new SuggestionArgumentNode(r) : builder.build(); + final CommandNode suggestion = builder instanceof RequiredArgumentBuilder r ? new SuggestionArgumentNode(r) : builder.build(); if (!this.commandToSuggestion.containsKey(commandNode)) { // done here because this check is applicable if (!this.playerNodes.containsKey(commandNode)) { - final List> children = new ArrayList<>(); + final List> children = new ArrayList<>(); children.add(suggestion); this.playerNodes.put(commandNode, children); } // If the current root suggestion has already got a custom suggestion and this node has a custom suggestion, // we need to swap it out. - if (commandNode instanceof ArgumentCommandNode argNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { + if (commandNode instanceof ArgumentCommandNode argNode && CommandUtil.checkForCustomSuggestions(rootSuggestion)) { rootSuggestion.addChild(SpongeSuggestionTreeResolver.cloneArgumentWithoutSuggestions(argNode)); } else { rootSuggestion.addChild(suggestion); @@ -176,10 +167,10 @@ private static Collection> getChildren(final Com return node.getChildren(); } - private static ArgumentCommandNode cloneArgumentWithoutSuggestions(final ArgumentCommandNode toClone) { - final RequiredArgumentBuilder builder = toClone.createBuilder(); + private static ArgumentCommandNode cloneArgumentWithoutSuggestions(final ArgumentCommandNode toClone) { + final RequiredArgumentBuilder builder = toClone.createBuilder(); builder.suggests(null); - for (final CommandNode node : toClone.getChildren()) { + for (final CommandNode node : toClone.getChildren()) { builder.then(node); } return new SuggestionArgumentNode<>(builder); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java index b3fb1590986..5eef6065a65 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/commands/CommandsMixin_Vanilla.java @@ -27,7 +27,6 @@ import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; @@ -49,27 +48,25 @@ public abstract class CommandsMixin_Vanilla { private SpongeCommandManager impl$commandManager; - @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Lnet/minecraft/commands/CommandSourceStack;Ljava/util/Map;)V")) - private void impl$addNonBrigSuggestions( - final Commands self, - final CommandNode rootCommandNode, - final CommandNode rootSuggestion, - final CommandSourceStack source, - final Map, CommandNode> commandToSuggestion, - final ServerPlayer playerEntity - ) { + @Redirect(method = "sendCommands", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;fillUsableCommands(Lcom/mojang/brigadier/tree/CommandNode;Lcom/mojang/brigadier/tree/CommandNode;Ljava/lang/Object;Ljava/util/Map;)V")) + private void impl$addNonBrigSuggestions( + final CommandNode rootCommandNode, + final CommandNode rootSuggestion, + final S source, + final Map, CommandNode> commandToSuggestion, + final ServerPlayer playerEntity) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(playerEntity); frame.addContext(EventContextKeys.SUBJECT, (Subject) playerEntity); final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap<>(commandToSuggestion); + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) - .fillSuggestions(rootCommandNode, rootSuggestion); + .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); - for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { - rootSuggestion.addChild(node); + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { + rootSuggestion.addChild((CommandNode) node); } } } From fae5e2613774c85802d9079cc0ca2f4c213c6329 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 9 Jun 2025 21:45:02 +0300 Subject: [PATCH 284/586] Fire establishDataProviders & callRegisterDataEvent more early As we now fire our registry events much earlier, plugins are more likely to interact with DataHolders early on. Make sure we establish them before that. --- .../spongepowered/forge/SpongeForgeMod.java | 2 - .../spongepowered/neoforge/SpongeNeoMod.java | 2 - .../registries/BuiltInRegistriesMixin.java | 6 ++- .../common/mixin/core/server/MainMixin.java | 48 ------------------- src/mixins/resources/mixins.sponge.core.json | 1 - .../vanilla/launch/IntegrationTestLaunch.java | 6 --- .../core/client/MinecraftMixin_Vanilla.java | 3 -- 7 files changed, 5 insertions(+), 63 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/MainMixin.java diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index f42d15a6647..701528125e1 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -98,8 +98,6 @@ private void onCommonSetup(final FMLCommonSetupEvent event) { private void onClientSetup(final FMLClientSetupEvent event) { final Client minecraft = (Client) Minecraft.getInstance(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); lifecycle.establishClientRegistries(minecraft); lifecycle.callStartingEngineEvent(minecraft); } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java index 49d04dba88f..690d485b55d 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java @@ -93,8 +93,6 @@ private void onCommonSetup(final FMLCommonSetupEvent event) { private void onClientSetup(final FMLClientSetupEvent event) { final Client minecraft = (Client) Minecraft.getInstance(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); lifecycle.establishClientRegistries(minecraft); lifecycle.callStartingEngineEvent(minecraft); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java index 5181201e6d4..c3b6137e339 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java @@ -30,12 +30,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; @Mixin(BuiltInRegistries.class) public abstract class BuiltInRegistriesMixin { @Inject(method = "bootStrap", at = @At(value = "HEAD")) private static void impl$beforeCreateContents(final CallbackInfo ci) { - Launch.instance().lifecycle().establishEarlyGlobalRegistries(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.establishDataProviders(); + lifecycle.callRegisterDataEvent(); + lifecycle.establishEarlyGlobalRegistries(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MainMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MainMixin.java deleted file mode 100644 index 640f53b3f3a..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MainMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server; - -import net.minecraft.server.Main; -import net.minecraft.server.packs.repository.PackRepository; -import net.minecraft.server.packs.repository.ServerPacksSource; -import net.minecraft.world.level.storage.LevelStorageSource; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.launch.Launch; - - -@Mixin(Main.class) -public abstract class MainMixin { - - @Redirect(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/repository/ServerPacksSource;createPackRepository(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;)Lnet/minecraft/server/packs/repository/PackRepository;")) - private static PackRepository impl$configurePackRepository(LevelStorageSource.LevelStorageAccess levelSave) { - final var lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); - return ServerPacksSource.createPackRepository(levelSave); - } - -} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 37e5a6271dd..7182dd04c09 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -55,7 +55,6 @@ "registries.BuiltInRegistriesMixin", "resources.RegistryDataLoader_LoaderMixin", "resources.RegistryDataLoaderMixin", - "server.MainMixin", "server.MinecraftServerMixin", "server.PlayerAdvancementsMixin", "server.ReloadableServerResourcesMixin", diff --git a/vanilla/src/launch/java/org/spongepowered/vanilla/launch/IntegrationTestLaunch.java b/vanilla/src/launch/java/org/spongepowered/vanilla/launch/IntegrationTestLaunch.java index ef713e59dc8..104d7b5c9f7 100644 --- a/vanilla/src/launch/java/org/spongepowered/vanilla/launch/IntegrationTestLaunch.java +++ b/vanilla/src/launch/java/org/spongepowered/vanilla/launch/IntegrationTestLaunch.java @@ -28,7 +28,6 @@ import net.minecraft.server.Bootstrap; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; import org.spongepowered.vanilla.applaunch.util.MixinLoggerInjector; @@ -70,11 +69,6 @@ private void performIntegrationTests() { Bootstrap.bootStrap(); Bootstrap.validate(); - // Prepare Sponge - final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); - this.logger().info("Performing Mixin audit"); Launch.instance().auditMixins(); } finally { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java index 55ef4f6d204..9f518fc72df 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java @@ -50,9 +50,6 @@ public abstract class MinecraftMixin_Vanilla implements MinecraftBridge, Vanilla @Inject(method = "run", at = @At("HEAD")) private void vanilla$establishRegistriesAndStartingEngine(CallbackInfo ci) { final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); - lifecycle.establishClientRegistries(this); lifecycle.callStartingEngineEvent(this); } From 9e5798c62fe7c63fed8dd659eab62d1d5660ca94 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 10 Jun 2025 19:18:20 +0200 Subject: [PATCH 285/586] Remove unnecessary minecraft exclusion --- forge/build.gradle.kts | 5 ----- neoforge/build.gradle.kts | 7 ------- 2 files changed, 12 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 738df209ca9..8565bceedf2 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -156,11 +156,6 @@ val main by sourceSets.named("main") { } configurations.configureEach { - exclude(group = "net.minecraft", module = "joined") - if (name != "minecraft") { // awful terrible hack sssh - exclude(group = "com.mojang", module = "minecraft") - } - // Fix that can be found in Forge MDK too resolutionStrategy { force("net.sf.jopt-simple:jopt-simple:5.0.4") diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 6588563ff1e..ab2682e6e4d 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -140,13 +140,6 @@ val main by sourceSets.named("main") { } } -configurations.configureEach { - exclude(group = "net.minecraft", module = "joined") - if (name != "minecraft") { // awful terrible hack sssh - exclude(group = "com.mojang", module = "minecraft") - } -} - val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile AWToAT.convert(awFiles, atFile) From b05b93cd413a3facccae89ea23bab8d1f875e08c Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 15 Jun 2025 00:50:27 +0300 Subject: [PATCH 286/586] Fix mismatched phase context in secondary block interaction Also log the interaction only if the Pre event was not cancelled. --- .../level/ServerPlayerGameModeMixin_Tracker.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 32bff69f6bf..fb5a8939b35 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -102,26 +102,25 @@ public abstract class ServerPlayerGameModeMixin_Tracker { final org.spongepowered.api.util.Direction direction = DirectionFacingProvider.INSTANCE.getKey(blockHit.getDirection()).get(); final InteractBlockEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractBlockEventSecondary(player, stack, hitVec, snapshot, direction, hand); - final PhaseTracker tracker = PhaseTracker.getWorldInstance((ServerLevel) level); - final PhaseContext owningContext = tracker.getPhaseContext(); - owningContext.getTransactor().logSecondaryInteractionTransaction(player, hitVec, snapshot, direction, event); - contextRef.set(owningContext); - ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(event.isCancelled()); if (event.isCancelled()) { this.player.inventoryMenu.sendAllDataToRemote(); return InteractionResult.FAIL; } - useItemRef.set(event.useItemResult()); - useBlockRef.set(event.useBlockResult()); - + final PhaseTracker tracker = PhaseTracker.getWorldInstance((ServerLevel) level); try (final CauseStackManager.StackFrame frame = tracker.pushCauseFrame(); final PhaseContext context = PlayerPhase.State.PLAYER_INTERACT.createPhaseContext(tracker) .creator(player.getUUID()) .notifier(player.getUUID()) .containerLocation(ServerLocation.of((ServerWorld) level, blockPos))) { context.buildAndSwitch(); + context.getTransactor().logSecondaryInteractionTransaction(player, hitVec, snapshot, direction, event); + contextRef.set(context); + + useItemRef.set(event.useItemResult()); + useBlockRef.set(event.useBlockResult()); + frame.pushCause(event); frame.addContext(EventContextKeys.BLOCK_HIT, snapshot); From 4d8273813fd15125525494469fb384969f5d603e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 17:42:34 -0700 Subject: [PATCH 287/586] chore(git): update SpongeAPI for verification metadata Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 9bc0fc9edc9..7cb10b3b8ba 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9bc0fc9edc9caf957ba1972fa7184bec068374e7 +Subproject commit 7cb10b3b8bab3779f022335ac4cb1c7a73fe2d31 From 30a0fb3c619604e42021354df2054bc45b864a56 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 17:48:32 -0700 Subject: [PATCH 288/586] feat(minecraft): update to 1.21.6-pre4 See: https://minecraft.wiki/w/Java_Edition_1.21.6_Pre-Release_4 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7ee5a7980c5..ae7e24f54b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6-pre3 +minecraftVersion=1.21.6-pre4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 42b4272c660f00b91db576a9cdfe67318ea9f68a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 17:53:02 -0700 Subject: [PATCH 289/586] feat(minecraft): update to 1.21.6-rc1 Adds a trigger that was missed in a previous version. See: https://minecraft.wiki/w/Java_Edition_1.21.6_Release_Candidate_1 --- SpongeAPI | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 7cb10b3b8ba..20b50cf36e9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 7cb10b3b8bab3779f022335ac4cb1c7a73fe2d31 +Subproject commit 20b50cf36e97b6009f45365bac3ea6df9c7537ec diff --git a/gradle.properties b/gradle.properties index ae7e24f54b7..0c1818b8b2c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6-pre4 +minecraftVersion=1.21.6-rc1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From c63a42327139dcde9dfd08bbd3b35d4d2b931e5c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 17:56:10 -0700 Subject: [PATCH 290/586] feat(minecraft): update to 1.21.6 See: https://minecraft.wiki/w/Java_Edition_1.21.6 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0c1818b8b2c..64a2906a3a4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6-rc1 +minecraftVersion=1.21.6 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From b9bee3850ead8344e67b820780fc0c02fec7197e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 21:29:20 -0700 Subject: [PATCH 291/586] feat(neo|forge): update to 1.21.6 Highly experimental. It appears some registry handling is broken so it's not guaranteed to function with plugins using certain World related registries as early as server load. --- forge/build.gradle.kts | 5 +- forge/gradle.properties | 2 +- .../bridge/event/SpongeEventBridge_Forge.java | 14 +- .../launch/command/ForgeCommandManager.java | 3 +- .../forge/launch/event/ForgeEventManager.java | 122 ++------------ .../forge/launch/event/SpongeEventBus.java | 155 ------------------ .../launch/inject/SpongeForgeModule.java | 3 +- .../launch/plugin/PluginModContainer.java | 21 +-- .../spongepowered/forge/SpongeForgeMod.java | 11 +- .../forge/hook/ForgeWorldHooks.java | 5 +- .../core/api/event/EventMixin_Forge.java | 34 ---- .../ChangeBlockEvent_AllMixin_Forge.java | 66 -------- ...ChangeEntityWorldEvent_PreMixin_Forge.java | 49 ------ ...ChangeEventWorldEvent_PostMixin_Forge.java | 53 ------ .../core/commands/CommandsMixin_Forge.java | 15 +- .../MinecraftForgeMixin_Forge.java | 12 -- ...tityTravelToDimensionEventMixin_Forge.java | 75 --------- .../entity/ItemTossEventMixin_Forge.java | 85 ---------- ...layerChangedDimensionEventMixin_Forge.java | 72 -------- .../event/world/BlockEventMixin_Forge.java | 44 ----- .../BlockEvent_BreakEventMixin_Forge.java | 94 ----------- .../registries/GameDataMixin_Forge.java | 2 +- .../core/network/ConnectionMixin_Forge.java | 31 +++- .../server/level/ServerPlayerMixin_Forge.java | 4 +- ...rverGamePacketListenerImplMixin_Forge.java | 2 +- .../resources/mixins.spongeforge.core.json | 9 - gradle/verification-metadata.xml | 112 +++++++++++++ neoforge/gradle.properties | 2 +- .../core/commands/CommandsMixin_Neo.java | 7 +- ...EntityTravelToDimensionEventMixin_Neo.java | 2 +- .../core/network/ConnectionMixin_Neo.java | 30 +++- .../server/level/ServerPlayerMixin_Neo.java | 4 +- ...ServerGamePacketListenerImplMixin_Neo.java | 2 +- .../projectile/FishingHookMixin_Neo.java | 2 +- .../ServerPlayerMixin_Inventory_Neo.java | 6 +- ...ServerPlayerGameModeMixin_Neo_Tracker.java | 2 +- settings.gradle.kts | 13 ++ .../core/server/level/ServerLevelMixin.java | 2 +- .../entity/LivingEntityMixin_Damage.java | 2 +- .../entity/projectile/ProjectileMixin.java | 1 + 40 files changed, 228 insertions(+), 947 deletions(-) delete mode 100644 forge/src/launch/java/org/spongepowered/forge/launch/event/SpongeEventBus.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/EventMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEntityWorldEvent_PreMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEventWorldEvent_PostMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/EntityTravelToDimensionEventMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/ItemTossEventMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/player/PlayerEvent_PlayerChangedDimensionEventMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEventMixin_Forge.java delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEvent_BreakEventMixin_Forge.java diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 6f89908269f..cd6e7f6bcc1 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -40,6 +40,9 @@ description = "The SpongeAPI implementation for MinecraftForge" version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion, forgeVersion) repositories { + maven("https://libraries.minecraft.net/") { + name = "Mojang" + } maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } @@ -223,7 +226,7 @@ AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { - mappings("official", "1.21.5") + mappings("official", "1.21.6") accessTransformers.from(atFile) reobf = false diff --git a/forge/gradle.properties b/forge/gradle.properties index 606c020189e..d66c0a46217 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=55.0.22 +forgeVersion=56.0.2 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/bridge/event/SpongeEventBridge_Forge.java b/forge/src/launch/java/org/spongepowered/forge/launch/bridge/event/SpongeEventBridge_Forge.java index 883959d5d1e..9a5dfc120ac 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/bridge/event/SpongeEventBridge_Forge.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/bridge/event/SpongeEventBridge_Forge.java @@ -24,9 +24,7 @@ */ package org.spongepowered.forge.launch.bridge.event; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBusInvokeDispatcher; -import net.minecraftforge.eventbus.api.IEventListener; +import net.minecraftforge.eventbus.internal.Event; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; @@ -46,14 +44,4 @@ public interface SpongeEventBridge_Forge { return null; } - /** - * If there is a specialist dispatcher that we need to use for - * this given event, it can be defined here. - * - * @return The dispatcher to use. - */ - default IEventBusInvokeDispatcher bridge$eventDispatcher() { - return IEventListener::invoke; - } - } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/command/ForgeCommandManager.java b/forge/src/launch/java/org/spongepowered/forge/launch/command/ForgeCommandManager.java index 973827201be..09261d141db 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/command/ForgeCommandManager.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/command/ForgeCommandManager.java @@ -33,7 +33,6 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSourceStack; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; import org.spongepowered.api.Game; import org.spongepowered.api.command.CommandCause; @@ -82,7 +81,7 @@ public CommandResult processCommand(final CommandCause cause, final CommandMappi // Relocated from Commands (injection short circuits it there) final CommandEvent event = new CommandEvent(parseResults); - if (MinecraftForge.EVENT_BUS.post(event)) { + if (CommandEvent.BUS.post(event)) { if (event.getException() != null) { Throwables.throwIfUnchecked(event.getException()); } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/event/ForgeEventManager.java b/forge/src/launch/java/org/spongepowered/forge/launch/event/ForgeEventManager.java index 72179293a4f..77a711a64a2 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/event/ForgeEventManager.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/event/ForgeEventManager.java @@ -25,134 +25,31 @@ package org.spongepowered.forge.launch.event; import com.google.inject.Singleton; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.GenericEvent; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.IEventBusInvokeDispatcher; -import net.minecraftforge.eventbus.api.IEventListener; -import org.checkerframework.checker.nullness.qual.Nullable; +import net.minecraftforge.common.EventBusMigrationHelper; +import net.minecraftforge.eventbus.internal.Event; import org.spongepowered.common.event.manager.RegisteredListener; import org.spongepowered.common.event.manager.SpongeEventManager; import org.spongepowered.forge.launch.bridge.event.ForgeEventBridge_Forge; -import org.spongepowered.forge.launch.bridge.event.SpongeEventBridge_Forge; import java.util.Collection; -import java.util.Collections; import java.util.List; -import java.util.function.Consumer; @Singleton -public final class ForgeEventManager extends SpongeEventManager implements IEventBus { - - private final IEventBus wrappedEventBus; - - public ForgeEventManager(final IEventBus eventBus) { - this.wrappedEventBus = eventBus; - } - - // IEventBus - - @Override - public void register(final Object target) { - this.wrappedEventBus.register(target); - } - - @Override - public void addListener(final Consumer consumer) { - this.wrappedEventBus.addListener(consumer); - } - - @Override - public void addListener(final EventPriority priority, final Consumer consumer) { - this.wrappedEventBus.addListener(priority, consumer); - } - - @Override - public void addListener(final EventPriority priority, final boolean receiveCancelled, final Consumer consumer) { - this.wrappedEventBus.addListener(priority, receiveCancelled, consumer); - } - - @Override - public void addListener(final EventPriority priority, final boolean receiveCancelled, final Class eventType, final Consumer consumer) { - this.wrappedEventBus.addListener(priority, receiveCancelled, eventType, consumer); - } - - @Override - public , F> void addGenericListener(final Class genericClassFilter, final Consumer consumer) { - this.wrappedEventBus.addGenericListener(genericClassFilter, consumer); - } - - @Override - public , F> void addGenericListener(final Class genericClassFilter, final EventPriority priority, - final Consumer consumer) { - this.wrappedEventBus.addGenericListener(genericClassFilter, priority, consumer); - } - - @Override - public , F> void addGenericListener(final Class genericClassFilter, final EventPriority priority, - final boolean receiveCancelled, final Consumer consumer) { - this.wrappedEventBus.addGenericListener(genericClassFilter, priority, receiveCancelled, consumer); - } - - @Override - public , F> void addGenericListener(final Class genericClassFilter, final EventPriority priority, - final boolean receiveCancelled, final Class eventType, final Consumer consumer) { - this.wrappedEventBus.addGenericListener(genericClassFilter, priority, receiveCancelled, eventType, consumer); - } - - @Override - public void unregister(final Object object) { - this.wrappedEventBus.unregister(object); - } - - @Override - public boolean post(final Event event) { - return this.post(event, IEventListener::invoke); - } - - @Override - public boolean post(final Event event, final IEventBusInvokeDispatcher wrapper) { - if (event instanceof ForgeEventBridge_Forge forgeEvent) { - // intercept! - final org.spongepowered.api.event.@Nullable Event spongeEvent = forgeEvent.bridge$createSpongeEvent(); - if (spongeEvent != null) { - return this.postDualBus(spongeEvent, Collections.singleton(event), wrapper); - } - } - // Do as Forge does - SpongeVanilla has no role to play here. - return this.wrappedEventBus.post(event, wrapper); - } - - @Override - public void shutdown() { - this.wrappedEventBus.shutdown(); - } - - @Override - public void start() { - this.wrappedEventBus.start(); - } - - // EventManager +public final class ForgeEventManager extends SpongeEventManager { + private final EventBusMigrationHelper INSTANCE = EventBusMigrationHelper.INSTANCE; @Override public boolean post(final org.spongepowered.api.event.Event event) { - final SpongeEventBridge_Forge eventBridge = ((SpongeEventBridge_Forge) event); - final @Nullable Collection forgeEvents = eventBridge.bridge$createForgeEvents(); - if (forgeEvents == null || forgeEvents.isEmpty()) { - // Do as SpongeVanilla does - Forge has no role to play here. - return super.post(event); - } - return this.postDualBus(event, forgeEvents, eventBridge.bridge$eventDispatcher()); +// final SpongeEventBridge_Forge eventBridge = ((SpongeEventBridge_Forge) event); +// final @Nullable Collection forgeEvents = eventBridge.bridge$createForgeEvents(); + return super.post(event); } // Implementation @SuppressWarnings({"unchecked", "rawtypes"}) private boolean postDualBus( - final org.spongepowered.api.event.Event spongeEvent, final Collection forgeEvents, - final IEventBusInvokeDispatcher dispatcher) { + final org.spongepowered.api.event.Event spongeEvent, final Collection forgeEvents) { try (final NoExceptionClosable ignored = this.preparePost(spongeEvent)) { final RegisteredListener.Cache listeners = this.getHandlerCache(spongeEvent); final List> beforeModifications = listeners.beforeModifications(); @@ -167,7 +64,8 @@ private boolean postDualBus( } // Then, we fire all our Forge events for (final Event forgeEvent : forgeEvents) { - this.wrappedEventBus.post(forgeEvent, dispatcher); + +// INSTANCE.post(forgeEvent, dispatcher); // We must sync back the event's changes, if there are any. // For complex events, this will be a partial sync. ((ForgeEventBridge_Forge) forgeEvent).bridge$syncTo(spongeEvent); diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/event/SpongeEventBus.java b/forge/src/launch/java/org/spongepowered/forge/launch/event/SpongeEventBus.java deleted file mode 100644 index 388458b23df..00000000000 --- a/forge/src/launch/java/org/spongepowered/forge/launch/event/SpongeEventBus.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.launch.event; - -import net.minecraftforge.eventbus.BusBuilderImpl; -import net.minecraftforge.eventbus.EventBus; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.IEventBusInvokeDispatcher; -import net.minecraftforge.eventbus.api.IEventExceptionHandler; -import net.minecraftforge.eventbus.api.IEventListener; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.common.event.manager.SpongeEventManager; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.PhaseTracker; - -import java.lang.reflect.Field; -import java.util.Objects; - -public final class SpongeEventBus extends EventBus { - - // I hope ya'll like reflection... - private static Field busIDField; - private static Field exceptionHandlerField; - private static Field trackPhasesField; - private static Field shutdownField; - private static Field baseTypeField; - private static Field checkTypesOnDispatchField; - - static { - try { - SpongeEventBus.busIDField = EventBus.class.getDeclaredField("busID"); - SpongeEventBus.exceptionHandlerField = EventBus.class.getDeclaredField("exceptionHandler"); - SpongeEventBus.trackPhasesField = EventBus.class.getDeclaredField("trackPhases"); - SpongeEventBus.shutdownField = EventBus.class.getDeclaredField("shutdown"); - SpongeEventBus.baseTypeField = EventBus.class.getDeclaredField("baseType"); - SpongeEventBus.checkTypesOnDispatchField = EventBus.class.getDeclaredField("checkTypesOnDispatch"); - - } catch (final Exception ex) { - // Burn this to the ground - throw new RuntimeException(ex); - } - } - - // reflected fields that are stored again to prevent multiple reflection calls - private final int rbusID; - private final IEventExceptionHandler rexceptionHandler; - private final boolean rtrackPhases; - private boolean rshutdown; - private final Class rbaseType; - private final boolean rcheckTypesOnDispatch; - - public SpongeEventBus(final BusBuilderImpl busBuilder) { - super(busBuilder); - - // Sponge Start - I hope ya'll still like reflection - try { - SpongeEventBus.busIDField.setAccessible(true); - SpongeEventBus.exceptionHandlerField.setAccessible(true); - SpongeEventBus.trackPhasesField.setAccessible(true); - SpongeEventBus.shutdownField.setAccessible(true); - SpongeEventBus.baseTypeField.setAccessible(true); - SpongeEventBus.checkTypesOnDispatchField.setAccessible(true); - - this.rbusID = SpongeEventBus.busIDField.getInt(this); - this.rexceptionHandler = (IEventExceptionHandler) SpongeEventBus.exceptionHandlerField.get(this); - this.rtrackPhases = SpongeEventBus.trackPhasesField.getBoolean(this); - this.rshutdown = SpongeEventBus.shutdownField.getBoolean(this); - this.rbaseType = (Class) SpongeEventBus.baseTypeField.get(this); - this.rcheckTypesOnDispatch = SpongeEventBus.checkTypesOnDispatchField.getBoolean(this); - - SpongeEventBus.busIDField.setAccessible(false); - SpongeEventBus.exceptionHandlerField.setAccessible(false); - SpongeEventBus.trackPhasesField.setAccessible(false); - SpongeEventBus.shutdownField.setAccessible(false); - SpongeEventBus.baseTypeField.setAccessible(false); - SpongeEventBus.checkTypesOnDispatchField.setAccessible(false); - } catch (final Exception ex) { - // Burn this to the ground again - throw new RuntimeException(ex); - } - // Sponge End - } - - @Override - public boolean post(final Event event, final IEventBusInvokeDispatcher wrapper) { - // @formatter:off - - // Sponge - use the builder/member fields. Avoids reflection but remains very hacky... - if (this.rshutdown) return false; - if (this.rcheckTypesOnDispatch && !rbaseType.isInstance(event)) - { - throw new IllegalArgumentException("Cannot post event of type " + event.getClass().getSimpleName() + " to this event. Must match type: " + this.rbaseType.getSimpleName()); - } - - IEventListener[] listeners = event.getListenerList().getListeners(this.rbusID); - int index = 0; - for (; index < listeners.length; index++) - { - final IEventListener listener = listeners[index]; - if (!this.rtrackPhases && Objects.equals(listener.getClass(), EventPriority.class)) continue; - - try ( - final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame(); - final PhaseContext<@NonNull ?> context = SpongeEventManager.createListenerContext(null)) - { - if (context != null) { - context.buildAndSwitch(); - } - - wrapper.invoke(listener, event); - } catch (final Throwable t) { - this.rexceptionHandler.handleException(this, event, listeners, index, t); - } - } - return event.isCancelable() && event.isCanceled(); - - // @formatter:on - } - - @Override - public void shutdown() { - super.shutdown(); - this.rshutdown = true; - } - - @Override - public void start() { - super.start(); - this.rshutdown = false; - } -} diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/inject/SpongeForgeModule.java b/forge/src/launch/java/org/spongepowered/forge/launch/inject/SpongeForgeModule.java index b9187264f17..ff83a86d3c7 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/inject/SpongeForgeModule.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/inject/SpongeForgeModule.java @@ -25,7 +25,6 @@ package org.spongepowered.forge.launch.inject; import com.google.inject.AbstractModule; -import net.minecraftforge.common.MinecraftForge; import org.spongepowered.api.Platform; import org.spongepowered.api.event.EventManager; import org.spongepowered.common.command.manager.SpongeCommandManager; @@ -38,7 +37,7 @@ public final class SpongeForgeModule extends AbstractModule { @Override protected void configure() { this.bind(Platform.class).to(ForgePlatform.class); - this.bind(EventManager.class).toProvider(() -> (ForgeEventManager) MinecraftForge.EVENT_BUS); + this.bind(EventManager.class).toProvider(ForgeEventManager::new); this.bind(SpongeCommandManager.class).to(ForgeCommandManager.class); } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index 8dbf92eed98..dede8de6af1 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -25,12 +25,7 @@ package org.spongepowered.forge.launch.plugin; import com.google.inject.Injector; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.EventBusErrorMessage; -import net.minecraftforge.eventbus.api.BusBuilder; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.IEventListener; +import net.minecraftforge.eventbus.internal.Event; import net.minecraftforge.fml.Logging; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; @@ -45,7 +40,6 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.common.inject.plugin.PluginGuice; import org.spongepowered.common.launch.Launch; -import org.spongepowered.forge.launch.event.ForgeEventManager; import org.spongepowered.plugin.metadata.model.PluginDependency; import java.util.concurrent.CountDownLatch; @@ -55,7 +49,6 @@ public final class PluginModContainer extends ModContainer { private static final Logger LOGGER = LogManager.getLogger(); private final ModFileScanData scanResults; - private final IEventBus eventBus; private Object modInstance; private final Class modClass; private final CountDownLatch initializationLock; @@ -65,7 +58,6 @@ public PluginModContainer(IModInfo info, String className, ModFileScanData modFi LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", className); this.scanResults = modFileScanResults; this.activityMap.put(ModLoadingStage.CONSTRUCT, this::constructPlugin); - this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build(); this.contextExtension = () -> null; this.initializationLock = new CountDownLatch(1); @@ -81,12 +73,11 @@ public PluginModContainer(IModInfo info, String className, ModFileScanData modFi @Override public void dispatchConfigEvent(IConfigEvent event) { - this.eventBus.post(event.self()); } - private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable) { - LOGGER.error(new EventBusErrorMessage(event, i, iEventListeners, throwable)); - } +// private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable) { +// LOGGER.error(new EventBusErrorMessage(event, i, iEventListeners, throwable)); +// } private void constructPlugin() { try { @@ -109,7 +100,7 @@ private void constructPlugin() { final Injector pluginInjector = PluginGuice.create(pluginContainer, this.modClass, Launch.instance().lifecycle().platformInjector()); this.modInstance = pluginInjector.getInstance(this.modClass); pluginContainer.setInjector(pluginInjector); - ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners(pluginContainer, this.modInstance); +// ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners(pluginContainer, this.modInstance); LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), this.modClass.getName()); @@ -139,11 +130,9 @@ public Object getMod() { return this.modInstance; } - @Override protected void acceptEvent(final T e) { try { LOGGER.trace(Logging.LOADING, "Firing event for modid {} : {}", this.getModId(), e); - this.eventBus.post(e); LOGGER.trace(Logging.LOADING, "Fired event for modid {} : {}", this.getModId(), e); } catch (Throwable t) { LOGGER.error(Logging.LOADING, "Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index f42d15a6647..32afea7e51c 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -30,8 +30,7 @@ import net.minecraftforge.event.server.ServerAboutToStartEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStoppingEvent; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.eventbus.api.listener.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; @@ -63,12 +62,12 @@ public final class SpongeForgeMod { public SpongeForgeMod(FMLJavaModLoadingContext ctx) { // WorldPersistenceHooks.addHook(SpongeLevelDataPersistence.INSTANCE); // TODO SF 1.19.4 - final IEventBus modBus = ctx.getModEventBus(); + final var group = ctx.getModBusGroup(); // modBus: add all FML events with it - modBus.addListener(this::onCommonSetup); - modBus.addListener(this::onClientSetup); - modBus.addListener(this::onEntityAttributeCreationEvent); + FMLCommonSetupEvent.getBus(group).addListener(this::onCommonSetup); + FMLClientSetupEvent.getBus(group).addListener(this::onClientSetup); + EntityAttributeCreationEvent.getBus(group).addListener(this::onEntityAttributeCreationEvent); // annotation events, for non-FML things MinecraftForge.EVENT_BUS.register(this); diff --git a/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java b/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java index d5475bcd424..2d609eb95c4 100644 --- a/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java +++ b/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java @@ -30,7 +30,6 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.level.LevelEvent; import org.spongepowered.common.hooks.WorldHooks; @@ -59,13 +58,13 @@ public boolean isRestoringBlocks(final Level world) { @Override public void postLoadWorld(final ServerLevel world) { - MinecraftForge.EVENT_BUS.post(new LevelEvent.Load(world)); + LevelEvent.Load.BUS.post(new LevelEvent.Load(world)); world.getServer().markWorldsDirty(); } @Override public void preUnloadWorld(final ServerLevel world) { - MinecraftForge.EVENT_BUS.post(new LevelEvent.Unload(world)); + LevelEvent.Unload.BUS.post(new LevelEvent.Unload(world)); world.getServer().markWorldsDirty(); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/EventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/EventMixin_Forge.java deleted file mode 100644 index 475f7c6bf71..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/EventMixin_Forge.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.api.event; - -import org.spongepowered.api.event.Event; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.forge.launch.bridge.event.SpongeEventBridge_Forge; - -@Mixin(value = Event.class, remap = false) -public interface EventMixin_Forge extends SpongeEventBridge_Forge { - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Forge.java deleted file mode 100644 index d9ad83e55f4..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Forge.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.api.event.block; - -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.event.level.BlockEvent; -import net.minecraftforge.eventbus.api.Event; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.block.transaction.BlockTransaction; -import org.spongepowered.api.block.transaction.Operation; -import org.spongepowered.api.block.transaction.Operations; -import org.spongepowered.api.event.block.ChangeBlockEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.util.VecHelper; -import org.spongepowered.forge.launch.bridge.event.SpongeEventBridge_Forge; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@Mixin(value = ChangeBlockEvent.All.class, remap = false) -public interface ChangeBlockEvent_AllMixin_Forge extends SpongeEventBridge_Forge { - - @Override - default @Nullable Collection bridge$createForgeEvents() { - final ChangeBlockEvent.All thisEvent = ((ChangeBlockEvent.All) this); - final Player player = thisEvent.cause().first(Player.class).orElse(null); - final Operation breakOp = Operations.BREAK.get(); - - final List forgeEvents = new ArrayList<>(); - for (final BlockTransaction transaction : thisEvent.transactions()) { - if (player != null && transaction.operation() == breakOp) { - forgeEvents.add(new BlockEvent.BreakEvent((Level) thisEvent.world(), - VecHelper.toBlockPos(transaction.original().position()), - (BlockState) transaction.original().state(), player)); - } - // TODO: Other event types may go here - break is a PoC. - } - return forgeEvents; - } - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEntityWorldEvent_PreMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEntityWorldEvent_PreMixin_Forge.java deleted file mode 100644 index 30a236eefe4..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEntityWorldEvent_PreMixin_Forge.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.api.event.entity; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.event.entity.EntityTravelToDimensionEvent; -import net.minecraftforge.eventbus.api.Event; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.forge.mixin.core.api.event.EventMixin_Forge; - -import java.util.Collection; -import java.util.Collections; - -@Mixin(ChangeEntityWorldEvent.Pre.class) -public interface ChangeEntityWorldEvent_PreMixin_Forge extends EventMixin_Forge { - - @Override - default @Nullable Collection bridge$createForgeEvents() { - final ChangeEntityWorldEvent.Pre thisEvent = (ChangeEntityWorldEvent.Pre) this; - return Collections.singleton( - new EntityTravelToDimensionEvent((Entity) thisEvent.entity(), ((ServerLevel) thisEvent.destinationWorld()).dimension())); - } - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEventWorldEvent_PostMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEventWorldEvent_PostMixin_Forge.java deleted file mode 100644 index f85995d0727..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/api/event/entity/ChangeEventWorldEvent_PostMixin_Forge.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.api.event.entity; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.Event; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.forge.mixin.core.api.event.EventMixin_Forge; - -import java.util.Collection; -import java.util.Collections; - -@Mixin(ChangeEntityWorldEvent.Post.class) -public interface ChangeEventWorldEvent_PostMixin_Forge extends EventMixin_Forge { - - @Override - default @Nullable Collection bridge$createForgeEvents() { - if (((ChangeEntityWorldEvent.Post) this).entity() instanceof ServerPlayer) { - final ServerPlayer player = (ServerPlayer) ((ChangeEntityWorldEvent.Post) this).entity(); - - return Collections.singletonList(new PlayerEvent.PlayerChangedDimensionEvent(player, - ((ServerLevel) ((ChangeEntityWorldEvent.Post) this).originalWorld()).dimension(), - ((ServerLevel) ((ChangeEntityWorldEvent.Post) this).destinationWorld()).dimension())); - } - return null; - } -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java index dab0090da5f..013e5130da5 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/commands/CommandsMixin_Forge.java @@ -29,10 +29,9 @@ import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.bus.CancellableEventBus; +import net.minecraftforge.eventbus.internal.Event; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -56,8 +55,8 @@ public abstract class CommandsMixin_Forge { // The event fired by Forge is fired in ForgeCommandManager at the appropriate time. @Redirect(method = "performCommand", - at = @At(value = "INVOKE", target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z")) - private boolean forge$redirectToSpongeCommandManager(IEventBus instance, Event event) { + at = @At(value = "INVOKE", target = "Lnet/minecraftforge/eventbus/api/bus/CancellableEventBus;post(Lnet/minecraftforge/eventbus/internal/Event;)Z")) + private boolean forge$redirectToSpongeCommandManager(CancellableEventBus instance, Event event) { return false; } @@ -78,11 +77,11 @@ public abstract class CommandsMixin_Forge { final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) - .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); + .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); - for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { rootSuggestion.addChild((CommandNode) node); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/MinecraftForgeMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/MinecraftForgeMixin_Forge.java index 1f23d293092..da6df27b827 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/MinecraftForgeMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/MinecraftForgeMixin_Forge.java @@ -25,22 +25,10 @@ package org.spongepowered.forge.mixin.core.minecraftforge; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.BusBuilderImpl; -import net.minecraftforge.eventbus.api.BusBuilder; -import net.minecraftforge.eventbus.api.IEventBus; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.forge.launch.event.ForgeEventManager; -import org.spongepowered.forge.launch.event.SpongeEventBus; @Mixin(MinecraftForge.class) public abstract class MinecraftForgeMixin_Forge { - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraftforge/eventbus/api/BusBuilder;build()Lnet/minecraftforge/eventbus/api/IEventBus;", remap = false)) - private static IEventBus forge$substituteForgeEventBus(final BusBuilder builder) { - return new ForgeEventManager(new SpongeEventBus((BusBuilderImpl) builder)); - } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/EntityTravelToDimensionEventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/EntityTravelToDimensionEventMixin_Forge.java deleted file mode 100644 index 6c68bbcd05e..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/EntityTravelToDimensionEventMixin_Forge.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.event.entity; - -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraftforge.event.entity.EntityEvent; -import net.minecraftforge.event.entity.EntityTravelToDimensionEvent; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.forge.launch.bridge.event.ForgeEventBridge_Forge; - -@Mixin(value = EntityTravelToDimensionEvent.class, remap = false) -public abstract class EntityTravelToDimensionEventMixin_Forge extends EntityEvent implements ForgeEventBridge_Forge { - - // @formatter:off - @Shadow @Final @Mutable private ResourceKey dimension; - // @formatter:on - - private EntityTravelToDimensionEventMixin_Forge(Entity entity) { - super(entity); - } - - @Override - public void bridge$syncFrom(final ChangeEntityWorldEvent.Pre event) { - this.setCanceled(event.isCancelled()); - this.dimension = ((ServerLevel) event.destinationWorld()).dimension(); - } - - @Override - public void bridge$syncTo(final ChangeEntityWorldEvent.Pre event) { - event.setCancelled(this.isCanceled()); - } - - @Override - public ChangeEntityWorldEvent.@Nullable Pre bridge$createSpongeEvent() { - final Entity entity = this.getEntity(); - final ServerLevel toWorld = SpongeCommon.server().getLevel(this.dimension); - return SpongeEventFactory.createChangeEntityWorldEventPre(PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.getCommandSenderWorld(), - (org.spongepowered.api.world.server.ServerWorld) toWorld, (org.spongepowered.api.world.server.ServerWorld) toWorld); - } - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/ItemTossEventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/ItemTossEventMixin_Forge.java deleted file mode 100644 index 105a97f7b67..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/ItemTossEventMixin_Forge.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.event.entity; - -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.entity.item.ItemEvent; -import net.minecraftforge.event.entity.item.ItemTossEvent; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.cause.entity.SpawnTypes; -import org.spongepowered.api.event.item.inventory.DropItemEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.forge.launch.bridge.event.ForgeEventBridge_Forge; - -import java.util.ArrayList; - -@Mixin(ItemTossEvent.class) -public abstract class ItemTossEventMixin_Forge extends ItemEvent implements ForgeEventBridge_Forge { - - //@formatter:off - @Shadow private @Final Player player; - //@formatter:on - - private ItemTossEventMixin_Forge(ItemEntity itemEntity) { - super(itemEntity); - } - - @Override - public void bridge$syncFrom(DropItemEvent.Dispense event) { - event.entities().stream() - .filter(e -> e instanceof ItemEntity) - .map(e -> (ItemEntity) e) - .findFirst() - .ifPresent(e -> this.getEntity().setItem(e.getItem())); - this.setCanceled(event.isCancelled()); - } - - @Override - public void bridge$syncTo(DropItemEvent.Dispense event) { - event.setCancelled(this.isCanceled()); - } - - @Override - public DropItemEvent.@Nullable Dispense bridge$createSpongeEvent() { - if (this.player.level().isClientSide()) { - return null; - } - try (final var frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM); - final var cause = frame.currentCause(); - final var toSpawn = (Entity) this.getEntity(); - final var list = new ArrayList(); - list.add(toSpawn); - return SpongeEventFactory.createDropItemEventDispense(cause, list); - } - } -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/player/PlayerEvent_PlayerChangedDimensionEventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/player/PlayerEvent_PlayerChangedDimensionEventMixin_Forge.java deleted file mode 100644 index 27d38facc3e..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/entity/player/PlayerEvent_PlayerChangedDimensionEventMixin_Forge.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.event.entity.player; - -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; -import net.minecraftforge.event.entity.player.PlayerEvent; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.forge.launch.bridge.event.ForgeEventBridge_Forge; - -@Mixin(value = PlayerEvent.PlayerChangedDimensionEvent.class, remap = false) -public final class PlayerEvent_PlayerChangedDimensionEventMixin_Forge implements ForgeEventBridge_Forge{ - - // @formatter:off - @Shadow @Final private ResourceKey fromDim; - @Shadow @Final private ResourceKey toDim; - // @formatter:on - - @Override - public void bridge$syncFrom(final ChangeEntityWorldEvent.Post event) { - // nothing to do -- informational only - } - - @Override - public void bridge$syncTo(final ChangeEntityWorldEvent.Post event) { - // nothing to do -- informational only - } - - @SuppressWarnings("ConstantConditions") - @Override - public ChangeEntityWorldEvent.Post bridge$createSpongeEvent() { - final PlayerEvent.PlayerChangedDimensionEvent thisEvent = (PlayerEvent.PlayerChangedDimensionEvent) (Object) this; - return SpongeEventFactory.createChangeEntityWorldEventPost( - PhaseTracker.getInstance().currentCause(), - (Entity) thisEvent.getEntity(), - (ServerWorld) SpongeCommon.server().getLevel(this.fromDim), - (ServerWorld) SpongeCommon.server().getLevel(this.toDim), - (ServerWorld) SpongeCommon.server().getLevel(this.toDim) - ); - } - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEventMixin_Forge.java deleted file mode 100644 index a833bfbcbb1..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEventMixin_Forge.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.event.world; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.event.level.BlockEvent; -import net.minecraftforge.eventbus.api.Event; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(value = BlockEvent.class, remap = false) -public abstract class BlockEventMixin_Forge extends Event { - - // @formatter:off - @Shadow public abstract LevelAccessor shadow$getLevel(); - @Shadow public abstract BlockPos shadow$getPos(); - @Shadow public abstract BlockState shadow$getState(); - // @formatter:on - -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEvent_BreakEventMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEvent_BreakEventMixin_Forge.java deleted file mode 100644 index eb378c518ac..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/event/world/BlockEvent_BreakEventMixin_Forge.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.minecraftforge.event.world; - -import net.minecraft.world.level.LevelAccessor; -import net.minecraftforge.event.level.BlockEvent; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockTypes; -import org.spongepowered.api.block.transaction.BlockTransaction; -import org.spongepowered.api.block.transaction.Operations; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.block.ChangeBlockEvent; -import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.block.SpongeBlockSnapshot; -import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.util.VecHelper; -import org.spongepowered.forge.launch.bridge.event.ForgeEventBridge_Forge; -import org.spongepowered.math.vector.Vector3i; - -import java.util.Collections; - -@Mixin(value = BlockEvent.BreakEvent.class, remap = false) -public abstract class BlockEvent_BreakEventMixin_Forge extends BlockEventMixin_Forge implements ForgeEventBridge_Forge { - - @Override - public void bridge$syncFrom(final ChangeBlockEvent.All event) { - final Vector3i pos = VecHelper.toVector3i(this.shadow$getPos()); - if (event.isCancelled() || - event.transactions() - .stream() - .filter(x -> x.original().position().equals(pos)) - .anyMatch(x -> !x.isValid() || x.operation() != Operations.BREAK.get() || x.custom().isPresent())) { - this.setCanceled(true); - } - } - - @Override - public void bridge$syncTo(final ChangeBlockEvent.All event) { - if (this.isCanceled()) { - final Vector3i pos = VecHelper.toVector3i(this.shadow$getPos()); - event.transactions(Operations.BREAK.get()).filter(x -> x.original().position().equals(pos)) - .forEach(x -> x.setValid(false)); - } - } - - @Override - public ChangeBlockEvent.@Nullable All bridge$createSpongeEvent() { - final LevelAccessor accessor = this.shadow$getLevel(); - if (accessor instanceof ServerWorld serverWorld) { - final BlockTransaction transaction = new BlockTransaction( - SpongeBlockSnapshot.BuilderImpl - .pooled() - .world(serverWorld.key()) - .position(VecHelper.toVector3i(this.shadow$getPos())) - .blockState((BlockState) this.shadow$getState()) - .build(), - SpongeBlockSnapshot.BuilderImpl - .pooled() - .world(serverWorld.key()) - .position(VecHelper.toVector3i(this.shadow$getPos())) - .blockState(BlockState.builder().blockType(BlockTypes.AIR.get()).build()) - .build(), - Operations.BREAK.get() - ); - return SpongeEventFactory.createChangeBlockEventAll(PhaseTracker.getInstance().currentCause(), - Collections.singletonList(transaction), serverWorld); - } - return null; - } -} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java index 3d05bd93b3f..2e4dc5287ff 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java @@ -40,7 +40,7 @@ @Mixin(GameData.class) public class GameDataMixin_Forge { - @Inject(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEventWrapContainerInModOrder(Lnet/minecraftforge/eventbus/api/Event;)V", shift = At.Shift.AFTER)) + @Inject(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEventWrapContainerInModOrder(Lnet/minecraftforge/fml/event/IModBusEvent;)V", shift = At.Shift.AFTER)) private static void forge$registerSpongeTypesLast(final CallbackInfo ci, @Nullable @Local final Registry vanillaRegistry) { if (vanillaRegistry != null && Registries.ENTITY_TYPE.equals(vanillaRegistry.key())) { SpongeEntityTypes.register((Registry>) vanillaRegistry); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java index ed066933318..fa1e4bbdb98 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java @@ -24,23 +24,38 @@ */ package org.spongepowered.forge.mixin.core.network; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; +import net.minecraft.network.protocol.Packet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.network.channel.PacketSender; @Mixin(Connection.class) public abstract class ConnectionMixin_Forge { - @Inject(method = "lambda$doSendPacket$15", at = @At(value = "INVOKE", target = "Lio/netty/util/concurrent/Future;isSuccess()Z")) - public void impl$onPacketSent(final PacketSendListener listener, final Future future, final CallbackInfo ci) { - if (listener instanceof final PacketSender.SpongePacketSendListener spongeListener) { - spongeListener.accept(future.cause()); + @WrapOperation(method = "doSendPacket", at = @At( + value = "INVOKE", + target = "Lio/netty/channel/ChannelFuture;addListener(Lio/netty/util/concurrent/GenericFutureListener;)Lio/netty/channel/ChannelFuture;", + remap = false + )) + public ChannelFuture impl$onPacketSent( + final ChannelFuture instance, final GenericFutureListener> genericFutureListener, + final Operation original, final Packet packet, + final ChannelFutureListener listener, final boolean abool + ) { + if (listener instanceof PacketSender.SpongePacketSendListener spsl) { + original.call(instance, (ChannelFutureListener) (future) -> { + if (!future.isSuccess()) { + spsl.accept(future.cause()); + } + }); } + return original.call(instance, listener); } - } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java index 25f11215d82..33f2f79f41d 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java @@ -39,12 +39,12 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Forge extends LivingEntityMixin_Forge { - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // override from LivingEntityMixin_Forge @Override protected void forge$onElytraUse(final CallbackInfo ci) { - final ServerLevel level = this.shadow$serverLevel(); + final ServerLevel level = this.shadow$level(); final PhaseContext context = PhaseTracker.getWorldInstance(level).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java index f3c363bcbec..fed272e3a05 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java @@ -54,7 +54,7 @@ public abstract class ServerGamePacketListenerImplMixin_Forge implements ServerG private RecipeBookMenu.PostPlaceAction forge$onPlaceRecipe( final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final var player = this.player; diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 1c0b3e43166..2ee6aa34db4 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -4,17 +4,8 @@ "package": "org.spongepowered.forge.mixin.core", "priority": 1301, "mixins": [ - "api.event.EventMixin_Forge", - "api.event.block.ChangeBlockEvent_AllMixin_Forge", - "api.event.entity.ChangeEntityWorldEvent_PreMixin_Forge", - "api.event.entity.ChangeEventWorldEvent_PostMixin_Forge", "commands.CommandsMixin_Forge", "minecraftforge.MinecraftForgeMixin_Forge", - "minecraftforge.event.entity.EntityTravelToDimensionEventMixin_Forge", - "minecraftforge.event.entity.ItemTossEventMixin_Forge", - "minecraftforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Forge", - "minecraftforge.event.world.BlockEvent_BreakEventMixin_Forge", - "minecraftforge.event.world.BlockEventMixin_Forge", "minecraftforge.internal.BrandingControlMixin_Forge", "minecraftforge.registries.ForgeRegistryMixin_Forge", "minecraftforge.registries.GameDataMixin_Forge", diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 178638e4689..1758726e646 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1972,6 +1972,14 @@ + + + + + + + + @@ -4094,6 +4102,14 @@ + + + + + + + + @@ -4220,6 +4236,14 @@ + + + + + + + + @@ -4346,6 +4370,14 @@ + + + + + + + + @@ -4472,6 +4504,14 @@ + + + + + + + + @@ -4767,6 +4807,14 @@ + + + + + + + + @@ -4901,6 +4949,14 @@ + + + + + + + + @@ -5035,6 +5091,14 @@ + + + + + + + + @@ -5469,6 +5533,17 @@ + + + + + + + + + + + @@ -5484,6 +5559,11 @@ + + + + + @@ -5655,6 +5735,20 @@ + + + + + + + + + + + + + + @@ -5695,6 +5789,14 @@ + + + + + + + + @@ -7654,6 +7756,11 @@ + + + + + @@ -7680,6 +7787,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 8700d76c8d4..64c666155c7 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.5.75 +neoForgeVersion=21.6.5-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java index 7ad771cefc5..1b813b71921 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/commands/CommandsMixin_Neo.java @@ -29,7 +29,6 @@ import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.server.level.ServerPlayer; import net.neoforged.bus.api.Event; import net.neoforged.bus.api.IEventBus; @@ -78,11 +77,11 @@ public abstract class CommandsMixin_Neo { final CommandCause sourceToUse = ((CommandSourceStackBridge) source).bridge$withCurrentCause(); // We use this because the redirects should be a 1:1 mapping (which is what this map is for). - final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); + final IdentityHashMap, CommandNode> idMap = new IdentityHashMap(commandToSuggestion); new SpongeSuggestionTreeResolver((CommandSourceStack) sourceToUse, idMap, new IdentityHashMap<>(), this.impl$commandManager) - .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); + .fillSuggestions((CommandNode) rootCommandNode, (CommandNode) rootSuggestion); - for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { + for (final CommandNode node : this.impl$commandManager.getNonBrigadierSuggestions(sourceToUse)) { rootSuggestion.addChild((CommandNode) node); } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/entity/EntityTravelToDimensionEventMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/entity/EntityTravelToDimensionEventMixin_Neo.java index 9ebe6e0685a..b62c3c1e774 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/entity/EntityTravelToDimensionEventMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/entity/EntityTravelToDimensionEventMixin_Neo.java @@ -69,7 +69,7 @@ public abstract class EntityTravelToDimensionEventMixin_Neo implements NeoEventB final Entity entity = ((EntityEvent) (Object) this).getEntity(); final ServerLevel toWorld = SpongeCommon.server().getLevel(this.dimension); return SpongeEventFactory.createChangeEntityWorldEventPre(PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.getCommandSenderWorld(), + (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.level(), (org.spongepowered.api.world.server.ServerWorld) toWorld, (org.spongepowered.api.world.server.ServerWorld) toWorld); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/network/ConnectionMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/network/ConnectionMixin_Neo.java index 3ba167337f6..16563ebfbb0 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/network/ConnectionMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/network/ConnectionMixin_Neo.java @@ -24,23 +24,39 @@ */ package org.spongepowered.neoforge.mixin.core.network; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; +import net.minecraft.network.protocol.Packet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.network.channel.PacketSender; @Mixin(Connection.class) public abstract class ConnectionMixin_Neo { - @Inject(method = "lambda$doSendPacket$13", at = @At(value = "INVOKE", target = "Lio/netty/util/concurrent/Future;isSuccess()Z")) - public void impl$onPacketSent(final PacketSendListener listener, final Future future, final CallbackInfo ci) { - if (listener instanceof final PacketSender.SpongePacketSendListener spongeListener) { - spongeListener.accept(future.cause()); + @WrapOperation(method = "doSendPacket", at = @At( + value = "INVOKE", + target = "Lio/netty/channel/ChannelFuture;addListener(Lio/netty/util/concurrent/GenericFutureListener;)Lio/netty/channel/ChannelFuture;", + remap = false + )) + public ChannelFuture impl$onPacketSent( + final ChannelFuture instance, final GenericFutureListener> genericFutureListener, + final Operation original, final Packet packet, + final ChannelFutureListener listener, final boolean abool + ) { + if (listener instanceof PacketSender.SpongePacketSendListener spsl) { + original.call(instance, (ChannelFutureListener) (future) -> { + if (!future.isSuccess()) { + spsl.accept(future.cause()); + } + }); } + return original.call(instance, listener); } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java index 20edf213fbe..eeecdb3d90c 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerPlayerMixin_Neo.java @@ -40,13 +40,13 @@ public abstract class ServerPlayerMixin_Neo extends LivingEntityMixin_Neo { // @formatter:off - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // @formatter:on // override from LivingEntityMixin_Neo @Override protected void neo$onElytraUse(final CallbackInfo ci) { - final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java index 665f8bc25d7..d024545433d 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Neo.java @@ -54,7 +54,7 @@ public abstract class ServerGamePacketListenerImplMixin_Neo implements ServerGam private RecipeBookMenu.PostPlaceAction neo$onPlaceRecipe( final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final var player = this.player; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/projectile/FishingHookMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/projectile/FishingHookMixin_Neo.java index e02aaf794ce..0e0e52b4e53 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/projectile/FishingHookMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/projectile/FishingHookMixin_Neo.java @@ -45,7 +45,7 @@ public abstract class FishingHookMixin_Neo extends ProjectileMixin { if (SpongeCommonEventFactory.handleCollideImpactEvent(self, this.impl$getProjectileSource(), hitResult)) { this.shadow$discard(); } else { - this.onHit(hitResult); + this.shadow$onHit(hitResult); } } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java index 4a7805451de..a36159a7dbf 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java @@ -54,7 +54,7 @@ public abstract class ServerPlayerMixin_Inventory_Neo extends PlayerMixin_Inventory_Neo { // @formatter:off - @Shadow public abstract ServerLevel shadow$serverLevel(); + @Shadow public abstract ServerLevel shadow$level(); // @formatter:on @Nullable private Object inventory$menuProvider; @@ -69,7 +69,7 @@ public abstract class ServerPlayerMixin_Inventory_Neo extends PlayerMixin_Inven ) ) private void impl$afterOpenMenu(final CallbackInfoReturnable cir) { - PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); + PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); } @Inject(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initMenu(Lnet/minecraft/world/inventory/AbstractContainerMenu;)V")) @@ -95,7 +95,7 @@ public abstract class ServerPlayerMixin_Inventory_Neo extends PlayerMixin_Inven final MenuProvider menuProvider, final int containerCounter, final net.minecraft.world.entity.player.Inventory inventory, final Player player, final Operation original, final @Cancellable CallbackInfoReturnable cir ) { - final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); + final PhaseContext context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); try (final EffectTransactor ignored = context.getTransactor().logOpenInventory((ServerPlayer) (Object) this)) { final AbstractContainerMenu menu = original.call(menuProvider, containerCounter, inventory, player); context.containerLocation().ifPresent(((ContainerBridge) menu)::bridge$setOpenLocation); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java index 089f212ea2d..a2ed8becbe0 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Neo_Tracker.java @@ -63,7 +63,7 @@ public abstract class ServerPlayerGameModeMixin_Neo_Tracker { final ItemStack itemStack, final Level level, final BlockState state, final BlockPos pos, final Player player ) { - final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); // Log the prepare drops here because Forge rewrites // this method to call mine block before calling destroy block diff --git a/settings.gradle.kts b/settings.gradle.kts index f03b0eb07b8..4a622e7c1e1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,6 +30,19 @@ plugins { dependencyResolutionManagement { repositoriesMode = RepositoriesMode.PREFER_PROJECT // needed for ForgeGradle, unfortunately + repositories { + mavenCentral() { + content { + excludeGroup("org.lwjgl") + } + } + maven("https://libraries.minecraft.net/") { + name = "mojang" + content { + includeGroup("org.lwjgl") + } + } + } repositories { maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index d28fb99ba0f..d6372f7f2b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -182,7 +182,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel if (spongeData.configAdapter() == null) { final DimensionType dimensionType = levelStem.type().value(); - final ResourceKey worldTypeKey = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getKey(dimensionType); + final ResourceKey worldTypeKey = (ResourceKey) (Object) server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE).getKey(dimensionType); spongeData.setConfigAdapter(SpongeGameConfigs.createWorld(worldTypeKey, spongeData.key())); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index 2df79d0393f..13d69e638b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -128,7 +128,7 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li @SuppressWarnings("MixinAnnotationTarget") @Inject(method = "applyItemBlocking", at = { @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V"), // Vanilla and Forge - @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V") // Neo + @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;FI)V") // Neo }) private void damage$onHurtShield(final CallbackInfoReturnable cir) { this.damage$inventoryChanged = true; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java index eac9e4edf8d..98072781d2f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileMixin.java @@ -51,6 +51,7 @@ public abstract class ProjectileMixin extends EntityMixin { // @formatter:off @Shadow public abstract @Nullable Entity shadow$getOwner(); @Shadow protected abstract ProjectileDeflection shadow$hitTargetOrDeflectSelf(HitResult result); + @Shadow protected abstract void shadow$onHit(HitResult $$0); @Shadow @Nullable protected EntityReference owner; // @formatter:on From 0f1980e7d6c754128e3ce825d9d6ac0fe40f2a65 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 30 Jun 2025 20:38:09 +0200 Subject: [PATCH 292/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 50afa665a26..1323b1b4ffe 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 50afa665a26a4092bd111aab2d3c237158777453 +Subproject commit 1323b1b4ffe1b7f7e90c8c320b7fdfc3b33cd66e From 1e71290637b1f4003f1bdc0771c0021fd93d818b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 30 Jun 2025 18:09:11 -0700 Subject: [PATCH 293/586] feat(minecraft): update to 1.21.7 No real changes other than base versions for each platform. --- forge/gradle.properties | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 131 +++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 134 insertions(+), 3 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index d66c0a46217..da4d4bdafed 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=56.0.2 +forgeVersion=57.0.0 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index 64a2906a3a4..c502cc69d44 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.6 +minecraftVersion=1.21.7 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1758726e646..424255c0178 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4102,6 +4102,14 @@ + + + + + + + + @@ -4244,6 +4252,14 @@ + + + + + + + + @@ -4378,6 +4394,14 @@ + + + + + + + + @@ -4512,6 +4536,14 @@ + + + + + + + + @@ -4815,6 +4847,14 @@ + + + + + + + + @@ -4957,6 +4997,14 @@ + + + + + + + + @@ -5099,6 +5147,14 @@ + + + + + + + + @@ -5506,6 +5562,14 @@ + + + + + + + + @@ -5564,6 +5628,11 @@ + + + + + @@ -5749,6 +5818,20 @@ + + + + + + + + + + + + + + @@ -5797,6 +5880,14 @@ + + + + + + + + @@ -5861,6 +5952,14 @@ + + + + + + + + @@ -5925,6 +6024,14 @@ + + + + + + + + @@ -5989,6 +6096,22 @@ + + + + + + + + + + + + + + + + @@ -8277,6 +8400,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 64c666155c7..ad970ef6796 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.6.5-beta +neoForgeVersion=21.7.1-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From f9d0c42ba22f837c235328533f764bd7fcf242cb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 1 Jul 2025 23:35:02 +0200 Subject: [PATCH 294/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index a490075071b..c61d8f6c71e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a490075071b22f7b6a51d92ed1dda84cae796ca5 +Subproject commit c61d8f6c71ec17098fe86e0f7f449239f052ae79 From 35c0ec8b409333fba9c1f9727e640dad39df8330 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 2 Jul 2025 11:59:50 +0200 Subject: [PATCH 295/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index dea0a26d1e4..f65e9df0172 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit dea0a26d1e45adba0a34a01df9812beaf4cfb37c +Subproject commit f65e9df0172b75f8c12f9a60204b9e18b8089ed8 From 68c1b372a12fe8362ee6068e3c03338bcebbe526 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 2 Jul 2025 13:18:09 +0200 Subject: [PATCH 296/586] Fix Forge mappings version --- forge/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index cd6e7f6bcc1..6390fb2f30f 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -226,7 +226,7 @@ AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { - mappings("official", "1.21.6") + mappings("official", minecraftVersion) accessTransformers.from(atFile) reobf = false From 5fdcf53f9a0bd24602b465221c1d0c3bb91ca254 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 2 Jul 2025 13:38:38 +0200 Subject: [PATCH 297/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 5388f17d48b..4b5dddc5e9f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 5388f17d48b7ae4cf7bd4bd8d359b82c676042b3 +Subproject commit 4b5dddc5e9f44d4191a72b49a0f4c77d50e24aa9 From 272bf8a7e52da36245279073ddb2215b9eb822c2 Mon Sep 17 00:00:00 2001 From: aromaa Date: Thu, 3 Jul 2025 23:24:53 +0300 Subject: [PATCH 298/586] Support WorldArchetype mutation in world load options --- SpongeAPI | 2 +- .../storage/PrimaryLevelDataAccessor.java | 39 +++++++++ .../resources/mixins.sponge.accessors.json | 1 + ...pongeServerWorldPropertiesLoadOptions.java | 31 ++++++- .../world/server/SpongeWorldManager.java | 85 +++++++++++++------ 5 files changed, 129 insertions(+), 29 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java diff --git a/SpongeAPI b/SpongeAPI index c61d8f6c71e..01362ce9f5f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c61d8f6c71ec17098fe86e0f7f449239f052ae79 +Subproject commit 01362ce9f5facd993f41fdb879b74d5d4c8830c9 diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java new file mode 100644 index 00000000000..a0ea05e5271 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.level.storage; + +import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PrimaryLevelData.class) +public interface PrimaryLevelDataAccessor { + + @Accessor("worldOptions") @Mutable void accessor$worldOptions(WorldOptions worldOptions); + + @Accessor("specialWorldProperty") @Mutable void accessor$specialWorldProperty(PrimaryLevelData.SpecialWorldProperty specialWorldProperty); +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index c9589f78254..842d03e32d9 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -211,6 +211,7 @@ "world.level.portal.TeleportTransitionAccessor", "world.level.saveddata.maps.MapItemSavedDataAccessor", "world.level.storage.PlayerDataStorageAccessor", + "world.level.storage.PrimaryLevelDataAccessor", "world.phys.AABBAccessor", "world.scores.PlayerTeamAccessor", "world.scores.ScoreboardAccessor", diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java index 80f51b4f370..4d3e9f8b49c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerWorldPropertiesLoadOptions.java @@ -59,7 +59,19 @@ public Optional> getCallback() { } } - public record LoadOperationImpl(@Nullable Consumer callback) implements LoadOperation { + public record LoadOperationImpl(@Nullable WorldArchetype overrideWorldArchetypeValue, + @Nullable WorldArchetype fallbackWorldArchetypeValue, + @Nullable Consumer callback) implements LoadOperation { + + @Override + public Optional overrideWorldArchetype() { + return Optional.ofNullable(this.overrideWorldArchetypeValue); + } + + @Override + public Optional fallbackWorldArchetype() { + return Optional.ofNullable(this.fallbackWorldArchetypeValue); + } @Override public Optional> loadCallback() { @@ -95,7 +107,7 @@ public GetStep get() { @Override public LoadStep load() { - this.loadOperation = new LoadOperationImpl(null); + this.loadOperation = new LoadOperationImpl(null, null, null); return this; } @@ -111,9 +123,22 @@ public GetStep getCallback(final Consumer getCallback) { return this; } + @Override + public LoadStep overrideWorldArchetype(WorldArchetype worldArchetype) { + this.loadOperation = new LoadOperationImpl(worldArchetype, null, this.loadOperation.loadCallback().orElse(null)); + return this; + } + + @Override + public LoadStep fallbackWorldArchetype(WorldArchetype worldArchetype) { + this.loadOperation = new LoadOperationImpl(null, worldArchetype, this.loadOperation.loadCallback().orElse(null)); + return this; + } + @Override public LoadStep loadCallback(final Consumer loadCallback) { - this.loadOperation = new LoadOperationImpl(loadCallback); + this.loadOperation = new LoadOperationImpl(this.loadOperation.overrideWorldArchetype().orElse(null), + this.loadOperation.fallbackWorldArchetype().orElse(null), loadCallback); return this; } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 0ed9d6ceb8f..6fdd3a2e983 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -89,6 +89,7 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.MinecraftServerAccessor; import org.spongepowered.common.accessor.server.level.ServerLevelAccessor; +import org.spongepowered.common.accessor.world.level.storage.PrimaryLevelDataAccessor; import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.level.chunk.storage.IOWorkerBridge; @@ -245,12 +246,14 @@ public Collection worldsOfType(final WorldType type) { public CompletableFuture> loadWorld(final ResourceKey key, ServerWorldProperties.LoadOptions propertiesLoadOption) { final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); - final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOption.getOperation().orElse(null); - if (getOperation != null) { - final ServerLevel world = this.worlds.get(registryKey); - if (world != null) { + final ServerLevel world = this.worlds.get(registryKey); + if (world != null) { + final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOption.getOperation().orElse(null); + if (getOperation != null) { getOperation.getCallback().ifPresent(c -> c.accept((ServerWorldProperties) world.getLevelData())); return CompletableFuture.completedFuture(Optional.of((ServerWorld) world)); + } else if (propertiesLoadOption.loadOperation().isPresent() || propertiesLoadOption.createOperation().isPresent()) { + return FutureUtil.completedWithException(new IllegalArgumentException("World is already loaded!")); } } @@ -263,7 +266,7 @@ public CompletableFuture> loadWorld(final ResourceKey key, try { final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess(key); try { - final Optional result = this.loadLevelData(storageSource, registryKey); + final Optional result = this.loadLevelData(storageSource, registryKey, loadOperation); if (result.isPresent()) { loadOperation.loadCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.get().data())); return this.loadWorld0(registryKey, result.get(), storageSource); @@ -363,20 +366,22 @@ public CompletableFuture unloadWorld(final ServerWorld world) { public CompletableFuture> loadProperties(final ResourceKey key, ServerWorldProperties.LoadOptions propertiesLoadOptions) { final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key")); - final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOptions.getOperation().orElse(null); - if (getOperation != null) { - final @Nullable ServerLevel level = this.worlds.get(registryKey); - if (level != null) { + final @Nullable ServerLevel level = this.worlds.get(registryKey); + if (level != null) { + final ServerWorldProperties.LoadOptions.@Nullable GetOperation getOperation = propertiesLoadOptions.getOperation().orElse(null); + if (getOperation != null) { final ServerWorldProperties properties = (ServerWorldProperties) level.getLevelData(); getOperation.getCallback().ifPresent(c -> c.accept(properties)); return CompletableFuture.completedFuture(Optional.of(properties)); + } else if (propertiesLoadOptions.loadOperation().isPresent() || propertiesLoadOptions.createOperation().isPresent()) { + return FutureUtil.completedWithException(new IllegalArgumentException("World is already loaded!")); } } final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOptions.loadOperation().orElse(null); if (loadOperation != null && this.worldExists(key)) { try { - final Optional result = this.loadLevelData(registryKey); + final Optional result = this.loadLevelData(registryKey, loadOperation); if (result.isPresent()) { final ServerWorldProperties properties = (ServerWorldProperties) result.get().data(); loadOperation.loadCallback().ifPresent(c -> c.accept(properties)); @@ -522,7 +527,7 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr } try { - final Optional levelData = this.loadLevelData(copyRegistryKey); + final Optional levelData = this.loadLevelData(copyRegistryKey, null); if (levelData.isPresent()) { this.saveLevelDat(levelData.get().data(), copyKey); } @@ -583,7 +588,7 @@ private CompletableFuture moveWorld0(final ResourceKey key, final Resou } try { - final Optional levelData = this.loadLevelData(movedKeyKey); + final Optional levelData = this.loadLevelData(movedKeyKey, null); if (levelData.isPresent()) { this.saveLevelDat(levelData.get().data(), movedKey); } @@ -781,24 +786,25 @@ private T initializeLevelData(final ResourceKey key, final Supplier loade return result; } - private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey) throws IOException { + private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) throws IOException { try (final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess((ResourceKey) (Object) registryKey.location())) { - return this.loadLevelData(storageSource, registryKey); + return this.loadLevelData(storageSource, registryKey, loadOperation); } } private Optional loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, - final net.minecraft.resources.ResourceKey registryKey) { + final net.minecraft.resources.ResourceKey registryKey, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { return this.initializeLevelDataOptional((ResourceKey) (Object) registryKey.location(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) - .map(t -> this.readLevelData(registryKey, t))); + .map(t -> this.readLevelData(registryKey, t, loadOperation))); } private LevelDataLoadResult loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey, final Supplier defaultSupplier) { return this.initializeLevelData((ResourceKey) (Object) registryKey.location(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) - .map(t -> this.readLevelData(registryKey, t)) + .map(t -> this.readLevelData(registryKey, t, null)) .orElseGet(defaultSupplier)); } @@ -816,19 +822,48 @@ private LevelDataLoadResult loadLevelData(final LevelStorageSource.LevelStorageA } } - private LevelDataLoadResult readLevelData(final net.minecraft.resources.ResourceKey registryKey, final Dynamic dataTag) { + private LevelDataLoadResult readLevelData(final net.minecraft.resources.ResourceKey registryKey, final Dynamic dataTag, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - final net.minecraft.core. RegistryAccess.Frozen access = this.server.registryAccess(); + final net.minecraft.core.RegistryAccess.Frozen access = this.server.registryAccess(); final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions( dataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); - return new LevelDataLoadResult((PrimaryLevelData) levelData.worldData(), - levelData.dimensions().dimensions().getOptional(Registries.levelToLevelStem(registryKey)) - .or(() -> Optional.ofNullable(((PrimaryLevelDataBridge) levelData.worldData()).bridge$spongeData().key()) - .flatMap(worldKey -> levelData.dimensions().dimensions().getOptional(Registries.levelToLevelStem( - SpongeWorldManager.createRegistryKey(worldKey))))) - .orElseThrow(() -> new IllegalStateException("The world has no valid WorldArchetype!"))); + final WorldArchetype worldArchetype = SpongeWorldManager.resolveWorldArchetype(levelData, registryKey, loadOperation); + final LevelStem levelStem = (LevelStem) (Object) worldArchetype.type(); + final PrimaryLevelData worldData = (PrimaryLevelData) levelData.worldData(); + worldArchetype.generationConfig().ifPresent(o -> + ((PrimaryLevelDataAccessor) worldData).accessor$worldOptions((WorldOptions) o)); + ((PrimaryLevelDataAccessor) worldData).accessor$specialWorldProperty(SpongeWorldManager.specialWorldProperty(levelStem)); + return new LevelDataLoadResult(worldData, levelStem); } + private static WorldArchetype resolveWorldArchetype(final LevelDataAndDimensions levelData, final net.minecraft.resources.ResourceKey registryKey, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { + if (loadOperation != null && loadOperation.overrideWorldArchetype().isPresent()) { + return loadOperation.overrideWorldArchetype().get(); + } + + // Worlds that were loaded with Sponge know the associated world archetype. + final Optional spongeWorldKeyStem = Optional.ofNullable(((PrimaryLevelDataBridge) levelData.worldData()).bridge$spongeData().key()) + .flatMap(worldKey -> levelData.dimensions().dimensions().getOptional( + Registries.levelToLevelStem(SpongeWorldManager.createRegistryKey(worldKey)))); + if (spongeWorldKeyStem.isPresent()) { + return WorldArchetype.of((WorldArchetypeType) (Object) spongeWorldKeyStem.get()); + } + + // Fallback to best guess. + // TODO: Expose API to iterate the candidates or allow to specify the lookup key? + final Optional worldKeyStem = levelData.dimensions().dimensions().getOptional(Registries.levelToLevelStem(registryKey)); + if (worldKeyStem.isPresent()) { + return WorldArchetype.of((WorldArchetypeType) (Object) worldKeyStem.get()); + } + + if (loadOperation != null && loadOperation.fallbackWorldArchetype().isPresent()) { + return loadOperation.fallbackWorldArchetype().get(); + } + + throw new IllegalStateException("The world has no valid WorldArchetype!"); + } private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, final WorldArchetype archetype) { final LevelStem levelStem = (LevelStem) (Object) archetype.type(); From ac53bdc8e879360b4eaaff2fcf2e176c73de60a2 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 6 Jul 2025 15:06:20 -0700 Subject: [PATCH 299/586] chore(release): update for 14 release Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 01362ce9f5f..c6a3881ca48 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 01362ce9f5facd993f41fdb879b74d5d4c8830c9 +Subproject commit c6a3881ca48352b504e5deda786ccb85e3ca009c diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5fdab3c7f96..27bae32ce98 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2170,6 +2170,14 @@ + + + + + + + + @@ -2186,6 +2194,11 @@ + + + + + From bca0867f2826a899df681542cf44f739712da49a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 6 Jul 2025 15:07:06 -0700 Subject: [PATCH 300/586] chore: update towards 14.1.0-SNAPSHOT Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index c6a3881ca48..4be411afdf9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c6a3881ca48352b504e5deda786ccb85e3ca009c +Subproject commit 4be411afdf9bb7d8c803bd847723572755597e48 From f1d605e4943a4157107d75c704663a47ea81461c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 12 Jul 2025 11:43:33 -0700 Subject: [PATCH 301/586] fix(explosion-event): use a mutable list to filter The API dictates the event can filter entities to be damaged by the explosion, so let's re-enable this. --- .../mixin/core/world/level/ServerExplosionMixin_Forge.java | 3 ++- .../mixin/core/world/level/ServerExplosionMixin_NeoForge.java | 3 ++- .../mixin/core/world/level/ServerExplosionMixin_Vanilla.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java index 31aa0405179..1b2f324c8f6 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java @@ -46,6 +46,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.VecHelper; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -84,7 +85,7 @@ public abstract class ServerExplosionMixin_Forge { if (ShouldFire.EXPLOSION_EVENT_DETONATE) { final var apiWorld = (ServerWorld) this.level; - final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).collect(Collectors.toCollection(ArrayList::new)); final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); final Cause cause = PhaseTracker.getInstance().currentCause(); final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java index 936c7d081d6..c1baa5318b7 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java @@ -46,6 +46,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.VecHelper; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -85,7 +86,7 @@ public abstract class ServerExplosionMixin_NeoForge { if (ShouldFire.EXPLOSION_EVENT_DETONATE) { final var apiWorld = (ServerWorld) this.level; - final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).collect(Collectors.toCollection(ArrayList::new)); final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); final Cause cause = PhaseTracker.getInstance().currentCause(); final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java index 1c16efb0182..e8ed777f954 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java @@ -46,6 +46,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.util.VecHelper; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -86,7 +87,7 @@ public abstract class ServerExplosionMixin_Vanilla { if (ShouldFire.EXPLOSION_EVENT_DETONATE) { final var apiWorld = (ServerWorld) this.level; - final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).toList(); + final var apiEntities = entities.stream().map(org.spongepowered.api.entity.Entity.class::cast).collect(Collectors.toCollection(ArrayList::new)); final var apiBlockPositions = this.impl$affectedBlocks.stream().map(bp -> ServerLocation.of(apiWorld, VecHelper.toVector3i(bp))).toList(); final Cause cause = PhaseTracker.getInstance().currentCause(); final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); From 8f139a0657386c74fe33c663b26851a4306764c6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 18 Jul 2025 23:05:19 +0200 Subject: [PATCH 302/586] Cross-platform bootstrap --- bootstrap-dev/build.gradle.kts | 3 - bootstrap-dev/src/main/java/module-info.java | 6 - ...e.bootstrap.api.BootstrapClasspathModifier | 1 - bootstrap/build.gradle.kts | 21 +++ .../bootstrap/forge/ForgeBootstrap.java | 50 ++++++ .../bootstrap/forge/ForgeLikeBootstrap.java | 76 ++++++++++ .../bootstrap/forge/VanillaBootstrap.java | 41 +++++ .../spongepowered/bootstrap/Bootstrap.java | 142 ++++++++++++++++++ .../bootstrap/dev/DevClasspath.java | 78 +++++----- .../spongepowered/bootstrap/dev/Multimap.java | 0 .../bootstrap/dev/SourceSet.java | 0 .../bootstrap/neoforge/NeoForgeBootstrap.java | 85 +++++++++++ forge/build.gradle.kts | 17 ++- gradle/libs.versions.toml | 5 +- gradle/verification-metadata.xml | 24 +++ neoforge/build.gradle.kts | 74 ++++----- .../applaunch/resources/META-INF/MANIFEST.MF | 1 + settings.gradle.kts | 2 +- .../client/multiplayer/ClientLevelMixin.java | 8 +- vanilla/build.gradle.kts | 47 +++--- .../vanilla/installer/InstallerMain.java | 23 +-- 21 files changed, 557 insertions(+), 147 deletions(-) delete mode 100644 bootstrap-dev/build.gradle.kts delete mode 100644 bootstrap-dev/src/main/java/module-info.java delete mode 100644 bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier create mode 100644 bootstrap/build.gradle.kts create mode 100644 bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeBootstrap.java create mode 100644 bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java create mode 100644 bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/VanillaBootstrap.java create mode 100644 bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java rename bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java => bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java (80%) rename {bootstrap-dev => bootstrap}/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java (100%) rename {bootstrap-dev => bootstrap}/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java (100%) create mode 100644 bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java create mode 100644 neoforge/src/applaunch/resources/META-INF/MANIFEST.MF diff --git a/bootstrap-dev/build.gradle.kts b/bootstrap-dev/build.gradle.kts deleted file mode 100644 index 408470bf53e..00000000000 --- a/bootstrap-dev/build.gradle.kts +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - api(libs.bootstrap.api) -} diff --git a/bootstrap-dev/src/main/java/module-info.java b/bootstrap-dev/src/main/java/module-info.java deleted file mode 100644 index c46b80848e7..00000000000 --- a/bootstrap-dev/src/main/java/module-info.java +++ /dev/null @@ -1,6 +0,0 @@ -module org.spongepowered.boostrap.dev { - requires net.minecraftforge.bootstrap.api; - exports org.spongepowered.bootstrap.dev; - - provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer; -} diff --git a/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier b/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier deleted file mode 100644 index 32a491ef8a6..00000000000 --- a/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts new file mode 100644 index 00000000000..beea2d28538 --- /dev/null +++ b/bootstrap/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("implementation-structure") +} + +val main by sourceSets.named("main") + +val forge by sourceSets.register("forge") { + spongeImpl.addDependencyToImplementation(main, this) +} + +val neoforge by sourceSets.register("neoforge") { + spongeImpl.addDependencyToImplementation(main, this) +} + +dependencies { + val forgeLib = forge.implementationConfigurationName + forgeLib(libs.securemodules) + + val neoforgeLib = neoforge.implementationConfigurationName + neoforgeLib(libs.securejarhandler) +} diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeBootstrap.java new file mode 100644 index 00000000000..f76438fae77 --- /dev/null +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeBootstrap.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.forge; + +import cpw.mods.jarhandling.SecureJar; + +public class ForgeBootstrap extends ForgeLikeBootstrap { + + public ForgeBootstrap(final String[] args) { + super(args); + } + + @Override + public String name() { + return "Forge"; + } + + @Override + protected boolean filterApplicationModule(final SecureJar jar) { + final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); + return data.findFile("META-INF/mods.toml").isPresent() || data.findFile("net/minecraft/client/main/Main.class").isPresent() + || data.getManifest().getMainAttributes().getValue("FMLModType") != null; + } + + public static void main(final String[] args) throws Exception { + new ForgeBootstrap(args).devBoot(true); + } +} diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java new file mode 100644 index 00000000000..df9c6d38c5d --- /dev/null +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java @@ -0,0 +1,76 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.forge; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.securemodules.SecureModuleClassLoader; +import net.minecraftforge.securemodules.SecureModuleFinder; +import org.spongepowered.bootstrap.Bootstrap; + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.net.URL; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; + +public abstract class ForgeLikeBootstrap extends Bootstrap { + private final String[] args; + + public ForgeLikeBootstrap(final String[] args) { + this.args = args; + } + + @Override + protected SecureJar createJar(final Path[] paths) { + return SecureJar.from(paths); + } + + @Override + protected String getModuleName(final SecureJar jar) { + return jar.name(); + } + + @Override + protected URL getJarURL(final SecureJar jar) throws Exception { + return jar.getRootPath().toUri().toURL(); + } + + @Override + protected ModuleFinder createModuleFinder(final Collection jars) { + return SecureModuleFinder.of(jars); + } + + @Override + protected ClassLoader createApplicationClassLoader(final Configuration config, final List parentLayers, final ClassLoader parentLoader) { + return new SecureModuleClassLoader("APP-BOOTSTRAP", null, config, parentLayers, List.of(parentLoader)); + } + + @Override + protected void runApplication(final ModuleLayer layer) throws Exception { + final Class appClass = layer.findModule("cpw.mods.modlauncher").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); + appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); + } +} diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/VanillaBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/VanillaBootstrap.java new file mode 100644 index 00000000000..b1165f2f5a2 --- /dev/null +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/VanillaBootstrap.java @@ -0,0 +1,41 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.forge; + +public class VanillaBootstrap extends ForgeLikeBootstrap { + + public VanillaBootstrap(final String[] args) { + super(args); + } + + @Override + public String name() { + return "Vanilla"; + } + + public static void main(final String[] args) throws Exception { + new VanillaBootstrap(args).devBoot(true); + } +} diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java new file mode 100644 index 00000000000..484520df1ec --- /dev/null +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -0,0 +1,142 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap; + +import org.spongepowered.bootstrap.dev.DevClasspath; + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class Bootstrap { + public static final boolean DEBUG = Boolean.getBoolean("sponge.bootstrap.debug"); + + public abstract String name(); + + protected abstract Jar createJar(Path[] paths); + + protected abstract String getModuleName(Jar jar); + + protected abstract URL getJarURL(Jar jar) throws Exception; + + protected abstract ModuleFinder createModuleFinder(Collection jars); + + /** + * When filtered, the jar content is still accessible via the application classloader but is not loaded as a module. + */ + protected boolean filterApplicationModule(final Jar jar) { + return false; + } + + protected abstract ClassLoader createApplicationClassLoader(Configuration config, List parentLayers, ClassLoader parentLoader); + + protected abstract void runApplication(ModuleLayer layer) throws Exception; + + public void devBoot(final boolean isolated) throws Exception { + this.boot(DevClasspath.resolve(), isolated); + } + + public void boot(final List classpath, final boolean isolated) throws Exception { + if (Bootstrap.DEBUG) { + System.out.println("Bootstrapping " + this.name() + " from classloader: " + getClass().getClassLoader()); + System.out.println("Isolated: " + isolated); + } + + // Collect the jars + final List filteredJars = new ArrayList<>(); + final List appJars = new ArrayList<>(); + + for (final Path[] paths : classpath) { + final Jar jar = this.createJar(paths); + final String name = this.getModuleName(jar); + + // Ignore modules already present + if (ModuleLayer.boot().findModule(name).isPresent()) { + if (Bootstrap.DEBUG) { + System.out.println("Boot: " + name + " " + Bootstrap.formatUnion(paths)); + } + continue; + } + + if (this.filterApplicationModule(jar)) { + if (Bootstrap.DEBUG) { + System.out.println("Filtered: " + name + " " + Bootstrap.formatUnion(paths)); + } + filteredJars.add(jar); + continue; + } + + if (Bootstrap.DEBUG) { + System.out.println("App: " + name + " " + Bootstrap.formatUnion(paths)); + } + appJars.add(jar); + } + + // Create the layer configuration + final ModuleFinder finder = this.createModuleFinder(appJars); + final List targets = appJars.stream().map(this::getModuleName).toList(); + final Configuration config = ModuleLayer.boot().configuration().resolveAndBind(finder, ModuleFinder.ofSystem(), targets); + final List parentLayers = List.of(ModuleLayer.boot()); + + // Isolation + final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader parentLoader = isolated ? ClassLoader.getPlatformClassLoader() : contextLoader; + + // Intermediate classloader to include resources but not modules + if (!filteredJars.isEmpty()) { + final URL[] urls = new URL[filteredJars.size()]; + for (int i = 0; i < urls.length; i++) { + urls[i] = this.getJarURL(filteredJars.get(i)); + } + parentLoader = new URLClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); + } + + // Create the application classloader + final ClassLoader loader = this.createApplicationClassLoader(config, parentLayers, parentLoader); + final ModuleLayer layer = ModuleLayer.boot().defineModules(config, moduleName -> loader); + + // Run the application + try { + Thread.currentThread().setContextClassLoader(loader); + if (Bootstrap.DEBUG) { + System.out.println("Starting application ..."); + } + this.runApplication(layer); + } finally { + Thread.currentThread().setContextClassLoader(contextLoader); + } + } + + public static String formatUnion(final Path[] paths) { + return Arrays.stream(paths).map(Path::toString).collect(Collectors.joining("&")); + } +} diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java similarity index 80% rename from bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java rename to bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 3167b04b24c..a2ad50a357b 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -24,7 +24,7 @@ */ package org.spongepowered.bootstrap.dev; -import net.minecraftforge.bootstrap.api.BootstrapClasspathModifier; +import org.spongepowered.bootstrap.Bootstrap; import java.io.File; import java.nio.file.Files; @@ -35,28 +35,22 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -public class SpongeDevClasspathFixer implements BootstrapClasspathModifier { - private static final boolean DEBUG = Boolean.getBoolean("bsl.debug"); - - @Override - public String name() { - return "sponge-dev"; - } +public class DevClasspath { /** * IntelliJ only builds source sets that are explicitly on the classpath. * So we declare everything into the initial classpath then we sort things and put them back in the right classloaders. * Since different IDEs might want to put things in different locations, we sadly have to identify the resources by their filenames. */ - @Override - public boolean process(final List classpath) { + public static List resolve() { + final String[] cp = System.getProperty("java.class.path").split(File.pathSeparator); final Path spongeRoot = Paths.get(System.getProperty("sponge.dev.root")).toAbsolutePath(); - final Set ignoredLibs = Set.of("bootstrap-dev.jar"); - final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); - final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); + final Set bootNames = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); + final Set gameShadedNames = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); // boot layer final Multimap bootUnions = new Multimap<>(); + final List bootLibs = new ArrayList<>(); // game or plugin layer final Multimap unions = new Multimap<>(); @@ -64,22 +58,25 @@ public boolean process(final List classpath) { final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false); - final boolean modified = classpath.removeIf((paths) -> { - if (paths.length != 1) { // empty or already merged by another service - return false; + for (final String str : cp) { + final Path path = Paths.get(str); + if (!Files.exists(path)) { + if (Bootstrap.DEBUG) { + System.out.println("Non-existent: " + path); + } + continue; } - final Path path = paths[0]; final SourceSet sourceSet = SourceSet.identify(path); if (sourceSet != null) { if (sourceSet.project().startsWith(spongeRoot)) { - if (DEBUG) { + if (Bootstrap.DEBUG) { System.out.println("Sponge SourceSet (" + sourceSet + "): " + path); } final String projectName = spongeRoot.relativize(sourceSet.project()).toString(); switch (projectName) { - case "bootstrap-dev": + case "bootstrap": // ignore break; case "modlauncher-transformers", "library-manager": @@ -98,7 +95,7 @@ public boolean process(final List classpath) { break; } break; - case "", "vanilla", "forge": + case "", "vanilla", "forge", "neoforge": switch (sourceSet.name()) { case "applaunchConfig": case "applaunch": @@ -117,48 +114,50 @@ public boolean process(final List classpath) { break; } } else { - if (DEBUG) { + if (Bootstrap.DEBUG) { System.out.println("External SourceSet (" + sourceSet + "): " + path); } unions.add(sourceSet.project().toString(), path); } - return true; + continue; } final String fileName = path.getFileName().toString(); - if (ignoredLibs.contains(fileName)) { - if (DEBUG) { + if (false) { + if (Bootstrap.DEBUG) { System.out.println("Ignored: " + path); } - return true; + continue; } - if (bootLibs.contains(fileName)) { - if (DEBUG) { + if (bootNames.contains(fileName)) { + if (Bootstrap.DEBUG) { System.out.println("Boot: " + path); } - return false; + bootLibs.add(path); + continue; } - if (gameShadedLibs.contains(fileName)) { - if (DEBUG) { + if (gameShadedNames.contains(fileName)) { + if (Bootstrap.DEBUG) { System.out.println("Sponge: " + path); } unions.add("sponge", path); - return true; + continue; } - if (DEBUG) { + if (Bootstrap.DEBUG) { System.out.println("Game: " + path); } libs.add(path); - return true; - }); + } - if (!modified) { - return false; + final List classpath = new ArrayList<>(); + + for (final Path lib : bootLibs) { + classpath.add(new Path[] { lib }); } for (final List sourceSets : bootUnions.values()) { @@ -170,7 +169,7 @@ public boolean process(final List classpath) { if (Files.isRegularFile(path)) { final String fileName = path.getFileName().toString(); if (fileName.startsWith("spongeapi") && fileName.endsWith(".jar")) { - if (DEBUG) { + if (Bootstrap.DEBUG) { System.out.println("Removing spongeapi jar in favor of sourceset: " + path); } return true; @@ -193,10 +192,11 @@ public boolean process(final List classpath) { resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); final String resourcesEnv = resourcesEnvBuilder.toString(); - if (DEBUG) { + if (Bootstrap.DEBUG) { System.out.println("Resources env: " + resourcesEnv); } System.setProperty("sponge.resources", resourcesEnv); - return true; + + return classpath; } } diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java similarity index 100% rename from bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java rename to bootstrap/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java similarity index 100% rename from bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java rename to bootstrap/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java new file mode 100644 index 00000000000..88b931ae17b --- /dev/null +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java @@ -0,0 +1,85 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.neoforge; + +import cpw.mods.cl.JarModuleFinder; +import cpw.mods.cl.ModuleClassLoader; +import cpw.mods.jarhandling.SecureJar; +import org.spongepowered.bootstrap.Bootstrap; + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.net.URL; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; + +public class NeoForgeBootstrap extends Bootstrap { + private final String[] args; + + public NeoForgeBootstrap(final String[] args) { + this.args = args; + } + + @Override + public String name() { + return "NeoForge"; + } + + @Override + protected SecureJar createJar(final Path[] paths) { + return SecureJar.from(paths); + } + + @Override + protected String getModuleName(final SecureJar jar) { + return jar.name(); + } + + @Override + protected URL getJarURL(final SecureJar jar) throws Exception { + return jar.getRootPath().toUri().toURL(); + } + + @Override + protected ModuleFinder createModuleFinder(final Collection jars) { + return JarModuleFinder.of(jars.toArray(SecureJar[]::new)); + } + + @Override + protected ClassLoader createApplicationClassLoader(final Configuration config, final List parentLayers, final ClassLoader parentLoader) { + return new ModuleClassLoader("APP-BOOTSTRAP", config, parentLayers, parentLoader); + } + + @Override + protected void runApplication(final ModuleLayer layer) throws Exception { + final Class appClass = layer.findModule("cpw.mods.modlauncher").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); + appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); + } + + public static void main(final String[] args) throws Exception { + new NeoForgeBootstrap(args).devBoot(true); + } +} diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 924a62d5f7b..c0212ff9802 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -25,7 +25,7 @@ plugins { } val commonProject = parent!! -val bootstrapDevProject = commonProject.project(":bootstrap-dev") +val bootstrapProject = commonProject.project(":bootstrap") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -78,6 +78,10 @@ val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(gameLibrariesConfig.get()) } +// Bootstrap source sets +val bootstrapMain = bootstrapProject.sourceSets.named("main") +val bootstrapForge = bootstrapProject.sourceSets.named("forge") + // SpongeCommon source sets val commonAccessors = commonProject.sourceSets.named("accessors") val commonLaunch = commonProject.sourceSets.named("launch") @@ -158,6 +162,10 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) spongeImpl.addDependencyToRuntimeOnly(mixins, this) spongeImpl.addDependencyToRuntimeOnly(lang, this) + + // The bootstrap + spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) + spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } configurations.configureEach { @@ -202,7 +210,6 @@ dependencies { spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) } - runtimeOnly(project(bootstrapDevProject.path)) testPluginsProject?.also { runtimeOnly(project(it.path)) } @@ -223,8 +230,8 @@ extensions.configure(UserDevExtension::class) { configureEach { ideaModule("Sponge.SpongeForge.main") - // property("forge.logging.console.level", "debug") - // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath + main("org.spongepowered.bootstrap.forge.ForgeBootstrap") args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) environment("MOD_CLASSES", "nop") @@ -240,7 +247,7 @@ extensions.configure(UserDevExtension::class) { afterEvaluate { extensions.configure(UserDevExtension::class) { - // Configure bootstrap-dev + // Configure bootstrap dev val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) runs.configureEach { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a8daadffe93..9c3e015613d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,10 +9,10 @@ log4j = "2.24.1" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" mixinextras = "0.4.1" -bootstrap = "2.1.3" modlauncher = "10.2.2" neo-modlauncher = "11.0.3" securemodules = "2.2.22" +securejarhandler = "3.0.8" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" @@ -32,11 +32,10 @@ log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4 log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } log4j-jpl = { module = "org.apache.logging.log4j:log4j-jpl", version.ref = "log4j" } log4j-slf4j2 = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" } -bootstrap-api = { module = "net.minecraftforge:bootstrap-api", version.ref = "bootstrap" } -bootstrap = { module = "net.minecraftforge:bootstrap", version.ref = "bootstrap" } modlauncher = { module = "net.minecraftforge:modlauncher", version.ref = "modlauncher" } neo-modlauncher = { module = "cpw.mods:modlauncher", version.ref = "neo-modlauncher" } securemodules = { module = "net.minecraftforge:securemodules", version.ref = "securemodules" } +securejarhandler = { module = "cpw.mods:securejarhandler", version.ref = "securejarhandler" } tinylog-api = { module = "org.tinylog:tinylog-api", version.ref = "tinylog" } tinylog-impl = { module = "org.tinylog:tinylog-impl", version.ref = "tinylog" } tinylog-slf4j = { module = "org.tinylog:slf4j-tinylog", version.ref = "tinylog" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a538e17aa88..6e1451d09fd 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -8176,6 +8176,14 @@ + + + + + + + + @@ -8224,6 +8232,14 @@ + + + + + + + + @@ -8285,6 +8301,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index f22043736af..fb6deb72cfc 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -22,6 +22,7 @@ plugins { } val commonProject = parent!! +val bootstrapProject = commonProject.project(":bootstrap") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -68,6 +69,10 @@ val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(gameLibrariesConfig.get()) } +// Bootstrap source sets +val bootstrapMain = bootstrapProject.sourceSets.named("main") +val bootstrapNeoForge = bootstrapProject.sourceSets.named("neoforge") + // SpongeCommon source sets val commonAccessors = commonProject.sourceSets.named("accessors") val commonLaunch = commonProject.sourceSets.named("launch") @@ -143,6 +148,15 @@ val main by sourceSets.named("main") { configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } + + // The rest of the project because we want everything in the initial classpath + spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) + spongeImpl.addDependencyToRuntimeOnly(mixins, this) + spongeImpl.addDependencyToRuntimeOnly(lang, this) + + // The bootstrap + spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) + spongeImpl.addDependencyToRuntimeOnly(bootstrapNeoForge.get(), this) } val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files @@ -157,11 +171,10 @@ extensions.configure(NeoForgeExtension::class) { runs { configureEach { - // jvmArgument("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + // jvmArgument("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath + mainClass = "org.spongepowered.bootstrap.neoforge.NeoForgeBootstrap" programArguments.addAll(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) - - disableIdeRun() // Source sets are broken } create("client") { @@ -173,36 +186,6 @@ extensions.configure(NeoForgeExtension::class) { programArgument("--nogui") } } - - mods { - create("applaunch") { - sourceSet(appLaunch) - sourceSet(commonAppLaunch.get()) - sourceSet(commonAppLaunchConf.get()) - } - - create("lang") { - sourceSet(lang) - } - - create("main") { - sourceSet(main) - sourceSet(mixins) - sourceSet(accessors) - sourceSet(launch) - - sourceSet(commonMain.get()) - sourceSet(commonMixins.get()) - sourceSet(commonAccessors.get()) - sourceSet(commonLaunch.get()) - } - - testPluginsProject?.also { - create("testplugins") { - sourceSet(it.sourceSets.getByName("main")) - } - } - } } bootLibrariesConfig.get().extendsFrom(configurations.getByName("modDevCompileDependencies")) @@ -230,21 +213,24 @@ dependencies { spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), bootLayerConfig.get(), serviceShadedLibrariesConfig.get()) spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) -} -// Put libs in game layer -extensions.configure(NeoForgeExtension::class) { - val gameLibs: MutableList = mutableListOf() - gameLibs.addAll(gameManagedLibrariesConfig.get()) - gameLibs.addAll(gameShadedLibrariesConfig.get()) - val resourcesEnv = gameLibs.joinToString(File.pathSeparator) - runs.configureEach { - jvmArgument("-Dsponge.resources=" + resourcesEnv) + testPluginsProject?.also { + runtimeOnly(project(it.path)) } } -// Put libs in boot layer -configurations.getByName("additionalRuntimeClasspath").extendsFrom(serviceShadedLibrariesConfig.get()) +afterEvaluate { + extensions.configure(NeoForgeExtension::class) { + // Configure bootstrap dev + val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev + val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) + runs.configureEach { + jvmArgument("-Dsponge.dev.root=" + project.rootDir) + jvmArgument("-Dsponge.dev.boot=$bootFileNames") + jvmArgument("-Dsponge.dev.gameShaded=$gameShadedFileNames") + } + } +} val neoManifest = java.manifest { attributes( diff --git a/neoforge/src/applaunch/resources/META-INF/MANIFEST.MF b/neoforge/src/applaunch/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..56abec99072 --- /dev/null +++ b/neoforge/src/applaunch/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Automatic-Module-Name: spongeneo.services diff --git a/settings.gradle.kts b/settings.gradle.kts index f03b0eb07b8..e874de1bbaf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -72,7 +72,7 @@ includeBuild("SpongeAPI") { } include("modlauncher-transformers") include("library-manager") -include("bootstrap-dev") +include("bootstrap") include("generator") // Optional projects diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java index 1803a96b6de..b1451a95f34 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java @@ -36,15 +36,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.mixin.core.world.level.LevelMixin; -import java.util.function.Supplier; - @Mixin(ClientLevel.class) public abstract class ClientLevelMixin extends LevelMixin { @Inject(method = "", at = @At("TAIL")) - private void impl$onInit(final ClientPacketListener $$0, final ClientLevel.ClientLevelData $$1, final ResourceKey $$2, final Holder $$3, - final int $$4, final int $$5, final Supplier $$6, final LevelRenderer $$7, final boolean $$8, final long $$9, final CallbackInfo ci) { - this.bridge$adjustDimensionLogic($$3.value()); + private void impl$onInit(final ClientPacketListener listener, final ClientLevel.ClientLevelData data, final ResourceKey key, final Holder holder, + final int storageRange, final int serverSimulationDistance, final LevelRenderer renderer, final boolean isDebug, final long biomeZoomSeed, final int seaLevel, final CallbackInfo ci) { + this.bridge$adjustDimensionLogic(holder.value()); } @Override diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 8eda2331494..9a2129e87f6 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } val commonProject = parent!! -val bootstrapDevProject = commonProject.project(":bootstrap-dev") +val bootstrapProject = commonProject.project(":bootstrap") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -26,7 +26,6 @@ version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVer // SpongeVanilla libraries val installerLibrariesConfig = configurations.register("installerLibraries") -val initLibrariesConfig = configurations.register("initLibraries") // JVM initial classpath val bootLibrariesConfig = configurations.register("bootLibraries") val gameLibrariesConfig = configurations.register("gameLibraries") { extendsFrom(configurations.minecraft.get()) @@ -39,7 +38,6 @@ val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") // ModLauncher layers val bootLayerConfig = configurations.register("bootLayer") { - extendsFrom(initLibrariesConfig.get()) extendsFrom(bootLibrariesConfig.get()) } val gameLayerConfig = configurations.register("gameLayer") { @@ -47,6 +45,10 @@ val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(gameLibrariesConfig.get()) } +// Bootstrap source sets +val bootstrapMain = bootstrapProject.sourceSets.named("main") +val bootstrapForge = bootstrapProject.sourceSets.named("forge") + // SpongeCommon source sets val commonAccessors = commonProject.sourceSets.named("accessors") val commonLaunch = commonProject.sourceSets.named("launch") @@ -60,6 +62,9 @@ val commonMain = commonProject.sourceSets.named("main") val installer by sourceSets.register("installer") { spongeImpl.addDependencyToImplementation(commonAppLaunchConf.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) + configurations.named(implementationConfigurationName) { extendsFrom(installerLibrariesConfig.get()) } @@ -128,6 +133,10 @@ val main by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) spongeImpl.addDependencyToRuntimeOnly(mixins, this) + + // The bootstrap + spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) + spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") @@ -147,14 +156,17 @@ configurations.configureEach { dependencies { val installer = installerLibrariesConfig.name + installer(libs.securemodules) + installer(libs.asm.commons) + installer(libs.asm.util) + installer(libs.jarjar.fs) + installer(apiLibs.gson) installer(apiLibs.checkerQual) installer(libs.joptSimple) installer(libs.tinylog.api) installer(libs.tinylog.impl) - installer(libs.asm.commons) - installer(libs.asm.tree) installer(libs.forgeAutoRenamingTool) { exclude(group = "net.sf.jopt-simple") exclude(group = "org.ow2.asm") @@ -162,17 +174,10 @@ dependencies { installer(project(libraryManagerProject.path)) - val init = initLibrariesConfig.name - init(libs.securemodules) - init(libs.asm.commons) - init(libs.asm.util) - init(libs.jarjar.fs) - val boot = bootLibrariesConfig.name boot(libs.securemodules) boot(libs.asm.commons) boot(libs.asm.util) - boot(libs.bootstrap) boot(libs.modlauncher) { exclude(group = "org.apache.logging.log4j") @@ -234,7 +239,6 @@ dependencies { spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), bootLayerConfig.get(), gameManagedLibrariesConfig.get()) - runtimeOnly(project(bootstrapDevProject.path)) testPluginsProject?.also { runtimeOnly(project(it.path)) } @@ -258,7 +262,7 @@ minecraft { args("--launchTarget", "sponge_client_it") } - // Configure bootstrap-dev + // Configure bootstrap dev val bootFileNames = spongeImpl.buildRuntimeFileNames(bootLayerConfig.get()) val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) @@ -274,10 +278,9 @@ minecraft { jvmArgs( "-Dlog4j.configurationFile=log4j2_dev.xml", "-Dmixin.dumpTargetOnFailure=true", - "-Dmixin.debug.verbose=true", + // "-Dmixin.debug.verbose=true", "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.strict=true", - "-Dmixin.debug.strict.unique=false" + "-Dmixin.debug.strict=true" ) allArgumentProviders += CommandLineArgumentProvider { @@ -292,8 +295,8 @@ minecraft { } // ModLauncher - // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath - mainClass("net.minecraftforge.bootstrap.ForgeBootstrap") + // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath + mainClass("org.spongepowered.bootstrap.forge.VanillaBootstrap") // Configure resources jvmArgs("-Dsponge.dev.root=" + project.rootDir) @@ -403,7 +406,7 @@ tasks { archiveClassifier.set("installer-shadow") mergeServiceFiles() - configurations = listOf(installerLibrariesConfig.get(), initLibrariesConfig.get()) + configurations = listOf(installerLibrariesConfig.get()) exclude("META-INF/INDEX.LIST", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", "**/module-info.class") manifest { @@ -420,6 +423,10 @@ tasks { from(commonAppLaunchConf.map { it.output }) from(installer.output) + from(bootstrapMain.map { it.output }) + from(bootstrapForge.map { it.output }) + + exclude("org/spongepowered/bootstrap/dev") } shadowJar { diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index c4d54b05bf8..d1ae9561381 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -31,6 +31,7 @@ import net.minecraftforge.fart.api.SourceFixerConfig; import net.minecraftforge.fart.api.Transformer; import net.minecraftforge.srgutils.IMappingFile; +import org.spongepowered.bootstrap.forge.VanillaBootstrap; import org.spongepowered.libs.LibraryManager; import org.spongepowered.libs.LibraryUtils; import org.spongepowered.vanilla.installer.library.TinyLogger; @@ -47,11 +48,8 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.UncheckedIOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.URI; import java.net.URL; -import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.file.AccessDeniedException; import java.nio.file.FileSystem; @@ -217,32 +215,17 @@ private ServerAndLibraries recoverFromMinecraftDownloadErr } private static void bootstrap(final Path[] bootLibs, final Path spongeBoot, final String[] args) throws Exception { - final URL[] urls = new URL[bootLibs.length]; - for (int i = 0; i < bootLibs.length; i++) { - urls[i] = bootLibs[i].toAbsolutePath().toUri().toURL(); - } - final List classpath = new ArrayList<>(); for (final Path lib : bootLibs) { classpath.add(new Path[] { lib }); } classpath.add(new Path[] { spongeBoot }); - URLClassLoader loader = new URLClassLoader(urls, ClassLoader.getPlatformClassLoader()); - ClassLoader previousLoader = Thread.currentThread().getContextClassLoader(); try { - Thread.currentThread().setContextClassLoader(loader); - final Class cl = Class.forName("net.minecraftforge.bootstrap.Bootstrap", false, loader); - final Object instance = cl.getDeclaredConstructor().newInstance(); - final Method m = cl.getDeclaredMethod("bootstrapMain", String[].class, List.class); - m.setAccessible(true); - m.invoke(instance, args, classpath); + new VanillaBootstrap(args).boot(classpath, true); } catch (final Exception ex) { - final Throwable cause = ex instanceof InvocationTargetException ? ex.getCause() : ex; - Logger.error(cause, "Failed to invoke bootstrap main due to an error"); + Logger.error(ex, "Failed to invoke bootstrap due to an error"); System.exit(1); - } finally { - Thread.currentThread().setContextClassLoader(previousLoader); } } From 272d6ddb3a7f6d9a616bdbd3532ab3ab46788a7d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 31 Jul 2025 14:08:12 +0200 Subject: [PATCH 303/586] Update to Gradle 8.14.3 and Shadow 8.3.8 --- SpongeAPI | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 150 +++++++++++++++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 12 +- gradlew.bat | 6 +- 7 files changed, 165 insertions(+), 11 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 4be411afdf9..8cb3594abc5 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 4be411afdf9bb7d8c803bd847723572755597e48 +Subproject commit 8cb3594abc5bab0ba3854b3b7a5ea3366253af8a diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c3e015613d..d6aefb1ff35 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -74,7 +74,7 @@ at = { module = "dev.architectury:at", version = "1.0.1" } [plugins] blossom = { id = "net.kyori.blossom", version = "2.1.0" } indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = "3.1.3" } -shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } +shadow = { id = "com.gradleup.shadow", version = "8.3.8" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } modDevGradle = { id = "net.neoforged.moddev", version = "2.0.78" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6e1451d09fd..a614c5b28c6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -282,6 +282,11 @@ + + + + + @@ -487,6 +492,14 @@ + + + + + + + + @@ -1316,6 +1329,19 @@ + + + + + + + + + + + + + @@ -1854,6 +1880,14 @@ + + + + + + + + @@ -5571,6 +5605,14 @@ + + + + + + + + @@ -5579,11 +5621,24 @@ + + + + + + + + + + + + + @@ -5785,6 +5840,11 @@ + + + + + @@ -6365,6 +6425,22 @@ + + + + + + + + + + + + + + + + @@ -6446,6 +6522,14 @@ + + + + + + + + @@ -6727,6 +6811,11 @@ + + + + + @@ -6803,6 +6892,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -7057,6 +7170,14 @@ + + + + + + + + @@ -7081,6 +7202,14 @@ + + + + + + + + @@ -7102,6 +7231,11 @@ + + + + + @@ -7363,6 +7497,14 @@ + + + + + + + + @@ -8993,6 +9135,14 @@ + + + + + + + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 35073 zcmXuKV_=ZQFLzI6K@ichI=8Z8x@UyRrTDzMk*@-Nmx&$7z}eRNg2`%LjH zsm3x@p*YfWOs<@Et_1QbQe5}9D(gyg^rtMJf~VPPyO5H5AxBlmJ*Cvj7wV%e-kfh& zT2}75JKKJ@$;I^pQr5Wg@nH>gmmWP)dY&)f5$AD~WZ~cuQ>?%K^?`tZNP+;*U=x5B zzDfX>R~L1df^gz^O3!~<57eol7aW%sf9oh-vBt|VOEqhTHzDqCz9RR$`r=FN{0%EB zF!0jyL!f(85W)x^4%wh-P5Y)FN2F?|(0BYG@v&vxt}2Gw?T|F1P^v>RnDl!D9Xe^N zNbA=^6yFXkN~5?V+B(uWHx5%4Je2*bpbi11=X1l9K{Rv?Qam)V;s(*XRT>knW2kdd zfs>p^F!cZm(BX^ebhc$-s%J3@>#+rR1eHLWavqmJFgzwa#)&pNxoY~`=LrgI4Bfe# z^ThVC*^6Zs&VqJo@gt#Cj{$!Aw1ra6G%<64evmq|j7sTGc*5SV6heCyuduJxg0XlD zge87Z|2rGVUg#}SFh80GP*)LC8SUdMR!S3{(rS$e^xG6s-Y%Jh#VrKgw(Z~ zI^v+pu!-0JM56TF4t<}Iq}v9#C`cOAzj{~?M>|QD)z6~`R7!|+@M|eBxuSNC96cwm z3h6y^*QK5Yz?$ucW=}C^k9lCXxeyqtIHN4hwM63Er(j+py3FhAL>BL=1Au3tk&s1m z!}(GJtl^6(W{!^GWoCL zCc`nu8X~EIs)ATLpU|wzh9`r0paG2m+`6<9dov$u)(~S}oRRWe;!ZPSc^pndBBMLL zx(qnL)=<<=abEw`S1?RlGOoYL#R!fZR`>4YU|4sz;Fnr87>_s@ zRx{j{F328%!6|x;zrvS-|EoSbvnqK9NC=2}CEhmM?oCkO^Eoz@LH}+^s+sNx54t_%Zn1-g9>4&?@jrLf> zKuc%8pmeo7%yzv@cRXX^Y>y=WeaY z)(;MUFoe44(S*1ZinhavgeFBj(7B=>(H1d$jgAvFLVmHBR!i}`@DA!hPE!4e)y%Kl z^rN{0?@1u_XEJH$HZ7KocOel%<4kyH7~Tu63_p#1J?^!X6#!@^rEQ4@o9|5`gyfKe zR6oxA)Sv8dmt;)2grB`-ay(Ue&^$Yxu$XJi9YaD61_-4X_aB9E2)n4w3&8bxR<#YG zdamrv(l|;uPo&)PA@>Eo!8OmpEQNY0?;a#JKxNY*XI(ohF50#-1$*3JX!mgk9~V_x zR(i|wGu7$ON&^WoTO=L4&F5ebqFLq2yl zm(H6=mA9Hx(2NV7hZ9%C+AkBp8RWDPGkJ@>p;bW4YIY5&O#pilOa7h!k&4_ zAn9U;zkG>i$05SFs;c$fBCf<9QNFg|gnNP2_>2t(g3VomJa!W%)i74K@jl(IW6}p5 zp%Tar`Bc{T;%U&SaWA6~8li3_=hreLfoZ{0lT*-{p$^Y2``1MI#+$7_6JJZGN78BR zF!unDky|XUhtc_9kAOqzx(e(r)QIl?6`pMcT$=8`!fOHtk`aQpzEgk;v&n&t>b8n= zMp*s^LWqsjIM@ET*tm9dnA1GJxc=yp{&tpOm1DnbORbz8oBjEl<%Lb|u3k_G6PxV% zW}=_i{D;0JwD2g-QpLH?=27Nt=9tgR-cd0VgoJbO&cf}HN1fsV=~8Nlz6zC^pR#;u zo2fbq_!VSoo1%(A?h#7ULS+T4@8y@ThW8sO*Usjx9hO%tn77fc_f%(t#2=8e5F_T7 z)#7^91=d=mlV8#5;pZ0CjDZ+JY?sXw8IhLA49Tay#-Ug?CTeNqGzPK^dles^?xq_f zf};0Q=FC%5(tgV<%R-x^a?I2ZO|_F z5k2q|JEr_da+7lxssRR{*0AoBqjIs+M<{DoOssmu(V)+mk|^0Tr`B9A7<((nAx3IM zv%e`M#;BrUrkJ8js9tRJ$df;I$9~wmv}aDf3fs75P>3cZ;YDbrLPbii*UwB3)1*EMN(*q{RYSle7gcHY;dtHAF)n zzmb1d@|~pErqsNb$GOi)?NEyzZJEbAfpV)8z*=P96XZ~}HFPG|ss_F-C}}98-LI^& zLtu%JfzpdT-4Gz~Rm18xmfUwLQ-UL0@8%i|SU=@K0OPsY-TIqkAQi5GHc$+7CkLp^0O&VXSW}Yc6?RDKJXX|}~ zVe9kxU_Z*(>isfqrT>x(4%g)wB%qNWm()5w4D9mJI zj8?IIxvBGpb7=3+jrk2iMWS-B&h-NmuJC*WmpCXos$W-X5K@nRlQDO+VO)U^JmoTH zer$7t%dWOnH5jBISULQYOz;f{$xGrO|JB@ z#qy>#?T-xCp(N7K(UMbYo;AD~jw&FHXi6nk8sV&M+461@eb($?r zwc$q;YY@YMD(`T*G9E%qlJngD zCd|!=kqvAWTL3{V?2}};2jF}r{ zq=SLqU#<;<(swQz%h=}Ru8Gcw&7^P_HjKsh6jm4ct=p-pdQgzZCJS5Xs`2rfDb@k~ z@>;^C&HeGYxhk6ufwXNl@uNZ$2UfbQVsuUKUW{Zocr7iC;kkp2k@)7$sspUJAVxRT zS+Fo677*uEj91@OTrEmQ1Jc}*JNFPi38na3b5Nq1;ZJ(wkjSXSk(%6DCu*D#?&#X@ z63+N()blX1HWUmh4~KSVrPFVO2O*2kP?q7h1ETMYNr z=XgU`%SEMY$ zpPT)1@y^Jvr&kyTMci^2nYv+fG~U?N2%Sr~Hf&AFQz%LqBc5|d*Ohf5S1rDL;d_wc zC_we#<|JxyOD`seGE8pV{sqs}mS(R-JQCh59Hf12f$x-l35&XNo09$_g5QoBj377e zmJ)3=)g%=K_=e8~+^4sf#dJmU1X~tLaMm(6PX`zuvl~V_sm`4*rG2*M$Omh}{RQto z0J7v?I73w7zN*O^pIFl?o~QMWUO{U#%YkQ!uz|{T*^*Q5JI)n^l6P!&{&2dwlruk( z?|0_8dD8kH0;TobPubg43K}gGx9RksOyd>v1+lY5PSv#jr2TA95d!xN?7*Z=cz2IY?DK(6D#l`CaTORcWRw&rNe^)b0^VX zVJV<*ob8$ke5Dg!6)I&ydy3Hr0dhot-^b3{4O5VQJcfc`aUD#$ zu}D#NNj~N7DDwAtqQ3d>u!ScYHt|0ihdSrKqsAYa&VQd$@#zq<_Q@Fi3*9(0q!n#g z3*D{k_ZDmZ1U0sT$X>V5AneoGUUt0bRq}%LzY%vCaFMwV?)q*ERJB)}Q^N9RghJF! z2vq3jY6$wtw6Q+l8ZbjW({C1p9-QFlv7uku&@8*gz#`!v-ra+mek}L4jd~@Ct0-$Z zO)qQ(_POBq%Rb7?cD##@Mi&HA}VMn&;GsW9A+F7MJCFXn+#JRa&f9ORQ4;*!ae*3qi?WfIU zIC|!25-?VdY5*2~GIaO-K1L1dP-axvVZZ(er5;A_KOnhhSE>zoW}n<8=!>TMOx(gH z5hUFniB#tU3dr_|r=u!jG@OOUAMO=>5YM0vsXOD!TI=;6j(wMU4!Wi7GE)Q2cG5}EJu&st5mD&Ff)?rj{%^$9-tM@=E0iOmFov>b-H z?PJV16OiYWRyh)&MbfNq@x6c*xgGaYd__GSbjIcSqMRG#U}vreJt#g*ZYAYJFGT(nn&}>ADjFKvb2@DV%efkM?kWwM9;FJC6mGkJb`S6%S+zkQgUB4=3R)ZUK0#718^!-jrD%Au%n}~>5!4}53#J>#A z6uufqRt2Y8UY1!7yD)*3oJotcP}jny)@p5?rXpS?R#tO3Z~;p2XdI4_DZxF?M?^TD zM0?>GBuOY5{E^f9yJ{T+NIi$NWM+YT+Mz#32xtxSqspAhW+R--u=K<%SEwcu_+SiT z#uF(K#}s95`U{2L5R&^HPnch%t28Ee;Bd%GI8>&3mKhYgJW3?EPZPx_VY6{NWzPAL zEgZqn;%v{Y90#}Wk&*X1gPQZvifA34D32|g=uYJ6K^Bw9KrmI(kIdY#A*ys0P4WjRR5wd| z;u2vae^Lxh^hfj&pe0iumU@J6 zq7>OD75dwFUt*6Ah)WGHE#V4jwsKA_vx^$2HrIxg-iD#<1q_h~Yc#H;5k~6pFl!2@ z8(&SzZ3;T0kB6|J@aArl`kf+AbkXS6-HJF|bx;Jov%4d{JK3P!hoM>^JDA~jG>O@E+#V2i`?GNma>m4mVkW%3%&2;#b?>H2w4IU& z)9b2Wiz|_Q!N^mAE-B@9y7i{Q4_<1o>r|#t6DR=oAe4srLlB1o!oGWpK5ZX)IUagh zTwHv9Km~lQV19D-d(Zd5?$^`HQwTa2LJqnY+Sew*_F!EyPN9 z9vg>U1432NSHX$nS#-b`K880paf%<&9i(5VzW-K>gy-Aep$siiEk%!+r>P}lPx&D2 zYQHwm$EV~*^q+z-ojyJ)ME9h|Wv_G2Qe{$4_vhAnKj3GCg)@+^fd(3(Gf8neCX;*X{+v4}L5Pfop zSlK*xdZw-nuE7%)X>-42+=N}wtD@#50k%9?ki*E|rcF@kE+rmap?ahDZ_E--=MSy~ zO%{Y=%A1ZdD6EYR*6}78zqoYWIIQ^@sop6*H^A<&uoEDQZoQs;Bd+B(PXuo~va2dhF(clC;@U``4;5e%r95 zhZe+8olTV8bksa8t{C#ZafHk3^!;r8HTx`hHW{*k`0Y^(>c4MY1S(Acl@Fnyprcse zkr)#|LuSuwPwF||O!hz&WyzT=irv9x*vK1ii8-HyFB%a!ZJ3x9a42&ijV*^O0o(jR z`(Bp2W+nx2#twDND(Pbu%x$;CatZ+!3TC=wip9yTzO>5Jdqu3D!rUw%jr)Ir#qxGcY6&A37s_{u_03%# z>O|Fg0u@>uv?z6i_{XjYWZx;jgzUmsy&(W88AX#Hu>8X4Sg5J4|MNk5(9Is`U%^Ur zCjXy=sYqm@XlP)(Pjl(MN++AcU{gc(e-SH`LH{1~|4TTwBSQ*48Fhz=o8p;wpO~e>E5NAPbm^oI}Yw_ zKTn}RqCtfUi!g7ZB`LaJ1;>BRw;0axAV^pkSd0th_0hx%P(!0Fj~(3S6W& zWUs=z!ztSSf}E9kbSxYpe4dEvRnnr+yLXHsej%JD?4@awcF97$2*f|SWkw>V-4+fN zF8wHXHVDMETvG8TB#~ZuYq{j@F>2lXs9qY`*z>@{K`xW%9&7&<&$VOWbLx=|v*l|O z){{9SDbby@nsZlh(tAl^E72{@Gtc6_8!$L%)B_U>YaQ|sEr}?*Rl-Bmq7Hk=D|y7~ zl>?8vGyVwotKGwQf@|j1^o7pYSWc60!pOWrm=oocjQ)?6QNg|wxboNsb#4?w2_V3M=o;r|2c;SsGHo%Ber zGwU09gZ~HC3ygMAiT{MLPBMt&lUqO4vw2udrm?v`e!RTzQ3ZI7v-%2fdn$jFXtp*| zLFyXLSK4=$=;j)_@)NZi8$IPRP&0;7d6HAN_L23iqAwb#J(Br312cRQs82bDuDm9k zuqEA%jVIH)WgF{!gSM)Ch+y&v9mZ#rp=0skNjCoE9(To~-{*O@x)rN&+SOJAPrsNB zSA@A+M+{X_0WQL3SqMk$6@R51rPJkJ-u|gVn{#C(BPlk7@ezJv)GDVr8LGYiHAMPP z+`f`exGfGKwE{g5P^FMe7~d^|q^GctS!?Csb^XqB``1}*`Y#o~MM3&t|Mb=o)8=c; zg4aO&mTOVigx8!}ww~wyBQ8KZO~t#4j9X$VlXz)~;LZ+Mg}3AwSF89TrY zqO96vSFZHahCy~Wya6<$v|HyOd2mVLw!fev;PoOlFC=}1Xi>m-PE0C zr>8hX*dZ1GfKYb~GuDxl(sg~I6I>COfJ~l#r)#wQL6X7lFY@aYdJgK3U~{wfL_?ic zx?ffYb(MN$P9e62x+gSxj{2I&ac1CyF!B`wlujlB|ODNHF5Wy=+ z@xPs|Tukt7f-q#zFo6FtLPHlB3b%hAUHNMgJ$HBXp2?a1RQ9px(|o=2);DbIEgiLHzl4gC~S)gFHpVpMDHP%h_4& zsJVL*(#weP802VI;gGw)Z2~5jEw_DdCzI>Z7mhN&C~ByiKHSh5h(R59nZwSywxLnq zSx6%B8^61Ex8*NJIJ>JpqK#9e1qbe~hxqUgiuWvRf>#tGS*)i%4lJUu^EJTW2p zV1^zS%H6Z_K^Ou^75p~ zsd0n})tb~DA%9;N?wpKC^FdJ25E~dQipc|7EWQFQ=xN%KxKVUIPCTg)>eXP>GP4Sx=U3z5x%WtU# z@(3h}x9Ub0#(W6N1^!OU^~yknf$QZCKZGasEJjDMGKSB}pFjJW&dEBFj#Uu^5RGEg z>qGapV0a1|>P$Z)_Mi)ToWUDJCy4nT?KgYi3|j0zk22h<5*YraQF-HJyj~l2=V?NpqHIjI8O%eNDd_QFe+jrX6D#dr+%7v&ph+JTF)) za?w0kOcw`>j_IjswyL#iGq|22w$-PXDf8;()3&)$Ei|cRe5N^^A?~myJ1zdC768@r zO>;Dgax~?Wwgf3s6l!{qY;^PFgeDBY_x<@Cmoj;C0hT?MWU@LSdPeVf`p;1YbEd^^ zzvPugX`j+%2|YKLDf%a`+uF+SYclL{`zA1&2Lg63N_H^Fs4&})E*%q@M?ZKSLRca) z$VnqA%kS5tjO7CQrD~T#%*)}iL+;%0J@62o2RQw5&0!1^e*@GcFIML37$PQek*iln zMvxnrf!tD`d2379<0^nV-QkE=18DPx3sD4E(P>hsz8nAJ908R5?m2cB7&XYO;l_H-dSh@%&b#ZWehjt7OWdaM=!-6%;B`G} zyg4f5=YLZ*mu&jA_Fq>sh5yeZ8=zr=zw@Gl(>bVsYqNOX5NkTn=?zjzcqL&Y;|jdz zW|Wh1ZAPtT&k$V!9T3ee8uowalj)fBx&l(W!tb|ugiPw@^~OJraxMkWFW30G-|zRP zAc~Axe|Wt;Ioy;xDJ(p+6owu3=?D-Y+5W6G`&DMStkGe0mihLTtM%07r6s@3**?tH z$D#EY2s*kgJGs$nQ47aeP+3RgadCB3UA?0>&N5>YFyxeXY2mZ+jWlRgXQrPd?4ynM z$l+sLAO*U(Sg_(QJ^MeMK>&g?YsX>-9RZY<@GA-=%1&w<`v?>47#?av2QOv%^kpg8 zdA=BL$U`0rejLVS8YH!8YX|96xp6zc^fC5;Ep&0L*(IY+r0P&9{C#rkY8zP%Iyy!G zdY<)zlxFQPk6zYwOy)40bHA$YAe5W1?0iPPP?v$-Xb`E~zdJ=(`Uw^0rbQU!I2uNZYYZ^*rcyF@T zLY}K6)t+oEV42Wuln3vY95vb9gQQG~KTmXN@QWrRA|A~vB1(g+(K*sxD6_IqVVzW+ zmNAiFoHCNiQe@m{nEQwL%H6&>VC7n?NJa7DBiqpj@D-3uIb^r}%*G$VS_g_tg!mR1 z!IZPo#7*|d?F~bSVvp8;6Z_xrJY= z-N8`ecJ*Q4&LJ~77e=<)wFP;g)(Qp0coI6@Ns@00(NDahGP?{C^8x#B7U%K>yThLD zkw`dr$5e_1bmkIh7wgWj*RPnm{xE>tDwG{g^(xXB?x9`CTl~W(7}Cj}a+&jXmAU+) z6yyBk2zK`@8(Bp~T4Pv|*t>ETp$7=J-(2k~iMKHrN}=?AQ*1n97W{nxF(qD0vUS$V zG2;Vc6*D3P`i^46>N%21!WJXoQ6w50QybvUy7RbhDiE{pqu9^7tSGg@m3(2^yXRGE zR^$1v-v8r(c89_(Kfr%^bb(3}GJQg5AB$zBjUNrC3!-21Opw)+RK(GGqCz8sww>G4 zifp;0SL6{%AB268P)VtuAOw=Q89Z-U#~RxH~5K3i)-aUAW$VRjo=150l0mA;BUr@;gx)5Gjv`8MEGTEn~opA*<&cmiV{ z)RR-;pROqw`%Vql3&X`DlWQmKM>_MD5}_~-~VgYs#dWo zs{epS1z7kWetMxs1^*EI3Kq&I1G=l~y3R>peQPV5AluFAmOShy? zi|}JHPY2%Ar7YD6;dppt#TyTQmH>rbS9f}tneDe;^8vB_%sYuT60;W`lh2bL51H?m z_hUc^`rjkW>#J?*z}*I~E2#oP%N2yS$xKW$X~D?W*t&)kGeY4OtlDiEV0`V6I>T|q zb^;#xsP@H;Rs>Hm@gl}%wK$KYkF~Xc7Poj;-3MbAU$`lxTHMm1HQg+;OlZ6^9!48u zL7ra7Qm1&e!CAQbQ7OWplC?P$ZaAGXJ-{Xn`CaKof&PtpL8R!%L%Z3Hqtiw^gV$u= zo&=+U6qGsW9rc;_(KH(b{FpiqBb|mF#4U^T5GQiYqU!fCDQZ1moNX;hUQx_NUEVZ- zrA3w~SWN8NG^3sv->lAy)B>oZ9wI zyT>LJ;ebCIk|#Yfy%K|m4zk9r>6#4o*4{kyw_34iURw)%5l*Y|CZC(G$FKaQd9iF> z`eOy&WHNj!AlBMZ;I>`6L5wN-%~KvST!hs9>YmWu?F^?=Y)^(jRnfWBigl5_!%?uY zEACyMyD_+ay@Ad8(OT{Ao6vC!BXhI|Tbk2^lSP=p$LgEs{?A1}gc!X?^E};{S*e`Y zoS7Eg0qi%W9i|1pGE=voo%#7{j(?&=efo%yq#gRJ)p^IV{FVea_yR-;yG zLsEta%}NqlSVk0evAK7!|KkKp9L!~3{_S&Q{mJE+;Zp zyk1;CA&hYFA-k)pyHTop#mZ<_lv{|)oLdOXeq>maA!V&mk4g5okcrM>f-z6XI7m3| z%@6zDYuSO>O?}#U<}Tk(M#)yz@JlvOE8P2l?|ZWV*f%i=D8`YZRSX_`Rf(hhA5$j2 zEw}!bfEX*H54|8XE8vuD@iCZ_+$p}DT_KAAH?omoSlfD+MYVQhA*pgV4resUVCoEH zS~&cwYHcpVC?slhuQzFKM^4vGepC<%5d|3)whBDml`=ARJ*x<&Xjp}x{&sAB!7KiogvvxpmI_~(lO61%$k&zi_ZR*h*)t=DeoYT5eJ(Jzb8 zcvQZ$$kY2L3qCN)41L!On*5VNuJypEgAAQ%5x5P@mkqYgS)f=mFpLYbd*;cx&nQ@2 zzv3I)h+%~v&c}Z(Yyy}S9QLn;LH!?-r59EJD*kU>k}Pzfjuw945_K^(Xrs!A9EGFH zNKTF!50Bk1Q^Bzrs=hvBWu*)7O!9%4EkhbnP5D8+M-RhcwMz~j;dhju9%5ro?V$T`*337})_~U1zQz#2@7X61j(?$Weh! zuzCmc@O9jBp5I36BpqE{_3eJR>do;kp&}L%#G`t(T*%DU&WlN$F6WZ5w%)pUmOnSF zAilCA3QPpCsPS1FLw6=d0(43v@|Ul=@=9t{#8q@z)60*8ceEuA3&$%HI`as8r%KM% z+9zXob9G^q6k8o-=yvyEYKAljP*pvK}! zTAn8QA*c%e2iphLl@EKt!lKr|cpT~NHm4f0YR#{tbr}6$$QAxA@9YM&Gz^{JbJy3G zr`7U&zajC3!eRXGybbk4Ew=XM3r4E7ySuvk#P}nzVfPpALH$tF)Kn(8%USdjq@R0t z>~z74Qie2mGGsoV|1+FC3egFX{6I?d`X?VZ@ryn2kYZSD63ngr_Zc z0`B)AMqXeb^+h+Z>u3vu6X)9P>CuuFVpND>=Cv&Q{~G|Co?pr&)SLNfa`yl?jd!R z^bi%Vl%_3G!zjw>Dk_;TLJwWSd~$zry(*Lry;5i%SZUHmEzWxNj-H;~W-Z@Rqy6-< zPDttX&@+TTdHE_1Cj#mhzdr3<3AGvd26g)Z4+!2wHnEPd{l`{q0^LSq_nW9j*AgFJ zMN+C^*Sc_=UiZ~!c4~1tfd)VdD9K1>yMK4E_dSq=z|hgYkC%jxKGyH16&u4tU1 zyxna&%Yd$RksIddZrnK(B6kh~sxqSP^56H~xenjMP~9{CR7AFS1;!avDSp`YPe_fF z?_dRUZX3`q@~Vk-8CbpHsItXN3J(oYvl94OPT?I|^V06Bu2|l@-YBuv(OmTRHjCK{ z_9R13tYv>sgh_G-COLtmZs;zB8EEFUL8gvqXSKww{MQ5evUdxe(@xpO-arJdcGhJD zl@6?fpjgB*@{?Zp6cmC1mMpiHVdk_<=U^8*0jv@$|R^m5_??R=Z;JZ$_asm)Fq}(@ML%}{^?i}AQ6F%>TSX3+J?njX5|0iZy2*E#Y6x6e z@}B`NEE$wQ+KkP<6McG%L)w!gYV)~vZjUHLF7?+Y>5 zy5QqKUlGSH;70q;SM2}iD;}k!fnmC`@S5oT_;^ZlBD!CCT+jna4FUqc82`Q6CYTk) zmjZhy21Sz*@4`Jr$EGM-5ahTG#<{HT>^2PGj)*4KKd$;z)=$a!zkj@-2nkx?Zl0er z3~X7QtuJHzl);~gMyb?f%e0$pXtCt|Nq$xUJy2K!?EyoNlrfFj+kk!MAlZ4B= zmXfivbqqE_9<2kXf_||u^q{$$@usBwFppS{-EYl|ueG)uY9h!!HAtE~+ZgFcMQ^gi zTX!{sP)D}U@XZ*q+Zh;j0dgSAUsRn%(5tIZO<^&L?yaK>T&8K*Wgki4+6>CA-3{XE z+|}t>CFiQ3R+cIKriK4)Adc49SRz3tDyiccweIdgkVczVWY6k$lH1zd_JKlrNO@XA zZg3DP8)1@fiKJG zK`B(md(`QRJ+bpWKWFa{-=SegP`Ei^h%K4Vd0$-bad!Za4hoF#?U zL!c65i*TT$x4_M%#-K2d?(nN1>NqC%K6lV4I!R) z1YwiehPo7s3$F=ylCLA8X+qQjka?sdlMxk}*+p6U`u9kAEEofn7(x{18vMkE2!C9I zlM%sVe(W5aVG(AdqlbyC`ORe5x?+70F4?VjbZ5hLIaJCuvkTlH5}h(C4?^Oz!=Fn@ zw>nl+X*hw5(ampTSudw-&29o{;rEFv>yuS$?RY_+mfZr$Gj*-1M#wHz#z`bSSAOKd z`MZo@mlf&g0wT+8U;MN{2L|-wJbiT{b^QO5zuk26=rA5!Esd<|XsHPSy&!A@XeXM! zL~U833Q~iGU69Gi{_Kr*hrKp0Li}~_fae!lz}xK-e~He>It*v6b`Fl|8&ajcfL;L7fF@sG zAs9`O9f;};_@*q^J71iLm1KZk%KRcluIzDAbkOGz_FxjWSc$J-kWjc}8mG0Ap|4y) zLTs@6ck`(KrH!47S{o~j`%lfUa6V*;?1JDYG}q(#T9t)c%p+fF`%nCgz1J2cfqtiv z*86OB9`2FmIB_o-&z0bJH55K9n{t+w*@GmLUqX76OVU!z^Ne=xm+`rAv``4y3&mdl zQqWaff8^f1^up)^nvMkCjd=4y5gPP60Wdzsxb{Y`gMxLWh#q^|7!nvt$@S~q_D>Za zACG2}bT@mO!PS1$@i z`*d04z_? z78{;kvRG+wPU}&x2_qI7QdrXAZrAeoVd<=8iAFBq!k4Gtt^6gnJ>wZyk7Evi(wLmqWQo-%x zbpy^;A1c6M*xgE*0S0j_NmAX`DzH~wUVDyVMXp%It$vO|vccI~W_an&LuKcknhR-_ za(_cb5LhHCmMq3DUro%2H@V0yUHD;I+z)^MBdg=K{_h|3Q2{;jH&R{g+=P9e-D<0# z>52Fv^45?oB}h!x`X@e1WtKcqjF0aYD6hZrF+Ri;12`}~fb++%;v`lUb)`%$p;0kV!t^Q_J4E4^3HHC1VgPKV?X{_oc(c_ z3zktO2g;J2gIlPBlT}-ybMqY#IgmY!+5Dh!74k?hPBMFWLCBo$^2Tg^xKb6j)G708 zfCN6<;Co!X*4N_|)yARkA6A@0DHU}b1$xxw6)}G|_#(SRil#F7oXVFLN z9f?HUA=T%&_&aN#Pok#k;Y-6yCC$2;*uSr9Q&*O)ljQe|#FQwnM=?FmL(UV9PL`rb zG1X=tZGy}_2@Njc&EZBQDWI8Zz(6$yU@2p;hX>5m9}Z!|_m9WFW83eN+hp3h@5JNV z`5$qONFQH6sVG@?sHWs4NaYzn)nMbE1ohw0E~d6;D4Rc{{|H`^{!sb*De^1)3s=6m zBCI0X0w%&YN0-;`lpe0s_Q#nUOf!;F!*0Iq8=&r$K=RaB9lfqyY%&ih-;%hx8d!2u2U!Vzbg$yF=tkAGGl zFU-Rl!6HS?Rt{2z&?k3rn=Hi+k|0KRb7{fyr`__wr|dEzaw@c*vEm=X6q~+63illq zMZe`wz2E!LA8F-fCNB&k*WLe7g`L7ZVG9HZ2wIH);>j^D95B8H4-f?)9o!FH_(v3_ zsE}NMV{T*ZeD;0xuLBCpjp!TBAao4n2Lv$by2&bfH<*ddb#mSHven~o?QzQRONFWQ z_Qr{I{e#4%jIB^$rQ@lFqTxd2bex_dr2_!qZ-sdq`6H3#+T3suv_NHxR_tHl_)vf| zS4PAGVj}A!JUDi+16F9C#qnq?_@DTc9cm*n; z*9%@1EpokzV0@q;wwpkNB5FZJQPis_zP(<>*Y$-8O7H)h*-f&^rqti9z;ySGH||=0_xhSXEp|vx$7{khvHqI+nwXIqN+dNiVWdMTBd%jT zqbGGOt7CIe%Z6fudhAd(m&(?J`?X|Nudf*z2&J^4P(sk?Yie2@TXPv;GwX`@{kdck z3)w*}v>LB^dLWV3^-Ll?fYrl#CX2JMzOLbthIOI1ez@k13Ne$~W8^Y_F@19)sWUA% zG6RhR87-dF8;@kPp&>ofxW#(iW50E2iL^{kruo-thqcC}mL6!_(RZC5Gi7o!IaAnY zS{U3HncVL&1rr-;uVR`vx!RW0vRRo_Cf|T=?#vh_h=9d*!=_OathH%m^;j;GFozqb z!))-9m*%KcL35dwo*hR@ELSvS<~ z^-?{BRH~x}*vjT4VKfSwjXO1S5JtS1$pMDoKfzKViZV@w2WxBS5|vidrA(DG_ho7V zOQvCadwpmlj7oiH~}6K}#Rz0^Xj zDm7D^t=64dMo*i6Ug{78nrX95v|CH*UfOD}!CvnD4cBRzn3AY}j{t7l}2!l*%;-aeJ~(tcQ9OD2tfBfaTEY2!$G$B=M%cn!lt zuAze-z+8*B0fqWtH=B4U2U?*)BL)A9Lu3U&_dR@SWD*g+6IMgzzK0Z8_OgL`l&4E3~!(}3O;Wv#<6vJOD3ZYBL@Ek+SRgx7p4^@ z+ARihq?Bb4yoqjB>CJS@OkG+|5TBw^ncf2BO;Xr@s$~Zuu1vQftJ_x1whr5@!ciin zkX_mkj(aP;O*qNF&LD(snf?s|SPFqlEecNMw#`T;?PLxjchWmlx`Y0m$sa5aWBcs8 zRJxtsEoxC@2G<3U_o#F$y_c!!wSr-JtKM&9>~QYM^%eGIx|?ZB@GMSiV{e!aF+;fp ze(q6!>3#Gc#iVH2uG7>rTAxU6|H-5z#G7ekgj7=%)LB@EdOk?^R?r9NLq#ej`!d~+ zY=-utTR&=A;f>H8p^sG1hv}oJ6KQL?w4M~a$4eil2L#+FnCf3sU-qNN)J$;xApA9@ z4fpAI&zL(39$q#XgPl*&!zw*QpJtLmA%#wVGKF6AxR!nhSja~*jfwy`SDini(ilAo zt%O4Ru4z6{r_g8clG02R*Q}Qw7u?j*DU^n6t}k0~@9JP@*=+q;dQw1t4w=_Tmq@$! z9817!ifR*_qF)^Q1v)KM_7u~ae;!|^FCv>2*cE=!l7WO52hV|*QZBwsez`Uge4=;oAI=%FDdQRx-8^V`6XH)051jv7(Nj1_fg*498 zTF!I+S#G~W&kJt9ivnSBE10!-eF52PIqHHa=WwU?L{`LK+)F>OOWY5UstXvQ0|Md4 z#s1LZr=^J5k;#aF`>9Gl6Q#2vW~5DjG@{w<`mmRNE*h#k=zo~bn=VRgE|H9j`uj^1 z9|XX!RC-agCT`Jxr%^*gWyPO`3?%(6{Z5ehU*r$dus6N*2hqs9NPmQ}&?6u%7S-#e zKhsBqW?r(i4mA!XbrZeAUv2aL4V)w~TbP4Z{(vE0p}z|&{R1)@>29OY7kKG^jL`5y z5Q64gbc*KaNXNY_iJsyic9gcHR_T=4Rp?wMnyTpqVRC1Kmt|H|cC$w)6pFt5T)bmO zHkfQL*o&&bbC_OtZa6Z}Lqdp5E69ZcdnYgO@O-W;HqNC0GFPcwEpjzCD}3H8IZ?z4 zV}Ph*3=pI+h6cw_ZhBi;NYk@_mi>}k&Py4i#T|^%qN;`1#!TVNCT`HZyao=2g-d4S-HFn)hA$Hkm>VvfQaaHP3}{I!;5&|g#`J=<)-f%% zSq-2N22#1CnShH2?AD_};jqfHjp+vJwUgUwT z=zAlEaVR$=GX{}G?H!w2dLz3JZrRn+9_cvP+tab@;MN^o9bRrhYsZ_ob)s=@5RG$# z)i`szJ!2N^GYr=}rxXBxrElgfA~v>y?DR7g-Ub_kte!sX<%kW4*=0fD{3#<1?_gRM zEFHsU89n$)3>dtNDOg4^lMW_GY(*F)k?450eFb1g|J0zraN3!*)BMoOSMeT|d--ZK zgJsT(7y|?1fW4yV?6vvZukt=VAZFg9h(NgDL6Pp78Iwy*84`tmYmbhjnEgcq#eML4 zk!Dtw)yMSgWS^<49Ai{IHypn|f$Cb4kER{fX2Ik#nw^k%kP{xDW0F~12B{r`Sklnq zGAGMBV>zlaqa&G%8U2WnIkY>G(hZSLxYNr+e7%PaMuT}Ccs&d$W?H2#IE$?1dVV%J zr*euhF|7%fliId_(S|a(owo9h3Uv7V`DKth(^(TEsm!l0onR&$PBRBZK~D8qj`qfx zE;Y@;tP|g)@{Npf>cCkUK8rERZkF&;IO!&p-@rGc1&Jp_YuT5xo5i`)Zi4t2zeSkk zRv4*K;oFf8Fu9tYc1Pvqx7p7@4>qCY*ri4+Yh`+5Zu=) zYSsPxVL@|$q*(3H-48alCI&jwrfww&%s%e8#ev8a7P*h}0|E!rjyu?Ck%7G)RQY54 zkm#PC6u%x8EfjLW{Hf+^)v~BrCq+ItI1gLw+_hs{N84_N$EHDA_f-6-4LJ_T8xlh{ z_G9+i4MnPed8ce00RxTt8)XMIa&4#uWzNqrk{3Y8f ztScPUkCKtKaIeG9@K;ol`KvH$Lo#+q;jh7(sY7v$@m_w;&ij}@DiY}OGw39Y4BC%x z+3Og8I?kV@xGR@7kte6L5#Pa#)Mn(8ajP|mWpsF4V92^_3&e}m0{uoNAk-cZ1_&sO zabq61Zt2S!$(*U%mVLpxROIig{JiKpl(d#ML{_#M>}_8D5&u}!=AXDo{F&Ff$wBaP#lCy%!jJZNKGs6)`Dbmesq{Tky{(=9f^6&XiOdI|mekwDjlLgkDLR-?v z>Q{>Ey5#U=cEIV@h8W$fcJ;6PHZZ`w7vG*6ljw~`hVXUxJ^ z2P-%ts8Ud)ADsO>DJaznbPOv?VX=lnOPthl>DVCJa=XJ9_EMyJVIg1^GSP~E*J#ZP zxk+k}8igJ(<@n0ngv-(z1*4wzJ)%oD2MtKNsSM?PGbm3zE2H;|JJCj)0uH@QYEr2} zT3d2sQ3@qX>yacA>BGh$B%t+WM$Fl-mP>{*X@hjRDupEsNv@cPMXz*)2#6|a6H~`z z>P(6+XS#JqZmTs=RC8ck%dS9wB3)dbS~>$OS7cW>VRft zuz+b;#UKpon6})a;EUfFu_^+IY#?WUTv4PearC5?Fscqh7Z}L{_9Y~LgzsTmb@ppT zgoAOUm;(_+y(lr#RZR7T>Kd3F^6UyF)H*rvS|bt;!g#f@4Y>|Wam^vc-a#f*eCO7oToXgT?htcP`bZXLbu7=pu5FY?W8U z94Yw6l1}7#3BM|cl!cY9Jk85fb)FXI>7r;PPb({H^VE1;exYuRE_;MFFhxeFa?dz5 zN4x6sv}u&u>m#e`itk(SZ(C)gvO7<^MyWSXSKEIh?N~B+d00)kUL@ z%2v6>aDdx|SLtQ-+5(aK=}R=)luy=jb&jnl2suydSlkA_ar z+w=6!QMzlCj*rv(qG4Ca?;NG~KSK90h24JlBlIz*<9yoh62Cvm^aMzUM${o;Xf^pvh3q=l$}*JUyMKuZCSCXCA=**R1^pu|K~# zPv2}3fYku~whdbCa$alw`h1?gCyH8K^Kp;6MLH)9O5^U$g^rO3J5rBVU0lP=2 zVw`>!9i{(16#^O{!wRJKD|!0GajFuu#P1?+^FsyNVUK`+@>oze`(5MoV$|#DIse!^Kuv^v_R1F@sd1Wv}feZbAC${zwD@1gfz1A z+JdRA?N9ri(U3TDWo1n0iRbP)!F6Jx;W+j9;egFyS7i+A(XiX%VYTxn;S=`DrOpr0 zdBW}R=E(C}FoUQWA$^?JM}53ulrKMJ|J*2kKFn=@dwkq6#+^9pG*yexf=Djl_}!47 zLO$L;#@(~*&a+lrpdvyu6cw*^KHfRXJ!2e&3}V6WDp}!u(Qe3Cc|D@3C>?$@jPf;k z){Z-#8s}IvT0hRqqN5xi<$)7?sB4^401wrl;4CaL#zzj0@(ttshG-WeZ=7!gNmtz{ zzd1C2%C`VM+I@m=6ZB~l820g7^ZfQ`lYEbG?74n-wXJhuJ0IUs+*2WwJVJB)Zb!9j zStb+(nK6E6p6?1PK7Q{QzdsuG`0?`tdA={t9~tM5!H=9xN}fMit$?Rb&0n79Ph0LK zKWMvISQhqEPVguQLA6#MQ2nlduxA8rf|WI-xU#3szqWe>;0a(DTJOZB~6i2Ttd)hMT_R4dE`*OI-!_ZH*C(*C9qrEZH}9s^Az@FNgU7e6loA-{=c59D zxBj4yzb8VEe^A8x;VJIsFv9GoRs6G*kAHqlTkGPm?3bUS-oola*Sqeat>gTQs1;u? z)`Npz<@tA(BmFtr{S+-lq=UvQ_`86fJ~k%t2&vosa`y-?M2hN$ea}3!eS|%J`80i} zE-yLZKG1^X0fu$_D^FnDw?(b5UQJ3>ES`u~C_l!wP^HN|`S~e!F#L1u@%1f)U zTM>;oe9|R7KIu}dufvLrl~p~Aw~c%9Qp=}=-mK;Ajyiy~ts0ZI2$juXp1V(f6?F{b z_@qwDI6u!z5uem8tn4XK`KnM+TN7x0^`KAMX{SY>v}+P}0>Cp1z;*%QlXkBfmG+#P z!f`z~juttdCdt0yx`hnPYfe!WI)=H5SGtxK({c(*ea;7+C*^0QxO2>T+Il|Y{H}Pq ztK5s-M~U34+^enUT6frbZgg*dww{~ao$f(ABkmp6bGQ2%>)GcXw4QHvACp`0Jm$XB zf`6y`F7cFGFQ|_^zz4CzdyiUGJJkiJWI(bk`_9a z(0PskEpn_NzoVAUcQnyrM;l$>*hxzqgS6CZA>>9dx-XMa{0mw9z$8SGe9wn_Lf4i@S;Gfd{H}O(sc zKrycgSqW!_6&EPWa&fCW$&p$cj~v_-Go8k@t6OP*Qwc94tvyya8J7_iSkRWok$f46`*Ts1hik&{O=T)GTNle}?3pp6i5yc>)u{ zrnAa_;Dbz`*5vHQtfxAT!Lb_VqefursK^e7bMCaH6$zPf1+^OLSiM5x+Ks3=-h%XU z66Qk#3u~lEa|~i30bk9b3lH6!QAHvaVKHkvj+}3>H>zk7P#rtHO2-MTpbkp}=H@-Y zF{CrInzJq(Is6Ei$m@>o^(9c=i;3GS^D56dlXcL#GK$B4?L(C+tYlF;^K* zuZ|UI?@kw}JbX$h_yk=@BN#Ljl#vT5C&M*I%%K10#Su2o%g`1E8j4*jKB?ghoGEbZ zQEpOj7FnBKc!nLN0G!PU*^X6XV4`D7!ZD)?R#W86INj^=gJ!QHD;=`cG@@j|8mujU zLI=*JJKkehk!0LFi{fB}DP>CYCCqsUu(tCFDe?$Zu%42xj|U=z2<7=wi4OTw=+bZj zE~H}&5db^nMR)obgOogUj4cr(ksuXgl2#6q2_|~@c7^i?E#GBUV39GosMgVIEN*J< zNJe#RWREt0ZmHH|Gbo!*uvcJq-gM1>LJWHmgUyH6M_!nlNp?a|QWCQ#NFMQDW8lf;sm1?$FR!6o=K>$^02 z8dA#gc-)ZU6?{g+<%|PvBNQ5U92pSeTlG17p4VMLIWX211y|B}SdK|yv?+;yD#lpb zni(fMuELj!@kLxs4jnqL;2KH_s;}+lW=F?Yu&fx@;yMDym>l>j=JLP|6vv1i4x6NC zdcHfKB0%?BN$ zjrZYx-uUBm(MaRxj3>Fn7BzOyNMv8`tY?PdsB2gh!K{5@(_8O)p}a8 zr^k$&q1C1#>(#?_PT9HESYI*&C)w#ovb8Q_aLy71kL5WiSxA1O;c+}6P`Gx@O5YL{ zPYTqIF3gc}*i!VghDWi7ap>T-v`LxypK92JpV1W|DWNv%{B%6WA=`zYliFa!PSD6N zxEa`mUy_S0b}|yGirG$oRS$zq72S#6DgqtK*%v73^JHo^F%@^5EXx-lFpeGx5+Vw!0ni$YBb1yq_^<4Mm6f4Y=ukX z6DKyQ{;Pm%ZO6fCl`}^>-^JgH@Hf0Swl+$+3jRq3Id+@fPt}6n0HX%w%E)Wb2l$tU z_wjFXuiuJ=?EZv`|4^i;A$ANaMqoWX*SD5lBi>H5cAM^eL6t!+EmN|1( z(8FNb=q?HrwRH2Y#TrQ269ka+@d2L0JYY&`u$+}#9;ioa)kV3e(8Lrm zm8uDumUGSM66bWYx%W>OUQx-LrjIFPBs6L`4m&?n6SHK0KRrJ&Kc))$^7P1Afu(uU zXx(9Reym{9TrK93Y%z}&EE$t0l;3o%6>%&9c;irPMAS;~YcauqK$lG{WVIyNG26|4+3SkM zvb_-0YFCbbYG0jeRI(4lg*B3(nK?tzL{C{Fhf%=4x1!2QkUdrO zoU=kzR4?RQgDU)49Wr1v(MT`I934x?KtayLvYgJa_3WI9Qwg?4ceG~XV}^3pP#0g& zLN9A-<{3`glhJN7zJ?=2xKv0@A4L|0lS}wL1`ySMGnC$9lF~~|QhK=oaMAiQOraO| z3gT*MzlZ3o+Q9nt-hv&dsM~>Q^*d1M+kqM0!X213ggN(t|4LAex#@j{+es%$cVAaK zg86~A+CfZ9VZjLM0<~R3sF&=*6pk-#rhh4%IE1Bxs7&G1t!S!Cp=B!?Xio+GDg!C3 z97bDz;H*KM6KLNJ&wzVk-Tmk!A?s2wQV4a{1_JA8HLaM|K8P9q0@~&;9K@`E-&3DL zZ|5MQe#PCadYX%TQo35MZiQCw^A@CVk+(1fXB&!#aj{<=Kr8c?1^nuhr0c*tUUdYQ z2mIO)KKpQUvAbC>*UO9Vz-+Htt}hPwCrG1zi@lnczP`|Tg)RmTyz15bs#kpgUlvGz zTraQ{$MM(K1RkM~_%*Ws8ypa?)>XQ72;0fcbSzT1Z5VfU4jg!z?DGs_AccE;US$~f zvSEYd#sFULEHCohj_16}lh{))R|Wiv6sK^2QyAjtK9H5T)31(5tzOlu`7%f0ORrpi zn6r}3fdVpuU4iwy(b*l4^9ccQqZiH7r8DBG#A|>{N?Jlk2|v|K))GM z*gZLkAT*v1_zU=eOaDBKzub?1r0`*X=|?FJwr2n@NS6zJWx_>%iS`ju5b*58`+0_LrGuhfloIplEMI9Kz-0PWvY=ys=%d0n zEb3FDk%B;+>SOBLjXB7y+ZC(6D1%EU>Tv!!_~rl-SA;yiIOweELIdJi?eOb79Rq>oY4$8-;#mGouolk_$0 zm-J0)ADDhfwU;Q>SWVIiRKA#hR*E^2R*MrQJz1=lG%EVUtKt-Kk+@3ItHrgFUN5#w zdb1do^dYfV(!Jt&u^$jGikBq6U%bWCb&cyr_XM$A(jw8~+U~kl@=Te(&2^{bnKD1% z8k9U!=7(GlN}eh6J6(@Ro+xt@?bQ|6y?y&`$0%Oo?}wxGR{Klz0Nn(+NB`ppt-B;7kJGPPnlS1@z=Eq<5wVR}u){02Ox; zsD1=ZEJrbctS-WsAflM)T82rkHJI$W041&M%LYJ zOKqvn8>I&WVJ`e@>#4mHnuhz zUW>Zd%6?zt$4SI~lcxhlC4TO|$3j~w-G4Q7M%K!ZiRsf{m&+`_EmNcWDpuKn zz~ahZga7dAl|W%-^~!;R$uf$lI4EIk3?ryIC}TXYW(0;0`IS)TrpP}tglbN4Rm~aB zg2TZCuXEfjpuhoC)~>H#Ftz@S>Dn`9pMU{c7+4fO0Z>Z^2t=Mc0&4*P0OtV!08mQ< z1d~V*7L%EKFMkPm8^?8iLjVN0f)0|RWazNhlxTrCNF5O=L$(|qvP}`96jDcE$(EPE zf?NsMWp)>mXxB>G$Z3wYX%eT2l*V%1)^uAZjamt$qeSWzyLHo~Y15=<+Qx3$rdOKY zhok&&0FWRF%4wrdA7*Ff&CHwk{`bE(eC0czzD`8jMSo7v#dGI|cRk)Zs-;iqW~MdK zn$EVyTGLj3!pLc^VVUu~mC-S7>p5L>bWDzGPCPxXr%ySBywjSH8!T(g4QQ%tWV0x-GTxc>x`MRw2YvQwFLXi(-2*!pH1fqj&WM* z)ss%^jy-O~~=Jod&rs3`p^lQh*xx z>$V^%w2Z&j!JV31wR!8-t%AmCUa;)Y-AU<8!|LS2%021Y5tmW3yZsi6H<#N!hAI1Y zOn-O#a+>1^Y7Vzo?Ij0y2kCaYgRP(n3RWNMr&c&bKWjLyBMtUYkTz4BLYwF=K`m0W z;2OEkJ}Z|4-hg4pPhmj~dVa#4Ok$m&rpk#@lE-jhgrW+yQw*XxjPPMNp)uTkZ2rB2 z)Iptm9_-aTw@Z(0YjS%(ZC7XqyKkA{^nV*Rl(6i{Anhz^*#)h&3?SVSPA&|N-F%x} zbT_Y02wE{;M?c*o$Zt4%`65BuLv73GUb;`vqYp@vs~HH{#%O^rt!`;^wx}6PcU04I z)wE^0nqjJ%ISH|nPKNGusC&;&prdD0*HW{FnNjt#TH4J`s@rDeCOZPuGcS}&{(tsU zA6${O?7Rk>-W^^Hh+{QwxL7Jkd+C0K`so2dTfRpG`DsAVrtljgQiju@Li;Ew$mLtxrwweRuSZebVg~sWWptaT74S$#u1s7ZB zTHa52W{3I8m+)pOWYR>19WXa<84{8gUtj=V_*gGP(WQby4xL6c6(%y83!VL#8W`a1 z&e9}n@)*R^Im^+5^aGq99C`xc8L2Ne1WWY>>Fx9mmi@ts)>Sv|Ef~2BXN7kvbe@6I zI43cH)FLy+yI?xkdQd-GT7R<$v9kgDZhDVGKTPlCRF1mA9S_ov&;gF&AH@(u#l-zK zg!>k+E-Qjf-cLWyx_m%Td}$9YvGPN_@+qVd*Q)5cI$TrLpP-Mh>_<6kysd!BC`cEX zVf*Q0Y(UgdE^PYo5;;FDXeF@IGwN8mf~#|e4$?Ec!zTJEQCEM2VSjC;Wf`Vg*;)ah zW;Gxob7z~`W~NXn)s)F=lj^v3T31JP-BevIkI)8>oH5+-jyAK;GP8!ASKV>V#gDFT zsa`xXt|1Uc3i&PSgl%D=JEwjW^F5vD1UeDg2OE5$hxnCFVvbUDpIEl_O19mVOmP_8bVz-kCsYEtX_1Ovbj+KS444hDH zKJfNHwq&hQ29#QGU>;3PSjf!&)Yr_T8HS#)Y zF@1v9`RQjDr1yF0XiA~y=y{YGCGep{s6iwTA*ge*SZSH9K;{Gc1^NWT@{>XOdHMwf z#oVVr5e4%x1I%+r&CEE*Qu8V$tmu5mm?%|OR}{L++~wCzm$RIp(7a-4uUW|Jw)8G^ zn5G$)e{tS^RevIWx`v3t^JKqe>w9y09=jp{Kg*@dXXrZU#?;Tc<%xwMJewbXg?^RA ze+_wMk=A>m=A@r~0~#Z6hmh`q^b!Z`=jde+%aR2&hxQ>`<7bXmDk+!%e+$*7qh)2_ z^In4P`ktr>O8z!|UZGd$clcz~c=h>Hr~z=--z_oAmw!Nq6({r-vRRJz0|mD#FZ{ls z+p66(fA$X)`U?9cH0RlBfikrIP@yl=AE9!T32=5+P-i$<+jN!7%+FG|&!5nrvTOeg zUa57UpZ*+hJA>p2ga0MxsK21E^Uo8!3b{#gdjViLwDj?{%qL2b= zfc}>G8GrHM04YZSz|%^HpkOH)4w1W41*h(bOQ8mmEBsPEo@ObLg93$OR0O5mp zOMj_muJWzicd5+~DdKi<2U`M<%O>D6UC5#6I_&6n&lq+LidLWk)0^OY9*xW4fM}}_ z(4tNKVhgr%baxmv1}d_H<;08!&5{N0g2W)&MMM!{5rt{6{~60ZbqGntDu5ToKv2X* zM+0=~M6SR&<)ddMykRaD#Wt~>_t=3wq<=D6rYsQ@J4;ibrnTWEV_xiHnY-c4F?oiI zdnZc;p4g2750m%IdkG@6bOz!c03W3^!@e}MkjzV?@Z_6Ck0S09y;xv4TzT4dVFJ}b zQ1pW-F|*f4{BIQzPD0Kdvk|QP{?*Mzf6Q4J5u5wBBE`9VlR!DpSj`QxGz*C1KwY`uOsHURS@Wb04YUIC8;j5AVHYM92El2AI3|7!eaOO$$wm{yCc6}sue43iB z(dyLTG_^#o(%R@%3dOF{`pXhN4YYwamKKQzu%sUCvS_48cOEU$mW!m!P=9=IitdXR zXsou|$KQ-uyjWqQ}X6V7eYqT$w6p?A#KSdvb6cFIOR4q2LNNghFd6ACR zq1M@i@lB~zGSZZqriY;H1%C=h<@t9;uhDT<@L}{HO(kEVmC@_oXQ(0S**-;H@pAPM zql=DME;|u{PV`eSkr1cw8-cy+VdH~Tho_^5PQzI5hn1hk=oGB~D*W}B#^ZpzM3Zs;1Bsf0H=O>b*lMV|>Id?7De>`bbw{(os|iidojmii(+ zJ_T#jhg$0EF0t9a77uxgbgoE0g!SjKewv>2bop9*@$1i0N4&+iqmgc&o1yom5?K6W zxbL!%ch%M+eefu@$Iyq5p7+5aUyAWQ7g9q-`pFAWDVi$MB{=)pq@RtFI-c-)A|u}D zh%Yu$A0KJ@nUJ?+p?~L6u+PukkXqb;1zKnw?ZnMCAU$*2j^CZL_F4f6AMEu3*y|O1 zH*on~MrSW(JZQTj(qC~jzsPRd?74SC6t~&Ho{dB|Y=>iK=<-GKd0seQ2i;$T8Bdj+ z^cwz8-F(Mj1Sh?ABUYrpy39W}5TOdE+ z*bM#6<z)Ddox>o2N5DqtOG!qxx|%NBqc+6Fj^Fz(uu%!QGdXaA8r=)rLCl^E*&i&6g$x@ z0yt?#tSE}ciVo|C*xX<);bC`*gjXbdQe-WHg1wsXvs(d>ud+wQMn*g0ivOoLF2tQh zvAJ2?b)qO@SH#w$c$56?E{a6L*BFNL_ZP*zUEYT7Kts0@^2Hfeo@y3{rp4hK(U3pni(e5(n#Egj{R-^BgMlcU zDgtvJJ9-)Hy>pP4vE5+TX7MmA3PKQ#&Ef<;Z3EAhC`=6xC zvd=B|IeNLzE%#rd&&xiy-2Xa#L-x7l{_7|Jxz8>7!Xp~FFI(=%M7Qj7%l))?O6pmP ziz6nW|1H4kBUC4nix*$<2{av@xW8pXsPUVs;6 zJVT3+(1xAt?9Q3@Iqyu)%%8u%egjy8DR6vr^rrerZ%S*Q{Fc6`FJH6}@8{p6nQo%F$e3uUKnOSQ}Q)_}#>H zIS{p_QQ;x^w&N3pj&F1Hkiv+)I9^?SyjnF{bf|wGg%C(Lf+V!)h2xUId=T2E9mcN1L$QF^ z5g2*u_)h#xV5qoL+7?I^OWPS_a6JtT*$mPcAHy(mJmUtoz)Z1zp0^RJebf|pVGWIs zQB0nO8D@fneP+6d6PT}AA2UVLt7UKlb7PprygKtn-5>!^V1XRwIrG!}4+mn=`W zBk<_rS~lAZls_hOj;GnnAs;L$9u zaRbuj_dhXN_<^afP)`ndO!qW}o+exVj;Uj$zv1Tc32vVWmrHP`CoJ`Zxvp@$E4=rv z{Dp%8tK5(97c5fP{T{ZAA#Omvi%lqOVetgT%V6phEDiQ6oM7cL#+QIm<(v8kP)i30 z>q=X}6rk(Ww~N);x^ ziv)>V)F>R%WhPu8Gn7lW${nB1g?2dLWg6t73{<@%o=iq^d`ejx{msu;S`%=Y2!BRo z(WJ^CT4hqAYqXBuA|4G-hEb5 zmu9WW%-NT3U(UDppMSsn9l$6&h9?gmEM$I+<+-sY>_TijW)x$|nBi1h)8fAA*r|$B z5Pu|>!V=sQq%3nUWt4@n=2a_RY`n-VPb6b*DOKTa%2XKnv9S?j^a|O^%)WoIYFQ-k z$~-kfM`4#tTL@{|C6cZS=}|0_XNE5iXHo^R9{V{2#-J}cRcVM@rX?8Sjx421k{2wI z-jLjNg-qX(4!wL+c*$)WrJ}VISa*F}M;|US1T2Ra7|u70n*8gwmk?87`Wa3dmg9*C-c^D7 zFhJOiT&KBLrcyM-bquPcf@@-PQTVOpl8DM3LQ;XI7}^i1G^D9jrY|J-9m#O+knhZ% zoB&2J8piv$%+PsMui*-VMr@rE_kaBeK16#MW5`goHVLT3`>0J6An!!!qN!5A#Eh8;<}j}mcj#PFH!u)CTJEtOSbxBxx|St! zBoZ)Wj&b~-P8eeez$}_PZ;AQ|KROTh@U@zUZx}8#z!$2vZ&t+A zeM7ivvNU|RPyVLP+^CvXL2ZKX8TzNBbYyg+EbORaI;o@X!Bjf6RAnERF=+$>eOC%OUDW-w7m}IbH1s5 zhd4b+YnHm4rL8(wt>lGVQtp9EI7tLmKVlO?^f3HDr`HIQ2KX&e!|5l`o}>HOHhOZo z>=xeKMqh4rD49!aAzH&bHN3Zt!QAaFkn!*fe84c9e1VS`9%Gz7u75G)=4$w~bFzk+ z$2+f6^xYAzVKz4&sNsuWcm7KB28KxbB`IpiEkE7)Bk>&HKFdBuC`stAwy~1i2G1o{ zI*lz9YgnyeZDgR{}rT%7+Bt3;T+QP(koWLXc zCK8kM1ls-qP)i30T?r=oZ}tNK0QLrx(G?t%tCCTFTcB1zlqZ!0#k7KfkdSS=y&hce zn!76`8u=i82484mW8w=xfFH^@+q=`!9=6HN?9Tr;yF0V{>-UeJ0FZ%A0-r7~^SKXV zk(SPwS{9eZQbn8-OIociE7X)VHCfZj4Ci&GFlsOiR;iIJRaxoGXw(dGxk43#&53m> zS)=uTq|9>^v)ObhvxHhb=kS$=qTqy4rO7l7nJURDW4f$LID5`?1J}a&-2B3PE?H*h z;zu740{(*5&`a#OtS|ymO_x%VPRj~QUFfu4XL{-O9v0OB=uyFEst^tz2VT!z4g<2#lRmMJ`j5ZM7xZ*AM>%2rvSpe(=Ig+{%mm`qu9D$$nuwfAVtg)wU1D1@Oa-0qBDX0)tL} zsrdd3AKVr|u!4652w2`d0fsD36d(v8?%fw448z=eKw!vV=GK+cg<@B0$2aAJ0j^IF z7?!T;tpbe1;%>zpHr&Lcv2JbrpgXly(as#!?0ARvZ(9Tyw9dPLBI6nnUO(iIoc8&R z_JI|#ma!w&AcT?E9qq-QVS__Pcf=Ea+u?_rKX*`?w+8~YR z^5P4}7sOkF9^v<)Wd+*~+BRU@A=_f}TNYc7Hi#bHH2iMhXaTblw9&-j;qmcz7z^KO zLL_{r36tEL;@)&98f?OhrwP%oz<(i#LEKIdh93L_^e1MUFzdwUAZf=#X!!zWeTi=n z`C^CXA?1cg9Q>gxKI!0TcYM;pGp_iegD<(`iw>T3#itznkvl%+;5k=(+QA>Y9v3?#|5p?&G^NcjljeZ~g^f18y^%J9)Cd^>|=N zijQzL5oimxJIZx~e9?Ss^Ty`Z zaDtBpPPoAsJW(yH$N4T<;S2#yPeoF?lu&qNOqVhlu1EGea_2aYXH89ap^|@L(Gh7> ziYStriu4X0;c?T2YBH74HPSR?ZZItAvUReitVH^z=C?2`C}=rO7dV=-77=68sE%uD zQcf{6cFi77hpm&o07Yne+0~cxtd5_*)sP&)@ zHC}ize=e%9#0xj(imzo}crbrYe63*c7RTYjDhiU1%Z6##t_Qui5BGbp8h+wH(WFEn zJTC%R=pic)GR)Vxl-NNqUE8ZG40R2ST?P81rl{~1FV5^e_8Pg(x$FW_6(mpMLKFJ(* zW5>({#DW*QoCKbj>CJyx?{us_MShE|Mu(*hn_8mTv>ROv%chy0TJ@sGvER$E`JN~l zoQ0D;f|Gu7Wz6bozzKCPos?s8CQ8kPJJs7yy@Vnhlrv7zVopqhG;I`3KjYvJ7U3Q8 z4o~47P9z6EG=+Dj6AqqAR72W5+#J*NkpVf)wXA6$(M~T?7#4pzGDBrUr>GEi zFyui0#Il7feTyMnkzrLN9=k=`_CN6Ie zzr4J@x_~MF!ZH07B1P5dwMerC-8)peeldTHiFmtYw~FezE_um2lAh)(G@j}3 z0!Pn8|GYWq|D%=5GOF(N?!wRmr@znXHvHk+@}b(3#@WpG zkVVaQ!w2@M`A`6i61n>$ zUwnAGnIh+VCyDh%ctls6YsySKbLgXY z#MN4E^`xoW>mPP~4KZ=8)o)S%7?r`a{9VlAD@+;3Q}=Z8eYv%XpFOvdLwQ?B!I^2t z3r|g3{xaS}Ahgj&lS5EdRAu_zLo*}FgEcG~%bmsSwiUdSI$2!qkuR5doylzDmjfpi ze+Twjszf(k-*~6|-l6dFhrGYeZT33#ZB@q{v9NdRgdQH>rBze^eDTzSE8fpmJC(>J z{!U=hL;qjjCrp+46_?|^>sax(zdKLdIkGFah%3t-0*m7j%9?wb?G zIW3d#O*QbWwJDRo&T*1uI>d5c3D^-U0AfQ1;ISxh@QsgQa-x9rP&s<7O2XC?~wuq z;5nd5BNSEBv>{INS*RtAeB+NjimEk}CoYU;1>c)7`Qt)S=4l2XU5db)fcU||2R;TL z=-r3x=)u3llwq=fl_KzR4Twtkaqd9Z=%CnPYXwqi1~w0Vo;A=+R9}6zW|(YXF9kdR z-dGxOt}<{s5yh;y$$g7sSs};sepoEZ9P7w1S>MrPvcd{MY4`!L3=H}xnx;5UZd@ih zxzbq``QegS8RR1ZO;8Nd@&p@{ztl&00 z;INSaoeOgl7%rQDv80Ql*fI>LSbDO>GF@rJ76;%7K`4sKCO0f|llFrzcw%5sLXrP7 z`Qb7<8RX?SsFqk&fn5}^+*k%N0?ELjfMN(|4Or2JYB5kCv4TgHCf{E!$`siRmRR2< z3X+h4kDmbjgPI{<_ktBV^vZx0#=^T$3=DcGR^{}A6k?9LfNhomH$#B|6#&eSsQx%U o8Ek>-N@E#tp#oHJl!t*q1I2Ku>0m{jE48=;c!3#XE~r=m0855eHUIzs delta 34912 zcmXVXV_cp8|NoX2PS(k*W!qS`-LmbLJ4+|?WLwM2u9I7~ZDVoOf1mH~f9JY&-MAjt z`-P|8ck?ivvoN)GXiB$=zsD5hnV6?h<(cRweoy{VW1ZvJ+Q0eDG%P!=IL;u;_!0R8 zY@V`Lq(|3+PgSy4L?41rg@;pwckO!Z`tgH`{3k?*I$@!&A3l5#`2e{VAckO|OMx01 zs~QdASV-N}R?pQ=O{yqlrqz|1yp(^RK)Bhkwq`;Yh)md4RrtR%sNbw?F7+wVN@9oT5^KvyxHCChVwDz29-_(~6`YI}kOI zb^sOR2x~T#ZdIJ>Rf@`fWMMck8Z~Fk7!ymA-q=^Hp5eZ$X)}%69EWv#a)HMQBo+#f z36F86&q=PH!h1hfL>Ol{cXt`zy7GFq%Eq79O{IA-u!cH*(wj1wN}D2M4WT6o(qxrW zEB}r}@-+r4&wIr;xO0(AI@=cYWb?m21~K;0A^-T{gEQnxfCN&@N(#Zq#RXZY87O0m z;t0Wp7M~;I&<5qU1T+?pjfUye_TixR_f>$?rT1}+*6u;9Gn0cXM{`4grB6(W zyBDpHwv$&%UIzt(jZMh^e3jZ{I@kE301olpI{yj0+;ZWogmFjno1+v zMW;sMFf7sR(_fhVjl~QhEC!kN?S1GnQ8&fuPw9z{5eDbyAAsT&CyjpUf=RK)X*YhW zwf>HLeXJxlm0mFjo>lB@ni;CUkg)*JRligsG*5>@wN*UJvbS&X^}x zn@^UJmJ90QY)d4OLkji-vg;l*>VWz+eRS?0G0Bg!HhZc?2Wz}S3kMg^_@+65nA?uo zkBwh=aDQVGH8XVK>zh0u{gJbev&iTnS1h3p(pF$?`aC^rhJj2lK`5&HHV#_?kJb zGMSi_SJ(*5xg|k>>Dvgt0#5hN#b8)>x5&pj4Wy_c7=p-XQ=>p*vRykohWoq+vj1uk znu?X~2=n2?uaB_*+Lr;+&434q#3lhbD9@_k1Te#nwy}MM^TTHt=B7p23Hvw*C##@< z$6AnfJ+Ri~X^`J(;3$v;d?J5C5U~zQwBA9#k|t1Y#>7ZrY#I@2J`|kfQ=Sxhc*rH| z{varkusu6HJ$Ca6x^v$ZA6sX;#AVi73(ebp61*3)LCF6yToc0LMMm{D%k+S_eJ<3CTZgjVEpgE=i5mX z0o|kFlPT7$0gM?NfN_Wk=T=zCXFhtz_fJrXuKFQ#uaUzUCWj%}$pz$g05t#ar{-1o z#ZYh6o&A&s>>NA5>#m&gf?X>M)bj>Q7YY}AR8nPC<0CJ`QolY!M*@PhNF4%4$5nFf z4{VxA-;8{~$A&>%Yo@~y4|O}IqYemSgP7Sy?d}}+e`ng%{?_hDUhCm`I`hP=rda|n zVWx~(i&}Q|fj^k+l$Y30zv6ME&AX7HTjy~frLaX)QgCMmQq3_qKEcRyY7nk_fa}Z$ ztrwMjNeJ|A@3=y7o^6LMBj@LkTyHm7pK(Vxq%M=uXr;M7{wWsrG~I1ki5OQ6#92Ih%Quj|8Z|qUzyy6 zUf%s*-I*73e%AX}cTI5r+ZsgVR1jr6I*hnu%*rSWqzs(T0KD7A4U}76 z)lH{eBF=pRy0q*o<*iM4@ojv65`y{#TKm=!5+7PwC>z)to^he4BI9`z60IYcFC8XC zZ<65C;OV<=0*{u4*i@nn?J4m6_p_jauY-;RSof^%yxer|uPQvyzOCP1x_-}6H;)~6 zkQH$^6A(lu&B^q)5vwSypjGu5P`Y#UdzM%Uhuh>vlisoS7c?a}|1hah-vo_i`e5;! z93hb``au;ow+t;(wB3-=ww(pgb`ZrEODvFvfEiQvXaSX6+A0ooWdEx3u-oBf9V((3iwRO z7r|AqsNjl$(oTUVvOf^E%G%WX=xJnm>@^c!%RBGy7j<>%w26$G5`?s89=$6leu-z; zm&YocPl2@2EDw6AVuSU&r>cR{&34@7`cLYzqnX)TU_5wibwZ+NC5dMyxz3f!>0(Y zJDdZUg*VS5udu>$bd~P>Zq^r)bO{ndzlaMiO5{7vEWb3Jf#FOpb7ZDmmnP?5x?`TX z@_zlHn)+{T;BtNeJ1Kdp2+u!?dDx4`{9omcB_-%HYs2n5W-t74WV76()dbBN+P)HN zEpCJy82#5rQM+vTjIbX*7<~F)AB_%L*_LL*fW-7b@ATWT1AoUpajnr9aJ19 zmY}jSdf+bZ;V~9%$rJ-wJ3!DTQ3``rU@M~E-kH$kdWfBiS8QL&(56OM&g*O73qNi( zRjq8{%`~n?-iv!fKL>JDO7S4!aujA}t+u6;A0sxCv_hy~Y2Pbe53I*A1qHMYgSCj0z6O zJ!z}o>nI#-@4ZvRP|M!GqkTNYb7Y)$DPWBF3NCjNU-395FoDOuM6T+OSEwNQn3C`D z-I}Tw$^1)2!XX+o@sZp^B4*!UJ=|lZi63u~M4Q%rQE`2}*SW$b)?||O1ay`#&Xjc! z0RB3AaS%X&szV$SLIsGT@24^$5Z8p%ECKsnE92`h{xp^i(i3o%;W{mjAQmWf(6O8A zf7uXY$J^4o{w}0hV)1am8s1awoz0g%hOx4-7 zx8o@8k%dNJ(lA#*fC+}@0ENA#RLfdZB|fY9dXBb;(hk%{m~8J)QQ7CO5zQ4|)Jo4g z67cMld~VvYe6F!2OjfYz?+gy}S~<7gU@;?FfiET@6~z&q*ec+5vd;KI!tU4``&reW zL3}KkDT;2%n{ph5*uxMj0bNmy2YRohzP+3!P=Z6JA*Crjvb+#p4RTQ=sJAbk@>dP^ zV+h!#Ct4IB`es)P;U!P5lzZCHBH#Q(kD*pgWrlx&qj1p`4KY(+c*Kf7$j5nW^lOB#@PafVap`&1;j9^+4;EDO%G9G4gK zBzrL7D#M1;*$YefD2I-+LH{qgzvY8#|K=-X`LN578mTYqDhU}$>9W&VOs z*wW$@o?Vfqr4R0v4Yo_zlb?HKOFS zU@WY7^A8Y{P)qU9gAz52zB8JHL`Ef!)aK7P)8dct2GxC*y2eQV4gSRoLzW*ovb>hR zb0w+7w?v6Q5x1@S@t%$TP0Wiu2czDS*s8^HFl3HOkm{zwCL7#4wWP6AyUGp_WB8t8 zon>`pPm(j}2I7<SUzI=fltEbSR`iSoE1*F3pH4`ax^yEo<-pi;Os;iXcNrWfCGP^Jmp935cN;!T8bve@Qljm z>3ySDAULgN1!F~X7`sAjokd_;kBL99gBC2yjO+ zEqO##8mjsq`|9xpkae&q&F=J#A}#1%b%i3jK-lptc_O$uVki1KJ?Y=ulf*D$sa)HC z=vNki?1aP~%#31<#s+6US0>wX5}nI zhec(KhqxFhhq%8hS?5p|OZ02EJsNPTf!r5KKQB>C#3||j4cr3JZ%iiKUXDCHr!!{g z=xPxc@U28V8&DpX-UCYz*k~2e)q?lRg<{o%1r;+U)q^{v&abJ9&nc6a32ft(Yk}`j ztiQP@yEKf@Nu3F;yo9O})Roh9P08j7@%ftn7U1y;`mard4+5 zB62wpg$Py_YvQ!PE2HpuC}3el-F3g{*&a z3q{eLy6Xz|F+aMrn8R8IW2NZu{tgsyc(>*TdV79@?V$jG(O+Iz2rnDBc|1cK8gR$Y zthvVTI;(eYhOdjapHe=9KI`|2i;{VIfvnR6`qof=4a=(BTZkev78+6GJW**Z!|yvS zes)T%U573C~Hm`&XJzE=2t7tFIZM`!^r^&z;W?dOj-N+a10^>wV(l~2naa?s; zTxU{z;Go|Ve!vUjUrZ$B#mWH)NSdxi;dWa-@w)-$wBOpo`DEG<;C#W||W}&@z>C`*j9V|`ai)z*2PG`TZt6T{a zj!#m3`Vz5R9wJkNMsJ1`fSCS2mHnizWDT!G0Ukp$%*_^X1=k=%mmO$^_0_d|kc8ek4_DZwomL(>GGtfEB)Wy&cfZ@9-T|hAq&fx;XR$$_yl6iogcR{u zm9g)axS6=_IL4=wQXf|EkzO68$Ms4*JXAt8gFxLCibt^C#C|I|v|U{%A;+NaBX-Yn z`HAmP*x5Ux@@Wkpxest$F~K8v0wlb9$3gHoPU(RMt+!BfjH?`8>KMK|!{28+fAk%6 zWdfyaD;Dr~`aJHn0}HIf^Y9*keGvm6!t?o%;je)wm`Dm$fN?YtdPI7S=Y23+15L{J zr;n3MYg`<50nW^`BM$&M(+PQ7@p7Lvn(kE`cmoNS7UkQmfvXQBs_unhdfM){k`Ho! zHL0#a6}Uzs=(bu;jnBAu>}%LzU3+{sDa6~)q_|pW1~*Is5J(~!lWvX(NpK_$=3Rbn zej|)%uR0imC;D5qF7p}kdg(-e{8#o!D_}?Fa<&{!5#8^b(dQl40ES%O_S(k8Z$?Hs z;~ee=^2*5S#A*gzEJgBkXyn*|;BBH97OOmvaZ>&U&RfU0P(?jgLPyFzybR2)7wG`d zkkwi) zJ^sn7D-;I;%VS+>JLjS6a2bmmL^z^IZTokqBEWpG=9{ zZ@<^lIYqt3hPZgAFLVv6uGt}XhW&^JN!ZUQ|IO5fq;G|b|H@nr{(q!`hDI8ss7%C$ zL2}q02v(8fb2+LAD>BvnEL8L(UXN0um^QCuG@s}4!hCn@Pqn>MNXS;$oza~}dDz>J zx3WkVLJ22a;m4TGOz)iZO;Era%n#Tl)2s7~3%B<{6mR!X`g^oa>z#8i)szD%MBe?uxDud2It3SKV>?7XSimsnk#5p|TaeZ7of*wH>E{djABdP7#qXq- z7iLK+F>>2{EYrg>)K^JAP;>L@gIShuGpaElqp)%cGY2UGfX1E;7jaP6|2dI@cYG%4 zr`K1dRDGg3CuY~h+s&b2*C>xNR_n>ftWSwQDO(V&fXn=Iz`58^tosmz)h73w%~rVOFitWa9sSsrnbp|iY8z20EdnnHIxEX6||k-KWaxqmyo?2Yd?Cu$q4)Qn8~hf0=Lw#TAuOs(*CwL085Qn9qZxg=)ntN*hVHrYCF3cuI2CJk7zS2a%yTNifAL{2M>vhQxo?2 zfu8%hd1$q{Sf0+SPq8pOTIzC&9%Ju9Rc1U9&yjGazlHEDaxY|nnS7rATYCW_NA&U? zN!7-zF#DXu0}k4pjN05yu#>x8o#Jx7|Fk=%OR((ti%UVKWQNH>+JhH#ziW1hD=rk* zD#1j?WuGxd-8VqG@n_Lqj^i=VBOg@GLePo0oHX9P*e7qBzIs1lzyp;}L3tP1 zl5;OiHG&-flQ;rYznH%~hz>fuJ!n*H#O)3NM3`3Z9H|VFfS-_xHRCuLjoIS9wT!F0 zJ-kV3w>7EguDzoBPxW>Rra0#+Y?;Woi7qJ1kpxTad?O?^=1cG@GeNtRZRi8_l-1CS z`(#oF<;VYR(l(gHIYH$y2=rj5m3QL{HQgbW9O!TU*jGj!bFazIL?MYnJEvELf}=I5 zTA6EhkHVTa0U#laMQ6!wT;4Tm4_gN$lp?l~w37UJeMInp}P>2%3b^Pv_E1wcwh zI$`G-I~h!*k^k!)POFjjRQMq+MiE@Woq$h3Dt8A%*8xj1q#x?x%D+o3`s*)JOj2oD7-R4Z*QKknE3S9x z8yA8NsVl&>T`a;qPP9b7l{gF&2x9t5iVUdV-yOC12zJnqe5#5wx0so2I)@8xb$uPG zNmv=X)TjpHG(H!$6Xp>)*S}r538R99Y{Pofv}pAFlUK;xi{E43^->z1srWR=J$8N! z4jRu;EAiLG9R$5#{gR){5?o^W^!t140^f=vCVSs@vK7#`-fv`P*WV|>nX610pK08< z>r#{r)fR?2pNG}8o)?uvX#UJI)YM5CG@0E8s1lEV`rom|kBmf={%h!o|26a=lNJbX z6gkBS7e{-p$-Vubn$(l_IbwS02j;+6h2Q5F7P?Du2N!r;Ql$M>S7Frf*r3M`!bvWU zbTgl2p}E<*fv?`N8=B71Dk03J=K@EEQ^|GY*NoHaB~(}_ zx`Su{onY@5(Owc#f`!=H`+_#I<0#PTT9kxp4Ig;Y4*Zi>!ehJ3AiGpwSGd<{Q7Ddh z8jZ(NQ*Nsz5Mu_F_~rtIK$YnxRsOcP-XzNZ)r|)zZYfkLFE8jK)LV-oH{?#)EM%gW zV^O7T z0Kmc1`!7m_~ zJl!{Cb80G#fuJa1K3>!bT@5&ww_VSVYIh_R#~;If$43z`T4-@R=a1Px7r@*tdBOTw zj-VzI{klG5NP!tNEo#~KLk(n`6CMgiinc1-i79z$SlM+eaorY!WDll+m6%i+5_6Mc zf#5j#MYBbY)Z#rd21gtgo3y@c(zQVYaIYKI%y2oVzbPWm;IE#Cw$8O$fV}v}S%QDA zkwxW{fa#Goh1O|+=CF3h3DWNw+L^ly?BNQ7DY~Eca}5nt^>p#3cc9s3iDub0nh`Wy z?oH|dW8-HG@d5E@U>NWPjnhTjr7C${Iwj#;F2G@++N=Y2tjV;z57RNgE|kXQC)1h- zx8ODU>kk};J8KiSUx5jSsA_XPou1OH8=R~q9{`r>VnHkU6A=!zNOH8IGJoO!+bQys zDS2-H(7+Jfe+&zf#;OSV=83I|^M;0`Kv*#4%%O7x>@BgGMU*@ajUvY>cYw^`*jm@+ z{LZ2lr{OTMoQXn2XUsK-l72oysi9vgV4Sux^1GsW6zTV;?p#J06EvSVyUq5$f4kq< z{Chq5Z?I%ZW}6&uL+f&0uCW#^LyL!Ac2*QRII5TDGfZ43YpXyS^9%6HBqqog$Sal3 zJjI$J+@}ja9Xp)Bnbk+pi=*ZAHN}8q@g$$g<6_4?ej&Rw)I%w(%jgGlS5dTHN`9(^<}Hg zD$PbZX+X>;$v4NjGJxMDvVBiIam$cP-;h0YqQ{YgxYn-g&!}lHgaG3^B=>Z!D*7tp zu19e;r`u*+@4h41Da&NZv$qy-i6#DdI)EVvmKO*PvIKz-9E5R*k#|`$zJza8QJ)Q{ zf~Vl+I=8oaq)K!lL7Et5ycH;m&LKIvC|z4FH5bo|>#Kg5z+Jy*8Ifai}5A#%@)TgPRaC4f>Qk&} z4WciN&V(T~u^xBgH=iP(#nd;_@L&`7FUF>Qm-;hOljv(!74f&if;fz2Mg=b%^8$^C zna!2I&iCz&9I5ckX-5mVoAwz~)_&b#&k$e+pp=U2q-OjkS@yZ8ly1$2Vh?}yF0={P zPd3O@g{0L=eT-Dm9?imeUP(!As&DJ_D=5lwQ=3)XWXg)12CoB=-g-HX9RSXgL;yo0 z?$7z8Sy9w?DvA^u`Fnl7r_J&_jJ7claq*2l9E~#iJIWAPXuAHfmF3-4YjFYhOXkNJ zVz8BS_4KCUe68n{cPOTTuD<#H&?*|ayPR2-eJ2U0j$#P!>fhd(LXM>b_0^Gm27$;s ze#JTrkdpb*ws{iJ1jprw#ta&Lz6OjSJhJgmwIaVo!K}znCdX>y!=@@V_=VLZlF&@t z!{_emFt$Xar#gSZi_S5Sn#7tBp`eSwPf73&Dsh52J3bXLqWA`QLoVjU35Q3S4%|Zl zR2x4wGu^K--%q2y=+yDfT*Ktnh#24Sm86n`1p@vJRT|!$B3zs6OWxGN9<}T-XX>1; zxAt4#T(-D3XwskNhJZ6Gvd?3raBu$`W+c(+$2E{_E_;yghgs~U1&XO6$%47BLJF4O zXKZLVTr6kc$Ee0WUBU0cw+uAe!djN=dvD*scic%t)0Jp*1& zhjKqEK+U~w93c<~m_Oh;HX{|zgz=>@(45=Ynh{k#3xlfg!k z>hsq90wPe(!NljYbnuL6s`Z!wQSL8|(A*@M8K>`nPJ<9Hb^ zB6o?#^9zP>3hp0>JAite*3N?Rm>nJ1Lpq4)eqSe8KM_f(0DB?k8DNN6(3 zU#>-{0}3~vYJ7iIwC?Zbh@aJ8kfIvY%RveZltThMN73#Ew}jOwVw+|vU5u-wMoo9C zO(tv#&5`DOhlzunPV?M~qlM|K74x4cBC_AC?2GNw_-Uv&QtPOj(7L4NtVh$`J%xci zioGVvj5s|GY886)(}g`4WS3_%%PrF(O|s-n&-SdfbssL`!Gi7Hrz_r$IO@*$1fYbQ zgdp6?(IUaNPaH7}0%U|9X8HFonsJRrVwfmf*o1;k0+PwV^i%f7U{LAayu`!x*FmhN za(#a^@Idw9)jN)K!=sFC(G)ZNaYY169*IJ_ouY9>W8tC>S&MEp$+7 zy)NFumpuE>=7T@`j}8pa)MGpJaZoG(Ex3AzzH>gUU^eyWp*N2Fx+9*4k~BU;lQ1PG zj4)_JlelzJ==t*7=n2(}B4^^bqqcKFcJ7yVzbH_CWK?{eXdpKm);4|o{aM=M&`E$=_~PVi2>>L zKTN_x&qA)@ak=v=0Hl5H6~?LOfO@1+fu5(sB|VWID)w?%{m+n#7bLaszEJ#;$HMdt z9qP0gk)hIYvE1!jseA^FGTyK=i4eTPjTL$R;6FywMBZBPlh2ar9!8wlj1sinLF-1g zR5}hLq>pb1|AC-WcF!38e*kFv|9n<$etuB=xE%B=PUs}iVFl>m;BiWUqRIxYh7}L&2w@{SS-t(zUp`wLWAyO=PEE=Ekvn@YS*K@($=i zBkTMaH<&cAk${idNy0KZ8xh}u;eAl*tstdM8DYnM5N;bDa`AB+(8>DqX+mj17R2xBp45UES|H*#GHb_%Nc{xWs7l{0pqmiBIPe@r=X%Y-h<-Ceo;4I>isrw1Hd zZd*VjT`H9gxbf{b3krEKNAaV$k>SzK(gzv}>;byq##WEhzTN^@B4+VJvW>y|U}}AQ z4^Bdz9%QKBWCy+h$I?L@ffl{fLLL41Tx|M+NjjRf(`KjHG4^y=x3l z!!-{*v7_^6MiJOC@C$WV=hz9J^Y^lK9#tzs6}-

Gn4F+B~IivciU9^t0j-Mgao3 zSDF_?f~c=V=QJRSDTG0SibzjML$_?2eqZ;J*7Sv$*0SQ|ck$fX&LMyXFj}UH(!X;; zB_rKmM-taavzEk&gLSiCiBQajx$z%gBZY2MWvC{Hu6xguR`}SPCYt=dRq%rvBj{Fm zC((mn$ribN^qcyB1%X3(k|%E_DUER~AaFfd`ka)HnDr+6$D@YQOxx6KM*(1%3K(cN)g#u>Nj zSe+9sTUSkMGjfMgDtJR@vD1d)`pbSW-0<1e-=u}RsMD+k{l0hwcY_*KZ6iTiEY zvhB)Rb+_>O`_G{!9hoB`cHmH^`y16;w=svR7eT_-3lxcF;^GA1TX?&*pZ^>PO=rAR zf>Bg{MSwttyH_=OVpF`QmjK>AoqcfNU(>W7vLGI)=JN~Wip|HV<;xk6!nw-e%NfZ| zzTG*4uw&~&^A}>E>0cIw_Jv-|Eb%GzDo(dt3%-#DqGwPwTVxB|6EnQ;jGl@ua``AFlDZP;dPLtPI}=%iz-tv8 z0Wsw+|0e=GQ7YrS|6^cT|7SaRiKzV3V^_ao_ zLY3Jnp<0O6yE&KIx6-5V@Xf^n02@G2n5}2Z;SiD4L{RAFnq$Q#yt1)MDoHmEC6mX1 zS^rhw8mZJk9tiETa5*ryrCn&Ev?`7mQWz*vQE!SAF{D@b7IGpKrj^_PC2Cpj!8E{W zvFzy&O4Z-Exr$Z*YH4e|imE`&n<$L-_Bju=Axiik+hBtA4XNDik(G_;6^mQ3bT)Y% z6x=a+LKFZbjyb;`MRk~Dbxyc&L; z8*}!9&j0wewMM#O`c#7HJ|+Gh5%3~W10b6sdmCg3G_v+@H>n*c5H`f+7%{TeSrzt89GYJqm>j-!*dReeu&KHubhzjSy_c~BJcbaFtZWAB}~KP3%*u{zHi zVSUi2H8EsuSb3l7_T1hP!$xTtb{3|ZZNAJ{&Ko;#>^^43b7`eE;`87q81Jp;dZfC< z$BD`h-*j=%uTpG8Me6dF zrH%)Bw-a0}S41ILo*k2zn6P@?USXtC>pX*tzce7A^JD7^^p7K5kh-HO&2haDTL%2^ zSWQb2B6}e*;x?eKq?CdG7F=wHVY)Lb(kQu1R#1Fx|3?>_%cjNM-xJlAg9kr`!>&;E zTYmHhqHh&qbfO`~w3V;BM(q(_Q-5^!esaBI&QbZ^%N-ZDYft#FTS;%{ zKzlSwZIS%zDi#%DMK>`_vmE^krJL5@PmpT2m26Q`O)VRAL>){MN45|7GTk=q^zLpF zjS(Os=`#On$XI#$A5ewac9Ma}mDxSu^5{#jHC+24a2GbfBJ&Zn8W= zm=l7VE0g^z$3ikyU#ysh8b-PH(&-yZL$JV-of-ZM@~N^#DbQ3Ltlq*5@>WzSNxrRK zYl2VS8r;TT`wLfD_O0dhX9vR#S8rMOuUCRkWZE#OjRi$l*#C7}mgGzZBD%Z=p3z|CaVM$$pyW5-pJJDCToY zO3R5)P(Gnd>6wh9Z$Sr@cMXmClU(h-@5kmiBTNTU-|5vq&Fs!ah|o47kW?SO8uWv> zW$=Ud@@|*9p@Rb=!wl;%>k)kH7fPtcD=gd}^IxN^=Cg>zq^jij!f=1PlT|9jh3K9g zF~Z)B;kb^a0hLmJvON8Ho)foq-oC)&E)b|a^|b}6n!8&AIaousO^VnYzYfuijuEo5 z7IcUMbYD=vec4eZX7;p31NB+T9BOMJp9ZI9$dH1kJsJpEtf@}tL4)_*PxgdOge9_EaR!?wWtBx%*f$IGoR>f3Qf2aT0%+fq=1xVEqRl;UaA2Ncs4B1M1#foI2bj4 znX}t7;-FCLK&;>ZGP}{GxK67$Kz&pO%%J>DBMP_zZsLOmdpDUDp&f8=L>(Kcj+S^jA5dco4-7XN z)h;m#54CEy9)Ch-E7gHP@a@TXl=_%&|iUlIrQzn=LqONBu9FCn`3f8aqvRu=RrJ_RH1^Uf=t z%Ir*({+wEeC??C+u!hCi<5m`RsRO6ti7YaEtY0|U)-QfNsdN{=83K_}m$0Z=ElWyt znvo5=%f<;|hNnL-r#v5ab&S2*yK>~a7m(My$cfd*tff?=?7-j3^|&9H7G*W`)m8M7 zzd0+b)c@`bQN1-^dC$_04tK0{mU5tx_zo;&TWou8F(H_J?O+Y)VLXzmU^> zvL!5+1H?opj`?lAktaOu%N#k4;X;UX5LuO`4UCVO$t+kZBYu`1&6IV@J>0}x1ecuH zlD9U=_lk1TIRMm6DeY2;BJJEE%b0z;UdvH_a3%o)Z^wM&<$zhQpv90@0c+t?W`9kolKUklpX5M&Qw06u=>GPCr5Imvh*% zfI`tI-eneDRQo?m*zD1i;!B>*z4Xioa_-S=cbv-k_#Wg=)b$0@{SK>Mr!_T?H`S-?j;3$4)ITn$`g;J$^TppD)^pRz#^l?XgZ2CW z3g5G^iF*GZYQ}{B|H-fqh=_>)E~=3y3Zg=i75G5E)*a>R9bn~cNW{h5&P(vQ6!WHv zw1-89smtY~JnCQS(=9zM)6>UAi%G-r^LA9_HF0Vp3%JF2P%+E&^afy61yxnAyU;Z{ z$~H5X6?sMoUuOT_tU7i5i%5HI{^@#Hx@zhtP55>r_<3LwusK*SC#%i+gn&iRg z_8UN=rLVp*gT(K~{0X0f_=?~bBbfB`=XrTFn3U!)9n*@Uj$-mr^9PNi<22UJKAK&D z|1@Ck3(Ub;>68;)gIn_Zu{uoVRMhAkIqgBS(v2b2{gf?0xd(1sJfY`56mVy>~^w!wmX_kjW8#?_Nk{}zB9ULo>4fO(vnWfC+pG4>%*KZ?JuCdXu%aZ}q7pC%E50@U9+KQZL5 z!*I`SOtNf$Y$CsRsNaf~yyw^>#X_mCiF&*gr=cBb zoPu7PwX(+Wvl~i(XH|)jj@Cu+rzpJMn4kVvCJ~ReCf08viF$q9;CYnv-96k{G?pf_ zQglN`JiS#vok)~^Z2>41#7LPFgd_xrqNO%DQI|!Qs|nWt`co#BwY$&Wm^6#~)`_1k zpwiR~&z#mtSDuYm(=NoLv$%Y}bTjog$RJ8$j1(s})=}su0b?o8i28-|xu58ipFBml z2`4qZ$BbY5>(i2%wmh!+C}$97?X3LgTQ_{(SaFZvq9YCn@BNz z&h#;4h?5#`&_0()uJ;_rR(Q^eY*=&vu)#EeMeaN1puPv5+iQFg1EC(`_99_5v<1r4D ztc(+-eVWf_np;q$M*H49#{R)eIWCI%R&6F34;h9eNG(XNO5ao2MI8;j}y% zZeA>zX{#$;muhtY{_|;bkk~!U~Ih z2QUO}hk~o?sn;#|Mt$0}4=+BRa703n6>fBm(cesk8Cmugg_wi|BWj}V-VuU9jNH+o zgNYGSKPm>qR&nI(2Gu*})AOBfXf0J~CC50C!3KXu6-qZAG!VMZbmnqL6HWG>o$^sjoSLbQxra@WyKV$+_Qe}t7d)c`bpJG++ zw|9D3>XUH^Wplo~MN%WK18n3HeXoe*jKwVRK!=RMtIr1v z;Py~7;eZl&=^UyumN&CecrGBEat}4?mtZ>@`wPjVK@Z)FZ;05^9kztq;qmbxQIJ4kXTk)) zaVfD^K2x7SB6E!Zz@0p|Fkge*0(0?ogmTX8d=?n{2x)}K2$`bjDmcLg3#wU)i)by? zW^G8rRQKBwjke5zHScinRlE|wo0XyhBc9R52IsKWf4-@=l!yO&+l=K`-7Ib9U~hPy z!cH>H)e6$;m&w^0d`axGqDwBgu`B+L4a`xr#5g%b=0?c41`|lx0O9fiIVaFAsO$Ol zayhm4C9X%hzUf&ctylV$%ntuA$(yo*X`gaVX0$|x{#!YK^cvLmNWPZaTd3&xP7ny% zkn}2AdJkpAgmsh}Q$tY3(2RtO;%R*~8r#ZbSbMR4LaL9Sb6O&Ce(GlO${jtl&`n|D z9;zUQPXCHqTm&t^lk9RlZiiquSY_og^?kgVruz%myd95Fr!V z-$OIXSt?(pxN-M{NjA)j1KKIp(&c2RVjd_}7+CbQfw zTRjg}A0~}Ht_?-@wD0bI-;LQwT?mKywmDZ7*j4>4pR6@UVU3mb?-cbQt~aIG&RBjl zs-4UNtOH3+dAF%U=={qB@qijh4J6K?Et zPLlfPlv<+i>ty5rh;Q>iGFoaq4LyBIZl3L{KGUmqPL~ZCosOl;7w2SxcE}pvK;5|6 zly3JjUsvk|d7L3bFs&;q@_|p?vdU_UzhrS$Fw-_NoEdoIT#-0hKC37!>-i6FaO(es zY97)m4YO<|eqGMrYejC&-IFmc{=P7>qFWX;)}q!&e9-F59o>V+`X>J}%Te0$|A_jg z;6Q>k+$6iPv$1Vs<78u-8{4*LW82u+wryJ*+qQFa&bf8(!&F!IOw~M0&-C>FDa>dUDb=K0XL# zw0(2m3{A-k482S5U_oqLwJfXJ&hK;~y*=aC=O6A%-%#42Q&b23|5jxM95JBdZPYaZ zXfK@oM8KAHHezs8pGKBg&~JxSIEpSkAV#PMNmn9cSho6yp99k1>@s>RtEd>t9C~AY zeIPxowntzs?~#6MLEx}yoP#?zox$DeG|R2BTpWm4|ur~9xSfHIzuGC@6pqmX7pgMjJ(%@TfPe-_R*z} z?G`log;t%`w|osj`Q=o;b3eUdr7~vMs%u_SR~yw5YSV< zCjH3%P;{@}YsQnd2niYKw5xjRT=l+KGNc4EBJEhU5PcL0&AYJKT=%F!lBO~|KuS?F z#mZmJ&r`D*k0xzZ+7V|y*>7PfIAw%7o6`O+>Y}zX?gyoA#bS-k=Btq|Iv8>=dwnLq ztDGW(e=|)RNp1FXF0QVRnl;%RKu53$thEYFoy>CS@23w@i&e{$OdG1VBc}{JU{U#F zwH%=_7+?@4tR&iKFXxIGfF3882kwL)Z+a6Yc*w$8caV7zWp0M|OH&ZTtUl$fzzh#& zfw9Hj1ksBWn&|*dfx>cCXv{oNbnHk_y#R4gg-YIl4M#RdMVfxM71t{QDB(iNv{;mB zc;!)+6No%125qe63{8*pGufr*E8npy2|=hf+Uhk-sj)I=2RnEW=^NHaOWMk z=vz>3?zz{j1469&r^ENB>a+(8+P&hk!jU4m$P-G4+Yz(o+nB)VtQ&P^hgF!{uFi3e ziN#EDsD^dJ#q69Y^=Xa^Adnr}xGdaum%p83{eXS8&oymVk*QNTi@@=#Pj5xo&S+Ou zv_SSM@h8NOR;W@Z2#tU82W!k32`oFZD`czy_}r)?i9zTbNy?fvcRO8_d`xgb_sYKD&sII$b$Nn7Eh#KqU? zyNW40j=^DE+N#hk&{>`!#~=4qwdc zc`O`^P?=MJd7}t9kQ_;Y-FFRFyU7H#U}*IIGrMaGS;(huDhrSCZMEv`4l*L>0|Ka~ z<0N%Sj}sER6P_%#mOu8$Kw@E@aca-bDs`B=67`7Rx(zbG)huE!ntMSqxYEtm<|T2{ z*HFk^Hy{j_`VG;Oenf}ek-EX9ot*TepWIwIr%Ay52WsOnkO~@7Hq9NgU|nXS5oD#h zO}VW&EbEOlv@UsxDtl8k2c@r>1Neg^32rIEev5ChX8Qrno$5b~cSj#-Qv{gafRFYq z^S#(3t?&|H*;Eg`2V&Z|ba_X@Zu$wr(L3s;tW zKzre+#aaoc-&J3Pu?@IjT-OxH%9hKO%`e}d^-#RRNAwQ6_+gi2QVM8$|BKEn&jdew z?9+{Zk+1T7baFB6=^G!aj@VAR~humfi-l zViyGGBO|vZW+t#1P6BtOhIdVD?K?3NuRtmg1F<$l%`tH z=i3)1Ib_~WIlSU|DA>Jfqe6vi_LL8tKE`$=<_b1e1F^AbX+GeL2#+t15&ilJV)<(eJC1YsLq!kBURWXm@j=aN ziggg*6ED!xp3@7Qi|rZpjb^yp4bmUGdL+Q=L|nQ@2^jbIkAQ&04-DqC68gGn47Vd7 zV*2VElHY-bQ`mu-+yD=4Xyy*6OG0D5>ap_j?<1|j^wJV=eFM|@U^G=Wml{n<)UeJw zt#(6=pDAVx%l@U^bt&{b?6`r4ghT;FsC$CG9sV@yJjrEYk&aY$mwB9NncS#pS_C!jJrsaZ&3!#?70o=Q`BV3U<~{1wqp*2!2*pO zz|j(MQ{$6wVIq^63d8^To0EK-!n%YkLI)J=cyYHh*ipmnh3JC(f-8D<&=JDkV$9_b zOoDmVpgwmk2BnEicb0JQb-qFN^$yJ4T)3HQ^d&<FZ)~tN-}tfNZD#4}_=Q4DXJ$TJ2(7xfGP%}@jZ5;_B$!j_jIYL%vx-MOvcYDG^%g8P0Fnk0|*KF5n< zZ;aH_%5w!xFnU~}VKO$So2y_AEMN0(o2(*Rqb_PUv8I8 zqa<;%Sv@?43q6F+)=eGU{26?G&Q9@)CPLT_2^OBUG#F=KGZsgs=U<5iux2vM@|rO^ z8R8~JYc*2S^3GV`Bl99&4*gyq2NVpYYG)JjH0V;aG@9m65bf6BoyJ+hM+qDBaivl` zq_>6LlWE0N^zX>(m`VuP=7L>^;)AH-U|ikYVyYbLM$A|+{w$Hi7_=InfUyi~EDHXf zG|w;^m$3xf&u_G@FM+cGf-Bk$!SFHx9jv`5W%BSIof=dDP8zKnfRnL zj;-qFizeC%D0aW4oman7BX-Tvqoh<~wm{D%#Lc`$@E&u_#bH$f#)A@@J(nmjgYs-N zmOmfsU7S#{!F`&XBYQFPasOH;7r*hj=^b0E7sZYoy^CtLZz7SMH~%fC&CBnnTRlmQ zS8>PQI{fC104|v;iuhugCeH-Vy-(3wc{^u5{J!-JsX0Z z?+(-k{q)JMA=}slVn?x65ilVX$GQ6ZvcBVid{QKV;i2a3EJ!2O-)S~s?U3<;-}T3uZmj=(+a4wKN z&lTKS>}k`6jd#S#E&m;up`IMiD@`LA)SB1o4iNq3Dxf$6PU`}&c;W7UHco{gtn&@( z+VySYn{ojMdK#S?+Y~9Yrtk@h4Ah4g;1n+OY zoOX(NSJu*iK!piCa$Oj}YTdo?=D%p2#;=-xaLF>~ljG9G_(yjiBjw=F>A^-s>aa2V zYAu7tQqY@rWERHXz_eMV!r^9B*pBr+{w;#AlUEXoP<}^^pWGo`_v-eQe_GoVs3!8Q zB~B~jfuLs&Z{>Ymvo}WtTeh51P~Jpld9Wl1a_x3N^n4-0xDE_T`O(rxBKsrA{Q9>5 z+6P_+YdSuRkYuc+2{GM+z$4$P( za&zLg<{!gYJ5W#V*5>^Mclq+Ns;J@bO7y*C(X6mGWE1qVv4NK`s&)YizS*MYmCaZ8 z7@aHuym4w?;p*fQLM*&w8DW^WvAjd+H4*^#POr5F+=}Lwan9acKKQIVzC{!8m%-?t z?hBO>gcZ$E0a=gm)Xnh&?137cU2q`g6j##6wMGBc-sw+o7nldAQg5$P|wyNjBm|Kth6{boc4!xwg zo=3iAM429B7TOz69wIYLt`}G-mN+dyYNw$#m?6=o2Fq3K)tl#w<@&L+nxen%w`y^Z zv2eDzv34F^6gCzwRRrvZjgLa8plkxRF@_2wMOPZ4{Kjr{vVw|r^L~{Af)5pxcda`n zI*BU-rrpd-a`6{(`4vZCq~r3DK2P{hQP0sQ*R+4i&-iu9-dhuU-hR(fLlDVhkR(w) z?YLr!z3yTGlOJBWlG+>|f>M~GklCprh($i0`nxXusZLIM8n^(o(wh1UT}CPhRg z@0`{bib0MxLFfkAi2B7RfBy$Y?Zq&y;IDdWuM=}7^P9r9jX$McQc9rF!DeOAySF*Z zada9}9!4!1U4z=%Y(`*1h@Q1>jW?|mJg-nmxsO%ui6mrLmIEEOcH#c5wdf`~OLEvh zSBu$&fm2ji6BOn__TOF^BJcn@2CH_9QB~{)om+On9_aveRS2izb##Fa@nhC?nVMnX|RtX-z6>cT=(0Iy4|#8qaerCl0#%2f#;}^UDDsND zKMm#amLtRipGBl4?fMl*@yk2R63lAJ|8BR zhZ6Uf1^YA#v(QbEjROeSdLbLo{l@H#9ml8{DdenI`2}0CBUixPgHsMb_LLJk;(34P za1Zxev1)&aKxC*2%9wPvXgKk2)oD9yi03nHpw=ZJtx%;?5GoZ>r6aOrxwU{IzQE(V&6q+NDB>tpA&Ml{Rbp&tc<0Q*g$^T8Qxyr! zbbHwNp+$j?9i58XnGuR6vKomH*7I7(0e-g|y^FnsI5=wFOQZWzHX z+TLy+z`$$#*)IL&6{Gp+(c+!JZMSG%ik<@=o6&vULJ07KceEQOw3#gbHLTze5D740 zB-S}?Z?_Ea6y*fN>i3)aUEBLgq8(Fn!X>Pv!1ZQ^xm|W!PTL3EC$(TQ0q) zI{6F8wFY9HN7s96OkcGY8YctK+r2#P<@}{b87FR9a2LXiQ}w+X2oyoEA#V#tzK^_>=#sxaQAwv64r{n^)q(cy=kLJ^xA3$`MFrRsG%f#w6H zo-RxL&YH!thaVKJHy{Z+>vA|~3L^Ong0nqBe|VARqm{IH zPgWx-(4c7kzI0rYA$BTFkl!w{%s7Dl*umt-f_^0|l&cKp%bL8cQ-z6g3L|VOMdD8K zTBSqL#Ty!Q$)}mxYz|k23}iA#$KR~I2?ZjuqM_DagmgZlLbyM4kS|}0n!|-cY6zxw zvjEbLx4HEDdszf3zJ00{CH23TUXSbb))4@Hjo)eV{nnP6`$xsT2oUDPD7dV`{i;yCdXEf8@xzYf_WNKD$@`=h3jn2cSmi44u%J}bhjW6rk7&=cmDsKOi3 zB;$EIYn+AVQJ3V(aRSolzEC_*uKY97{enwno+)BCu~B{S*<9!3N|HMuah;4>7eJ%6 zu*97x!n=|D>mqw6$xWd*1iHooa)yMYa~!5ZGJByE&ru0Eq=wF!Nj#!5;0%kE@+vpO zQx99G(&Q9_KH~r*9=!LuA3s_bM;|?^Tc0^K%n(vkHrp_rNa9f8#HK#gPw|*ss@X7 zx-AMkGyTHXy5G*LvC|_-XXqWK`Qk=?_5Gm0fX_K^L581dn?70-!p=#Wr5F)AVD&lqX?k5ZCds@PNa`~e= z*yPAeGHRc+C#7XzwT`<72+_NC2LI%~%rj9VYiM3nEIXC8aO{X)(Vm(^FNkcUZkqkM zPcxs>F20(WoI^8yI-M*W^*@Au9kneO9t{MfgzCR#a&#Le0M<*>80`~~nDg{ZxArby zo$Y9~@vpRA>Ck9o#MgvWq%7slroQS4b@mDy zwlj{A+LBP!64Pk42y5qWq_|?<|~2`d{dWc@J)8NmQ1MmwU_f z(BhP6Aaou_Bbqj;2YZltnJCz;lOw4y{cm!X+dOQ0@Y59Nt?>VQeK`Y zMy!(JQ>Id5nwc-i=r8*!6!`6TawnWg?7!bqfiP8tAV$Ly42msb_*(@s#(T!GpTUkc zD!mZ_@R|Y*LD=Y3NNuXT77gwIP&U-y1=5x6r1H`l@=2F8? zT$bTs5TFY+ibd@lq2Tj+soiTC$hagTt@Pb6_Bv_yqv8$;#std<9Eq-SB+e5Y zfaA4+v4weJHz~7=vFTbEDXwAU#hqIXm+?9l*uIz?G&n&XY)P=7Xa=(b(Y}%E0u#&8 z=Wlzs9e4BP{=guwrHDGVj6lclvOKcH;D>RICH|(r6&$+VGh!;#Sqi1=t)sa`m3uU9 zGW6#<=y6m$;mwa@DueLJ;1~71L09ZRf%R+p^$1d{U9B7c4H+t>I2wI=;g|yJY{^*v z96y-^r;c`{oG|$$n#8ZCpCi;aWX}}HBn`eyM8l<|52tV=kC{&F@pbP((h4n7G&ra0 z^OMQ*dadN&z7nHGY7LF}-u6Ojs2jYd)(4+H=os9HCnMbF@M!xppFtaL09QkH@DOGPUKwd^GG0o>i2e{jp+U<=FlNCQH{3 z|3r*7l%mxP?dZO3a%0$ka`97q`cBKWSi~l-UenGJl=EZE=-xt>K(Z{%u25OI_=!3> z7J;6d`@5Iee*Tur4P5Bm4g%i?o7Z2SOiA&7u;D`mAg?E~YXbtGKgpd z-3w_IInyw|OL-O7@x%JZ^{PWArTKAB@s;cTLz1$>Bvpri4aW_!v%}K?>4pHg#K~ zr11WXr^rE}+clwR%9s#fWG#A9Dy){QkF(tnME|-#lG-m}neZE66+<$Lchl-Kd_qxl=;leBAoN&dF(zq1F0ni*m!O z0B~bVIq<}9qlH^^|+A?q7%7w(c7%hGj9 zp@fs;Hg*|}%^z*_e`<)f;n^dQ%3{M04W!CqBetpWaFCDu}| zR;)Z`F5cC~Li}|b7J3QH8u=5Cu4sViy=%nsuL&)lBN_peG`F-!)Q-Ns)5=STQfaWx zcWMMh5zdkvUr}4;2%J>>Is@`!8ioYB5ntivmIND~Q4oNX2m6D@tn*QRsR@sM^JieLBJ#3<|;Fox;Kk{n*JG)EdD6C7ROyIRUeyQHT}k#(8dhbt4dLU7at$qs5Ld*{lVk4`G7`qZ3?u9E;k4JZsj-!8ik0#{ z)CsIl%*M|cNeY2g34VV)DSAXUx%xU&fJP|2w1K$<$-9)nGmGy(>x_K7 zuoC}ChzZR5=$DfnXGGFgi$4edax2F3w@Luf(k16_ij}mW9PyeC9-K|?oRfjZDWS>t zn-JP9tp0L6!mgj8nGXWO-@@7yCTwZ1q%JH{R}d=}FUO>IP_ihXO(9`|?ahDT{bJcw zgZOsB7w3G0m&N5*<_BsGmF1ORGrfL9cbkN^5%`a0!G@!<`yao|HQfFQXsH^U)V>DEQk+ zNWzJdcN#w)3~;j7TON-J=`alS@SPoC8ZgXXNAlqb@Rm43ESBKeRr)pxqVZ1-oKI(2 z31=KL*D2vG0uF1iD$XruuRy_)`PD*f1l0VxWw*Kw%kiejS*M10=+>zYc|;P{;JBb;Y^k^qYNJz-4%1Wx7_Acm~mKQ|k-aWX$!d_Tztg z+}e+lUrn1<+kXa$mf}%Nho9yu4@tjz7}^X{U+1b?H)1%11~(l#DC~nG2%P?NrCn)| zj4~E`9xjhbTZYg=1D=hQFn-4(@15}YP=m6*ZBSTSiGk1eNHdrL3pWvV@(@b$R&2%* zXM`}VQ~9%%KPXEgl+K(fXMFI+7j;Yn9S}f#NzkC zf`GK5{a;oL&;P85fi-bvm8nq z2h=j{9PpveLTUMA8)xFD;CL`LR_u)zvYHlB@a#Z%yShmxHBWIv2U_FLRJMt%XBRa~ zbSp8BQ}8%pY9eOpQ1$cJ8ZY$IiH3=WLJY;J4gz1KVy%4bAJaLrq}2&&!_g6NY|l-i zCRkXX95pTT9@pFis2DVc@_IKK5BXKbD9@%9mM}NWLH{l--zX#hRe8*sDxY9{w9(cV z%xVKdMMf17DJfjf&Mm{?tITZeMJS1vu(Y(FY)^C20X6t-({kWO+;WYr^GM=$_m3_tz>=$FF)g?aj{lez zlkyIqrTC8&p!9pZq{Wv|?eOdP|6Z9SUJPH`E~P_fen^QVFJ#13Ok(^{1G^Zqu>)kr zlz{o4q)h1122d)5L`$;`-U6*l9gi?}wbM2vt1C9AD}{(=IJH*cb#&*WUjUfKa@k0d z^LeZDdFJ|}(fVRX>&3hH@uyc@gweKaH%jV-(dE$`!5WvsUeV;6z8A8O@w7+aC1E)B&M4l@QdZvMqvfzvV7H2$6V2-;3rgffxC ziVCk|?5Z$y9BMRLbFZ#EwDI~D;dC(&MEg^8U5#xWG+KD zsJ(AoUCBE6g@7*c6x^MR7{M*Amua?g?Qfh+6z*e16&!K}_bjK@u~67=PXg<=Ho;e| zp3-A?F3h|rZGoLl^VN$xpzAp2_Sz);34ITZ!6{xfjlsS3DM=Qn`4EM8pNJj)^Z7H( z7Enql=nG1Jl7gv(?{AznQ&=@9b!oO`wa+!0^!p$RW79Bbxt+u$Ip^xR_p5KjTU@4p z%%7RH4IDTduTU_eZAM}0=mN5?+J%Mcnu)Y*EhN%Sb9e@UluFGn%Y+TxM1xp!_gco) z!F}~n8f+R;u1st+i+-jDT(4(Z2yWkk)(HnvP9on@*fV?i3I|6+!;}u}^fFMe8x*+J z9aCca>;#3%&yU7EgG>Cm_IZ}ejtdj;hh`F=2(4$$>Y8nHjxU(;C;@%$UHuisSqGZ> z#kxOEjWGgSocM0G-6CFCl#fuDmM-GsLqbCu0W3zqrvL76uze|6S zF2cmoWWQmb=b*-KvJtSOn!WVZM?Zu=BM_Dzvg!V_ppP&VyZuyK#p{p#)#ldTWnC%K z>lA_zP8|p0a3CMDLC)dZY0VZfW4VeyKR@&!SR)|k8iTfI4F}9BL`Fd$teC9y&)&vi z^GGnV*}WBKIAxemrIUz9E#bACuqNfQxomfG%{e3>I=Z#TeY}h|gqlmiC$zWx0DbL& z^o&byw1P**ZI-NQ7A@RL*>F45$!9QX*FFd#5@7c0_HRMcD2H2SU*xDe3tnN?!;Y6V zW0j;xRaLfJvIQd1ctRNOykc(R@Jy(6d($goMGOC={ZPIHD7eE1-{1`UeD5A|e@{HsJRyo`U@nvK_+qV^_2`d!K{eVOeFbNQ%N zU)gGJ+cR!lK>e02dib3Zo}KeWK|^`qi6~{Vj(~MC;Q<&IICJX$fa;LSBPev0q7vKO ziVQjyGwKaUGczdA;j0MF6N>TWPEWYC_oEP*y|-)KfbN31qX zatVn|`+F5hDs&(rjb?7^w}nxC82^&p(bc@ZsK0<%f~RaxBJE*mXO$2=`nrmDdY^11 z_sU75MxtAE;aOay75FN=SB+8p>|bwIf|@mWPBz9f%fYsa1;vC_(&Kq(oCa@Vd>@4<_uB63O3CR}x~ z3hAIp#Z-dTxq+ND;2FA34hvBee*88^;1gOxnohDGq+u9Gh&zV48@r?F{U{q=bFANh zXB+arJDtYNsX+uMlV*?-_lnXHIGS9|l?1ME9h}_7j|y_>s1Dd?rdnRAVd!E9oR%I@ z-{fzaj&89#B)jM+^1@5UvV;={w1FbjHeJEq5{{fEMjl$^hOR9Yl@R1X!C>IcA^F(1aLeB z(lkdY$M~cxj`rmE()z|j)fV&41}*~Kpq1hi>mz~mqINX*awbS$X3=O65_Dus`i&U> zO|etx&Q&^s>m9NAw0$a-&|7K+*^^XyGs*3R;>FZx)!)rdQaSiYmu6q)`DnV>Fl#aR z`^G22fL^+T0Q?*Pqx|9jQPzrk0aU^4eS-3Pi1SdwGq7;!>irH{a(~k6f+-h40zlly zZX|7|3u+pF|AoI8`tzLuNed+3H;Rc>k_Z9BtF1InJH-Ep+~(Q_)`3@#!HxGUMY?Io z#GJ(u^B@p+QGHjWPI9Ha!&XINm&^`@p@PSCl-Yj`>Yn%Ysz-T2L@JyL7if-1XS3Pa zXK5<%^THtv+hb_xr{?vKkvBc>YJrfTaZemX)`>*@b0|@Dk(QbXRtkz@OO?ENMo07b zR}Pan(DsnKAH}Vc4J<2F5W#vvf62~6l#pqh?iYB{QtvZ!y7C;6O$BK-r=Wj3ey&y@ zcL;S<=HaiFyX_H1TPe;mM!*hdh%L$%ZDJ)F;m(Jb?BSlLdK9_T@>Q=_h z%pC4VO1)uwEPH6gL`+V?Or3EQqb(I35nDyb1kP={j9X)0D#-~P;-hS$2IYn?I!yTE zxSJ(WJsjwcEC|6wX?G_p8+U55$@WN-UG(6iJ;TqG$~%`RB}}1bc;J@aNV5D4A?8g} zG9Z4MB!UA<)m1MVrFyK?S!UPw@=S9heibFnHh-6mx1` zrfBdPV^Kk4m2v$ycwnJLfQ_Gs4`M!1v-P4_&B2)!eMhXIqhbbEP3+DPWyTHu`Nl>w zghl#VQ^=VsJjntcXF5GN7NtnYU|JNdLhr@|#duE!$oeb7tQE&hXQ)fWZ^RKSjA|{c z0@b_9XA#r&xm70c@sekjg6<0e>OWBbo%8m)=xNU-q&Auy0g#?QSXNKV%P28%O;b;7 zA4q(zX0|{Ep5>t-V=0;b1Zq|CO*cC8s>*p-_A-xSWTFp*U4!5IYPrnkkb?^Pj(A z3L(AD{UbZB0V)r>E$VZLA`U(YPl}_yEikY*jIw_aht-h--V8Ib;787j20qqYf5X@d zDUS6iJu?lUoj?ADmN`kIdVSv=nk`8-m)J@B{9P*d^iw7#OSgp2z-$sZe4cO;lavqq z2UAwRE$&05etPpf~iROHh&|FcLi&9Q!3XSS{y*n;ZTx%BVQ8F1~W-!yi5Fc^Sr zWvhHk{QeAXKgYG%QTC&G!s6PBr^e$4F1JWBy*$wUxYGhY{qAh1<5dHv#VTctV@oGC zOX~8+2%~qcco&n1u6+0Nj=KhN^2<8O*F4}5 z5L=B`J09zOPONt`iR;9MmYyX*JGNZ^fcT^Zyc3d?-|koXBW=m&j43*zK7X)pa3T#! zQ~|oS470jAaapG!^6=LyWwiCuGiazP^?@2_ku$0yO>?p$u5}hEBMP zWV7b#GYVhaiD^&NMBQyqesAHKI9=AKZ_E8BV0%%v%2pvQ*`t_{DCbIdOUbjZJI7^_chALvk^LD--8{O9|ZKtE!(GLR2Y)saWDf213{Umho(a)fVXaT(c;sBQ`b z6#u{g$&PDza`5D-5OgP0Fw#91)@vKC-h)hUt|XOgIoXN55jY=8=Lm=|bhD4eq2?-I zp*RpdFvx0-Z+lD)ei4kWt^ z#a^m*X^UK3Ah7mty>*Cmx|Vfy(kO2hh=85Lfa?nvvk!QSbbf;IHfm|&TOjZ|m(%3C zZYvE9G5Zkee%=jHwQE^E@ZaBoYs6~N$BU{RF&8m5XwlsCh*z&K;X=d+3nnk3r8Qrl z{UTjH&mwG+ZmXKbIVR_09SN@bG8*a;Cv;CGu-IwZenDF%LJUGNDCHP;zZ)hqx}^J7 zD{}_X_Vb#gni2(!o%Pz@i+lksIE_QI*2ybQtWr(NCsh#au@1S*tB0m)s7fh7^yoWc zP07(0IV^LsxJDi;D~G}jZ%|Op@D0I3Co*vK3H&7h8#eKp;yCWBsS&PHi1->berf;D z;LFj)?e5(E8cgMd~BxWokw$KLET# zR6{Fm-RhU;+9L(@X!Sg+(*H5>Ur8JCIVd`Z011>yU^lpt@^(<<+* zZ&lv^l&cF#>OBy@WI%Tjozj~Fm}r=slDJ{u{h7Z`N_M%gS$wzOboABqD0P=72>nmZ z%~Hk*Bd?hv2*+4#^kB#L%P`z6Yc#}u+b3HTdq)`Du#PkRAU$JQ63FQGns`Z}iqqlr z$5F@Z<3R^Ed4Xcx`(B>})9eE=mLg*a-PCO4-iYffmTXzVYOJ1@7x3i{HyUWsHINKG zUKW!{td>o)*#?&W?cd+OzCk!@Lf*6llw-kbPhQ4)2Z5iC-YBRlekvChfv!2-Mv3g} zWBp}HPpaF?TbUL}n7b5ZY2$|m0bML9TQgf-?pnJz;uxEs{mK`Rg_TkbCzIsX6r6RH^z6C!U;Y=Q}P>zfSGy#f7o5{U_Nx zCY)LR9wCCFNP?%ZJo4khOr?YlDaqUO{`+ed`&(&<#|mQc|*>t+4v=3Itus5GNf11GQL!cHmti$C)u z*7#ilkN52I{&ZKJ|9uBfsN(rZzY0ti|4BCmWsHwiM@Ld}cXTqgmUpnVGj?z?H~ykh zL}LN}^$?Dd;kHMquTKy}g$A{>`SK8kr*i`hkG%7Pmxp9rvBjPoo{zxY^7^hdo}J?W%${&ccU0?N>ta) zZj$tA2yz|v9U7QLT5FpPbuGCOKz;miFcQNwo3x4Y&ljP!f6NxC2VhVXk%x<_lo$9! z_%R(BSJBbg&$)aTT8zIJ)V?VtfjNz9(hx)+jeh^dYAY3u;7j+$c@d{>5yA+^5A0dC zZ`n2JsF(7fs%Gnl=-1Qx`K!Vm&fW4_uhJCjv80|Ga##QD#eKwqZD;GVdqXM~FvV=O zXmhz@>ifmz$PmR5bsVw{ALQ002j7=(@wz$?bMnq1%2>L~AfH3Nd+Fr8FTHwt1tb<~E42W-82ZiijQ}>nd7Vy1hUT|}i^^#&i&<)*+;8Ljw zf*n$At6VqJf}!PiQGB21zosWo*!F}QdI)7T!pwCcBt_&Iv2)0>K1P#8a2Otn3G88X zP_NAC&PLuuAIKw&3dfAx_SVV`(*i3t=GJ)?mF8pE{Z{ZuWQ^pdOlE(U4P5+`Y!%U( z$Mww#sP=|0OC9lZ-o?3wYIPTlW|L5yYTU}>Ew)~ zOGVGXLi&(DX3bumZtxIG256kbP1~6U=Xe)r+pfy0RP69-RQ;ynP1Ul6VlO!o-!ZaG zJ{ZBSdC)-B{gjgObn2`!1mBd8pWkT{HrwT2sbPSn-skqJ(&CXv#CCfK5%(Vc8+5nm zZtR*)&2`b6dur$!n)Gt=Mbuf#PN#Q3@b9O%&)X)E1cJE!esm*A0DmT|Fqj-W{n>>g ztPL0++r#bWw2rovF`ylpY*YRrOa^dZ>Y#|}fiV6n(CNC-E!WXhYV#+vN`LFWpT5OivhuVq z>lj&x|0iSZE`^N$jAsFI{_G3HP$YgIsQ2@YiLq|$z}LD=YqOMKy%BhW>zwW%?8oo{ z;ZLw{bS*02wTl0WR{6AbaW#2dx+LHS)x&Ru_G)b%HQ@_!*J#$WP|!k#C9@Z$HA^fl zmseVxHxi*?&R9zAE$(4dFBGknHwlEzQ)TK;L{WkJNupX{6sQWsGf(y0jKL0gVK;aT zZcDL=^g!oH$2)4}O4g31(3hc1E~eUSX>eqv%1oKWiKt@mzx+YEI;>CA(VH?3L=LfN zO^9>SP*y)tELxzRQ@W&Wt0*D+U3xsh>)9hj=q7v0S|G0?iMKcPyXQ`j0W^mar;z^8 zQcH}mdQ-V%TpABBc~p(Hh_v1Ig${W9G#*X$8ai)fpQrtSY4dk9@%U{=u~L<2%bP*1 zLVB&P9#rdEagJeQ6s>SU8q6rVTl_DzLu{H=5!p;mrQTh@ugkRZ(E~2u3-vegKSY=h z{unm9syasOt`DwL2##(4>XIR=T)Y{n{}9;R3m`@yAGt~b1CORpTa_SwXzdKYx^M8I z81>w9K?I=eFLOZjG50n|z`jASxK<|8qqgaAcTy4D*?aqSXFF-zqUlkhyV4wFZvk!Y`LE0&>7mk-1n1F+Ce>GJ3)a*ai zvb&4GcNxaO@s!KmxwR!#`4r&KZ$CtV%d;CM$Msap&3C*-Q+?tm=iS(6c~$={TF({N z3-71aRk1(6zYP1D4ef^1n~T8za*+>^zmHset@`r+oBFKD?7;JX7pzQe6hU?DQ3UL~ z>7O##F0fx&FVm9j*yu_DTryvooAId}EatFK7cgP3k^^Yq3d-^+s?<0BhgbeU!qBTp z9J#p?;^E%jr01oN>+^-@V+ZijagXr_zIlSt<;BVNcBK0cD#4BgaWx&19E6~6bJFB+ zn9*n&wyY%pEqlwQ)@)>_ftwIv=M^&)9AUKrWhEsU)+6LAO`Va%tp9s?>zgJ!8N|=H z%8iU6in=htAA{MbIt376qx9UFZpTT{V5d_&bhXAA_t^l zxYUYoR9;QjqRI;w9ukZC1P8%`i2#<@E+;7F@n|AY1b;qv5SHO!LI5qvZF>;+x?vm^ z@gNMSLWA4b;m}eS5x7zK#|XdboQ3hY3yP@PCx=U!mOvSBC;|e@W3*2cwa>Dz=;ICT=AB~$rzkyMq0^44P;myD>T*x1DrlBf%v{B`<)yg zlaM+H?NKjS7pMdCQ#xjoRwH$-!Fus6`!m#>dReJ#F=oj1Wi}SjnymqR3SSBn564Ad z6|YP#cGIA2M!>x9fNsWWB@!XXcurcb!eeHC`O;+BLoVTNqIZO^M}nb+*~GbF6Z#(H zZ^91;a>Di_+v5!?a(YfSpgU0>PNmdrGTv}8&%qRo_(f$ z+QKbd&QH2B(zjBR7m>W{!`Ae!>9BVRZK>DOMNDTIn+*EnD_I3?x7Zgo#kn~k?zfLE z?nR0ZO#(jy!!8=4PH!1p&*!H8E2OivFn0FC_TBLkFGnD|*)E21*euUjb$#<;eOYR` zglJ2G%XWnz;z$$e(7`HxMj!XQ%Gf#zeY=TYiq=y= z4t1rO!I%#@eY%`|W|~%ReW?xLHCf%LRYnPPb|TSt87==Scn&5b8+#|IG;Xb^n#Gwzcm$N%jW(pQ$E(p#755J%i`}Z(o%tmtZ_D-T zo{Q%N)VH>-Xl>rNJhQ@Ld&QOSI=zo}23|U3$eqc3KGHz9C&Hpqa2(p| zuE|%vJ5?~PZ#`D{>|CjrZbMki!Pyzk+jXl8j!bhmOz~z_qj dDuazZG^u*-) zCV{{p$D*4m=Z;!QJ0C3EBfaUv#@3CmRgS-#a4+Uk9LtR(mzdSt-?*B-Q{Jgs!F;+_ zT&Jc~{N951OskjVtnWOLnfUacmSEkQ#fQojqa=HN?aN#ubFA){K&TrfoSnBphJ<43S zS5?OUrqPYpEqf;(zc;IIty0d`-n-Ke%PlArJt^DN>ZYW)ZS5z$Rnx=cxbM1#zPRNS1N0u>c z*gpBeTvyKAjdr#Uz%$J3C+p2~l9`-P6`=_1Y83#nAp`Kd5jfb*H#u;=%w#=&g~|Q% z1!N9S7n+#|tj#t98*^$X3S9)i3I*n?N+YghXJ9Z!QN%wvV7|W$;;Lx|1{)Ol%c4L- zlz|txtAK4ozLL`xMPZR7Sm6grRj@+Db&BXF9#sG|gMywm=IO1O01imHv3 zFjX9ri>su;HX}wK85k5$R0A&?fdtA5_Q_vX$jc(elo%M~QB>A-K~#2igOjH$d^80Z zC8#NjzZarXrcVZJJEF73z+ix4=7c`5N>TJt7>~rfl$^E}UAMlP2$P)vS26{cE?ONf_&Vd@-E2?PMU+S~pB diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8a1f6b97f47..78cb6e16a49 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a42690..23d15a93670 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -203,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 25da30dbdee..db3a6ac207e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -68,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From 656f06c5ef999b4ebd5a71a26d39f15a6ea42bf2 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 10 Aug 2025 10:36:08 -0700 Subject: [PATCH 304/586] chore(minecraft): update to 1.21.8 --- SpongeAPI | 2 +- forge/gradle.properties | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 168 +++++++++++++++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 5 +- gradlew.bat | 2 + neoforge/gradle.properties | 2 +- 9 files changed, 180 insertions(+), 7 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 3cc044c1173..6f5f4d6747d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3cc044c1173c4e579aba3d559d583d4d067d717f +Subproject commit 6f5f4d6747d397db0dc906349e39beea132fda91 diff --git a/forge/gradle.properties b/forge/gradle.properties index da4d4bdafed..5919c25080f 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=57.0.0 +forgeVersion=58.0.5 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index c502cc69d44..122e233ee07 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.7 +minecraftVersion=1.21.8 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 191cfbf1cb1..1c5583bc573 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -208,6 +208,14 @@ + + + + + + + + @@ -278,6 +286,14 @@ + + + + + + + + @@ -2335,6 +2351,14 @@ + + + + + + + + @@ -4273,6 +4297,14 @@ + + + + + + + + @@ -4415,6 +4447,14 @@ + + + + + + + + @@ -4557,6 +4597,14 @@ + + + + + + + + @@ -4868,6 +4916,14 @@ + + + + + + + + @@ -5018,6 +5074,14 @@ + + + + + + + + @@ -5168,6 +5232,14 @@ + + + + + + + + @@ -5654,6 +5726,11 @@ + + + + + @@ -5853,6 +5930,20 @@ + + + + + + + + + + + + + + @@ -5909,6 +6000,14 @@ + + + + + + + + @@ -5973,6 +6072,14 @@ + + + + + + + + @@ -6045,6 +6152,14 @@ + + + + + + + + @@ -6117,6 +6232,14 @@ + + + + + + + + @@ -6125,6 +6248,14 @@ + + + + + + + + @@ -6887,6 +7018,11 @@ + + + + + @@ -6953,6 +7089,14 @@ + + + + + + + + @@ -6991,6 +7135,11 @@ + + + + + @@ -7041,6 +7190,14 @@ + + + + + + + + @@ -7868,6 +8025,14 @@ + + + + + + + + @@ -7901,6 +8066,9 @@ + + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 zcmY+pRa6|n(lttO3GVLh?(Xh3xVuAe26uONcL=V5;I6?T_zdn2`Oi5I_gl9gx~lft zRjVKRp?B~8Wyrx5$mS3|py!Njy{0Wt4i%@s8v88pK z6fPNA45)|*9+*w5kcg$o)}2g}%JfXe6l9ig4T8ia3Hlw#3f^fAKW63%<~GZJd-0YA z9YjleCs~#Y?V+`#nr+49hhsr$K$k!lg}AZDw@>2j=f7t~5IW6#K|lAX7|^N}lJ)I!km`nrwx> z))1Es16__aXGVzQM0EC8xH+O!nqTFBg9Ci{NwRK*CP<6s`Gq(~#lqb(zOlh6ZDBK* zr$|NDj^s6VanrKa+QC;5>twePaexqRI%RO~OY075y?NN90I|f^(P# zF=b>fZ73b5JzD`#GC3lTQ_B3lMeBWgQUGYnFw*HQC}^z{$6G4j(n4y-pRxPT(d2Wgb%vCH(?+t&Pj z)QM`zc`U`+<~D+9E{4Uj2kc#*6eZMU$4Oj6QMfA^K!rbl`iBix=2sPrs7j@aqIrE zTaZJ2M09>rp$mgyUZ!r2$UK{+DGqgl`n;*qFF~M(r#eh`T{MO?2&j?xgr8FU$u3-` zhRDc_I23LL4)K&xg$^&l-W=!Jp-P(_Ie07q>Je;QLxi8LaEc%;WIacJD_T69egF?7 z;I_Sg_!+qrur8$Hq4grigaiVF>U7uWJ@Hkd&%kmFnQN-P^fq0gB1|uRt!U#X;DnlV zo?yHWTw7g5B;#xxY`adhi4yZn@f(7-Xa(J6S=#d@&rlFw!qfvholE>MEb|VWn^g}G zMSrK&zQ^vDId&ojL!{%{o7?s{7;{+u%L{|tar(gp?Uxq3p?xAysB>0E$eG#$tvkk9 z2Q2gEP17{U6@UD*v({5MP-CTZfvWMItVjb4c;i~WLq&{?Q1(koX&vt7+$z}10{^Id z{KDjGi0JpD7@;~odF__0m|p;5rIrHidOP9^mwKe#-&JX-X@acc)06G{LO1Wu)#gvZ za~y9(fhA%UwkDOVU1LBJ`0ROE z4&)dJKK%mG@+CIm?+wt9f~@xIMr8}UH*K1j| z0pppo{7gv3v{URwxVMeg>Ps!L5IKxm zjac2egjgb0vH5i75$s|sY_RYec#>faqJk|AGgV;v=^%BM(^p{p;(^SVt-88G9f!q; z>p}9E4^f0=01S2pQBE4}9YqE%TV)*hlU^8k9{&=K76+*Ax^r=AkBb%OCP^P2nm0Ri z;D-|Zk?gGeU<12ti2CnPVNA(Pb)02+r|&yTWW-OJO7 zNLb0pps6aN?A~NJp5kj{{IOlf!5KWMleV@-hYLift)D>-7K+tgs=7Ake}oBnIy-y1 z(Hn@Hjw=_(x>dO5ysQsrnE%A*bk0K<-j{1Yqz@#n#jOL^AzCr#wR|WYzqk6i7v)Lf zkXdKxzuu20aP{Tbg$(+9&oh7cd(Uoqqf<#ujb$q4sZ~gxFbQfS zS)kNklyL*{2AELgjZ(LBu*>S(oH5AaJ;YiB@;l@=O%F6B?oanzoYRM^fQ9-<~^=3$H0g^JPMLQo@SZ@QuNvy)tyJ)LSj`+()#fy?{aV4Yg^7dlQ7AQM^3GLCR2dAFR zJjtfKiVqF`l-H_fz0HD|9g>)pOxn}k!vdZ=DO!7Sikm{Z%P6BrRkBS6W?ZB5W&7rT z@uYpf@M@a!z7H&o@-yrcCL^Ff3e7p3T`R9p?@o-acXmbTSa0>ZANzCSgovsd%;i$| zVus`not!oL#(W`L-!9w0jdaECaG4hk{V7IOs676ZquZH~0TX5hDq|)x z6T497l|E?f4)LA>j=S8}b$0LS=I4h|hUFJYJODT8Li@#6kF$k0)@*l{RnM1HQ%?VT ze-Pqlc!~t(oumVC*?5fwR;P6u{tHaZ~*LlD;B)4f? z?lpWfa2P@)g57flVl83Ej%P`2)gGyaPjhvD(%i~{`2b>#3!+y&` z!2nuwHMFA-zUY}f1^0B8<`N)Gr=A4TS@b1qykmd0Pq{?r)+1^^+D(=xasb^Tf!oK9 zBLL+*p6M_#ufgLzgq1zcSwZsZnQWFLC3`Yxdg-2=*tT`J9nrfYt)RF)YryBf8_gW{ zvKbB+oZLehfT)S#<|y1)E0hW^?+AnqPXq9Hu;v3dsMGdr{SVyF63;K<8VcgI#~}1i zLYSBL0K;RTT(;>2x=*!1Di9w0mwr;`CN}kM65|Ay{~z}_^JKOsRaN<~#9O^iiW<5P zYN7r~HV!#Nz~IZU`P>1Xe%4f~K}KcF#X&5kO*G}-)74S*tQ8CietdPcA1Yl;S=Mr# z`#MYY!{s^uo=jn7;k6O%(}fN+*0cWMpt~#n9DR<3NyU?+3D^AgI}S)Cu-Tljg`VY} zX1=fq$?8$DtOeGxE6f8lbS_6Q3C4+LDTO$}_IpM$Xv<|QSC%+Oll^q$y`7o@jD{dp zNDl|&X)r7wETa-#h*d`KXntxI(Y{vLha{$0i7@G8xx^m=c<{lJ9?p-i!^W{%j7-oo z0W^SzZ^(Wkyz*We{lEn%Yhu-ycUOHtrRiVJL4~&S91*D0MrLu}Q>v-Mc?GcWfpyz% zX|UvcN@krFO#@v|CtYM}g|=L3%aMo$E5<@CM%c*;?u>LOTz00@+dt1{yg1y=$h+{|D17U}$*^fE^H&8b431EUE z<9tv0V_#%#&1N#j7AKCj!tTK@J%oFW*ESW<(#Gl#Xs%v<@AitI?s92nLzm<)w3Wkkom1f$gcdUi%g_*jofy&}N#luL<$GVIe{iQkQ)sIHVy zBgItnPBFamrv6Kb{eE($Q(f`ZPeW!Hm%Y@F*OF1sKB{Yy|C>WEv_mfvv-N-jh)B-5 z4a!1WcT@9a+hGaBrc~sz=>G?Q!*Zp^JFRUvBMyNR1;`)j$RhH$6gEyVKhd$&K-CFT zXaWC-Y=fyOnqT84iMn9o5oLEOI(_3fk!W^8-74|q1QhQ|CmT0i=b;6Z3u?E{p7V{? z;f#Q-33!L+4&QQcZ~GAqu$NS{M;u%`+#9=7^Oa5PKvCCCWNG_~l(CidS!+xr-*gg{ z$UQ`_1tLT_9jB=Hckkwu>G{s0b0F4bnR7GibmHo?>TR&<3?D;5Fb#gd8*wYa$$~ar z7epl1qM)L{kwiNjQk}?)CFpNTd?0wAOUZ|gC{Ub|c-7h~+Rm(JbdoRe!RNVBQi!M8 z+~U6E2X&KSA*T6KJvsqwqZl#1&==Dm(#b^&VAKQ>7ygv*Fyr;)q9*^F@dCTg2g!w~ z%hg)UXAUyIpIbLXJv1nZX+a_C)BOH2hUim|>=JHCRf(!dtTidb&*~I!JrfRe+PO>w z@ox$G2a3i9d_N9J=|2$y2m-P&#PTNwe!oLBZFs;z|F5kXvBDn<)WwE0E3$ow=zg3R zK(9;sf0t;VEV3@gAg7jRtnj%-6O@!Hvg*;XcUAw}!=2*aErvB(eQIm(-UGmq^J=XN zTqJo$Y|WKo^HlBF3BXJrA#}7ZLg=r*w`I*~Ix`o&2k8^(0mt8Rp=A>F`&gehhp@Jy z^e^#B2!~$LvNCKugg)8)-G%&THdk~kfextilegP9?#C#()F59U$&eo(h|5>ceo*Em z{PEE79T$YP|Kr7K`WBHbtQwyxFkCl6xX&+oUf90B5xoi3_5KHHCyEE*oPbOQkfMz& z6^hT8_NXd2iWk{q9IKae1{_7hMPH8I7_BMtVOM4 z6jm?E0QJOn$qrgsJ`9w##GB9?G})-GXSQo6(tYS(Q0-Ct$co?Zzl0?NHsDRron?;_ zZZgQg)%XW>P?8_&zoGuF(>Och2kEJXsu1_X&~w87x!b z>~h!a>e7{`p@+#hXF88wI*JeWRZ;J4ev4<}HWf|Z;(7$E!S5l9wzBHFe>^I{2`a;a)QnAwa2xv1e(bq$<}!8o^ofGvYpk7dBR+`*%iE;hUY5 zaHF}OjGO9r*{%lmcK^uFiTHgoUD`^9Nx@~;Bg!V* zuuJ&ti{DQiq7RyJAR94wem{}cPK1J(Yxnn_{=>?USqz-~&QXRStS^s-7TksZ$AEI! z#og36s3JGtGU{CnDHRFtipFqvrE*gw7_K@NN0h+ItTq@4fqN!HeQU1y7*X?9+IfZT4Vxebpt z%#VzgdDK~-&+=Z*#>=n#XUhNvBZp3=Cr41jMqwJkHLf3L7Vm~V#GgJ(Jpii~PmJ#s zA7Ft!{xD@z>9DUb4JbiUBdNEcU4BO$651iN*mp*f)HbRRM`Cx5cR?5IfEcU{IZWwf zz(M6CDv)>xa3x}K6%tP^i15P1&&DOLK=k~+jNR$UK3frSl+|PjSC-dBItvD~LL! z>_g(YYdO4k(5EbPOw+v+;G7~jYm>F@Ai|o`gs%F)F8tDz$dl7Q%aCe|v|$UkAul_R zNlA-beBX^IJU?kgS`E$it7nF4DaI!SJAGq)2P&Few(-|tp z?K+%D3e4{pfkayrcbm0ftu6Ol2ZzdKM+4i!hNP3NRL`EvvZJ3yvNr2MV%igZ4kj``Qrdb_OI$7jWP z;l0DYf&0(-*QcP5zrP`HVznW+SbH63Qx$7_9~NjRNg7eKqI!UJ=XH`g^=t8GiFTu( z?2L{JKEu%jJx&XjNzU(*!ZNmL1@RlJA0G$2_LrAb_7lmjil(GSlSM zwTes`m+3R;3#N~Xg#9owh3ycXV8@ZlaY_16kpPFA={721b~URO4HD3sp%fmkZM}k) zZB0#)kP=RkNB~R-MCk8aljG_bagt4vIb~8)BV%(b8_;)&Kf9GX+%O_cNG|(D$!3&D zL(I8}*LqN5NntipFlN13=`D>6!{D@CFMBH0kW3=HccJV+xW~|$qeFR5i-2{X+iWMu zI2$gepQ)H_B%ip_BlWOQ*|pErXs|4ir{IHccgaIJ84irE{?+$KDABXr&f`jB^V-c% z$$u`uU1YB^{<+UN2cNg#7&0bz@yF?5>j|;)5&IV3wIQp58X#OE-M^$HdyvL|Um5t? zhZlAG!Mz%XkUe3t471JM*Yur}o30vzu6RN7gJyNcf!IItsDO730mcJ*O!~V``y5=3 zNJGp34DZ}wd1H6V`Uuy%es>BiO_aE-S8jzir#$& zyk)@2a5tP$@g%jW^b^JGdo)X@Q%sE`^lDQmY9m%uDFpPX`w9%=yQ+nneMm#OaXcD` z9}{tn5A2b2z9783vL2_jSao?uxJhWJoq%47*RafM4o0@gY(p)F>qT4^XM5GLzV#6j zC+HoGhAne7o_w{WUo(B++z7lU3Y0k1rYv9|TSv0vR-Du(5=VakbbelgZTeDn+a_Wv zq_j-^+Qz1WAl;Zg>ahX|CERbX1V%B!hTKN?M}fGoA07M(WU&NfT&TmN`P@56U2 z^)vLDs|Ln~0iTtn-?KTeQl@T&bskJFuTUS!m+$CS9vnd}8(UMO|Kv6TCfGN9NUu&4 zL{)GTxPq>fwsJ~aU=4Qhuq8*RzDsP(LZh$BHezq&9gK$IS<|DYbm})$QTGCS6T;Dr zEkLct!b+#<1r9OKG@P!f1wm8>=Nz!7OzJm!g<+`?N3;YaA3(P@EL=(sTaRMDD!c8=-XN^4BXp(eVkj$NmEMYPP>YJ4bJ3yUud z<3BeJAJ$6z^TuywnfH5lv#$lgwraNw{IV=tIznPH1DT`v-5yS=!)J<}xxl}uZf9azA2A97Haf!;<3y01hlw?dWNEv@TLi1s-mO4vmIT%O_42nS z$VRWrs9NngqRRkWAnWkn%`Rw@?wH|)7XL`EL5EZu$qyJW31&CB^T_)qwIv!{;E_6 zo-9XAryQRlk-O0>o#-SZO>|6OYq;}<*>Wu1AsVRiXY4f8qb;+sItv3AyS!4Ry+q}) zA!pAB|BmC;=RIOk^^vlsEH(!Q!7_1FK~ZB2err*o!+b(r=m1b?$6d!%zmN+69LXnT z&gRmM+n_R-F@sT*IYv0_mGPvur!u`iWbQO7SqiGFLeY&yga zf`lM&B74FA2C?N@8_z652fjhBEoDUKbP8hL{0{HAF%qDo7)o3=3rg#6)T7%%5^wl% z9R0*S*<~>nzYOdQk2l`9h#t+gJy_xujw6xjV(8S<_DbVg61&pT%Hi42l%D73G?adn znB%UdNM0p}lEF-P2%TAMam2zpQev71e>a$$%i+r~b+D9G9pF|oY_*(-u*89oKsXLY+UIbqq)MQ%(GYS{(*n_S_*RN$*~`zUtab%0aKwhx znc)Yo?{xq1sJCgQD)TeTci1ucvbez9q=A72H(-SB18Kl&6^vHV8^i!p@>iF!DIw17 z+8Q)TNisB7>pwyww4y)yJx*wX6SJO78eLBC-ar1+k$Z9fy;wBD|3kzI{<+l*>PSY^ z_?nLOZaeWbU@C3hfK?X;Di*8CHCPkx2qco6(ZyJdqSzp^TJ_5Lpa0UP{Gy+!b0Lr% z@xYxSjUKoY6L#>$qx~KD$-0=|OF7zhVP~ntMgEALYPIfhj@+ z!;JJ7te>CcovruwHsJH6Lta$nm|%^C@=V-rmhU{+I~0(|XHQ9jt@L7pb{gx#{4r!) zg($FyFTslcgu(~6lYr$nW?)%*l#VJ=R-jxK(x=t1bWlu(nL66T#qj%3aZ@uVhy}Co zDU_q61DD5FqqJ*#c|(M5tV)XBN?Ac^12*q)VN4yKPJ|#==S_`_QD9|0ls!`2)SwuHDRA_OfXQDq3%qW&MZB}Z!=k-9xqev8jHz(H z{^D@cIB~QiK>~wa)A&^Ll^Wi6QgCzU;iv-BHsLBs zH7=jN%|>0S`SjP%M&AF1PNVDp_FZ?2Bm@7`DC&v(pYrw!!yD#4 z6+<=HS0Ln6MhoKxF<%~H`y20{vf#pxh=;j{zY381gvAFekgG|>G1zo8$&az{V=;JR zy_puF4$L$?EMhT?;TpQoR*j16ll`#AS4e96C}yp_aGKkBe?1H|k_;gG-~Xorc<;lI zkB}fB{$c-D2mGA&{rm<*@F5)c3X+6??g~XoEwuzSuch0D@W~P5(2I8v8F$c2$Vw51 zP#YLSBDqtWW^EYBl^QYHF+MA7am6f4DOhwnJM=W9$uvMOsZ%_~?)2C#wb?CkI$7{K zEi)=#|5pFvg^){zK5kpBLjB2kZ+$ZB|L=W|aNwyyb(gC2l7bcpx{E-H@)q6@D6N^xh`{1E%ItF2$eeB_SjI@b2WgTpS1thwg&n`jiIzw^TtXUyB{00($GIq>vbj|}bav}}Q_~wp3>k8!E@hVC;OMUTu|= zAy#vXH*GrUHu7^cNZWe1>y;2(51js9wbu+R3Aa*(wzH9+X0dIsf&gc_x|_LP z>~CF^?(~U}+l~ehe|i>?4eo!xkq&Lk+RR-1duNP#o~>@1x)s&i&u zRaYL@+D&_M|JLI6fHbEr_`U;HgPTh#E3?sB)A$*gqyBgg*ql|a-m*TX5rACbWKCE6 zdeQ`v8m6>g^ugv`p|HY^#1QZrGGUj0^HVDc@{?Q0yhalbBEV{+|HzC^-{&e{5K%z9 z6Bxtnfu1!@Mp+Q&*&~;FOg&*Vm<@4b;{FG0-!UUXX!|)1w}op!B_|7_s~d(+=9Gba zKp8`LaB4D(H=cGcspJ_TjYaOwMb=sGn^gtUVhK!UI~2KKYEE-NC}F>+BEY7IVvy%KRvm00tg!Q`y=er}wpEetX}K@;}(}{s9AzV#q2@ zBy7}->|N?13POrs`;U?(qAG(I$~Gt+Rgw%aNZ_0fs_utVvRJT-7z4!@x36v@=NBX=IqkK{#Kg0w48de@?#Yb4M(Svj5=T+<ONr8-oh7l?Cji@+erqur zFhZ=9|Lk=$`c}v4u`)-!!UI=!9Jo@h&7p4RlS#u! zZ7-prn75JkV?VjptX;@$#`U`{vB!=Z?V`T*FBF>J?vsML7e6@2GbUteMFfX-TUu{2 zLNIG*;dV)8GV8gAgEf#)X3A>p3^CRka1v?~8x^anBhQ=L=LsOl=&pcOYHo98m##ye z34MtGCDK!`ptl?taGMr5q{!zVc? zG00e){TV?`YA9eB;(lA3lXI?RrB4BYQGk?vOmTIUJED=(`_*gtn2DB-t4WW54as*W zb2kD-lWX>lb$+W!VFakki>B^Vc+u$?NLF>)!U%b@Y}gYJ>m2H=^x0=nsE0TF^Yu0h ztgH8-o1%+jCk(+&`|)tTfEVHq0cMeFa{Uz)X$;fCq%Y=SOWML6bYfeP8j5hktL`KK z(18`XrUn&WN9PtFxh&dX`y~YBsmdhi7Kw%tKzM%^VEhdD<_XkulW-x=JN6OPbFI4@ zzDDRN+f=@{0h*MswwOqG6gJ?{NuHx(y-|FUGsxyZ*x0~$MW(eY>vqq4Fh#t7uzw=- zKB?|!0N~!h^AMdLa)oR!Ca#HZ9&Zf)ghuO<^RN)4twRlygHnQG(BE{cDc5E}OF4;xss6gYyV~EcJvJkX)xNWb=@yw!uq0v-sf^rvkp-;?DPWK@*SEw|V;IH=7 zfQqEV_>DjOPT~8X*J|H8=&RnzK4~S7ML~nLX^%s-Vqc^aWy7N$y57qciZGcqy#=zU zs8hcHiI=D$+RB{|62{ohCTiaML6FI4Uhzo5D{Jik@poCs0w7F)*w}F4r0sJ~#u-72 z5bK=ANt=M$Dh5NKnxGsg9NRR?WD-x|FhTwBjd zD<-K>44DB~i%frJOfnzh1R>PRY34kw!6~p3M$JLaD1r@`=h)~Ngks-(gdXh^Q?BTP zZ^Zj5w1AwtuR2$~E7s9iZdF}z%pv1em^V2rM{1tLUY@-+Sc0(9jA|iZWml1;v13=U zHf?y@#mb--7z6$ue>`qjhE~brk$AY-RG90~5wcBbDReXR2)pKg{L>;H(DI`U!MLNQ zY9rFJP@ZQ}jlcMh%WSCo%vf+nd0Gmd*F%KMIe>slCUh)8Ma|;M_I+v#;|ueg9oLg; zq2HtZX%&#F7vdpNlkX?}(C7dGC^y#NB#m4%69RzTNrk%4ol~hSI%>2r6B|*ZkW(*P z;u#s;+faHo{tfy+1L^RzWDi*^JR0iY(zJDB36y_QJ+|E-2x+cY z!V8uLNktH~q>WQZuY!Ap66WP|E!0PA1jK~)^8oJVGbspJs6QL!!-5Qm7 zHYI|_`Actg?vDzdg5{86w@GS$G6ANzff7->6i5pB$T4O}`fZ_;{217Om0gN5zTr12 z5mW{hCzCE-QubjxN$TAE-XgI-8dTY@OZmq`y+y_>dk*(qXF0{nam|q@~i}Utp*k{yurq(DW54hkDT4bbg z=_etM?Nf5W^o-HEu9_?&xEqPg^P^mTxLH8n%u$!mWvFG|{&)jtnU&6|5-`~eaNz0%D1BDo`{ zS1N5(KW5v^2eLdd_%`uaRndF@h0Uo6=M|8?b~KbOLZk{HXEnGmtgZXf2inI*1r%n! zQ3&%RI4r{f&dwW~HwH0Ked9b!k6{>_19H z_Ai>5IChDMY(FfMyG%;30?SQ{iV9KyGru62+Y)~qSQ91}b~}w<&*}R&1c#$O`H@~c z5)2S_eXx}M#N{MuGeQS9@#UJB@;W_j50b}jIhxMPloEFQZdvwxiU^RYycTzgK)-vl3LT&$L8~@68$C8~5_U{cR$E#w*x65(qw&eoL@>%ZHvj zWnEMlSh*(o&oy|J7eJ5OD`ssy%F?*Vp?`Cq;FShyl{ZoKCG5g{y}>usznni#8ki(i zO{w@n{iAj1_ooX@+s*!uW60WcH~*bNOT6z%0jVML5};wVrQp~`Uss_{cO2oud_nNA8^B$?07fJ6?iI)Q zuo9G)O-z)DqstrBqf>B%S05hf-wep0@$BFHKSrkZ{za3D)yVzRz)2{wf8(Wp+xyAM z$rtyx$gi3A=V~V!`Q3;BM0$>*VVtxEM|xDL^gew7ydy3Q6YzD&THRz*q33Ms_D;M- zbCx1Ft#UNB)V3bf`~{ImI72OTp^|bF8?G8#FRj+Biy8ET5#rA3sd|0FR@U(LAJ%w8 zS1%n8Z=Amhw)92rIsof=YVWF4jw&F*j1LG@-`+cR0-~2LqXRH8(Ccne{y#MCPncF64U`0uO zWmi$dlii~1D0rLR{qc|_2M!C$t8^=G7xQY)9!#Y331A|>N)EhmyVdLWL9I3YLJ`7? zZmpqUJB>Ni9oiL)^1IK1UoMyhWE{$9M2M6Xi zPKk7GpMsA6vjZbU7~i+u|J6Nk|Ci!Y3UMUT2|`M;JsNQACdJ%ooo9Yt{?A+0hMpxi znEa~~sxC>rKrU6bd=WRb;%wsH>A#j4{({&1GYSNR57Gama(3)2A;SM>qop}l>Jk2* zn1+C$fIxuwzg3mCU#SOqb-wOCb6mBcYlA5+mt<&_J~sBxc(GQtBFINUO~Mr7<-uu($>P HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ zF^}Ea+#Je`Xy6;#D0FPnSrR%Y!QGA~NA^{oWmW8C<3dr{x6wWQ{4+bzemqV5W$i5~ z=J0jXZ>uZb>DT@0Ks?4QJ{`z?8JWl3$y;2pj#$XP*pv$>$g(z43{YH9KmmR6<#sIn zA`#=0#sgycaBQ^&}Xba!|KaZ8~b30v~nLt z9%#gz_*=~KD{3t^X~l>480*}PhKN=??g`RV|4Ud{Gyyl187MJ}r(#e+H$GEdI+p1s zq_25h;fV)$EPK%Dw-(G=f`yHB-_tttsC!?k7*#!|4a>`Ahj8nm?&n>NRs%jkZW^3-0P_yMP5&*6a26{MRj1&TPF zyE#|c)5uUHzMWx=rMKpuPih*V=S;W3MzIZTw2uTbr}8`p2bm+Z6Sa%vvWAWSf4H)p(+ zSQ8;EvUa#wqWV+9vmIio(%7wukK2SwjUS8Yl%Rq%=~PU)2$Tvm6`1!r3H@U#_|bB0 zmlT1PS3wPB(b&^+@YY7Y$n4l3mV3-X0$>z|gZp6O*Lhzn&?Gad2ZCF;+#95-Y?#y+ z?*l@Yf=a4w{Px=o!N|3~_XKfk&G;fN>Ps&dp2FpA~qD=0~=!NOS@B#XAKKkND>Y{4>rqxrViKD7;?>j8`R` z&G)3FN|dfsxnaI^!d1G%=>AbTTxZWo;n-DLrQ!sj=f~VAOe5zhGS(dgx|!ls62fbX zV@<7Ck^!}R=`Swr?(7w1rY6Nmq~sfXJ?TiKJLn=&SQdEt9$@0 zA+h1Wbwbri0s-stc8yVq;mRa6@kEf8^KXUz&jcic!+avDvvJFa>k0ioWug=T3oPw; zyj4it&0@>_*uI@2=^+T7sL1_!^aJW@Xfo8aC#3^WtQC7fET8b9C} z*u^ue6Ojn z7@(eskJ2+cNnH9~VyfIh<-|7!je~vGy*odz(sk-u$~SrYF3glruZ*W`{sqnS+9=;Z zh{D@MSG91%lr&ua8%$sJF%y1I<|e;EdfJykY8#D$Hc_81n5`$7;1N|b0tvvPLzSg& zn7!5x?T*@rQUKcUhTIjV(rw*5oQYlm5DbEO?60#mohHfbR$3_x#+PZoYi@Vd4`#YgKyTd^!4n{fN~WZDY61sAOm6 zl!d^i*a01QxpWM9Pcl?&{RgO}uq%ErOk5WpECvnfEh!*YP&1Sl)uTN4hg??Vqs~i5 zYsfufz3?{TtwuBN=`0~Qg1PlWH#OGG$ zLLWU17$v``)CE1cds_7kj8mJ{-+l8{DS|zAQ&3|qpOY=!J|kXUhXue9|H>4gqk|n) z-i34GmxLFj8asb3D#D&=ya*a5`C<=o?G;Ev^LV%;l#nH#O=7Nh@z1Do>j6Q;I5S2P zhg|AZbC&|c7}uSJt57s2IK#rSWuararn-02dkptTjo*R{c5o(bWV}_k3BBnKcE|6l zrHl&ezUyw^DmaMdDFVn<8ZY=7_{u{uW&*F<7Al6};lD(u;SB=RpIwI)PTyL=e25h* zGi{lRT}snjbMK~IUx|EGonH+w;iC2Ws)x>=5_{5$m?K z5(*1jMn%u0V1Y%m@`YS3kskt~`1p(rA4uk;Cs!w^KL$w>MH)+cP6|XKr4FfHIATJH z!EGAK4N>1yFR`-zW|w%ByRe#=&kA&#WyUldDGpt!wf-8SFWiSi!5QZL+l7*CE?u!NW1T$<1rdLJ9y3u{_zvHaM?#Rm4 zFk}^1!ffcrB|XK3gsO-s=wr*sUe&^$yN|KxrA)uW00Gu60%pw_+DcUjW`oW<35OC8 zq2{j8SgC}W$?10pvFU83(SL$%C?Kctu3*cs0aa%q!fjn1%xD*Jrm!F3HGR9-C{b?- zHp(cL;ezXMpL@0-1v0DMWddSDNZ5h?q50cOZyVi#bU3&PWE=(hpVn|M4_KYG5h9LffKNRsfhr^=SYiKg?#r&HNMi2@cd4aYL9lw(5_IvQJ zcB*DD()hUSAD^PdA0y|QrVnqwgI@pUXZXjHq3lG2OU&7sPOxxU$Y3&ytj6Qb=2#cC z;{d-{k|xI*bu+Vy&N+}{i(+1me!M;nshY_*&ZQLTGG*xNw#{RpI`3^eGfHck+*38NRgiGahkFethtVY=czJs#)VVc{T65rhU#3Vf?X)8f0)X{w!J3J{z|Sq|%?)nA+zo?$>L9@o`Kc|*7sJo4UjIqu0Ir~S5k^vEH};6K?-dZ0h*m%-1L zf!VC%YbM1~sZOG5zu&Sh>R;(md*_)kGHP)<;OA44W?y53PI%{&@MEN}9TOiqu+1a3AGetBr$c)Ao3OX>iGxmA;^^_alwS818r4Pn&uYe^;z6dh z)68T|AN=hjNdGpF7n>y+RTAZc9&opTXf zqWfK_dUv=mW{p_vN>|(cIkd(+Jy}qnK{IW%X*3!l`^H~FbAHwof+vLZ0C2ZXN1$v7 zgN&R9c8IO`fkR{6U%ERq8FN<1DQYbAN0-pH7EfcA{A&nhT!Be>jj>J!bNRw4NF|}! z1c70_#fkk!VQ!q1h2ff@`yDyrI1`np>*e#D4-Z~*!T^8#o*$V~!8bWQaie?P@KGBb z8rXc!YDL!$3ZgZZ%;-%~0Kn<+d+{xJ$stQbtN8GWV?MCJvzPU|(E(1z;rFw{&6vy) z3*@y%7Tx8rH-p$boS>bLyod?OKRE8v`QSBvGfY6f}_{Zo1q85xoyOF16n~yHx2W ziydUoYLkJmzq|n&2S(O!ZmLdP1(o1Jsq88cX)x3V-BK5eF&0e_0G!5?U7&3KN0`mc zH&Lt)q8!d_VgzxyL^(@xrbp2y)Hmr^V48));RSfE=*Ly0uh9!$3dv-vMZr2URf@l5zdwLjGZB zugY>7_fd_vbV*Qv1?H~>Z%RD%nEeFSI$n$$Lrpc6g>i4+XdBB!%zM$Bhrz5Swzyg? z$~I~n@~-wTBY3-T&pr+|gC+OHDoR?I(eLWa{Z#Rsh>lc~%u0!&R|s0pA*w<7QZ}{i z*AFr~0F3y~f$MGh_HDL7J_1?SxKL}fWIk!$G}`^{)xh*dZ5kK>xGL9>V`WZZg_ z)^Vm)EQK`yfh5KiR(vb&aHvhich z_5o+{d~0+4BEBqYJXyXBIEb1UgVDs;a!N2$9WA>CbfrWryqT25)S4E4)QXBd*3jN} z?phkAt`1rKW?xoLzEm!*IfkH|P>BtECVr0l8-IGk_`UjE#IWkUGqvyS+dMrCnFl<7RCgSMX^qn|Ld_4iYRldO zY&cHhv)GDo8nKvKwAbfyLR%t?9gG?R7~PSD#4D-;?F&!kV59O}neYut5AGbKwy-(U zqyBi=&Mgj|VIo>$u!DHM`R7O?W8-idbePuxiJMH``6c_5L-chKd}=rGC5Gfrc{f!* zWFEBm?l@_b7kzY7%1RQQbG5V<4=ZlkZ%sF74Q|mKOc7Ak7dP2#quiGcZ0_J%7Q?j{ zv9{WFw;n5G-Mn%r#0R;{jLt{yy}9J6rQ(>X9pJ`7Xy?Zv z=lNit#qXaq?CnElK^zF~sG}U5oCpR0T>FH=ZX}Prju$);?;VOhFH8L3I><9P_A|C+ z{;>~dk%9rrq(snjsEm}oUz2FQ21MCG*e?g)?{!&|eg7PX@I+Q0!hL6C7ZVY|g2E>i zr!Ri2@OfEu$)d52+>+cpgh6Z;cLYCZ&EMR0i<^~4&wEu_bdo;y^6}+U2GIQgW$|Od z_jg{O=pU>0-H$P-EOlWyQy#W0r@@_uT}Lg+!d5NxMii7aT1=|qm6BRaWOf{Pws54v zTu=}LR!V(JzI07>QR;;px0+zq=(s+XH-0~rVbmGp8<)7G+Jf)UYs<$Dd>-K+4}CsD zS}KYLmkbRvjwBO3PB%2@j(vOpm)!JABH_E7X^f#V-bzifSaKtE)|QrczC1$sC<<*Y z$hY*3E10fYk`2W09gM_U<2>+r^+ro$Bqh-O7uSa)cfPE_<#^O) zF+5V;-8LaCLKdIh3UB@idQZL`0Vx8`OE#6*1<;8(zi&E7MWB1S%~HAm%axyIHN2vd zA(pJGm_PraB0Aat3~?obWBs?iSc*NhM!{-l_WNCx4@F7I?)5&oI|z{o@JKd1HZ}zf*#}JjK3$ z-;3V*WJZvUcKvSOBH4c7C{fl8oRw8-vfgKQjNiR|KhQ%k6hWNEke(k8w-Ro| z7Y3)FsY-?7%;VT64vRM)l0%&HI~BXkSAOV#F3Bf#|3QLZM%6C{paqLTb3MU-_)`{R zRdfVQ)uX90VCa3ja$8m;cdtxQ*(tNjIfVb%#TCJWeH?o4RY#LWpyZBJHR| z6G-!4W5O^Z8U}e5GfZ!_M{B``ve{r0Z#CXV0x@~X#Pc;}{{ClY_uw^=wWurj0RKnoFzeY` z;gS!PCLCo*c}-hLc?C&wv&>P1hH75=p#;D3{Q8UZ0ctX!b)_@Ur=WCMEuz>pTs$@s z#7bIutL9Pm2FDb~d+H}uBI#pu6R}T{nzpz9U0XLb9lu@=9bTY&PEyFwhHHtXFX~6C zrcg|qqTk(|MIM%KQ<@j=DOjt|V)+8K26wE_CBNnZTg+Z+s}AU|jp6CFoIptG1{J*# z7Ne~l;ba*=bSwAMQ|Vq#fW~+je4PXA91YFzBubNF?ovIOw-$C-8=Ehed{lGD0}(Id zRe4sh8L>&T%{>8o))he}eE;5_ zxoXk3wX?MyNl-xF!q1d$G?=wp^`@09(jU&X zOqZIBI#dN`2PJNdATR3ivtub|nO$dulSaP|e4)WXF1YAGN1pDQIbIjXFG!oC85Mt; zW$eteoL{y^5t4TMRwP$jNPjZFpGsWnGe=jMMqKtcZm9Y9PFZLi*1p@qoKKub^T@2+ zk$@*KYdQ?Z`}<%4ALwk*Yc{(WTf@#u;as(fvE^9{Gk)lWbJP*SjttWofV0s?AB({~l zZI1hZVWFT~W-T?nfMMcnCS4-#6H-MU7H$KxD;yaM46K4Kc@~Q>xzB+QnD_I`b_l3m zo9pRx46b!p?a^&zCDwygqqV3epjs(s0NQI6ARA1n!Yy-qduipxQ& zUAlqRpNjBS+y-ZheD(!R;F}&^V_}b_gqH%tVZ5%%ziO7k^w=es+wZtK^i*vmrWNLMs{oWu_CIov|s1raZiS)>38>pYu;i+-t zI_DiNe6aA4KTZ2P09qPj(0~K4nUq^0+f(2$g`229zkG4jLzRvJUWE0oF1XHL4t3UN zDH466G56sy9hTZoAJB!C3;@F;ONxEk5u6Mv%zdo}Rq`=* zw1n7MOhfNSV48TS989ArIcj`C%Gk8~93~u>)!Yt2b4ZriKj9x2d`H2HQNJ=I>hkDlcZn zqRj>!;oRMTIOu zx|Zfsu~v76T{z7AC(jxj^c@tnJHZtGPsq$DE!8kqvkDx5W?KUJPL+!Ffpwfa+|5z5 zKPCiOPqZZrAG;2%OH0T$W|`C@C*!Z`@Wkop{CTjB&Tk`+{XPnt`ND`Haz;xV`H^RS zyXYtw@WlqTvToi;=mq1<-|IQ(gcOpU%)b#_46|IuWL#4$oYLbqwuk6=Q@xZaJSKVF zZcHs~ZBl;&lF3=+nK; zF`4gSCeZXlwmC_t4I`#PUNQ*)Uv&oGxMALip|sxv^lyVV73tKI7)+QY5=tEMas{vTD-BaTJ^*Y6gq~PU;F5X!sxqiq$iFCo+Uv7m%1w((=e}Vf*=dtds|6 zbX}91!G?C*KG03eHoN}RZS9DJxa&8YwNCT8?JxMXyZqZr13NA|GB{+vG`08C{V(yy zf*Lw$+tYSU_+dI`3n{bMrPdDb`A=Mkg!O=k>1|*3MC8j~- zXL79J4E=U^H=iBLTeHE_OKzE&dws8RNynsSJ!d;`zK?P92U{f)xvD7VQVosrXZrL+ z6lMVdD1YgL;%(1cq{#bS6yXmp|DS@nax#AqqlZhtUQdh<^2vr5`EpAO

LGYq)sa(w9^3-f}NHy=GR4v%t2YZly3m1G@5y`xBh_HGrD%f z>;|Ty?9FiJAc&UVD(StT4I` zfVQwxhE9bXE6r2mKO8Ag7{L^jCyqQb0QqKDPE=RAgqn8q1O^>(z7h5kE(6va%QqRZ zkIOmp(})rLSS(2{=C12e&@!W2=Jel-^_R``0xHO^+t!(oXbcv5yhD4g*$t_F)_5Dl zSVCgesW%;DtYPCFs{G;GX_o?1J3;QQPPv)rWw;>} zJ&KwnUqwNXloNXlK_+pNDfI~hON#SokVJb&ilg8d7^NWo2ZQymCqQMnjfi>ePibjr z-Z@q!?RGN$Mj}Nk){X_vaj6?Mj$>ACR*z|6MsXy3VZ^PFn@yHkPo(>m(iWepn8SC@ z>D2;R4m+gDRZ=SIX!b+CP(qE=JDIUkn=D$aUu+Ihn9-+k1LS3PreQg0N5eWIG@x${nC3v^7caS>1!PKNAY9J z#}E}Q9w#SP>(GY7Hbj&z4$Li6o5taBO|4+F`yS9zq*LJ<38wy4I>HA9(&GYrk4dLajKGww))BWli6Ln1A^Lda@N~p+snkb9C z@OthI+<##vp8!HVQT4Wk(=@zQ{OvZ$EKWS73+JHb)eYLGD-cqi6^|vd$<+IHuc?Nq zW7JertT~3))4?J|28n$I@nAD0c1%9C&IVhEZX~mUsf{efyS(XNG%ch;!N~d7S(Ri7 zb&=BuON95aVA&kLn6&MVU|x}xPMp7xwWxNU1wS+F6#y}1@^wQZB*(&ecT?RnQcI}Y z2*z!^!D?gDUhc@;M^OpLs4mq>C&p{}OWVv<)S9KMars@0JQ{c_ScGsFo3BJ)Irg++ zAWwypJdTO-_{Uh8m(Z!3KL7K{ZZzKHj;{M8I$mV>k znTM?sa0);^=X^cglL`uC+^J)M7nEa$w=VwFULg~%DJllw+7dJAj3{qnP5i3@wr7%y zjXp?Wl2%Th=my&3u?Q$RV6N5tzKMSPTsc#J+-cDDp~qFB6bL2C8AS7Y3PKtVhdhl) zIaLqH5+OnWPWSt(lQCgkN8lczc-V%_iZ{>#1%Z$N*>lu#S;0MZ$T2Y8Kg!U;hAZj> z6S#%$DQ_`Ic%Zr@?}GgjRXg@qTj^17n`65oJ@Wj0u1X8&+UVd|Xs?J+i_^GZ94m6= zUc96~Q`OJvlKB_Lr15*Yw_PUPEr?f?H&00b^-W%26mD)(n(rGGNfK9~2h=C>p-7BZ zFd&*&Msdu{w~(eyFOglwCPH^Rb}O(N7LtS+nnEwDx*pGD?|&9Si~M43a+*L(b0$5A zv`T`(G3xO;I_sx;FwTP21ZlfDpz zOo?}Vlgf~fo{YWm@n_JyD*frOg{XsvBA~|Tn4V6hu>Gd>89-rblfVJUaGvj6X%NZ} z$tFF9sx=4_$*c~G`9iPLGh@=sV+O{D2-t*K@J7H=`V+oVt}8?04WwU3h1BgS!f%1P zFak-T#7`TtLcR=Yz>g0R!ZQrH!YiZOQN=_V-UyncN1Rc18?KY?#O`v#JK+pq0K$~H z3D@v9DZF42R)b9#BBX{^$DOMlJ!g)Gc za{o-1e%F6NvgKq9tC8pV+9S$;9*zNv{J*)n&dmf~anP1)4~N%~h#c(=B#3*KgzhCKhFdgDoWi2IDog{RVyzK|Y`rCUs3T~pJMmdZJy4?b z&s5G=zhf**(t7Y^oC_mcTsE-{^}wiaoUu&?kojLKs>SJPxjcP>{a5CbXCx92AcBE) zHtqP}LjZ{W>PH?Tu(E0X=%{PBMW@F_?#7b&#!^q`<-5$ur+-q6 z{dn=(^UZw6*3-XM_(=@<1_*i&XM4=0t5u!gm6 z{UlmNGPKgO_;e;q9|#esq~Sq`<}%d{+sRmhvsA{5i*91=tub>OZZ%)xUA#4q$dDyy z1`w4%?OPLg3JeZb#cqSMO?*Xn%|-FCcuH2i2fn_{IFusub6;NQdN|7TD1N?%E8*g? z$apAt@cEe!I%jB=*q$p_3=t_5R0ph%{qaq+QDg!c99Y!Xa!&oDZOeis_ot)gNXr{l zdY$|So2Qed2Y7KMNBrS^E169kG%h<+z{Z_p_;shB!uY)>yAVcK=&!bg`lVg)4T1|7 z0}7FpfydVH4F87K@c!nEG+WGKm{Ouo)Slpl;#qcEIQ0zdMfLA#;dBxYw;p;KoVv6| z3_D5&7rJdG12CnDSvZUW?$UC6^UVSW^|vw|o-_4bz)(w5(3AiVhpeT(|=f#x_}E?s#qHZF#xA6AF_ujl$G z-jHD%q(d2}v2PhXx&6YWps~m(^+RXl91Q#xRRJBhjKl$FG4bk);|ag;ieUZ&!Ii3$ z(iGz1+0m7#g5>ASldBbNZL=ZHh=tmmJt$!71; zIML2GhEz1pg@1rQN(M^_691wAGkJ@Pga_05WuQ6! zG5RkGY2^`@(H~pp7&Ga+Pwh3L!Njj!-rc;^bTIfo5hP@H##1X8xUZJckrx>id`bAd3QUx9GuomqBYZ!uN1-&o zvTxC?;p8vL67&fW8fw(YOqt>L@bdLrEF*3OgYe$4n4{ zEB40LiU#6-0@5jdN`0w}N0qi@c0~oT2FP z)LNk&a82my?jv(tQpiMi$TK_L@lub#lsM$R{Dk?Ya@%%%huZkct~tSWM714c!45k}-ZLVA-bVM`>|_ZBbW_m-7| z3U%xrAhi}n?T(2F{_n4EZ10inkIFl#y09?7$uwBoJgqY8vylwev)fDOn;>0R!aEnV zBz%j0Mqpx~EZU3q@%+oV7;}|vt7$~ou@faEIq{p?FY$XXg&6*K)b_LP=}gi9`Bij3 zN`zEo|B6*|-;>S`rNa^BKRDbDAk>X#MsR`EvL>6bqU@SaDDs z8>bu@3YdRaWs*Te@G-UHjU%F~kTHw5(0PVJ+pwh#ha2u;DB+UMo@A5UYIl#5rtBV- zGX_hIpw}3C@H*Us(Cc-d#-gNrG#w$(9+S=GxO>3SR`SE2fHZ2KrDc#_C^$jI>Y}#; zMwY=R6@+dWi~0RXw(c@3GZ&%~9K(q&ee0Zw;pwL`E_tZak-#8^_b)Dpyi73^he?xV zXJ08&wh5-M&}qy4f7!D&=E)puDD(Nmg1d_(j`4LvxM5x_huNg-pGG%9rYqO6mImyJ@}*3Y>^3OvcnTG%EV1) zq_Ap?Z!Iw__7#D=pOWnQN$gB!Mr0!9yx|g<4icJh{cFOu3B8}&RiYm+Mb;VEK``LK zL(NcpcTiGieOIssSjr?ob}^``nNf&UcJhXyncO9m{6gD$kqSD`S69(aF8dkWz5>!9 zBLe4Sib7Hs2x_L2Ls6Ish$MGVKrGt5+_2zCyP1byaCg3upo+-I}R4&$m)8 zQ7|jc1Z^VWggpuQj*cP;>Zo9LS!VSzrqmZczaf;u`d0J(f%Z9r%An@s!e>n9%y=n!IZ_tVGu{Jmsbp}Fk%HJIU?a+-~bjfLTuH|JExA8EROowzr zqW9{YyZhR0a4clRK>1I4Ncx&WER~{iE;F^$T7K%X@3PGOA%6#Z%p3TS^&M;Dnjw@i z^o!$9nhcsmcHcY4?4j9+ofL_CWsZ4Hcch(rjsGfGD(nsH>w}^ERqGnz%iGj0j{g}h z7wMkJ-2Z2~eS>2!i}0~B63i;>SyFJU2+>VCS^AxaDOx%g6-t0eM^P<3+*z`ztvOqrG3)&#$K?& z_Y0wbWID47@cU`E1A6A&!`aZk0ZE@z-h#l1NqX2#`$Uev2gepW`rf8*!=rD5&;Jb{ zl08rU>dPo=K%-1Ao1~G-@4ve~y5#9E8x;TE0k5d^TC(=Zc>mwjW^c=+U-<9}b0ku~}gj z3sbW>R2M6DR!g#NUP;nxo>)@7*=RP{U18SDop6b2&PHce^&h97@xx3t+VK+!keE#} z;(Uf&89as9k8{$nkLbuB!-d7TP`_VJpL^Xs8OKB~ri$YUbW8fch64}7|0EWoT(TRj{ z*GT<7Y<7DsrCi79ZsM)z#c(!nNOGySOCkY1fAuQOq12&iUVC!a`#O;dBLf=d?&4*B zI~LgAO7E0qxK(uRTM;IgJ}+z^gD+bi-6I!3x{r9`l~%8TRP%UE0V8E*Sz>Nl1NVG<<7(wDHZ+HcOkQm$O&k+vyx)y)x{Pz!U8hS$*m zByc0h6BUI*BOpuL==P+H|Hx%`>7!W+1H!l9vi&)`V zyn2o9{z=lc+VX*!Vh~SF=)L}Z40XeG>LF6cP^b+R$NxSeUqbK^Q*UTalKzP8X%{9@RSCXm_NhF>{=S2 zi}ezam_^P`S!!-cyEW9y7DBbK93roz@Raccy*v}?mKXScU9E_4g;hBU7}zSofAFda zKYEe?{{I54 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 22286c90de3..dbc089ed3d7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=89d4e70e4e84e2d2dfbb63e4daa53e21b25017cc70c37e4eea31ee51fb15098a -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionSha256Sum=ed1a8d686605fd7c23bdf62c7fc7add1c5b23b2bbc3721e661934ef4a4911d7c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf13397..f5feea6d6b1 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 25da30dbdee..9d21a21834d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index ad970ef6796..6edfca92836 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.7.1-beta +neoForgeVersion=21.8.31 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From affd1561df31d464a3f182ca8a30a81c5fbb4b49 Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 12 Aug 2025 13:12:07 +0300 Subject: [PATCH 305/586] Convert chunk CompoundTag to DataContainer in the I/O thread --- .../org/spongepowered/common/data/DataUtil.java | 13 +++++++++++-- .../level/chunk/SerializableChunkDataMixin.java | 17 +++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/DataUtil.java b/src/main/java/org/spongepowered/common/data/DataUtil.java index 1ad411087e0..e8cfbe9ab54 100644 --- a/src/main/java/org/spongepowered/common/data/DataUtil.java +++ b/src/main/java/org/spongepowered/common/data/DataUtil.java @@ -59,15 +59,24 @@ public static boolean syncDataToTag(final Object dataHolder) { return false; } + public static DataContainer convertTagToContainer(final CompoundTag compound) { + final DataContainer allData = NBTTranslator.INSTANCE.translate(compound); + + DataUtil.upgradeDataVersion(compound, allData); // Upgrade v2->v3 + + return allData; + } + public static void deserializeSpongeData(final T dataHolder) { final CompoundTag compound = dataHolder.data$getCompound(); if (compound == null) { return; } - final DataContainer allData = NBTTranslator.INSTANCE.translate(compound); - DataUtil.upgradeDataVersion(compound, allData); // Upgrade v2->v3 + DataUtil.deserializeSpongeData(dataHolder, DataUtil.convertTagToContainer(compound)); + } + public static void deserializeSpongeData(final T dataHolder, final DataContainer allData) { // Run content-updaters and collect failed data final Class typeToken = dataHolder.getClass().asSubclass(DataHolder.class); allData.getView(Constants.Sponge.Data.V3.SPONGE_DATA_ROOT).ifPresent(customData -> { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java index bc55b4669ed..247e4c46a97 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java @@ -31,6 +31,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.storage.SerializableChunkData; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -38,13 +39,15 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.data.DataCompoundHolder; +import org.spongepowered.common.bridge.data.SpongeDataHolderBridge; import org.spongepowered.common.bridge.world.level.chunk.storage.SerializableChunkDataBridge; -import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; +import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.data.DataUtil; @Mixin(SerializableChunkData.class) public abstract class SerializableChunkDataMixin implements SerializableChunkDataBridge { + private DataContainer impl$dataContainer; private CompoundTag impl$tag; private SerializationBehavior impl$serializationBehavior; @@ -52,12 +55,12 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat @Inject(method = "copyOf", at = @At(value = "RETURN")) private static void impl$copyOfSpongeData(final ServerLevel level, final ChunkAccess chunkAccess, final CallbackInfoReturnable cir) { final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); - if (level.getLevelData() instanceof PrimaryLevelDataBridge levelBridge) { + if (level.getLevelData() instanceof final ServerLevelDataBridge levelBridge) { final var behavior = levelBridge.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC); bridge.bridge$setSerializationBehavior(behavior); } - if (chunkAccess instanceof LevelChunk levelChunk) { + if (chunkAccess instanceof final LevelChunk levelChunk) { bridge.bridge$setTrackerData(levelChunk); bridge.bridge$setDataHolderData(levelChunk); } @@ -99,7 +102,7 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat } } - @Inject(method = "parse", at = @At(value = "RETURN")) + @Inject(method = "parse", at = @At(value = "TAIL")) private static void tracker$parseSpongeData(final LevelHeightAccessor $$0, final RegistryAccess $$1, final CompoundTag tag, final CallbackInfoReturnable cir) { final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); bridge.bridge$parseTrackerData(tag); @@ -108,7 +111,7 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat @Override public void bridge$parseDataHolderData(final CompoundTag tag) { - this.impl$tag = tag; + this.impl$dataContainer = DataUtil.convertTagToContainer(tag); } @Redirect(method = "read", @@ -126,9 +129,7 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat @Override public void bridge$readDataHolderDataFrom(final LevelChunk levelChunk) { - ((DataCompoundHolder) levelChunk).data$setCompound(this.impl$tag); - DataUtil.syncTagToData(levelChunk); - ((DataCompoundHolder) levelChunk).data$setCompound(null); + DataUtil.deserializeSpongeData((SpongeDataHolderBridge) levelChunk, this.impl$dataContainer); } From 816768afe7a3ebf3d435d6434a14dda03cb5eb0f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 15 Aug 2025 11:34:02 +0200 Subject: [PATCH 306/586] Do not use the dimension registry when migrating legacy world configs Legacy dimensions may differ from current dimensions. --- .../common/config/SpongeGameConfigs.java | 58 ++++++------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java index 25fd2811373..492c4da3e9b 100644 --- a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java +++ b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java @@ -24,15 +24,14 @@ */ package org.spongepowered.common.config; -import net.minecraft.core.registries.Registries; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.util.file.DeleteFileVisitor; import org.spongepowered.api.world.server.ServerWorld; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.config.inheritable.BaseConfig; @@ -46,7 +45,6 @@ import org.spongepowered.configurate.ConfigurationOptions; import java.io.IOException; -import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -64,7 +62,7 @@ public final class SpongeGameConfigs { private static ConfigHandle trackerConfigAdapter; private static volatile InheritableConfigHandle global; - private static ConfigurationOptions OPTIONS = SpongeConfigs.OPTIONS.serializers(c -> c.registerAll(SpongeAdventure.CONFIGURATE.serializers())); + private static final ConfigurationOptions OPTIONS = SpongeConfigs.OPTIONS.serializers(c -> c.registerAll(SpongeAdventure.CONFIGURATE.serializers())); private SpongeGameConfigs() { } @@ -84,7 +82,7 @@ public static InheritableConfigHandle getForWorld(final net.minecra final SpongeServerLevelData spongeData = ((ServerLevelDataBridge) level.getLevelData()).bridge$spongeData(); if (spongeData.configAdapter() == null) { final ResourceKey worldKey = ((ServerWorld) level).key(); - SpongeCommon.logger().warn("Level data ({}) has no Sponge config but is used by world {} ({}). World config will be reloaded.", level.getLevelData().getClass().getSimpleName(), worldKey, level.getClass().getSimpleName()); + SpongeGameConfigs.LOGGER.warn("Level data ({}) has no Sponge config but is used by world {} ({}). World config will be reloaded.", level.getLevelData().getClass().getSimpleName(), worldKey, level.getClass().getSimpleName()); // A custom level data has been set by a mod, so the key is likely missing too. if (spongeData.key() == null) { @@ -103,34 +101,25 @@ public static boolean doesWorldConfigExist(final ResourceKey world) { public static InheritableConfigHandle load(final DimensionType dimensionType, final ResourceKey world) { // Path format: config/sponge/worlds//.conf - final Path configPath = SpongeConfigs.getDirectory().resolve(Paths.get("worlds", world.namespace(), world.value() + ".conf")); + final Path configFile = SpongeConfigs.getDirectory().resolve(Paths.get("worlds", world.namespace(), world.value() + ".conf")); // Legacy config path: config/sponge/worlds////world.conf - final String legacyName = SpongeGameConfigs.getLegacyWorldName(world); - if (legacyName != null) { - final ResourceKey dimensionTypeKey = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getKey(dimensionType); - if (dimensionTypeKey != null) { - final Path legacyPath = SpongeConfigs.getDirectory().resolve(Paths.get("worlds", dimensionTypeKey.namespace(), - SpongeGameConfigs.getLegacyValue(dimensionTypeKey), legacyName, "world.conf")); - if (legacyPath.toFile().isFile() && !configPath.toFile().isFile()) { - try { - Files.createDirectories(configPath.getParent()); - Files.move(legacyPath, configPath); - final Path legacyParent = legacyPath.getParent(); - try (final DirectoryStream str = Files.newDirectoryStream(legacyParent)) { - if (!str.iterator().hasNext()) { - Files.delete(legacyParent); - } - } - } catch (final IOException ex) { - SpongeGameConfigs.LOGGER.error("Unable to migrate config for world {} from legacy location {}", world, legacyPath, ex); - } + final String legacyDimAndName = SpongeGameConfigs.getLegacyDimensionAndName(world); + if (legacyDimAndName != null) { + final Path legacyFile = SpongeConfigs.getDirectory().resolve("worlds/minecraft/" + legacyDimAndName + "/world.conf"); + if (Files.isRegularFile(legacyFile) && !Files.exists(configFile)) { + try { + Files.createDirectories(configFile.getParent()); + Files.move(legacyFile, configFile); + Files.walkFileTree(legacyFile.getParent(), DeleteFileVisitor.INSTANCE); + } catch (final IOException ex) { + SpongeGameConfigs.LOGGER.error("Unable to migrate config for world {} from legacy location {}", world, legacyFile, ex); } } } try { - final InheritableConfigHandle config = new InheritableConfigHandle<>(WorldConfig.class, BaseConfig::transformation, SpongeConfigs.createLoader(configPath, SpongeGameConfigs.OPTIONS), + final InheritableConfigHandle config = new InheritableConfigHandle<>(WorldConfig.class, BaseConfig::transformation, SpongeConfigs.createLoader(configFile, SpongeGameConfigs.OPTIONS), SpongeGameConfigs.getGlobalInheritable()); config.load(); return config; @@ -142,22 +131,13 @@ public static InheritableConfigHandle load(final DimensionType dime } @SuppressWarnings("EqualsBetweenInconvertibleTypes") // ResourceKey is ResourceLocation - private static String getLegacyValue(final ResourceKey dimensionType) { - if (dimensionType.equals(Level.NETHER.location())) { - return "nether"; - } else { - return dimensionType.value(); - } - } - - @SuppressWarnings("EqualsBetweenInconvertibleTypes") // ResourceKey is ResourceLocation - private static @Nullable String getLegacyWorldName(final ResourceKey world) { + private static @Nullable String getLegacyDimensionAndName(final ResourceKey world) { if (world.equals(Level.OVERWORLD.location())) { - return "world"; + return "overworld/world"; } else if (world.equals(Level.END.location())) { - return "DIM1"; + return "the_end/DIM1"; } else if (world.equals(Level.NETHER.location())) { - return "DIM-1"; + return "nether/DIM-1"; } return null; } From 154e44f587cbf8cb6d71a3f7f146975b9f7323f6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 15 Aug 2025 18:12:07 +0200 Subject: [PATCH 307/586] Fix missing natives in dev runtime Despite having different classifiers, os variants have the same module name, causing them to be ignored if passed directly to a modular classloader. --- .../spongepowered/bootstrap/Bootstrap.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 484520df1ec..31f84d76ada 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -34,7 +34,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; public abstract class Bootstrap { @@ -72,7 +74,8 @@ public void boot(final List classpath, final boolean isolated) throws Ex } // Collect the jars - final List filteredJars = new ArrayList<>(); + final Set moduleNames = new HashSet<>(); + final List resourceJars = new ArrayList<>(); final List appJars = new ArrayList<>(); for (final Path[] paths : classpath) { @@ -91,7 +94,15 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (Bootstrap.DEBUG) { System.out.println("Filtered: " + name + " " + Bootstrap.formatUnion(paths)); } - filteredJars.add(jar); + resourceJars.add(jar); + continue; + } + + if (!moduleNames.add(name)) { + if (Bootstrap.DEBUG) { + System.out.println("Duplicate: " + name + " " + Bootstrap.formatUnion(paths)); + } + resourceJars.add(jar); continue; } @@ -103,8 +114,7 @@ public void boot(final List classpath, final boolean isolated) throws Ex // Create the layer configuration final ModuleFinder finder = this.createModuleFinder(appJars); - final List targets = appJars.stream().map(this::getModuleName).toList(); - final Configuration config = ModuleLayer.boot().configuration().resolveAndBind(finder, ModuleFinder.ofSystem(), targets); + final Configuration config = ModuleLayer.boot().configuration().resolveAndBind(finder, ModuleFinder.ofSystem(), moduleNames); final List parentLayers = List.of(ModuleLayer.boot()); // Isolation @@ -112,10 +122,10 @@ public void boot(final List classpath, final boolean isolated) throws Ex ClassLoader parentLoader = isolated ? ClassLoader.getPlatformClassLoader() : contextLoader; // Intermediate classloader to include resources but not modules - if (!filteredJars.isEmpty()) { - final URL[] urls = new URL[filteredJars.size()]; + if (!resourceJars.isEmpty()) { + final URL[] urls = new URL[resourceJars.size()]; for (int i = 0; i < urls.length; i++) { - urls[i] = this.getJarURL(filteredJars.get(i)); + urls[i] = this.getJarURL(resourceJars.get(i)); } parentLoader = new URLClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); } From 147d77f3c695c7475573ff60297987676ab9b694 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 17 Aug 2025 15:49:35 +0300 Subject: [PATCH 308/586] Fix Forge dev dootstrap --- .../main/java/org/spongepowered/bootstrap/Bootstrap.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 31f84d76ada..393503b05d3 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -75,7 +75,7 @@ public void boot(final List classpath, final boolean isolated) throws Ex // Collect the jars final Set moduleNames = new HashSet<>(); - final List resourceJars = new ArrayList<>(); + final List resourceJars = new ArrayList<>(); final List appJars = new ArrayList<>(); for (final Path[] paths : classpath) { @@ -94,7 +94,7 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (Bootstrap.DEBUG) { System.out.println("Filtered: " + name + " " + Bootstrap.formatUnion(paths)); } - resourceJars.add(jar); + resourceJars.addAll(Arrays.asList(paths)); continue; } @@ -102,7 +102,7 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (Bootstrap.DEBUG) { System.out.println("Duplicate: " + name + " " + Bootstrap.formatUnion(paths)); } - resourceJars.add(jar); + resourceJars.addAll(Arrays.asList(paths)); continue; } @@ -125,7 +125,7 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (!resourceJars.isEmpty()) { final URL[] urls = new URL[resourceJars.size()]; for (int i = 0; i < urls.length; i++) { - urls[i] = this.getJarURL(resourceJars.get(i)); + urls[i] = resourceJars.get(i).toUri().toURL(); } parentLoader = new URLClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); } From 94b3e6d6b5ab2f3a2ff45b695ce97e7c39201b5b Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 23 Aug 2025 00:15:08 +0300 Subject: [PATCH 309/586] Move lifecycle events more early on Forge The FMLCommonSetupEvent is called too late, and the postRegisterEvents can be called async, so yeah, thats fun. Thanks! --- .../org/spongepowered/forge/SpongeForgeMod.java | 13 ------------- .../registries/GameDataMixin_Forge.java | 14 ++++++++++++++ .../org/spongepowered/neoforge/SpongeNeoMod.java | 13 ------------- .../neoforge/registries/GameDataMixin_Neo.java | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index adfc5e5c0e3..9731d6c632f 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -40,15 +40,12 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.api.Client; import org.spongepowered.api.Server; -import org.spongepowered.api.Sponge; import org.spongepowered.common.entity.SpongeEntityTypes; import org.spongepowered.common.entity.living.human.HumanEntity; import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.common.launch.config.core.ConfigHandle; -import org.spongepowered.common.network.channel.SpongeChannelManager; -import org.spongepowered.common.network.packet.SpongePacketHandler; import org.spongepowered.forge.hook.ForgeChannelHooks; import org.spongepowered.forge.hook.ForgeEventHooks; import org.spongepowered.forge.hook.ForgeGeneralHooks; @@ -82,16 +79,6 @@ public SpongeForgeMod(FMLJavaModLoadingContext ctx) { } private void onCommonSetup(final FMLCommonSetupEvent event) { - final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.callConstructEvent(); - lifecycle.callRegisterFactoryEvent(); - lifecycle.callRegisterBuilderEvent(); - lifecycle.callRegisterChannelEvent(); - lifecycle.establishGameServices(); - lifecycle.establishDataKeyListeners(); - - SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); - this.logger.info("SpongeForge v{} initialized", Launch.instance().platformPlugin().metadata().version()); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java index 3d05bd93b3f..954b8163925 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java @@ -30,12 +30,16 @@ import net.minecraft.world.entity.EntityType; import net.minecraftforge.registries.GameData; import org.jetbrains.annotations.Nullable; +import org.spongepowered.api.Sponge; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.entity.SpongeEntityTypes; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.network.channel.SpongeChannelManager; +import org.spongepowered.common.network.packet.SpongePacketHandler; @Mixin(GameData.class) public class GameDataMixin_Forge { @@ -49,6 +53,16 @@ public class GameDataMixin_Forge { @Inject(method = "postRegisterEvents", at = @At("HEAD")) private static void forge$onRegisterEvents(final CallbackInfo ci) { + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.callConstructEvent(); + lifecycle.callRegisterFactoryEvent(); + lifecycle.callRegisterBuilderEvent(); + lifecycle.callRegisterChannelEvent(); + lifecycle.establishGameServices(); + lifecycle.establishDataKeyListeners(); + + SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); + Launch.instance().lifecycle().establishGlobalRegistries(); } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java index a4c9c096b76..8620448462d 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java @@ -39,15 +39,12 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.api.Client; import org.spongepowered.api.Server; -import org.spongepowered.api.Sponge; import org.spongepowered.common.entity.SpongeEntityTypes; import org.spongepowered.common.entity.living.human.HumanEntity; import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.common.launch.config.core.ConfigHandle; -import org.spongepowered.common.network.channel.SpongeChannelManager; -import org.spongepowered.common.network.packet.SpongePacketHandler; import org.spongepowered.neoforge.hook.NeoChannelHooks; import org.spongepowered.neoforge.hook.NeoEventHooks; import org.spongepowered.neoforge.hook.NeoGeneralHooks; @@ -77,16 +74,6 @@ public SpongeNeoMod(IEventBus modBus) { } private void onCommonSetup(final FMLCommonSetupEvent event) { - final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.callConstructEvent(); - lifecycle.callRegisterFactoryEvent(); - lifecycle.callRegisterBuilderEvent(); - lifecycle.callRegisterChannelEvent(); - lifecycle.establishGameServices(); - lifecycle.establishDataKeyListeners(); - - SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); - this.logger.info("SpongeNeo v{} initialized", Launch.instance().platformPlugin().metadata().version()); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java index 7489a1b533c..85a7541976f 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java @@ -29,12 +29,16 @@ import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.EntityType; import net.neoforged.neoforge.registries.GameData; +import org.spongepowered.api.Sponge; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.entity.SpongeEntityTypes; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.network.channel.SpongeChannelManager; +import org.spongepowered.common.network.packet.SpongePacketHandler; @Mixin(GameData.class) public class GameDataMixin_Neo { @@ -48,6 +52,16 @@ public class GameDataMixin_Neo { @Inject(method = "postRegisterEvents", at = @At("HEAD")) private static void neo$onRegisterEvents(final CallbackInfo ci) { + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.callConstructEvent(); + lifecycle.callRegisterFactoryEvent(); + lifecycle.callRegisterBuilderEvent(); + lifecycle.callRegisterChannelEvent(); + lifecycle.establishGameServices(); + lifecycle.establishDataKeyListeners(); + + SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); + Launch.instance().lifecycle().establishGlobalRegistries(); } From 7fafc4ecb8cddb78cb4e5f0bb470acaeb26b024c Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 23 Aug 2025 14:28:38 +0300 Subject: [PATCH 310/586] Shuffle more lifecycle events on Forge Gfit that keeps on giving --- .../registries/GameDataMixin_Forge.java | 4 ++ .../registries/GameDataMixin_Neo.java | 4 ++ .../phase/packet/PacketPhaseUtil.java | 1 + .../registries/BuiltInRegistriesMixin.java | 45 ------------------- src/mixins/resources/mixins.sponge.core.json | 1 - .../BuiltInRegistriesMixin_Vanilla.java | 7 ++- 6 files changed, 15 insertions(+), 47 deletions(-) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java index 954b8163925..0e1b63d34e8 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/GameDataMixin_Forge.java @@ -63,6 +63,10 @@ public class GameDataMixin_Forge { SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); + lifecycle.establishDataProviders(); + lifecycle.callRegisterDataEvent(); + lifecycle.establishEarlyGlobalRegistries(); + Launch.instance().lifecycle().establishGlobalRegistries(); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java index 85a7541976f..add30d4ac16 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/GameDataMixin_Neo.java @@ -62,6 +62,10 @@ public class GameDataMixin_Neo { SpongePacketHandler.init((SpongeChannelManager) Sponge.channelManager()); + lifecycle.establishDataProviders(); + lifecycle.callRegisterDataEvent(); + lifecycle.establishEarlyGlobalRegistries(); + Launch.instance().lifecycle().establishGlobalRegistries(); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index e9d49b7b6ec..a7be96b8e9e 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -270,6 +270,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n } try (final PhaseContext packetContext = context) { packetContext.buildAndSwitch(); + packetIn.handle(netHandler); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java deleted file mode 100644 index c3b6137e339..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/registries/BuiltInRegistriesMixin.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.registries; - -import net.minecraft.core.registries.BuiltInRegistries; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.launch.Lifecycle; - -@Mixin(BuiltInRegistries.class) -public abstract class BuiltInRegistriesMixin { - - @Inject(method = "bootStrap", at = @At(value = "HEAD")) - private static void impl$beforeCreateContents(final CallbackInfo ci) { - final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishDataProviders(); - lifecycle.callRegisterDataEvent(); - lifecycle.establishEarlyGlobalRegistries(); - } -} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 7182dd04c09..e850c287944 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -52,7 +52,6 @@ "network.syncher.EntityDataAccessorMixin", "network.syncher.SynchedEntityData_BuilderMixin", "network.syncher.SynchedEntityDataMixin", - "registries.BuiltInRegistriesMixin", "resources.RegistryDataLoader_LoaderMixin", "resources.RegistryDataLoaderMixin", "server.MinecraftServerMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java index 595724dd0f9..e8d8655da46 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/registries/BuiltInRegistriesMixin_Vanilla.java @@ -30,13 +30,18 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; @Mixin(BuiltInRegistries.class) public abstract class BuiltInRegistriesMixin_Vanilla { @Inject(method = "bootStrap", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/registries/BuiltInRegistries;freeze()V")) private static void impl$beforeFreeze(final CallbackInfo ci) { - Launch.instance().lifecycle().establishGlobalRegistries(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.establishDataProviders(); + lifecycle.callRegisterDataEvent(); + lifecycle.establishEarlyGlobalRegistries(); + lifecycle.establishGlobalRegistries(); } @Inject(method = "freeze", at = @At("TAIL")) From e7696bbcb37c48fa72041012a529f149470b8374 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 1 Sep 2025 14:22:25 -0700 Subject: [PATCH 311/586] chore(minecraft): implementation breakages of 25w32a Breaking Change: - Removed Spawn Chunk Radius gamerule - Removed jagged noise generation configuration See: https://minecraft.wiki/w/Java_Edition_25w32a --- SpongeAPI | 2 +- .../BlockStatePropertiesGenerator.java | 7 +++ .../BlockStatePropertyKeysGenerator.java | 6 +++ .../vanilla/generator/Context.java | 10 ++-- .../world/level/block/BlockRegistries.java | 24 +++++++++ gradle.properties | 2 +- gradle/verification-metadata.xml | 22 +++++++++ .../accessor/network/chat/StyleAccessor.java | 36 ++++++++++---- .../server/MinecraftServerAccessor.java | 6 +-- .../server/level/ServerLevelAccessor.java | 4 -- ...eProfileCache_GameProfileInfoAccessor.java | 8 +-- .../item/component/CustomDataAccessor.java | 3 ++ .../common/adventure/SpongeAdventure.java | 25 ++++++++-- .../common/ban/SpongeBanBuilder.java | 2 +- .../server/level/ServerLevelBridge.java | 3 -- .../SpongeGameProfileValueParameter.java | 3 +- .../provider/block/entity/BannerData.java | 5 +- .../block/state/BlockStateDataProvider.java | 2 + .../data/provider/entity/EntityData.java | 4 +- .../data/provider/entity/PaintingData.java | 2 +- .../data/provider/entity/VanishableData.java | 2 +- .../item/stack/SignItemStackData.java | 10 ++-- .../item/stack/SpawnEggItemStackData.java | 14 ++++-- .../common/effect/util/ViewerPacketUtil.java | 2 +- .../entity/living/human/HumanEntity.java | 43 +++++++--------- .../event/SpongeCommonEventFactory.java | 35 +++++-------- .../phase/tick/EntityTickPhaseState.java | 2 +- .../custom/CarriedWrapperInventory.java | 11 +---- .../custom/ViewableCustomInventory.java | 10 ---- .../common/item/SpongeItemStack.java | 37 +++++++++----- .../network/packet/SpongePacketHandler.java | 10 ++-- .../common/profile/SpongeGameProfile.java | 16 ++++++ .../profile/SpongeGameProfileManager.java | 2 +- .../service/server/ban/SpongeBanService.java | 23 ++++----- .../service/server/ban/SpongeUserBanList.java | 9 ++-- .../server/permission/UserCollection.java | 4 +- .../server/permission/UserSubject.java | 11 +++-- .../server/whitelist/SpongeUserWhiteList.java | 5 +- .../whitelist/SpongeWhitelistService.java | 11 +++-- .../common/user/SpongeUserManager.java | 3 +- .../world/server/SpongeTicketTypeBuilder.java | 7 ++- .../world/server/SpongeWorldManager.java | 49 ++++--------------- .../players/GameProfileCacheMixin_API.java | 18 +++---- .../CopperGolemStatueBlock_PoseMixin_API.java | 33 +++++++++++++ ...eatheringCopper_WeatherStateMixin_API.java | 33 +++++++++++++ .../block/entity/BlockEntityMixin_API.java | 2 +- .../entity/SpawnerBlockEntityMixin_API.java | 2 +- .../TrialSpawnerBlockEntityMixin_API.java | 2 +- .../level/levelgen/NoiseRouterMixin_API.java | 6 --- .../adventure/text/format/StyleImplMixin.java | 2 +- .../mixin/core/block/BedBlockMixin.java | 2 +- .../server/IntegratedPlayerListMixin.java | 11 +++-- .../syncher/SynchedEntityDataMixin.java | 2 +- .../core/server/MinecraftServerMixin.java | 27 ++++++---- .../dedicated/DedicatedPlayerListMixin.java | 9 ++-- .../dedicated/DedicatedServerMixin.java | 22 ++++----- .../core/server/level/ServerLevelMixin.java | 28 ++--------- .../server/players/GameProfileCacheMixin.java | 38 +++++++------- ...GameProfileCache_GameProfileInfoMixin.java | 11 +++-- .../mixin/core/world/entity/EntityMixin.java | 18 +++---- .../core/world/entity/LeashableMixin.java | 4 +- .../core/world/entity/LightningBoltMixin.java | 4 +- .../core/world/entity/LivingEntityMixin.java | 16 +++--- .../mixin/core/world/entity/MobMixin.java | 2 +- .../world/entity/item/ItemEntityMixin.java | 2 +- .../world/entity/item/PrimedTntMixin.java | 2 +- .../world/entity/monster/CreeperMixin.java | 4 +- .../entity/projectile/AbstractArrowMixin.java | 2 +- .../projectile/FireworkRocketEntityMixin.java | 2 +- .../entity/projectile/FishingHookMixin.java | 2 +- .../projectile/ProjectileUtilMixin.java | 2 +- .../core/world/item/FishingRodItemMixin.java | 2 +- .../mixin/core/world/item/ItemStackMixin.java | 6 +-- .../world/level/block/CampfireBlockMixin.java | 2 +- .../world/level/block/MagmaBlockMixin.java | 2 +- .../block/PointedDripstoneBlockMixin.java | 2 +- .../level/block/SweetBerryBushBlockMixin.java | 2 +- .../block/entity/BannerBlockEntityMixin.java | 2 +- .../level/storage/PlayerDataStorageMixin.java | 7 ++- .../core/world/ticks/SavedTickMixin.java | 3 +- .../AbstractContainerMenuMixin_Inventory.java | 2 +- .../entity/LivingEntityMixin_Tracker.java | 2 +- .../SerializableChunkDataMixin_Tracker.java | 2 + src/mixins/resources/mixins.sponge.api.json | 2 + .../client/gui/widget/MetadataPanel.java | 4 +- .../client/gui/widget/ScrollPanel.java | 4 +- .../gui/widget/list/FilterableList.java | 16 +++--- .../gui/widget/list/PluginSelectionList.java | 2 +- .../server/packs/PluginPackResources.java | 10 +++- .../server/MinecraftServerMixin_Vanilla.java | 4 +- .../level/block/FireBlockMixin_Vanilla.java | 4 +- 91 files changed, 508 insertions(+), 372 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/CopperGolemStatueBlock_PoseMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/WeatheringCopper_WeatherStateMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 6f5f4d6747d..6252dce257b 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 6f5f4d6747d397db0dc906349e39beea132fda91 +Subproject commit 6252dce257b18be1897b5c07d946ff2886fbf79b diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 42c43f0c7db..fbd3387f2e3 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -32,6 +32,8 @@ import net.minecraft.core.FrontAndTop; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CopperGolemStatueBlock; +import net.minecraft.world.level.block.WeatheringCopper; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -56,6 +58,7 @@ import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.block.state.properties.RedstoneSide; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; +import net.minecraft.world.level.block.state.properties.SideChainPart; import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; @@ -152,6 +155,10 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertiesGenerator.inDataTypePkg("VaultState")); vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeartState")); vanillaEnumTypeMapping.put(TestBlockMode.class, BlockStatePropertiesGenerator.inDataTypePkg("TestBlockMode")); + vanillaEnumTypeMapping.put(SideChainPart.class, BlockStatePropertiesGenerator.inDataTypePkg("SideChainPart")); + vanillaEnumTypeMapping.put(CopperGolemStatueBlock.Pose.class, BlockStatePropertiesGenerator.inDataTypePkg("CopperGolemPose")); + vanillaEnumTypeMapping.put(WeatheringCopper.WeatherState.class, BlockStatePropertiesGenerator.inDataTypePkg("CopperOxidation")); + // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertiesGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index 2950b25a61b..c012945d60a 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -33,6 +33,8 @@ import com.squareup.javapoet.TypeVariableName; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; +import net.minecraft.world.level.block.CopperGolemStatueBlock; +import net.minecraft.world.level.block.WeatheringCopper; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.entity.vault.VaultState; import net.minecraft.world.level.block.state.BlockState; @@ -57,6 +59,7 @@ import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.block.state.properties.RedstoneSide; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; +import net.minecraft.world.level.block.state.properties.SideChainPart; import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; @@ -150,6 +153,9 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("VaultState")); vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CreakingHeartState")); vanillaEnumTypeMapping.put(TestBlockMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("TestBlockMode")); + vanillaEnumTypeMapping.put(SideChainPart.class, BlockStatePropertyKeysGenerator.inDataTypePkg("SideChain")); + vanillaEnumTypeMapping.put(CopperGolemStatueBlock.Pose.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CopperGolemPose")); + vanillaEnumTypeMapping.put(WeatheringCopper.WeatherState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("CopperOxidation")); // Custom Mapping required see StateHolderMixin_API final ClassName portionTypeClass = BlockStatePropertyKeysGenerator.inDataTypePkg("PortionType"); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java index e47330f862f..2fcecf82f13 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java @@ -85,9 +85,13 @@ public ClassName relativeClass(final String relativePackage, final String simple public CompilationUnit compilationUnit(final String relativePackage, final String simpleName) { final String pkg = relativePackage.isBlank() ? Context.BASE_PACKAGE : String.join(".", Context.BASE_PACKAGE, relativePackage); - final CompilationUnit unit = this.sourceRoot.parse(pkg, simpleName + ".java"); - LexicalPreservingPrinter.setup(unit); - return unit; + try { + final CompilationUnit unit = this.sourceRoot.parse(pkg, simpleName + ".java"); + LexicalPreservingPrinter.setup(unit); + return unit; + } catch (Exception e) { + throw new RuntimeException("Failed to parse " + simpleName + ".java", e); + } } /** diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java index adae5b92228..59d1f58a69c 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java @@ -26,12 +26,15 @@ import net.minecraft.core.registries.Registries; import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.block.CopperGolemStatueBlock; +import net.minecraft.world.level.block.WeatheringCopper; import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DripstoneThickness; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; +import net.minecraft.world.level.block.state.properties.SideChainPart; import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import org.spongepowered.vanilla.generator.BlockStateDataProviderGenerator; @@ -90,6 +93,27 @@ public static List enumRegistries(final Context context) { TrialSpawnerState.class, "getSerializedName", "sponge" + ), + new EnumEntriesValidator<>( + "data.type", + "CopperGolemPoses", + CopperGolemStatueBlock.Pose.class, + "getSerializedName", + "sponge" + ), + new EnumEntriesValidator<>( + "data.type", + "SideChains", + SideChainPart.class, + "getSerializedName", + "sponge" + ), + new EnumEntriesValidator<>( + "data.type", + "CopperOxidization", + WeatheringCopper.WeatherState.class, + "getSerializedName", + "sponge" ) ); } diff --git a/gradle.properties b/gradle.properties index 122e233ee07..335000978ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=1.21.8 +minecraftVersion=25w32a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1c5583bc573..48cb727cd6e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1491,6 +1491,14 @@ + + + + + + + + @@ -1568,6 +1576,20 @@ + + + + + + + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java index d7d933d9354..cead56cb855 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java @@ -25,6 +25,7 @@ package org.spongepowered.common.accessor.network.chat; import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.FontDescription; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; @@ -40,23 +41,38 @@ public interface StyleAccessor { @Invoker("") - static Style invoker$new(final @Nullable TextColor color, final @Nullable Integer shadowColor, final @Nullable Boolean bold, final @Nullable Boolean italic, - final @Nullable Boolean underlined, final @Nullable Boolean strikethrough, final @Nullable Boolean obfuscated, - final @Nullable ClickEvent clickEvent, final @Nullable HoverEvent hoverEvent, final @Nullable String insertion, - final @Nullable ResourceLocation font) { + static Style invoker$new( + final @Nullable TextColor color, + final @Nullable Integer shadowColor, + final @Nullable Boolean bold, + final @Nullable Boolean italic, + final @Nullable Boolean underlined, + final @Nullable Boolean strikethrough, + final @Nullable Boolean obfuscated, + final @Nullable ClickEvent clickEvent, + final @Nullable HoverEvent hoverEvent, + final @Nullable String insertion, + final @Nullable FontDescription fontDescription + ) { throw new UntransformedInvokerError(); } - @Accessor("bold") Boolean accessor$bold(); + @Accessor("bold") + Boolean accessor$bold(); - @Accessor("italic") Boolean accessor$italic(); + @Accessor("italic") + Boolean accessor$italic(); - @Accessor("underlined") Boolean accessor$underlined(); + @Accessor("underlined") + Boolean accessor$underlined(); - @Accessor("strikethrough") Boolean accessor$strikethrough(); + @Accessor("strikethrough") + Boolean accessor$strikethrough(); - @Accessor("obfuscated") Boolean accessor$obfuscated(); + @Accessor("obfuscated") + Boolean accessor$obfuscated(); - @Accessor("font") ResourceLocation accessor$font(); + @Accessor("font") + FontDescription accessor$font(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java index ac4332bf6b3..a6d7e9e6127 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java @@ -27,7 +27,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.progress.ChunkProgressListenerFactory; +import net.minecraft.server.level.progress.LevelLoadListener; import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.ServerLevelData; @@ -49,7 +49,7 @@ public interface MinecraftServerAccessor { throw new UntransformedAccessorError(); } - @Invoker("setInitialSpawn") static void invoker$setInitialSpawn(final ServerLevel serverWorld, final ServerLevelData levelData, final boolean generateBonusChest, final boolean debugWorld) { + @Invoker("setInitialSpawn") static void invoker$setInitialSpawn(final ServerLevel serverWorld, final ServerLevelData levelData, final boolean generateBonusChest, final boolean debugWorld, LevelLoadListener listener) { throw new UntransformedInvokerError(); } @@ -59,8 +59,6 @@ public interface MinecraftServerAccessor { @Accessor("executor") Executor accessor$executor(); - @Accessor("progressListenerFactory") ChunkProgressListenerFactory accessor$progressListenerFactory(); - @Accessor("nextTickTimeNanos") void accessor$nextTickTimeNanos(final long nextTickTime); @Invoker("isSpawningMonsters") boolean invoker$isSpawningMonsters(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java index 52b13a0586e..aaa7ac898ae 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java @@ -46,8 +46,4 @@ public interface ServerLevelAccessor { @Accessor("entityManager") PersistentEntitySectionManager accessor$getEntityManager(); - @Accessor("lastSpawnChunkRadius") int accessor$lastSpawnChunkRadius(); - - @Accessor("lastSpawnChunkRadius") void accessor$setLastSpawnChunkRadius(int value); - } diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/players/GameProfileCache_GameProfileInfoAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/players/GameProfileCache_GameProfileInfoAccessor.java index e197f0ca804..7dac013db5f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/players/GameProfileCache_GameProfileInfoAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/players/GameProfileCache_GameProfileInfoAccessor.java @@ -24,18 +24,18 @@ */ package org.spongepowered.common.accessor.server.players; -import com.mojang.authlib.GameProfile; +import net.minecraft.server.players.NameAndId; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import java.util.Date; -@Mixin(targets = "net.minecraft.server.players.GameProfileCache$GameProfileInfo") +@Mixin(targets = "net.minecraft.server.players.CachedUserNameToIdResolver$GameProfileInfo") public interface GameProfileCache_GameProfileInfoAccessor { - @Invoker("getProfile") GameProfile invoker$getProfile(); + @Invoker("nameAndId") NameAndId invoker$nameAndId(); - @Invoker("getExpirationDate") Date invoker$getExpirationDate(); + @Invoker("expirationDate") Date invoker$getExpirationDate(); @Invoker("setLastAccess") void invoker$setLastAccess(final long lastAccessMs); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/item/component/CustomDataAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/component/CustomDataAccessor.java index 56e1b1af747..cdac3d9bcb2 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/item/component/CustomDataAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/component/CustomDataAccessor.java @@ -27,12 +27,15 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.component.CustomData; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; @Mixin(CustomData.class) public interface CustomDataAccessor { + @Accessor("tag") CompoundTag accessor$tag(); + @Invoker("") static CustomData invoker$new(CompoundTag tag) { throw new UntransformedInvokerError(); } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index b09679ab007..2478f2342f3 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -72,6 +72,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ComponentContents; +import net.minecraft.network.chat.FontDescription; import net.minecraft.network.chat.HoverEvent.Action; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.contents.BlockDataSource; @@ -226,6 +227,15 @@ public static Key asAdventure(final ResourceLocation key) { return (Key) (Object) key; } + public static Key asAdventure(final FontDescription description) { + return switch (description) { + case null -> null; + case FontDescription.Resource fr -> Key.key(fr.id().toString()); + case FontDescription.AtlasSprite as -> Key.key(as.spriteId().toString()); + default -> throw new IllegalStateException("Unexpected value: " + description); + }; + } + // ------------------------ // ---- ChatType.Bound ---- // ------------------------ @@ -322,7 +332,7 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c builder.append(SpongeAdventure.asAdventure(child)); } - builder.style(((org.spongepowered.common.bridge.network.chat.StyleBridge) component.getStyle()).bridge$asAdventure()); + builder.style(((org.spongepowered.common.bridge.network.chat.StyleBridge) (Object) component.getStyle()).bridge$asAdventure()); return builder.build(); } @@ -372,7 +382,7 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c // no caching public static Style asAdventure(final net.minecraft.network.chat.Style mcStyle) { final Style.Builder builder = Style.style(); - final StyleAccessor $access = (StyleAccessor) mcStyle; + final StyleAccessor $access = (StyleAccessor) (Object) mcStyle; builder.font(SpongeAdventure.asAdventure($access.accessor$font())); // font builder.color(SpongeAdventure.asAdventure(mcStyle.getColor())); // color @@ -802,11 +812,18 @@ public static ResourceLocation asVanilla(final Key key) { return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value()); } - public static @Nullable ResourceLocation asVanillaNullable(final @Nullable Key key) { + public static @Nullable ResourceLocation asVanillaLocation(final @Nullable Key key) { + if (key == null) { + return null; + } + return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value()); + } + + public static @Nullable FontDescription asVanillaFontDescription(final @Nullable Key key) { if (key == null) { return null; } - return SpongeAdventure.asVanilla(key); + return new FontDescription.Resource(SpongeAdventure.asVanilla(key)); } // Sound diff --git a/src/main/java/org/spongepowered/common/ban/SpongeBanBuilder.java b/src/main/java/org/spongepowered/common/ban/SpongeBanBuilder.java index 19069c6a432..07534861ac7 100644 --- a/src/main/java/org/spongepowered/common/ban/SpongeBanBuilder.java +++ b/src/main/java/org/spongepowered/common/ban/SpongeBanBuilder.java @@ -123,7 +123,7 @@ public Ban build() { if (this.profile == null) { throw new IllegalStateException("User cannot be null"); } - return (Ban) new UserBanListEntry(SpongeGameProfile.toMcProfile(this.profile.withoutProperties()), + return (Ban) new UserBanListEntry(SpongeGameProfile.toNameAndId(this.profile.withoutProperties()), Date.from(this.start), sourceName, this.toDate(this.end), reason); } if (this.address == null) { diff --git a/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java b/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java index 18055be3d61..33344a4fd35 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/level/ServerLevelBridge.java @@ -26,7 +26,6 @@ import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.server.bossevents.CustomBossEvents; -import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.api.block.BlockSnapshot; @@ -36,8 +35,6 @@ public interface ServerLevelBridge { LevelStorageSource.LevelStorageAccess bridge$getLevelSave(); - ChunkProgressListener bridge$getChunkProgressListener(); - boolean bridge$isLoaded(); CustomBossEvents bridge$getBossBarManager(); diff --git a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeGameProfileValueParameter.java b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeGameProfileValueParameter.java index 3f770dd39e5..7a58ebe1168 100644 --- a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeGameProfileValueParameter.java +++ b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeGameProfileValueParameter.java @@ -31,6 +31,7 @@ import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.GameProfileArgument; +import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.command.CommandCause; @@ -64,7 +65,7 @@ public CompletableFuture listSuggestions( public Optional parseValue( final @NonNull CommandCause cause, final ArgumentReader.@NonNull Mutable reader) throws ArgumentParseException { try { - final Collection profileCollection = + final Collection profileCollection = this.argument.parse((StringReader) reader).getNames((CommandSourceStack) cause); if (profileCollection.size() == 1) { return Optional.of(SpongeGameProfile.of(profileCollection.iterator().next())); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java index 7f1533ab577..18527783284 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/BannerData.java @@ -30,6 +30,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BannerBlockEntity; import net.minecraft.world.level.block.entity.BannerPatternLayers; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.meta.BannerPatternLayer; import org.spongepowered.common.bridge.world.level.block.entity.BannerBlockEntityBridge; @@ -49,8 +50,8 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.BANNER_PATTERN_LAYERS) .get(h -> h.getPatterns().layers().stream().map(BannerPatternLayer.class::cast).toList()) .setAnd((h, v) -> { - final Level world = h.getLevel(); - if (world != null && !world.isClientSide) { // This avoids a client crash because clientside. + final @Nullable Level world = h.getLevel(); + if (world != null && !world.isClientSide()) { // This avoids a client crash because clientside. applyBannerPatternLayers(h, v); return true; } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index 924648252de..dd2d82f4c66 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -69,6 +69,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_4_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_4_OCCUPIED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_5_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_5_OCCUPIED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CONDITIONAL, BlockStateProperties.CONDITIONAL); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.COPPER_GOLEM_POSE, BlockStateProperties.COPPER_GOLEM_POSE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CRACKED, BlockStateProperties.CRACKED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CRAFTING, BlockStateProperties.CRAFTING); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CREAKING_HEART_STATE, BlockStateProperties.CREAKING_HEART_STATE); @@ -139,6 +140,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SEGMENT_AMOUNT, BlockStateProperties.SEGMENT_AMOUNT); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SHORT, BlockStateProperties.SHORT); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SHRIEKING, BlockStateProperties.SHRIEKING); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SIDE_CHAIN_PART, BlockStateProperties.SIDE_CHAIN_PART); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SIGNAL_FIRE, BlockStateProperties.SIGNAL_FIRE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLAB_TYPE, BlockStateProperties.SLAB_TYPE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SNOWY, BlockStateProperties.SNOWY); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java index 69937fac579..215697af97b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java @@ -197,7 +197,7 @@ public static void register(final DataProviderRegistrator registrator) { .delete(Entity::ejectPassengers) .set((h, v) -> { h.ejectPassengers(); - v.forEach(v1 -> ((Entity) v1).startRiding(h, true)); + v.forEach(v1 -> ((Entity) v1).startRiding(h, true, true)); }) .create(Keys.PUSH_REACTION) .get(h -> (PushReaction) (Object) h.getPistonPushReaction()) @@ -224,7 +224,7 @@ public static void register(final DataProviderRegistrator registrator) { }) .create(Keys.VEHICLE) .get(h -> (org.spongepowered.api.entity.Entity) h.getVehicle()) - .set((h, v) -> h.startRiding((Entity) v, true)) + .set((h, v) -> h.startRiding((Entity) v, true, true)) .delete(h -> h.stopRiding()) .create(Keys.VELOCITY) .get(h -> VecHelper.toVector3d(h.getDeltaMovement())) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java index ae6cb564d62..33b1260e63a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java @@ -52,7 +52,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.ART_TYPE) .get(h -> (ArtType) (Object) h.getVariant().value()) .setAnd((h, v) -> { - if (!h.level().isClientSide) { + if (!h.level().isClientSide()) { final Holder oldArt = h.getVariant(); var newArt = SpongeCommon.vanillaRegistry(Registries.PAINTING_VARIANT).wrapAsHolder((PaintingVariant) (Object) v); ((PaintingAccessor) h).invoker$setVariant(newArt); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VanishableData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VanishableData.java index 4fb03550573..5a031072059 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VanishableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VanishableData.java @@ -49,7 +49,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.VANISH_STATE) .get(VanishableBridge::bridge$vanishState) .setAnd((h, v) -> { - if (h instanceof Entity && ((Entity) h).level().isClientSide) { + if (h instanceof Entity && ((Entity) h).level().isClientSide()) { return false; } h.bridge$vanishState(v); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java index 552e3c6c9c7..9560426e1c0 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java @@ -29,7 +29,8 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.TypedEntityData; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.SignText; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; @@ -50,10 +51,11 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.SIGN_LINES) .get(h -> { - final CompoundTag tag = h.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY).copyTag(); - if (tag.isEmpty()) { + final @Nullable TypedEntityData data = h.get(DataComponents.BLOCK_ENTITY_DATA); + if (data == null) { return null; } + final var tag = data.getUnsafe(); final String id = tag.getStringOr(Constants.Item.BLOCK_ENTITY_ID, ""); if (!id.equalsIgnoreCase(Constants.TileEntity.SIGN)) { @@ -76,7 +78,7 @@ public static void register(final DataProviderRegistrator registrator) { } tag.putString("Text" + (i + 1), gcs.serialize(line)); } - h.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(tag)); + h.set(DataComponents.BLOCK_ENTITY_DATA, TypedEntityData.of(BlockEntityType.SIGN, tag)); }) .delete(h -> h.remove(DataComponents.BLOCK_ENTITY_DATA)); } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java index 81f7b503cb3..aa2c98f0a1b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java @@ -25,11 +25,14 @@ package org.spongepowered.common.data.provider.item.stack; import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.SpawnEggItem; import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.TypedEntityData; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.EntityArchetype; import org.spongepowered.common.SpongeCommon; @@ -47,11 +50,14 @@ public static void register(final DataProviderRegistrator registrator) { .get(stack -> { final Item item = stack.getItem(); final SpawnEggItem eggItem = (SpawnEggItem) item; - final EntityType type = eggItem.getType(SpongeCommon.vanillaRegistryAccess(), stack); - final var tag = stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY).getUnsafe(); + final @Nullable EntityType type = eggItem.getType(stack); + if (type == null) { + return null; + } + final var data = stack.getOrDefault(DataComponents.ENTITY_DATA, TypedEntityData.of(type, new CompoundTag())); final EntityArchetype.Builder builder = EntityArchetype.builder().type((org.spongepowered.api.entity.EntityType) type); - ((SpongeEntityArchetypeBuilder)builder).entityData(tag); + ((SpongeEntityArchetypeBuilder)builder).entityData(data.copyTagWithoutId()); return builder.build(); }) @@ -61,7 +67,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(stack -> { final Item item = stack.getItem(); final SpawnEggItem eggItem = (SpawnEggItem) item; - return (org.spongepowered.api.entity.EntityType) eggItem.getType(SpongeCommon.vanillaRegistryAccess(), stack); + return (org.spongepowered.api.entity.EntityType) eggItem.getType(stack); }) ; } diff --git a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java index a8cfbed2216..e59feb0d429 100644 --- a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java +++ b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java @@ -102,7 +102,7 @@ public static ClientboundSoundPacket playSound(final Sound sound, final RandomSo public static ClientboundStopSoundPacket stopSound(final SoundStop stop) { Objects.requireNonNull(stop, "stop"); - final @Nullable ResourceLocation sound = SpongeAdventure.asVanillaNullable(stop.sound()); + final @Nullable ResourceLocation sound = SpongeAdventure.asVanillaLocation(stop.sound()); final @Nullable SoundSource source = SpongeAdventure.asVanillaNullable(stop.source()); return new ClientboundStopSoundPacket(sound, source); } diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index e96f11ea028..28ee38978fc 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -46,6 +46,7 @@ import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.NameAndId; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; @@ -310,22 +311,22 @@ private void setProfileName(final net.minecraft.network.chat.@Nullable Component } public boolean getOrLoadSkin(final UUID minecraftAccount) { - GameProfile gameProfile = SpongeCommon.server().getProfileCache().get(minecraftAccount).orElse(null); - if (gameProfile == null) { - ProfileResult result = - SpongeCommon.server().getSessionService().fetchProfile(minecraftAccount, true); + final var server = SpongeCommon.server(); + final @Nullable GameProfile profile = server.nameToIdCache().get(minecraftAccount).flatMap(name -> + server.getProfileRepository().findProfileByName(name.name()) + ).orElseGet(() -> { + final @Nullable ProfileResult result = server.getSessionService().fetchProfile(minecraftAccount, true); if (result == null) { - return false; + return null; } - - gameProfile = result.profile(); - - // TODO Should we put profile cache entries with UUIDs that don't have their names? - - SpongeCommon.server().getProfileCache().add(gameProfile); + server.nameToIdCache().add(new NameAndId(result.profile())); + return result.profile(); + }); + if (profile == null) { + return false; } - this.fakeProfile.properties().replaceValues(ProfileProperty.TEXTURES, gameProfile.getProperties().get(ProfileProperty.TEXTURES)); + this.fakeProfile.properties().replaceValues(ProfileProperty.TEXTURES, profile.getProperties().get(ProfileProperty.TEXTURES)); if (this.isAliveAndInWorld()) { this.respawnOnClient(); } @@ -335,22 +336,16 @@ public boolean getOrLoadSkin(final UUID minecraftAccount) { public boolean getOrLoadSkin(final String minecraftAccount) { Objects.requireNonNull(minecraftAccount); - GameProfile gameProfile = SpongeCommon.server().getProfileCache().get(minecraftAccount).orElse(null); - if (gameProfile == null) { + final var server = SpongeCommon.server(); + final @Nullable GameProfile profile = server.nameToIdCache().get(minecraftAccount).flatMap(name -> + server.getProfileRepository().findProfileByName(name.name()) + ).orElse(null); + if (profile == null) { return false; } - if (gameProfile.getProperties().isEmpty()) { - ProfileResult result = SpongeCommon.server().getSessionService().fetchProfile(gameProfile.getId(), true); - if (result == null) { - return false; - } - gameProfile = result.profile(); - SpongeCommon.server().getProfileCache().add(gameProfile); - } - this.fakeProfile.properties().clear(); - this.fakeProfile.properties().putAll(gameProfile.getProperties()); + this.fakeProfile.properties().putAll(profile.getProperties()); if (this.isAliveAndInWorld()) { this.respawnOnClient(); } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 4d694340aeb..3c1ca2c8de5 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -518,10 +518,6 @@ public enum CollisionType public static boolean handleCollideBlockEvent(final Block block, final Level world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.entity.Entity entity, final Direction direction, final CollisionType type) { - if (world.isClientSide) { - return false; - } - if (world.isClientSide() || pos.getY() < world.getMinY()) { return false; } @@ -529,30 +525,23 @@ public static boolean handleCollideBlockEvent(final Block block, final Level wor try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(entity); - if (entity instanceof CreatorTrackedBridge) { - final CreatorTrackedBridge spongeEntity = (CreatorTrackedBridge) entity; + if (entity instanceof CreatorTrackedBridge spongeEntity) { spongeEntity.tracker$getCreatorUUID().ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user)); } // TODO: Add target side support final ServerLocation loc = ServerLocation.of((ServerWorld) world, VecHelper.toVector3d(pos)); - final CollideBlockEvent event; - switch (type) { - case MOVE: - event = SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction); - break; - case FALL: - event = SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction); - break; - case STEP_ON: - event = SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction); - break; - case INSIDE: - event = SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction); - break; - default: - throw new IllegalArgumentException("Unknown type " + type); - } + final CollideBlockEvent event = switch (type) { + case MOVE -> + SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction); + case FALL -> + SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction); + case STEP_ON -> + SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction); + case INSIDE -> + SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction); + default -> throw new IllegalArgumentException("Unknown type " + type); + }; final boolean cancelled = SpongeCommon.post(event); if (!cancelled) { final EntityBridge spongeEntity = (EntityBridge) entity; diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java index 962b8c0cbd2..a370479c4dd 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java @@ -110,7 +110,7 @@ public Supplier attemptWorldKey( final net.minecraft.world.entity.Entity entity = context.getSource(net.minecraft.world.entity.Entity.class) .orElseThrow( () -> new IllegalStateException("Expected to be ticking an entity, but we're not ticking an entity")); - if (entity.level().isClientSide) { + if (entity.level().isClientSide()) { return () -> { throw new IllegalStateException("attempting a world key on the client???"); }; diff --git a/src/main/java/org/spongepowered/common/inventory/custom/CarriedWrapperInventory.java b/src/main/java/org/spongepowered/common/inventory/custom/CarriedWrapperInventory.java index d31b8dd6218..2797832abe3 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/CarriedWrapperInventory.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/CarriedWrapperInventory.java @@ -104,16 +104,6 @@ public boolean stillValid(Player player) { return this.wrapped.stillValid(player); } - @Override - public void startOpen(Player player) { - this.wrapped.startOpen(player); - } - - @Override - public void stopOpen(Player player) { - this.wrapped.stopOpen(player); - } - @Override public boolean canPlaceItem(int index, ItemStack stack) { return this.wrapped.canPlaceItem(index, stack); @@ -133,4 +123,5 @@ public boolean hasAnyOf(Set set) { public void clearContent() { this.wrapped.clearContent(); } + } diff --git a/src/main/java/org/spongepowered/common/inventory/custom/ViewableCustomInventory.java b/src/main/java/org/spongepowered/common/inventory/custom/ViewableCustomInventory.java index a62ffd5c089..59ebaf67625 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/ViewableCustomInventory.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/ViewableCustomInventory.java @@ -76,16 +76,6 @@ public ContainerType getType() { return this.type; } - @Override - public void startOpen(final Player player) { - this.viewers.add(player); // TODO check if this is always called - } - - @Override - public void stopOpen(final Player player) { - this.viewers.remove(player); // TODO check if this is always called - } - @Override public @Nullable AbstractContainerMenu createMenu(int id, net.minecraft.world.entity.player.Inventory playerInv, Player player) { if (this.vanilla) { diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java index ced0b591832..b11fb94a437 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; +import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; @@ -43,7 +44,9 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.ItemAttributeModifiers; +import net.minecraft.world.item.component.TypedEntityData; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; import org.checkerframework.checker.nullness.qual.Nullable; import org.jetbrains.annotations.NotNull; import org.spongepowered.api.block.BlockSnapshot; @@ -76,7 +79,7 @@ import java.util.Objects; import java.util.Optional; -public final class SpongeItemStack { +public final class SpongeItemStack { public static final class BuilderImpl extends AbstractDataBuilder implements ItemStack.Builder { private ItemType type; @@ -195,9 +198,16 @@ public ItemStack.Builder fromBlockSnapshot(final BlockSnapshot blockSnapshot) { final Optional itemType = blockType.item(); this.itemType(itemType.orElseThrow(() -> new IllegalArgumentException("ItemType not found for block type: " + blockTypeKey))); this.quantity(1); - if (blockSnapshot instanceof SpongeBlockSnapshot) { - ((SpongeBlockSnapshot) blockSnapshot).getCompound().ifPresent(compoundTag -> { - this.components = DataComponentPatch.builder().set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(compoundTag)).build(); + if (blockSnapshot instanceof SpongeBlockSnapshot sbs) { + sbs.getCompound().ifPresent(compoundTag -> { + final var blockEntityTypes = SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE); + final var blockEntityType = compoundTag.getString("id") + .map(ResourceLocation::parse) + .flatMap(blockEntityTypes::getOptional); + blockEntityType.ifPresent(beType -> { + TypedEntityData> data = TypedEntityData.of(beType, compoundTag); + this.components = DataComponentPatch.builder().set(DataComponents.BLOCK_ENTITY_DATA, data).build(); + }); }); // todo probably needs more testing, but this'll do donkey... @@ -275,9 +285,9 @@ public ItemStack empty() { public static DataContainer getDataContainer(final net.minecraft.world.item.ItemStack mcStack) { final ResourceLocation key = BuiltInRegistries.ITEM.getKey(mcStack.getItem()); final DataContainer container = DataContainer.createNew() - .set(Queries.CONTENT_VERSION, ((ItemStack) (Object) mcStack).contentVersion()) - .set(Constants.ItemStack.TYPE, key) - .set(Constants.ItemStack.COUNT, mcStack.getCount()); + .set(Queries.CONTENT_VERSION, ((ItemStack) (Object) mcStack).contentVersion()) + .set(Constants.ItemStack.TYPE, key) + .set(Constants.ItemStack.COUNT, mcStack.getCount()); // Cleanup Old Custom Data SpongeItemStack.cleanupOldCustomData(mcStack); // Serialize all DataComponents... @@ -305,15 +315,16 @@ public static EquipmentSlotGroup asEquipmentSlotGroup(final EquipmentType equipm @SuppressWarnings("deprecation") private static void cleanupOldCustomData(final net.minecraft.world.item.ItemStack stack) { - final CompoundTag unsafe = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe(); - unsafe.remove(Constants.Sponge.Data.V2.SPONGE_DATA); // and its V2.CUSTOM_MANIPULATOR_TAG_LIST - Constants.NBT.filterSpongeCustomData(unsafe); // FORGE_DATA > V2.SPONGE_DATA also removes it if empty + stack.update(DataComponents.CUSTOM_DATA, CustomData.EMPTY, data -> data.update(tag -> { + tag.remove(Constants.Sponge.Data.V2.SPONGE_DATA); // and its V2.CUSTOM_MANIPULATOR_TAG_LIST + Constants.NBT.filterSpongeCustomData(tag); // FORGE_DATA > V2.SPONGE_DATA also removes it if empty + })); } // TODO updater for old (maybe V2?) Constants.Sponge.DATA_MANIPULATORS public static final ImmutableList STACK_UPDATERS = ImmutableList.of( - ItemStackSnapshotDuplicateManipulatorUpdater.INSTANCE, - ItemStackDataComponentsUpdater.INSTANCE); + ItemStackSnapshotDuplicateManipulatorUpdater.INSTANCE, + ItemStackDataComponentsUpdater.INSTANCE); @NotNull public static Optional createItemStack(final DataView container) { @@ -341,7 +352,7 @@ public static Optional createItemStack(final DataView container) { final int count = updatedContainer.getInt(Constants.ItemStack.COUNT).get(); final ItemType itemType = updatedContainer.getRegistryValue(Constants.ItemStack.TYPE, RegistryTypes.ITEM_TYPE) - .orElseThrow(() -> new IllegalStateException("Unable to find item with id: ")); + .orElseThrow(() -> new IllegalStateException("Unable to find item with id: ")); final var mcStack = new net.minecraft.world.item.ItemStack((Item) itemType, count); if (!mcStack.isEmpty()) { // ignore components when the stack is empty anyways // Read and apply components from container to mc stack diff --git a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java index ed0bf11cd26..d8798e4b23f 100644 --- a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java +++ b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java @@ -24,13 +24,13 @@ */ package org.spongepowered.common.network.packet; -import com.mojang.authlib.GameProfile; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.core.registries.Registries; +import net.minecraft.server.players.NameAndId; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.api.ResourceKey; @@ -110,11 +110,11 @@ private static TrackerDataResponsePacket createTrackerDataResponse( final Optional owner, final Optional notifier ) { - final String ownerName = owner.flatMap(x -> SpongeCommon.server().getProfileCache().get(x)) - .map(GameProfile::getName) + final String ownerName = owner.flatMap(SpongeCommon.server().nameToIdCache()::get) + .map(NameAndId::name) .orElse(""); - final String notifierName = notifier.flatMap(x -> SpongeCommon.server().getProfileCache().get(x)) - .map(GameProfile::getName) + final String notifierName = notifier.flatMap(SpongeCommon.server().nameToIdCache()::get) + .map(NameAndId::name) .orElse(""); return new TrackerDataResponsePacket(ownerName, notifierName); } diff --git a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java index 1671fe3d08c..7c75e137602 100644 --- a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java +++ b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.JsonObject; +import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.persistence.DataContainer; @@ -54,6 +55,12 @@ public final class SpongeGameProfile implements GameProfile { private static final Gson GSON = new Gson(); public static final UUID EMPTY_UUID = new UUID(0, 0); + public static SpongeGameProfile of(NameAndId mcProfile) { + final UUID uniqueId = mcProfile.id(); + final var name = mcProfile.name().isEmpty() ? null : mcProfile.name(); + return new SpongeGameProfile(uniqueId, name); + } + public static SpongeGameProfile of(final com.mojang.authlib.GameProfile mcProfile) { final UUID uniqueId = mcProfile.getId(); final String name = mcProfile.getName().isEmpty() ? null : mcProfile.getName(); @@ -63,12 +70,21 @@ public static SpongeGameProfile of(final com.mojang.authlib.GameProfile mcProfil return new SpongeGameProfile(uniqueId, name, properties); } + public static SpongeGameProfile basicOf(final NameAndId mcProfile) { + final var name = mcProfile.name().isEmpty() ? null : mcProfile.name(); + return new SpongeGameProfile(mcProfile.id(), name); + } + public static SpongeGameProfile basicOf(final com.mojang.authlib.GameProfile mcProfile) { final UUID uniqueId = mcProfile.getId(); final String name = mcProfile.getName().isEmpty() ? null : mcProfile.getName(); return new SpongeGameProfile(uniqueId, name); } + public static NameAndId toNameAndId(final GameProfile profile) { + return new NameAndId(profile.uuid(), profile.name().orElse("")); + } + public static com.mojang.authlib.GameProfile toMcProfile(final GameProfile profile) { return ((SpongeGameProfile) profile).toMcProfile(); } diff --git a/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java b/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java index f9ea16c603b..49fbc37b122 100644 --- a/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java +++ b/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java @@ -67,7 +67,7 @@ public final class SpongeGameProfileManager implements GameProfileManager { public SpongeGameProfileManager(final Server server) { this.usernameCache = ((SpongeServer) server).getUsernameCache(); - this.cache = (GameProfileCacheBridge) ((MinecraftServer) server).getProfileCache(); + this.cache = (GameProfileCacheBridge) ((MinecraftServer) server).nameToIdCache(); this.gameLookupExecutorService = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() .setNameFormat("Sponge - Async User Lookup Thread").build()); } diff --git a/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java b/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java index d2779bc6e82..4b160a73533 100644 --- a/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java +++ b/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java @@ -27,6 +27,7 @@ import com.google.inject.Singleton; import net.minecraft.server.players.IpBanList; import net.minecraft.server.players.IpBanListEntry; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.StoredUserEntry; import net.minecraft.server.players.UserBanList; import net.minecraft.server.players.UserBanListEntry; @@ -78,8 +79,8 @@ public CompletableFuture> bans() { @SuppressWarnings("unchecked") @Override public CompletableFuture> profileBans() { - final StoredUserListAccessor accessor = - (StoredUserListAccessor) this.getUserBanList(); + final StoredUserListAccessor accessor = + (StoredUserListAccessor) this.getUserBanList(); accessor.invoker$removeExpired(); return CompletableFuture.completedFuture(Collections.unmodifiableCollection(new ArrayList<>((Collection) (Object) accessor.accessor$map().values()))); } @@ -87,7 +88,7 @@ public CompletableFuture> profileBans() { @SuppressWarnings("unchecked") @Override public CompletableFuture> ipBans() { - final StoredUserListAccessor accessor = ((StoredUserListAccessor) this.getIPBanList()); + final StoredUserListAccessor accessor = ((StoredUserListAccessor) this.getIPBanList()); accessor.invoker$removeExpired(); return CompletableFuture.completedFuture(Collections.unmodifiableCollection(new ArrayList<>((Collection) (Object) accessor.accessor$map().values()))); } @@ -95,10 +96,10 @@ public CompletableFuture> ipBans() { @SuppressWarnings("unchecked") @Override public CompletableFuture> find(final GameProfile profile) { - final StoredUserListAccessor accessor = - (StoredUserListAccessor) this.getUserBanList(); + final StoredUserListAccessor accessor = + (StoredUserListAccessor) this.getUserBanList(); accessor.invoker$removeExpired(); - return CompletableFuture.completedFuture(Optional.ofNullable((Ban.Profile) accessor.accessor$map().get(accessor.invoker$getKeyForUser(SpongeGameProfile.toMcProfile(profile))))); + return CompletableFuture.completedFuture(Optional.ofNullable((Ban.Profile) accessor.accessor$map().get(accessor.invoker$getKeyForUser(SpongeGameProfile.toNameAndId(profile))))); } @SuppressWarnings("unchecked") @@ -112,11 +113,11 @@ public CompletableFuture> find(final InetAddress address) { @SuppressWarnings("unchecked") public boolean isBanned(final GameProfile profile) { - final StoredUserListAccessor accessor = - (StoredUserListAccessor) this.getUserBanList(); + final StoredUserListAccessor accessor = + (StoredUserListAccessor) this.getUserBanList(); accessor.invoker$removeExpired(); - return accessor.accessor$map().containsKey(accessor.invoker$getKeyForUser(SpongeGameProfile.toMcProfile(profile))); + return accessor.accessor$map().containsKey(accessor.invoker$getKeyForUser(SpongeGameProfile.toNameAndId(profile))); } @SuppressWarnings("unchecked") @@ -131,8 +132,8 @@ public boolean isBanned(final InetAddress address) { @Override public CompletableFuture pardon(final GameProfile profile) { final CompletableFuture> ban = this.find(profile); - final StoredUserListAccessor accessor = - (StoredUserListAccessor) this.getUserBanList(); + final StoredUserListAccessor accessor = + (StoredUserListAccessor) this.getUserBanList(); accessor.invoker$removeExpired(); return ban.thenCompose(result -> result.map(this::remove).orElse(CompletableFuture.completedFuture(false))); } diff --git a/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java b/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java index 85e8b0d61f8..35ca1c9575a 100644 --- a/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java +++ b/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java @@ -25,6 +25,7 @@ package org.spongepowered.common.service.server.ban; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserBanList; import net.minecraft.server.players.UserBanListEntry; import org.spongepowered.api.Sponge; @@ -51,19 +52,19 @@ public SpongeUserBanList(final File file) { } @Override - protected boolean contains(final com.mojang.authlib.GameProfile profile) { + protected boolean contains(final NameAndId profile) { return Sponge.server().serviceProvider().banService().find(SpongeGameProfile.of(profile)).join().isPresent(); } @Override - public UserBanListEntry get(final com.mojang.authlib.GameProfile profile) { + public UserBanListEntry get(final NameAndId profile) { final Optional ban = Sponge.server().serviceProvider().banService().find(SpongeGameProfile.of(profile)).join(); return ban.map(x -> { if (x instanceof UserBanListEntry) { return (UserBanListEntry) x; } else { final LegacyComponentSerializer lcs = LegacyComponentSerializer.legacySection(); - return new UserBanListEntry(SpongeGameProfile.toMcProfile(x.profile()), + return new UserBanListEntry(SpongeGameProfile.toNameAndId(x.profile()), Date.from(x.creationDate()), x.banSource().map(lcs::serialize).orElse(null), x.expirationDate().map(Date::from).orElse(null), @@ -94,7 +95,7 @@ public boolean isEmpty() { } @Override - public void remove(final com.mojang.authlib.GameProfile entry) { + public void remove(final NameAndId entry) { final CompletableFuture completableFuture = Sponge.server().serviceProvider().banService().pardon(SpongeGameProfile.of(entry)); ((MinecraftServerBridge) SpongeCommon.server()).bridge$spongeMainThreadExecutor().managedBlock(completableFuture::isDone); } diff --git a/src/main/java/org/spongepowered/common/service/server/permission/UserCollection.java b/src/main/java/org/spongepowered/common/service/server/permission/UserCollection.java index 803e57f8ea1..3d9ba6409a3 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/UserCollection.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/UserCollection.java @@ -25,6 +25,7 @@ package org.spongepowered.common.service.server.permission; import com.mojang.authlib.GameProfile; +import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Sponge; import org.spongepowered.api.service.permission.PermissionService; @@ -73,8 +74,7 @@ public boolean isRegistered(final String identifier) { return false; } // Name doesn't matter when getting entries - final GameProfile profile = new GameProfile(uuid, ""); - return SpongePermissionService.getOps().get(profile) != null; + return SpongePermissionService.getOps().get(new NameAndId(uuid, "")) != null; } private @Nullable UUID identityToUuid(final String identifier) { diff --git a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java index 62637f1ba03..df90e34cd52 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java @@ -25,6 +25,7 @@ package org.spongepowered.common.service.server.permission; import com.mojang.authlib.GameProfile; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.ServerOpListEntry; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Cause; @@ -43,11 +44,13 @@ */ public class UserSubject extends SpongeSubject { private final GameProfile player; + private final NameAndId nameAndId; private final MemorySubjectData data; private final UserCollection collection; public UserSubject(final GameProfile player, final UserCollection users) { this.player = Objects.requireNonNull(player); + this.nameAndId = new NameAndId(player); this.data = new SingleParentMemorySubjectData(this) { @Override public SubjectReference parent() { @@ -67,9 +70,9 @@ public void setParent(final SubjectReference parent) { } if (opLevel > 0) { // TODO: Should bypassesPlayerLimit be true or false? - SpongePermissionService.getOps().add(new ServerOpListEntry(player, opLevel, false)); + SpongePermissionService.getOps().add(new ServerOpListEntry(UserSubject.this.nameAndId, opLevel, false)); } else { - SpongePermissionService.getOps().remove(player); + SpongePermissionService.getOps().remove(UserSubject.this.nameAndId); } } }; @@ -100,10 +103,10 @@ int getOpLevel() { Preconditions.checkState(Sponge.isServerAvailable(), "Server is not available!"); // Query op level from server ops list based on player's game profile - final ServerOpListEntry entry = SpongePermissionService.getOps().get(this.player); + final ServerOpListEntry entry = SpongePermissionService.getOps().get(this.nameAndId); if (entry == null) { // Take care of singleplayer commands -- unless an op level is specified, this player follows global rules - return SpongeCommon.server().getPlayerList().isOp(this.player) ? SpongeCommon.server().getOperatorUserPermissionLevel() : 0; + return SpongeCommon.server().getPlayerList().isOp(this.nameAndId) ? SpongeCommon.server().getOperatorUserPermissionLevel() : 0; } else { return entry.getLevel(); } diff --git a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java index 7b450b45d77..694aacc02c8 100644 --- a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java +++ b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.service.server.whitelist; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserWhiteList; import net.minecraft.server.players.UserWhiteListEntry; import org.spongepowered.api.Sponge; @@ -46,7 +47,7 @@ public SpongeUserWhiteList(final File file) { } @Override - protected boolean contains(final com.mojang.authlib.GameProfile entry) { + protected boolean contains(final NameAndId entry) { return Sponge.server().serviceProvider().whitelistService().isWhitelisted(SpongeGameProfile.of(entry)).join(); } @@ -66,7 +67,7 @@ public void add(final UserWhiteListEntry entry) { } @Override - public void remove(final com.mojang.authlib.GameProfile entry) { + public void remove(final NameAndId entry) { Sponge.server().serviceProvider().whitelistService().removeProfile(SpongeGameProfile.of(entry)).join(); } diff --git a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java index 337852b75ca..dd9d59dfc12 100644 --- a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java +++ b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java @@ -25,6 +25,7 @@ package org.spongepowered.common.service.server.whitelist; import com.google.inject.Singleton; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserWhiteList; import net.minecraft.server.players.UserWhiteListEntry; import org.spongepowered.api.profile.GameProfile; @@ -49,8 +50,8 @@ public CompletableFuture> whitelistedProfiles() { final List profiles = new ArrayList<>(); final UserWhiteList list = SpongeCommon.server().getPlayerList().getWhiteList(); - for (final UserWhiteListEntry entry: ((StoredUserListAccessor) list).accessor$map().values()) { - profiles.add(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())); + for (final UserWhiteListEntry entry: ((StoredUserListAccessor) list).accessor$map().values()) { + profiles.add(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())); } return CompletableFuture.completedFuture(profiles); @@ -59,16 +60,16 @@ public CompletableFuture> whitelistedProfiles() { @SuppressWarnings("unchecked") @Override public CompletableFuture isWhitelisted(final GameProfile profile) { - final StoredUserListAccessor whitelist = (StoredUserListAccessor) SpongeWhitelistService + final StoredUserListAccessor whitelist = (StoredUserListAccessor) SpongeWhitelistService .getWhitelist(); whitelist.invoker$removeExpired(); - return CompletableFuture.completedFuture(whitelist.accessor$map().containsKey(whitelist.invoker$getKeyForUser(SpongeGameProfile.toMcProfile(profile)))); + return CompletableFuture.completedFuture(whitelist.accessor$map().containsKey(whitelist.invoker$getKeyForUser(SpongeGameProfile.toNameAndId(profile)))); } @Override public CompletableFuture addProfile(final GameProfile profile) { - final boolean wasWhitelisted = UserListUtil.addEntry(SpongeWhitelistService.getWhitelist(), new UserWhiteListEntry(SpongeGameProfile.toMcProfile(profile))) != null; + final boolean wasWhitelisted = UserListUtil.addEntry(SpongeWhitelistService.getWhitelist(), new UserWhiteListEntry(SpongeGameProfile.toNameAndId(profile))) != null; return CompletableFuture.completedFuture(wasWhitelisted); } diff --git a/src/main/java/org/spongepowered/common/user/SpongeUserManager.java b/src/main/java/org/spongepowered/common/user/SpongeUserManager.java index 60b7c4e369d..08445d2b1ff 100644 --- a/src/main/java/org/spongepowered/common/user/SpongeUserManager.java +++ b/src/main/java/org/spongepowered/common/user/SpongeUserManager.java @@ -112,7 +112,8 @@ public CompletableFuture loadOrCreate(final UUID uuid) { return CompletableFuture.completedFuture(null); } return CompletableFuture.supplyAsync(() -> { - final com.mojang.authlib.GameProfile profile = this.server.getProfileCache().get(uuidToUse) + final com.mojang.authlib.GameProfile profile = this.server.nameToIdCache().get(uuidToUse) + .map(nameAndId -> new com.mojang.authlib.GameProfile(nameAndId.id(), nameAndId.name())) .orElseGet(() -> new com.mojang.authlib.GameProfile(uuidToUse, "")); try { this.createUser(profile); diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java index 9c281ee6f05..5abaf5ecb3b 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java @@ -77,10 +77,9 @@ public TicketType build() { if (this.comparator == null) { this.comparator = (v1, v2) -> 0; } + // This will load and simulate, but not persist nor keep the dimension active. + final var flag = 1 << 2 & 1 << 4; final var timeout = this.lifetime.isInfinite() ? Constants.ChunkTicket.INFINITE_TIMEOUT : this.lifetime.ticks(); - return (TicketType) (Object) new net.minecraft.server.level.TicketType( - timeout, - false, // TODO - Do we determine if a ticket type should be stored? - net.minecraft.server.level.TicketType.TicketUse.LOADING_AND_SIMULATION); + return (TicketType) (Object) new net.minecraft.server.level.TicketType(timeout,flag); } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 91d116ebd68..427e2f20f1e 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -39,16 +39,14 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.Mth; +import net.minecraft.server.level.progress.LevelLoadListener; +import net.minecraft.server.level.progress.LoggingLevelLoadListener; import net.minecraft.util.TimeUtil; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; import net.minecraft.world.entity.npc.WanderingTraderSpawner; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.CustomSpawner; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.TicketStorage; @@ -87,7 +85,6 @@ import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.MinecraftServerAccessor; -import org.spongepowered.common.accessor.server.level.ServerLevelAccessor; import org.spongepowered.common.accessor.world.level.storage.PrimaryLevelDataAccessor; import org.spongepowered.common.bridge.core.MappedRegistryBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; @@ -134,6 +131,7 @@ public class SpongeWorldManager implements WorldManager { private final MinecraftServer server; private final Path defaultWorldDirectory, customWorldsDirectory; private final Map, ServerLevel> worlds; + private final LevelLoadListener levelLoadListener; public SpongeWorldManager(final MinecraftServer server) { this.server = server; @@ -145,6 +143,7 @@ public SpongeWorldManager(final MinecraftServer server) { throw new RuntimeException(e); } this.worlds = ((MinecraftServerAccessor) this.server).accessor$levels(); + this.levelLoadListener = LoggingLevelLoadListener.forDedicatedServer(); } @Override @@ -693,12 +692,6 @@ private CompletableFuture unloadWorld0(final ServerLevel level) { PlatformHooks.INSTANCE.getWorldHooks().preUnloadWorld(level); - final int lastSpawnChunkRadius = ((ServerLevelAccessor) level).accessor$lastSpawnChunkRadius(); - if (lastSpawnChunkRadius > 1) { - final BlockPos spawnPoint = level.getSharedSpawnPos(); - level.getChunkSource().removeTicketWithRadius(TicketType.START, new ChunkPos(spawnPoint), lastSpawnChunkRadius); - ((ServerLevelAccessor) level).accessor$setLastSpawnChunkRadius(1); - } final var configAdapter = ((ServerLevelDataBridge) level.getLevelData()).bridge$spongeData().configAdapter(); if (configAdapter != null) { @@ -906,10 +899,9 @@ private ServerLevel createLevel( final long seed = BiomeManager.obfuscateSeed(levelData.worldGenOptions().seed()); final Executor executor = ((MinecraftServerAccessor) this.server).accessor$executor(); - final ChunkProgressListener progressListener = ((MinecraftServerAccessor) this.server).accessor$progressListenerFactory().create(SpongeWorldManager.getSpawnRadius(levelData)); final ServerLevel world = new ServerLevel(this.server, executor, storageSource, levelData, - registryKey, levelStem, progressListener, levelData.isDebugWorld(), seed, spawners, true, null); + registryKey, levelStem, levelData.isDebugWorld(), seed, spawners, true, null); this.worlds.put(registryKey, world); // Ensure that the world border is registered. @@ -939,7 +931,7 @@ private ServerLevel prepareLevel(final ServerLevel level) { final boolean hasSpawnAlready = levelDataBridge.bridge$customSpawnPosition(); if (!hasSpawnAlready) { if (levelDataBridge.bridge$performsSpawnLogic()) { - MinecraftServerAccessor.invoker$setInitialSpawn(level, levelData, worldData.worldGenOptions().generateBonusChest(), isDebugGeneration); + MinecraftServerAccessor.invoker$setInitialSpawn(level, levelData, worldData.worldGenOptions().generateBonusChest(), isDebugGeneration, server.getLevelLoadListener()); } else if (Level.END.equals(level.dimension())) { levelData.setSpawn(ServerLevel.END_SPAWN_POINT, 0); } @@ -985,18 +977,13 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel le final ServerChunkCache chunkSource = level.getChunkSource(); level.setDefaultSpawnPos(level.getSharedSpawnPos(), level.getSharedSpawnAngle()); - final int spawnRadius = SpongeWorldManager.getSpawnRadius((ServerLevelData) level.getLevelData()); - final int spawnSize = spawnRadius > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(spawnRadius)) : 0; - final CompletableFuture generationFuture = new CompletableFuture<>(); Sponge.asyncScheduler().submit( Task.builder().plugin(Launch.instance().platformPlugin()).execute(task -> { - if (chunkSource.getTickingGenerated() >= spawnSize) { - Sponge.server().scheduler().submit(Task.builder().plugin(Launch.instance().platformPlugin()).execute(() -> generationFuture.complete(level)).build()); - // Notify the future that we are done - task.cancel(); // And cancel this task - MinecraftServerAccessor.accessor$LOGGER().info("Done preparing start region for dimension {}", level.dimension().location()); - } + Sponge.server().scheduler().submit(Task.builder().plugin(Launch.instance().platformPlugin()).execute(() -> generationFuture.complete(level)).build()); + // Notify the future that we are done + task.cancel(); // And cancel this task + MinecraftServerAccessor.accessor$LOGGER().info("Done preparing start region for dimension {}", level.dimension().location()); }).interval(10, TimeUnit.MILLISECONDS).build() ); @@ -1013,21 +1000,10 @@ private void loadSpawnChunks(final ServerLevel level) { MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().location()); final BlockPos spawnPoint = level.getSharedSpawnPos(); - final ChunkPos chunkPos = new ChunkPos(spawnPoint); - final ChunkProgressListener progressListener = ((ServerLevelBridge) level).bridge$getChunkProgressListener(); - progressListener.updateSpawnPos(chunkPos); final ServerChunkCache chunkSource = level.getChunkSource(); ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos()); level.setDefaultSpawnPos(spawnPoint, level.getSharedSpawnAngle()); - final int spawnRadius = SpongeWorldManager.getSpawnRadius((ServerLevelData) level.getLevelData()); - final int spawnSize = spawnRadius > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(spawnRadius)) : 0; - - while (chunkSource.getTickingGenerated() < spawnSize) { - ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos() + 10L * TimeUtil.NANOSECONDS_PER_MILLISECOND); - ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick(); - } - ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos() + 10L * TimeUtil.NANOSECONDS_PER_MILLISECOND); ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick(); @@ -1035,11 +1011,6 @@ private void loadSpawnChunks(final ServerLevel level) { ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos() + 10L * TimeUtil.NANOSECONDS_PER_MILLISECOND); ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick(); - progressListener.stop(); - } - - private static int getSpawnRadius(final ServerLevelData levelData) { - return ((ServerLevelDataBridge) levelData).bridge$performsSpawnLogic() ? levelData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS) : 0; } private static void updateForcedChunks(final ServerLevel level, final ServerChunkCache serverChunkProvider) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java index e6d3552b6ad..c109b5c9ea2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java @@ -50,7 +50,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; -@Mixin(net.minecraft.server.players.GameProfileCache.class) +@Mixin(net.minecraft.server.players.CachedUserNameToIdResolver.class) public abstract class GameProfileCacheMixin_API implements GameProfileCache { // @formatter:off @@ -95,7 +95,7 @@ public Collection removeIf(final Predicate filter) { final Iterator it = this.profilesByUUID.values().iterator(); while (it.hasNext()) { final GameProfileCache_GameProfileInfoAccessor entry = it.next(); - final GameProfile profile = SpongeGameProfile.of(entry.invoker$getProfile()); + final GameProfile profile = SpongeGameProfile.of(entry.invoker$nameAndId()); final boolean isExpired = entry.invoker$getExpirationDate().getTime() < System.currentTimeMillis(); if (isExpired || filter.test(profile)) { it.remove(); @@ -136,9 +136,9 @@ public Optional findByName(final String name) { @Nullable GameProfileCache_GameProfileInfoAccessor entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); if (entry != null && System.currentTimeMillis() >= entry.invoker$getExpirationDate().getTime()) { - final com.mojang.authlib.GameProfile profile = entry.invoker$getProfile(); - this.profilesByUUID.remove(profile.getId()); - this.profilesByName.remove(profile.getName().toLowerCase(Locale.ROOT)); + final var profile = entry.invoker$nameAndId(); + this.profilesByUUID.remove(profile.id()); + this.profilesByName.remove(profile.name().toLowerCase(Locale.ROOT)); entry = null; } @@ -158,7 +158,7 @@ public Map> findByNames(final Iterable nam @Override public Stream stream() { return this.profilesByName.values().stream() - .map(entry -> SpongeGameProfile.of(entry.invoker$getProfile())); + .map(entry -> SpongeGameProfile.of(entry.invoker$nameAndId())); } @Override @@ -172,8 +172,8 @@ public Collection all() { public Stream streamOfMatches(final String name) { final String search = Objects.requireNonNull(name, "name").toLowerCase(Locale.ROOT); return this.profilesByName.values().stream() - .filter(profile -> profile.invoker$getProfile().getName() != null) - .filter(profile -> profile.invoker$getProfile().getName().toLowerCase(Locale.ROOT).startsWith(search)) + .filter(profile -> profile.invoker$nameAndId().name() != null) + .filter(profile -> profile.invoker$nameAndId().name().toLowerCase(Locale.ROOT).startsWith(search)) .map(this::api$updateLastAccess); } @@ -188,6 +188,6 @@ public Collection allMatches(final String name) { return null; } entry.invoker$setLastAccess(this.shadow$getNextOperation()); - return SpongeGameProfile.of(entry.invoker$getProfile()); + return SpongeGameProfile.of(entry.invoker$nameAndId()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/CopperGolemStatueBlock_PoseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/CopperGolemStatueBlock_PoseMixin_API.java new file mode 100644 index 00000000000..0ced2233a87 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/CopperGolemStatueBlock_PoseMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.level.block; + +import net.minecraft.world.level.block.CopperGolemStatueBlock; +import org.spongepowered.api.data.type.CopperGolemPose; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CopperGolemStatueBlock.Pose.class) +public abstract class CopperGolemStatueBlock_PoseMixin_API implements CopperGolemPose { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/WeatheringCopper_WeatherStateMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/WeatheringCopper_WeatherStateMixin_API.java new file mode 100644 index 00000000000..a01410ae563 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/WeatheringCopper_WeatherStateMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.level.block; + +import net.minecraft.world.level.block.WeatheringCopper; +import org.spongepowered.api.data.type.CopperOxidation; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(WeatheringCopper.WeatherState.class) +public abstract class WeatheringCopper_WeatherStateMixin_API implements CopperOxidation { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java index 9c57c3e94b1..75e3f3936b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java @@ -89,7 +89,7 @@ public ServerLocation serverLocation() { throw new RuntimeException("The TileEntity has not been spawned in a world yet!"); } - if (this.level.isClientSide) { + if (this.level.isClientSide()) { throw new RuntimeException("You should not attempt to make a server-side location on the client!"); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/SpawnerBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/SpawnerBlockEntityMixin_API.java index 18c8c25b2c6..ddf98728581 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/SpawnerBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/SpawnerBlockEntityMixin_API.java @@ -51,7 +51,7 @@ public void spawnEntityBatchImmediately(final boolean force) { bridge.bridge$setMaxNearbyEntities(Short.MAX_VALUE); bridge.bridge$setSpawnDelay(0); - if (!this.level.isClientSide) { + if (!this.level.isClientSide()) { this.shadow$getSpawner().serverTick((ServerLevel) this.level, this.worldPosition); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java index f8972753682..83e43cc55f2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/TrialSpawnerBlockEntityMixin_API.java @@ -40,7 +40,7 @@ public abstract class TrialSpawnerBlockEntityMixin_API extends BlockEntityMixin_ @Override public void spawnImmediately(final boolean force) { - if (this.level.isClientSide) { + if (this.level.isClientSide()) { return; } final var thisLevel = (ServerLevel) this.level; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseRouterMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseRouterMixin_API.java index c5831f8c3c5..39b4796b568 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseRouterMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/NoiseRouterMixin_API.java @@ -44,7 +44,6 @@ public abstract class NoiseRouterMixin_API implements org.spongepowered.api.worl @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction erosion; @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction depth; @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction ridges; - @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction initialDensityWithoutJaggedness; @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction finalDensity; @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction veinToggle; @Shadow @Final private net.minecraft.world.level.levelgen.DensityFunction veinRidged; @@ -101,11 +100,6 @@ public DensityFunction ridges() { return (DensityFunction) this.ridges; } - @Override - public DensityFunction initialDensityWithoutJaggedness() { - return (DensityFunction) this.initialDensityWithoutJaggedness; - } - @Override public DensityFunction finalDensity() { return (DensityFunction) this.finalDensity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java index bb26db49f6d..1ed65fb9aab 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/text/format/StyleImplMixin.java @@ -60,7 +60,7 @@ public abstract class StyleImplMixin implements StyleBridge { // insertion $this.insertion(), // font - SpongeAdventure.asVanillaNullable($this.font()) + SpongeAdventure.asVanillaFontDescription($this.font()) ); } // Style is immutable, no need to copy diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java index 97fee76c145..eecb90a85df 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java @@ -49,7 +49,7 @@ public class BedBlockMixin { @Inject(method = "useWithoutItem", at = @At(value = "HEAD"), cancellable = true) private void impl$onUseBed(final BlockState param0, final Level param1, final BlockPos param2, final Player param3, final BlockHitResult param5, final CallbackInfoReturnable cir) { - if (!param1.isClientSide) { + if (!param1.isClientSide()) { final Cause currentCause = PhaseTracker.getInstance().currentCause(); final BlockPos bedLocation = param5.getBlockPos(); final BlockSnapshot snapshot = ((ServerWorld) param1).createSnapshot(bedLocation.getX(), bedLocation.getY(), bedLocation.getZ()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java index 500a95baa45..5e73ff153f7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java @@ -27,6 +27,7 @@ import com.mojang.authlib.GameProfile; import net.minecraft.client.server.IntegratedPlayerList; import net.minecraft.network.chat.Component; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -42,11 +43,12 @@ public abstract class IntegratedPlayerListMixin extends PlayerListMixin implements IntegratedPlayerListBridge { // @formatter:off - @Shadow public abstract Component shadow$canPlayerLogin(SocketAddress param0, GameProfile param1); + @Shadow public abstract Component shadow$canPlayerLogin(SocketAddress param0, NameAndId param1); // @formatter:on + @Override public CompletableFuture bridge$canPlayerLoginClient(final SocketAddress param0, final com.mojang.authlib.GameProfile param1) { - final Component component = this.shadow$canPlayerLogin(param0, param1); + final Component component = this.shadow$canPlayerLogin(param0, new NameAndId(param1)); if (component == null) { return this.impl$canPlayerLoginServer(param0, param1); } @@ -54,9 +56,8 @@ public abstract class IntegratedPlayerListMixin extends PlayerListMixin implemen } @Redirect(method = "canPlayerLogin", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)" - + "Lnet/minecraft/network/chat/Component;")) - private Component impl$redirectCanPlayerLoginSuperCall(final PlayerList playerList, final SocketAddress param0, final GameProfile param1) { + target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lnet/minecraft/server/players/NameAndId;)Lnet/minecraft/network/chat/Component;")) + private Component impl$redirectCanPlayerLoginSuperCall(final PlayerList playerList, final SocketAddress param0, final NameAndId param1) { return null; // we'll handle it above which we'll indicate by returning null. } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/syncher/SynchedEntityDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/syncher/SynchedEntityDataMixin.java index e2175da5295..e135c13840b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/syncher/SynchedEntityDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/syncher/SynchedEntityDataMixin.java @@ -84,7 +84,7 @@ public abstract class SynchedEntityDataMixin { final var thisEntity = (Entity) this.entity; - if (thisEntity.level() == null || thisEntity.level().isClientSide || ((EntityBridge) this.entity).bridge$isConstructing()) { + if (thisEntity.level() == null || thisEntity.level().isClientSide() || ((EntityBridge) this.entity).bridge$isConstructing()) { return dataentry; } final Optional> converter = ((EntityDataAccessorBridge) (Object) accessor).bridge$getDataConverter(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 296f4f89f7a..c4c1efd11f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -41,12 +41,12 @@ import net.minecraft.server.ServerFunctionManager; import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.server.level.progress.LevelLoadListener; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleReloadInstance; -import net.minecraft.server.players.GameProfileCache; import net.minecraft.server.players.PlayerList; +import net.minecraft.server.players.UserNameToIdResolver; import net.minecraft.util.Unit; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Difficulty; @@ -138,7 +138,7 @@ public abstract class MinecraftServerMixin implements SpongeServer, MinecraftSer @Shadow public abstract PlayerList shadow$getPlayerList(); @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract RegistryAccess.Frozen shadow$registryAccess(); - @Shadow public abstract GameProfileCache shadow$getProfileCache(); + @Shadow public abstract UserNameToIdResolver shadow$nameToIdCache(); @Shadow public abstract CompletableFuture shadow$reloadResources(final Collection $$0); @Shadow public abstract WorldData shadow$getWorldData(); @Shadow public abstract boolean shadow$haveTime(); @@ -146,6 +146,7 @@ public abstract class MinecraftServerMixin implements SpongeServer, MinecraftSer @Shadow public abstract ResourceManager shadow$getResourceManager(); // @formatter:on + private final ChatDecorator impl$spongeDecorator = new SpongeChatDecorator(); private @Nullable SpongeServerScopedServiceProvider impl$serviceProvider; protected @Nullable ResourcePackRequest impl$resourcePack; @@ -213,8 +214,12 @@ public Subject subject() { frame.pushCause(Sponge.systemSubject()); } - @Inject(method = "createLevels", at = @At(value = "INVOKE", ordinal = 0, - target = "Lnet/minecraft/server/level/ServerLevel;(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;Lnet/minecraft/server/level/progress/ChunkProgressListener;ZJLjava/util/List;ZLnet/minecraft/world/RandomSequences;)V")) + @Inject(method = "createLevels", at = @At(value = "NEW", + target = "(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;ZJLjava/util/List;ZLnet/minecraft/world/RandomSequences;)Lnet/minecraft/server/level/ServerLevel;" + ), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/core/Registry;getValue(Lnet/minecraft/resources/ResourceKey;)Ljava/lang/Object;"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;readScoreboard(Lnet/minecraft/world/level/storage/DimensionDataStorage;)V") + )) private void impl$onCreateDefaultLevel(final CallbackInfo ci, @Local final ServerLevelData levelData, @Local final LevelStem levelStem) { ((PrimaryLevelDataBridge) levelData).bridge$populateFromLevelStem(levelStem); ((ServerLevelDataBridge) levelData).bridge$spongeData().setKey(DefaultWorldKeys.DEFAULT); @@ -234,10 +239,12 @@ public Subject subject() { } @WrapMethod(method = "setInitialSpawn") - private static void impl$wrapSetInitialSpawn(final ServerLevel level, final ServerLevelData levelData, final boolean generateBonusChest, final boolean debugWorld, final Operation original) { + private static void impl$wrapSetInitialSpawn( + final ServerLevel level, final ServerLevelData levelData, final boolean generateBonusChest, + final boolean debugWorld, final LevelLoadListener listener, Operation original) { try (final var state = GenerationPhase.State.TERRAIN_GENERATION.createPhaseContext(PhaseTracker.getInstance())) { state.buildAndSwitch(); - original.call(level, levelData, generateBonusChest, debugWorld); + original.call(level, levelData, generateBonusChest, debugWorld, listener); } } @@ -246,7 +253,7 @@ public Subject subject() { * @reason Multi world. */ @Overwrite - private void prepareLevels(final ChunkProgressListener progressListener) { + private void prepareLevels() { this.worldManager().prepareLevels(); } @@ -262,7 +269,7 @@ public String getServerModName() { @Inject(method = "stopServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;saveAllChunks(ZZZ)Z")) private void impl$callUnloadWorldEvents(final CallbackInfo ci) { - for(final ServerLevel level : this.shadow$getAllLevels()) { + for (final ServerLevel level : this.shadow$getAllLevels()) { final UnloadWorldEvent unloadWorldEvent = SpongeEventFactory.createUnloadWorldEvent(PhaseTracker.getInstance().currentCause(), (ServerWorld) level); SpongeCommon.post(unloadWorldEvent); } @@ -387,7 +394,7 @@ public boolean saveAllChunks(final boolean suppressLog, final boolean flush, fin // Save the usercache.json file every 10 minutes or if forced to if (isForced || this.tickCount % 6000 == 0) { // We want to save the username cache json, as we normally bypass it. - final GameProfileCache profileCache = this.shadow$getProfileCache(); + final var profileCache = this.shadow$nameToIdCache(); ((GameProfileCacheBridge) profileCache).bridge$setCanSave(true); profileCache.save(); ((GameProfileCacheBridge) profileCache).bridge$setCanSave(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java index 6a23e98a14a..992760e055e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java @@ -29,6 +29,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.RegistryLayer; import net.minecraft.server.dedicated.DedicatedPlayerList; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import net.minecraft.world.level.storage.PlayerDataStorage; import org.spongepowered.api.Sponge; @@ -51,13 +52,13 @@ public DedicatedPlayerListMixin(final MinecraftServer server, final LayeredRegis } @Inject(method = "isWhiteListed", at = @At("HEAD"), cancellable = true) - private void impl$checkForWhitelistBypassPermission(final GameProfile profile, final CallbackInfoReturnable ci) { + private void impl$checkForWhitelistBypassPermission(final NameAndId profile, final CallbackInfoReturnable ci) { if (!this.isUsingWhitelist() || this.getWhiteList().isWhiteListed(profile)) { ci.setReturnValue(true); return; } final PermissionService permissionService = Sponge.server().serviceProvider().permissionService(); - Subject subject = permissionService.userSubjects().subject(profile.getId().toString()).orElse(null); + Subject subject = permissionService.userSubjects().subject(profile.id().toString()).orElse(null); if (subject == null) { subject = permissionService.userSubjects().defaults(); } @@ -66,9 +67,9 @@ public DedicatedPlayerListMixin(final MinecraftServer server, final LayeredRegis } @Inject(method = "canBypassPlayerLimit", at = @At("HEAD"), cancellable = true) - private void impl$checkForPlayerLimitBypassPermission(final GameProfile profile, final CallbackInfoReturnable ci) { + private void impl$checkForPlayerLimitBypassPermission(final NameAndId profile, final CallbackInfoReturnable ci) { final PermissionService permissionService = Sponge.server().serviceProvider().permissionService(); - Subject subject = permissionService.userSubjects().subject(profile.getId().toString()).orElse(null); + Subject subject = permissionService.userSubjects().subject(profile.id().toString()).orElse(null); if (subject == null) { subject = permissionService.userSubjects().defaults(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java index 3539859ecd7..8f29486072b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java @@ -33,9 +33,8 @@ import net.minecraft.server.WorldStem; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServerSettings; -import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; -import net.minecraft.server.players.GameProfileCache; +import net.minecraft.server.players.UserNameToIdResolver; import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -55,21 +54,22 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin { @Inject(method = "", at = @At("TAIL")) - private void impl$setServerOnGame(Thread $$0, LevelStorageSource.LevelStorageAccess $$1, PackRepository $$2, WorldStem $$3, - DedicatedServerSettings $$4, DataFixer $$5, Services $$6, ChunkProgressListenerFactory $$7, CallbackInfo ci) { + private void impl$setServerOnGame( + final Thread $$0, final LevelStorageSource.LevelStorageAccess $$1, final PackRepository $$2, final WorldStem $$3, + final DedicatedServerSettings $$4, final DataFixer $$5, final Services $$6, final CallbackInfo ci + ) { $$4.getProperties().serverResourcePackInfo.ifPresent(packInfo -> { try { this.impl$resourcePack = ResourcePackRequest.resourcePackRequest() - .packs(ResourcePackInfo.resourcePackInfo(packInfo.id(), new URI(packInfo.url()), packInfo.hash())) - .required(packInfo.isRequired()) - .prompt(SpongeAdventure.asAdventure(Optional.ofNullable(packInfo.prompt()))) - .build(); + .packs(ResourcePackInfo.resourcePackInfo(packInfo.id(), new URI(packInfo.url()), packInfo.hash())) + .required(packInfo.isRequired()) + .prompt(SpongeAdventure.asAdventure(Optional.ofNullable(packInfo.prompt()))) + .build(); } catch (final URISyntaxException e) { e.printStackTrace(); } }); SpongeCommon.game().setServer(this); - $$6.profileCache().load(); } @Override @@ -77,8 +77,8 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin { return this.shadow$isRunning(); } - @WrapOperation(method = "initServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/GameProfileCache;save()V")) - private void onSave(final GameProfileCache cache, final Operation original) { + @WrapOperation(method = "initServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/UserNameToIdResolver;save()V")) + private void onSave(final UserNameToIdResolver cache, final Operation original) { ((GameProfileCacheBridge) cache).bridge$setCanSave(true); original.call(cache); ((GameProfileCacheBridge) cache).bridge$setCanSave(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 4920948720d..9c7f5dde43b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -44,7 +44,6 @@ import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.PlayerList; import net.minecraft.sounds.SoundEvent; @@ -55,7 +54,6 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.CustomSpawner; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.block.Block; @@ -159,16 +157,16 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel private LevelStorageSource.LevelStorageAccess impl$levelSave; private CustomBossEvents impl$bossBarManager; - private ChunkProgressListener impl$chunkProgressListener; private Weather impl$prevWeather; private boolean impl$isManualSave = false; private long impl$preTickTime = 0L; @Inject(method = "", at = @At("TAIL")) private void impl$onInit( - final MinecraftServer server, final Executor executor, final LevelStorageSource.LevelStorageAccess storage, final ServerLevelData levelData, - final net.minecraft.resources.ResourceKey key, final LevelStem levelStem, final ChunkProgressListener listener, final boolean debug, final long biomeSeed, - final List spawners, final boolean tick, final RandomSequences randomSequences, final CallbackInfo ci + final MinecraftServer server, final Executor executor, final LevelStorageSource.LevelStorageAccess storage, + final ServerLevelData levelData, final net.minecraft.resources.ResourceKey key, final LevelStem levelStem, + final boolean debug, final long biomeSeed, final List spawners, final boolean tick, + final RandomSequences randomSequences, final CallbackInfo ci ) { final SpongeServerLevelData spongeData = ((ServerLevelDataBridge) levelData).bridge$spongeData(); @@ -186,7 +184,6 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } this.impl$levelSave = storage; - this.impl$chunkProgressListener = listener; this.impl$prevWeather = ((ServerWorld) this).weather(); ((LevelTicksBridge) this.blockTicks).bridge$level((ServerLevel) (Object) this); ((LevelTicksBridge) this.fluidTicks).bridge$level((ServerLevel) (Object) this); @@ -209,11 +206,6 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel return this.impl$levelSave; } - @Override - public ChunkProgressListener bridge$getChunkProgressListener() { - return this.impl$chunkProgressListener; - } - @Override public boolean bridge$isLoaded() { if (((LevelBridge) this).bridge$isFake()) { @@ -355,18 +347,6 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel return server.getWorldData(); } - @Redirect(method = "setDefaultSpawnPos", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/GameRules;getInt(Lnet/minecraft/world/level/GameRules$Key;)I" - )) - private int impl$respectKeepSpawnLoaded(GameRules gameRules, GameRules.Key key) { - if ((((ServerLevelDataBridge) this.shadow$getLevelData()).bridge$performsSpawnLogic())) { - return gameRules.getInt(key); - } - return 0; - } - @Inject(method = "save", at = @At("HEAD"), cancellable = true) public void impl$postSaveWorldEventPre(final CallbackInfo ci, final @Share("manualSave") LocalBooleanRef manualSave) { manualSave.set(this.impl$isManualSave); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index 0d5c70af339..a3708770f1c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -24,7 +24,8 @@ */ package org.spongepowered.common.mixin.core.server.players; -import net.minecraft.server.players.GameProfileCache; +import net.minecraft.server.players.CachedUserNameToIdResolver; +import net.minecraft.server.players.NameAndId; import org.spongepowered.api.Sponge; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.asm.mixin.Final; @@ -45,11 +46,11 @@ import java.util.Optional; import java.util.UUID; -@Mixin(GameProfileCache.class) +@Mixin(CachedUserNameToIdResolver.class) public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { // @formatter:off - @Shadow public void shadow$add(final com.mojang.authlib.GameProfile profile) {} + @Shadow public void shadow$add(final NameAndId profile) {} @Shadow @Final private Map profilesByUUID; @Shadow @Final private Map profilesByName; // @formatter:on @@ -65,7 +66,7 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { if (accessor.invoker$getExpirationDate().getTime() < System.currentTimeMillis()) { this.profilesByUUID.remove(uniqueId, accessor); - this.profilesByName.remove(accessor.invoker$getProfile().getName(), accessor); + this.profilesByName.remove(accessor.invoker$nameAndId().name(), accessor); return Optional.empty(); } @@ -81,7 +82,7 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { } if (accessor.invoker$getExpirationDate().getTime() < System.currentTimeMillis()) { - this.profilesByUUID.remove(accessor.invoker$getProfile().getId(), accessor); + this.profilesByUUID.remove(accessor.invoker$nameAndId().id(), accessor); this.profilesByName.remove(lowerName, accessor); return Optional.empty(); } @@ -92,17 +93,18 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { @Override public void bridge$add(final com.mojang.authlib.GameProfile profile, final boolean full, final boolean signed) { GameProfileCache_GameProfileInfoAccessor accessor = this.profilesByUUID.get(Objects.requireNonNull(profile, "profile").getId()); - final com.mojang.authlib.GameProfile current = accessor == null ? null : accessor.invoker$getProfile(); + final NameAndId current = accessor == null ? null : accessor.invoker$nameAndId(); // Don't allow basic game profiles to overwrite the contents if already // an entry exists that is full. - if (current != null && Objects.equals(current.getId(), profile.getId()) && - Objects.equals(current.getName(), profile.getName()) && !full) { + if (current != null && Objects.equals(current.id(), profile.getId()) && + Objects.equals(current.name(), profile.getName()) && !full) { return; } - this.shadow$add(profile); + final var nameAndIDToAdd = new NameAndId(profile); + this.shadow$add(nameAndIDToAdd); accessor = this.profilesByUUID.get(profile.getId()); - if (accessor == null || accessor.invoker$getProfile() != profile) { + if (accessor == null || accessor.invoker$nameAndId() != nameAndIDToAdd) { return; } final GameProfileCache_GameProfileInfoBridge bridge = (GameProfileCache_GameProfileInfoBridge) accessor; @@ -113,18 +115,18 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { @Override public void bridge$add(final GameProfile profile, final boolean full, final boolean signed) { GameProfileCache_GameProfileInfoAccessor accessor = this.profilesByUUID.get(Objects.requireNonNull(profile, "profile").uniqueId()); - final com.mojang.authlib.GameProfile current = accessor == null ? null : accessor.invoker$getProfile(); - final com.mojang.authlib.GameProfile mcProfile = SpongeGameProfile.toMcProfile(profile); + final var current = accessor == null ? null : accessor.invoker$nameAndId(); + final var mcProfile = SpongeGameProfile.toNameAndId(profile); // Don't allow basic game profiles to overwrite the contents if already // an entry exists that is full. - if (current != null && Objects.equals(current.getId(), mcProfile.getId()) && - Objects.equals(current.getName(), mcProfile.getName()) && !full) { + if (current != null && Objects.equals(current.id(), mcProfile.id()) && + Objects.equals(current.name(), mcProfile.name()) && !full) { return; } this.shadow$add(mcProfile); accessor = this.profilesByUUID.get(profile.uniqueId()); - if (accessor == null || accessor.invoker$getProfile() != mcProfile) { + if (accessor == null || accessor.invoker$nameAndId() != mcProfile) { return; } ((GameProfileCache_GameProfileInfoBridge) accessor).bridge$set(profile, full, signed); @@ -136,9 +138,9 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { } @Inject(method = "add", at = @At(value = "RETURN")) - private void impl$updateCacheUsername(final com.mojang.authlib.GameProfile profile, final CallbackInfo ci) { - if (profile.getName() != null) { - ((SpongeServer) Sponge.server()).getUsernameCache().setUsername(profile.getId(), profile.getName()); + private void impl$updateCacheUsername(final NameAndId profile, final CallbackInfo ci) { + if (!profile.name().isEmpty()) { + ((SpongeServer) Sponge.server()).getUsernameCache().setUsername(profile.id(), profile.name()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCache_GameProfileInfoMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCache_GameProfileInfoMixin.java index 5a11c591048..5a29e3c28a7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCache_GameProfileInfoMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCache_GameProfileInfoMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.server.players; +import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.asm.mixin.Final; @@ -32,10 +33,10 @@ import org.spongepowered.common.bridge.server.players.GameProfileCache_GameProfileInfoBridge; import org.spongepowered.common.profile.SpongeGameProfile; -@Mixin(targets = "net.minecraft.server.players.GameProfileCache$GameProfileInfo") +@Mixin(targets = "net/minecraft/server/players/CachedUserNameToIdResolver$GameProfileInfo") public abstract class GameProfileCache_GameProfileInfoMixin implements GameProfileCache_GameProfileInfoBridge { - @Shadow @Final private com.mojang.authlib.GameProfile profile; + @Shadow @Final private NameAndId nameAndId; private boolean impl$isFull; private boolean impl$isSigned; @@ -75,7 +76,7 @@ public abstract class GameProfileCache_GameProfileInfoMixin implements GameProfi if (basic != null) { return basic; } - basic = this.impl$basic = SpongeGameProfile.basicOf(this.profile); + basic = this.impl$basic = SpongeGameProfile.basicOf(this.nameAndId); return basic; } @@ -92,11 +93,11 @@ public abstract class GameProfileCache_GameProfileInfoMixin implements GameProfi if (!this.impl$isSigned) { return null; } - full = this.impl$fullSigned = SpongeGameProfile.of(this.profile); + full = this.impl$fullSigned = SpongeGameProfile.of(this.nameAndId); } else { final GameProfile fullSigned = this.impl$fullSigned; full = this.impl$fullUnsigned = SpongeGameProfile.unsignedOf( - fullSigned == null ? SpongeGameProfile.of(this.profile) : fullSigned); + fullSigned == null ? SpongeGameProfile.of(this.nameAndId) : fullSigned); } return full; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 34d28462f2f..510944e8884 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -316,7 +316,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Override public boolean bridge$dismountRidingEntity(final DismountType type) { - if (!this.shadow$level().isClientSide && ShouldFire.RIDE_ENTITY_EVENT_DISMOUNT) { + if (!this.shadow$level().isClientSide() && ShouldFire.RIDE_ENTITY_EVENT_DISMOUNT) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(this); frame.addContext(EventContextKeys.DISMOUNT_TYPE, type); @@ -532,7 +532,7 @@ public Entity teleport(final TeleportTransition transition) { } for (Entity recreatedPassenger : recreatedPassengers) { - recreatedPassenger.startRiding(newEntity, true); + recreatedPassenger.startRiding(newEntity, true, true); } oldLevel.resetEmptyTime(); @@ -608,7 +608,7 @@ public Entity teleport(final TeleportTransition transition) { return event.destinationPosition(); } - @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", + @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At( value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;vehicle:Lnet/minecraft/world/entity/Entity;", @@ -616,9 +616,9 @@ public Entity teleport(final TeleportTransition transition) { ), cancellable = true ) - private void impl$onStartRiding(final Entity vehicle, final boolean force, + private void impl$onStartRiding(final Entity vehicle, final boolean force, final boolean createPortal, final CallbackInfoReturnable ci) { - if (!this.shadow$level().isClientSide && ShouldFire.RIDE_ENTITY_EVENT_MOUNT) { + if (!this.shadow$level().isClientSide() && ShouldFire.RIDE_ENTITY_EVENT_MOUNT) { PhaseTracker.getInstance().pushCause(this); if (SpongeCommon.post(SpongeEventFactory.createRideEntityEventMount(PhaseTracker.getInstance().currentCause(), (org.spongepowered.api.entity.Entity) vehicle))) { ci.cancel(); @@ -707,7 +707,7 @@ public void stopRiding() { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;fallOn(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;D)V")) private void impl$onFallOnCollide(final Block block, final Level world, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) { - if (!ShouldFire.COLLIDE_BLOCK_EVENT_FALL || world.isClientSide) { + if (!ShouldFire.COLLIDE_BLOCK_EVENT_FALL || world.isClientSide()) { block.fallOn(world, state, pos, entity, fallDistance); return; } @@ -727,7 +727,7 @@ public void stopRiding() { ) private void impl$onStepOnCollide(final Block block, final Level world, final BlockPos pos, final BlockState state, final Entity entity, Operation original) { - if (!ShouldFire.COLLIDE_BLOCK_EVENT_STEP_ON || world.isClientSide) { + if (!ShouldFire.COLLIDE_BLOCK_EVENT_STEP_ON || world.isClientSide()) { original.call(block, world, pos, state, entity); return; } @@ -748,7 +748,7 @@ public void stopRiding() { private void impl$onCheckInsideBlocksCollide( final BlockState blockState, final Level worldIn, final BlockPos pos, final Entity entityIn, final InsideBlockEffectApplier insideBlockEffectApplier, final Operation original) { - if (!ShouldFire.COLLIDE_BLOCK_EVENT_INSIDE || worldIn.isClientSide || blockState.isAir()) { + if (!ShouldFire.COLLIDE_BLOCK_EVENT_INSIDE || worldIn.isClientSide() || blockState.isAir()) { original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier); return; } @@ -1000,7 +1000,7 @@ public void stopRiding() { }*/ - @Redirect(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;canSerialize()Z")) + @Redirect(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;canSerialize()Z")) private boolean impl$allowRidingAnything(final EntityType instance) { //Vanilla has started to prevent riding non-serializable entities. //This results in players being unable to ride other players. diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java index 7388491b26c..c4ca8d3f104 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LeashableMixin.java @@ -45,7 +45,7 @@ public interface LeashableMixin { @Inject(method = "setLeashedTo(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Z)V", at = @At("HEAD"), cancellable = true) private static void impl$onSetLeashedTo(final E $$0, final net.minecraft.world.entity.Entity $$1, final boolean $$2, final CallbackInfo ci) { - if (!$$0.level().isClientSide) { + if (!$$0.level().isClientSide()) { final Cause currentCause = PhaseTracker.getInstance().currentCause(); if (Sponge.eventManager().post(SpongeEventFactory.createLeashEntityEvent(currentCause, (Entity) $$0))) { ci.cancel(); @@ -55,7 +55,7 @@ public interface LeashableMixin { @Inject(method = "dropLeash(Lnet/minecraft/world/entity/Entity;ZZ)V", at = @At("HEAD"), cancellable = true) private static void impl$onDropLeash(final net.minecraft.world.entity.Entity entity, final boolean $$1, final boolean $$2, final CallbackInfo ci) { - if (entity == null || entity.level().isClientSide) { + if (entity == null || entity.level().isClientSide()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LightningBoltMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LightningBoltMixin.java index 75cf1bfe0c2..7a781f50997 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LightningBoltMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LightningBoltMixin.java @@ -65,7 +65,7 @@ public abstract class LightningBoltMixin extends EntityMixin { private List impl$ThrowEventAndProcess( final Level level, final Entity thisEntity, final AABB boundingBox, final Predicate predicate ) { - if (this.shadow$isRemoved() || this.shadow$level().isClientSide) { + if (this.shadow$isRemoved() || this.shadow$level().isClientSide()) { return Collections.emptyList(); } final List originalEntities = level.getEntities(thisEntity, boundingBox, predicate); @@ -87,7 +87,7 @@ public abstract class LightningBoltMixin extends EntityMixin { ) ) private void impl$ThrowEventAndProcess(final CallbackInfo ci) { - if (this.shadow$isRemoved() || this.shadow$level().isClientSide || this.life >= 0) { + if (this.shadow$isRemoved() || this.shadow$level().isClientSide() || this.life >= 0) { return; } try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 9df4af654ab..75b665d9049 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -278,7 +278,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;useItem:Lnet/minecraft/world/item/ItemStack;")) private void impl$onSetActiveItemStack(final InteractionHand hand, final CallbackInfo ci, final ItemStack stack) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } @@ -303,7 +303,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;useItemRemaining:I")) private void impl$getItemDuration(final LivingEntity this$0, final int count) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { this.useItemRemaining = count; } // If we're on the server, do nothing, since we already set this field on onSetActiveItemStack @@ -332,7 +332,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt target = "Lnet/minecraft/world/entity/LivingEntity;getUseItemRemainingTicks()I", ordinal = 0)) private int impl$onGetRemainingItemDuration(final LivingEntity self) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return self.getUseItemRemainingTicks(); } @@ -375,7 +375,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;finishUsingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/item/ItemStack;")) private void impl$onUpdateItemUse(final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } @@ -405,7 +405,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V")) private void impl$onSetHeldItem(final LivingEntity self, final InteractionHand hand, final ItemStack stack) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { self.setItemInHand(hand, stack); return; } @@ -450,7 +450,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt target = "Lnet/minecraft/world/item/ItemStack;releaseUsing(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;I)V")) // stopActiveHand private void impl$onStopPlayerUsing(final ItemStack stack, final net.minecraft.world.level.Level world, final LivingEntity self, final int duration) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { stack.releaseUsing(world, self, duration); return; } @@ -475,7 +475,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "stopUsingItem", at = @At("HEAD")) private void impl$onResetActiveHand(final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } @@ -514,7 +514,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "stopSleeping", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;clearSleepingPos()V")) private void impl$callFinishSleepingEvent(final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java index 5f98ec106a0..2b8db878368 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin.java @@ -89,7 +89,7 @@ public abstract class MobMixin extends LivingEntityMixin { */ @Inject(method = "setTarget", at = @At("HEAD"), cancellable = true) private void onSetAttackTarget(@Nullable final LivingEntity entitylivingbaseIn, final CallbackInfo ci) { - if (this.shadow$level().isClientSide || entitylivingbaseIn == null) { + if (this.shadow$level().isClientSide() || entitylivingbaseIn == null) { return; } //noinspection ConstantConditions diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index 2d138fd14f1..a9c266be068 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -70,7 +70,7 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB @ModifyConstant(method = "mergeWithNeighbours", constant = @Constant(doubleValue = Constants.Entity.Item.DEFAULT_ITEM_MERGE_RADIUS)) private double impl$changeSearchRadiusFromConfig(final double originalRadius) { - if (this.shadow$level().isClientSide || ((LevelBridge) this.shadow$level()).bridge$isFake()) { + if (this.shadow$level().isClientSide() || ((LevelBridge) this.shadow$level()).bridge$isFake()) { return originalRadius; } if (this.impl$cachedRadius == -1) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java index 2850c4ee546..d8e8c9a6646 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/PrimedTntMixin.java @@ -104,7 +104,7 @@ public abstract class PrimedTntMixin extends EntityMixin implements PrimedTntBri @Inject(method = "tick()V", at = @At("RETURN")) private void impl$updateTNTPushPrime(final CallbackInfo ci) { - if (!this.impl$postPrimeTriggered && !this.shadow$level().isClientSide) { + if (!this.impl$postPrimeTriggered && !this.shadow$level().isClientSide()) { this.impl$postPrimeTriggered = true; try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { if (this.impl$detonator != null) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java index 3eacbbbc617..8c28d0a71bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/CreeperMixin.java @@ -101,7 +101,7 @@ public abstract class CreeperMixin extends MonsterMixin implements FusedExplosiv @Inject(method = "setSwellDir", at = @At("HEAD"), cancellable = true) private void impl$preStateChange(final int state, final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } @@ -118,7 +118,7 @@ public abstract class CreeperMixin extends MonsterMixin implements FusedExplosiv @Inject(method = "setSwellDir", at = @At("RETURN")) private void impl$postStateChange(final int state, final CallbackInfo ci) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java index 7dde827bfc2..54790720d92 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java @@ -135,7 +135,7 @@ private void onProjectileHit(final EntityHitResult hitResult, final CallbackInfo this.shadow$setYRot(this.shadow$getYRot() + 180.0F); this.yRotO += 180.0F; this.life = 0; - if (!this.shadow$level().isClientSide && this.shadow$getDeltaMovement().lengthSqr() < 1.0E-7D) { + if (!this.shadow$level().isClientSide() && this.shadow$getDeltaMovement().lengthSqr() < 1.0E-7D) { if (this.pickup == AbstractArrow.Pickup.ALLOWED) { this.shadow$spawnAtLocation((ServerLevel) this.shadow$level(), this.shadow$getPickupItem(), 0.1F); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java index 0eaf48bde87..b88791d9f7d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FireworkRocketEntityMixin.java @@ -120,7 +120,7 @@ public abstract class FireworkRocketEntityMixin extends ProjectileMixin implemen @Inject(method = "tick()V", at = @At("RETURN")) private void impl$postPrimeEvent(final CallbackInfo ci) { - if (this.life == 1 && !this.shadow$level().isClientSide) { + if (this.life == 1 && !this.shadow$level().isClientSide()) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(this); frame.addContext(EventContextKeys.PROJECTILE_SOURCE, this.impl$getProjectileSource()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FishingHookMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FishingHookMixin.java index 7972a3ada30..590ab40690a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FishingHookMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/FishingHookMixin.java @@ -94,7 +94,7 @@ private void onSetHookedEntity(final net.minecraft.world.entity.@Nullable Entity public int retrieve(final ItemStack stack) { final Player playerEntity = this.shadow$getPlayerOwner(); - if (!this.shadow$level().isClientSide && playerEntity != null) { + if (!this.shadow$level().isClientSide() && playerEntity != null) { int i = 0; // Sponge start diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java index 19c5a4d75cb..de5d48ad2d2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java @@ -81,7 +81,7 @@ public abstract class ProjectileUtilMixin { "getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/projectile/Projectile;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Lnet/minecraft/world/phys/EntityHitResult;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ProjectileUtil;getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;F)Lnet/minecraft/world/phys/EntityHitResult;")) private static EntityHitResult impl$onGetEntityHitResult(final Level $$0, final Entity $$1, final Vec3 $$2, final Vec3 $$3, final AABB $$4, final Predicate $$5, final float $$6) { - if ($$0.isClientSide) { + if ($$0.isClientSide()) { return ProjectileUtil.getEntityHitResult($$0, $$1, $$2, $$3, $$4, $$5, $$6); } try (final PhaseContext<@NonNull ?> context = EntityPhase.State.COLLISION diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java index 591098e940a..bde45e85057 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/FishingRodItemMixin.java @@ -71,7 +71,7 @@ private void cancelHookRetraction(Level world, Player player, InteractionHand ha ), cancellable = true) private void onThrowEvent(Level level, Player player, InteractionHand hand, CallbackInfoReturnable cir) { - if (level.isClientSide) { + if (level.isClientSide()) { // Only fire event on server-side to avoid crash on client return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java index 25230b4edb6..8a3eac09178 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java @@ -57,12 +57,11 @@ public abstract class ItemStackMixin implements SpongeDataHolderBridge, DataComp // @formatter:off @Shadow public abstract boolean shadow$isEmpty(); - @Shadow @Final private PatchedDataComponentMap components; + @Shadow @Final PatchedDataComponentMap components; // @formatter:on - @Override public Optional bridge$get(final Key<@NonNull ? extends Value> key) { if (this.shadow$isEmpty()) { @@ -87,12 +86,11 @@ public abstract class ItemStackMixin implements SpongeDataHolderBridge, DataComp return DataHolderProcessor.bridge$remove(this, key); } - @SuppressWarnings("deprecation") @Override public CompoundTag data$getCompound() { final @Nullable CustomData customData = this.components.get(DataComponents.CUSTOM_DATA); if (customData != null && customData != CustomData.EMPTY) { - return customData.getUnsafe(); + return ((CustomDataAccessor) (Object) customData).accessor$tag(); } return null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java index fec121c03e4..4db918c5136 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/CampfireBlockMixin.java @@ -47,7 +47,7 @@ public abstract class CampfireBlockMixin extends BlockMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;campfire()Lnet/minecraft/world/damagesource/DamageSource;")) private DamageSource impl$spongeRedirectForFireDamage(final DamageSources instance, final BlockState blockState, final Level world, final BlockPos blockPos, final Entity entity) { final DamageSource source = instance.inFire(); - if (world.isClientSide) { // Short Circuit + if (world.isClientSide()) { // Short Circuit return source; } final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java index ceafbdb938e..5b496394ec9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/MagmaBlockMixin.java @@ -48,7 +48,7 @@ public abstract class MagmaBlockMixin extends BlockMixin { final BlockState blockState, final Entity entity ) { final DamageSource source = instance.hotFloor(); - if (world.isClientSide) { // Short Circuit + if (world.isClientSide()) { // Short Circuit return source; } return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) world, blockPos, source); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java index 8a14da2e824..2edc3d52117 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/PointedDripstoneBlockMixin.java @@ -48,7 +48,7 @@ public abstract class PointedDripstoneBlockMixin extends BlockMixin { final BlockPos pos,final Entity ignored, final double distance ) { final DamageSource source = instance.stalagmite(); - if (level.isClientSide) { // Short Circuit + if (level.isClientSide()) { // Short Circuit return source; } return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) level, pos, source); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java index fd54083550a..d528e0f3a79 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java @@ -48,7 +48,7 @@ public abstract class SweetBerryBushBlockMixin extends BlockMixin { final Level level, final BlockPos pos, final Entity ignored ) { final DamageSource source = instance.sweetBerryBush(); - if (level.isClientSide) { // Short Circuit + if (level.isClientSide()) { // Short Circuit return source; } return SpongeDamageSources.createBlockBasedDamageSource((ServerWorld) level, pos, source); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java index 62bfbedae59..f257a850df7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/BannerBlockEntityMixin.java @@ -50,7 +50,7 @@ public abstract class BannerBlockEntityMixin extends BlockEntityMixin implements @Unique private void impl$markDirtyAndUpdate() { this.shadow$setChanged(); - if (this.level != null && !this.level.isClientSide) { + if (this.level != null && !this.level.isClientSide()) { ((ServerLevel) this.level).getChunkSource().blockChanged(this.shadow$getBlockPos()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java index a44d4984345..b5be3ddb4a3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java @@ -24,9 +24,13 @@ */ package org.spongepowered.common.mixin.core.world.level.storage; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.datafixers.DataFixer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.storage.PlayerDataStorage; -import net.minecraft.world.level.storage.ValueInput; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.asm.mixin.Final; @@ -34,7 +38,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java index e3e0edad8a5..32a8c386887 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/SavedTickMixin.java @@ -40,6 +40,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.accessor.world.item.component.CustomDataAccessor; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.data.DataUtil; @@ -90,7 +91,7 @@ public abstract class SavedTickMixin implements SpongeMutableDataHolder, Data .apply(instance, (t, blockPos, integer, tickPriority, customData) -> { final var tick = function.apply(t, blockPos, integer, tickPriority); customData.ifPresent(data -> { - ((DataCompoundHolder) (Object) tick).data$setCompound(data.getUnsafe()); + ((DataCompoundHolder) (Object) tick).data$setCompound(((CustomDataAccessor) (Object) data).accessor$tag()); DataUtil.syncTagToData(tick); ((DataCompoundHolder) (Object) tick).data$setCompound(null); }); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index 4f9cbd0a420..22a981b0e10 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -191,7 +191,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon private ItemStack impl$transferStackInSlot(final AbstractContainerMenu thisContainer, final Player player, final int slotId) { final ItemStack result = thisContainer.quickMoveStack(player, slotId); // Crafting on Serverside? - if (((LevelBridge) player.level()).bridge$isFake() || player.level().isClientSide || !(thisContainer.getSlot(slotId) instanceof ResultSlot)) { + if (((LevelBridge) player.level()).bridge$isFake() || player.level().isClientSide() || !(thisContainer.getSlot(slotId) instanceof ResultSlot)) { return result; } this.bridge$detectAndSendChanges(true, true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index c8b3c0fdd52..4531442bff5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -180,7 +180,7 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;pushEntities()V") ) private void tracker$switchIntoCollisions(final LivingEntity livingEntity) { - if (this.shadow$level().isClientSide) { + if (this.shadow$level().isClientSide()) { this.shadow$pushEntities(); return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java index dad3af2cb99..4d001901e9a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/storage/SerializableChunkDataMixin_Tracker.java @@ -55,6 +55,7 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable } } + @SuppressWarnings("deprecation") @Override public void bridge$writeTrackerData(final CompoundTag level) { if (this.tracker$intPlayerPos == null && this.tracker$shortPlayerPos == null) { @@ -83,6 +84,7 @@ public abstract class SerializableChunkDataMixin_Tracker implements Serializable } } + @SuppressWarnings("deprecation") @Override public void bridge$parseTrackerData(final CompoundTag fullTag) { final Optional spongeData = fullTag.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA); diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index f6688cf61c0..9cccab1d8b4 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -379,6 +379,8 @@ "minecraft.world.level.block.MirrorMixin_API", "minecraft.world.level.block.PortalMixin_API", "minecraft.world.level.block.RotationMixin_API", + "minecraft.world.level.block.CopperGolemStatueBlock_PoseMixin_API", + "minecraft.world.level.block.WeatheringCopper_WeatherStateMixin_API", "minecraft.world.level.block.entity.AbstractFurnaceBlockEntityMixin_API", "minecraft.world.level.block.entity.BannerBlockEntityMixin_API", "minecraft.world.level.block.entity.BannerPatternLayers_LayerMixin_API", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 73e36cc4d27..9bd67bf24d0 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -276,7 +276,7 @@ protected void drawPanel(final GuiGraphics stack, final int entryRight, int rela } @Override - public boolean mouseClicked(final double mouseX, final double mouseY, final int button) { + public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeated) { // Find an entry match for where we clicked final Entry entry = this.getAllEntries().stream() @@ -292,7 +292,7 @@ public boolean mouseClicked(final double mouseX, final double mouseY, final int this.screen.handleComponentClicked(component.getStyle()); return true; } - return super.mouseClicked(mouseX, mouseY, button); + return super.mouseClicked(mouseX, mouseY, button, repeated); } @Override diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 7fa79ba1be8..4e32fa9c1bf 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -122,8 +122,8 @@ public boolean isMouseOver(final double mouseX, final double mouseY) { } @Override - public boolean mouseClicked(final double mouseX, final double mouseY, final int button) { - if (super.mouseClicked(mouseX, mouseY, button)) { + public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeated) { + if (super.mouseClicked(mouseX, mouseY, button, repeated)) { return true; } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java index 7ebcc9ef51e..313026a015f 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java @@ -132,21 +132,21 @@ public void setSelected(@Nullable final E entry) { } @Override - public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_) { - this.updateScrolling(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); - if (!this.isMouseOver(p_mouseClicked_1_, p_mouseClicked_3_)) { + public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeatedClick) { + this.updateScrolling(mouseX, mouseY, button); + if (!this.isMouseOver(mouseX, mouseY)) { return false; } else { - final E e = this.getEntryAtPosition(p_mouseClicked_1_, p_mouseClicked_3_); + final E e = this.getEntryAtPosition(mouseX, mouseY); if (e != null) { - if (e.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_)) { + if (e.mouseClicked(mouseX, mouseY, button, repeatedClick)) { this.setFocused(e); this.setDragging(true); return true; } - } else if (p_mouseClicked_5_ == 0) { - this.onClick((int) (p_mouseClicked_1_ - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), - (int) (p_mouseClicked_3_ - (double) this.getY()) + (int) this.scrollAmount() - 4); + } else if (button == 0) { + this.onClick((int) (mouseX - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), + (int) (mouseY - (double) this.getY()) + (int) this.scrollAmount() - 4, repeatedClick); return true; } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java index 8790eb4acd5..e1bb2371155 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java @@ -66,7 +66,7 @@ public void render(final GuiGraphics stack, final int p_render_1_, final int ren } @Override - public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_) { + public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_, final boolean repeated) { this.getParentList().setSelected(this); return true; } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java index 8879fce54c7..88c8c8ffe37 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java @@ -31,8 +31,10 @@ import net.minecraft.server.packs.PackLocationInfo; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.metadata.MetadataSectionType; +import net.minecraft.server.packs.metadata.pack.PackFormat; import net.minecraft.server.packs.metadata.pack.PackMetadataSection; import net.minecraft.server.packs.resources.IoSupplier; +import net.minecraft.util.InclusiveRange; import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.spongepowered.common.SpongeCommon; @@ -43,7 +45,11 @@ import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.Collections; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -57,7 +63,7 @@ public final class PluginPackResources extends AbstractPackResources { public PluginPackResources(final PackLocationInfo info, final PluginContainer container, final @Nullable Path pluginRoot) { super(info); this.container = container; - this.metadata = new PackMetadataSection(Component.literal("Plugin Resources"), 6, Optional.empty()); + this.metadata = new PackMetadataSection(Component.literal("Plugin Resources"), new InclusiveRange<>(PackFormat.of(6))); this.pluginRoot = pluginRoot; } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java index 8215f95222a..b1f8e74e1f3 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java @@ -59,13 +59,13 @@ public String getServerModName() { Launch.instance().lifecycle().callStoppingEngineEvent(this); } - @ModifyExpressionValue(method = "lambda$reloadResources$28", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$29", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) public void impl$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/FireBlockMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/FireBlockMixin_Vanilla.java index 01c0191fa31..390e94c0881 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/FireBlockMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/FireBlockMixin_Vanilla.java @@ -48,7 +48,7 @@ public class FireBlockMixin_Vanilla { cancellable = true) private void impl$onCatchFirePreCheck( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } @@ -64,7 +64,7 @@ public class FireBlockMixin_Vanilla { cancellable = true) private void impl$onCatchFirePreCheckOther( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } From b56c1176b5f12f69560add3b20d2fd1e146cfe81 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 1 Sep 2025 16:49:56 -0700 Subject: [PATCH 312/586] chore(minecraft): update implementations for 25w32a Noticeable changes are in PlayerList management for server player loads. See: https://minecraft.wiki/w/Java_Edition_25w32a --- gradle/verification-metadata.xml | 16 ++ .../accessor/network/chat/StyleAccessor.java | 1 - .../item/stack/SpawnEggItemStackData.java | 2 - .../common/item/SpongeItemStack.java | 1 - .../server/IntegratedPlayerListMixin.java | 6 +- .../server/ServerFunctionLibraryMixin.java | 8 +- .../dedicated/DedicatedPlayerListMixin.java | 1 - ...rConfigurationPacketListenerImplMixin.java | 5 +- .../ServerLoginPacketListenerImplMixin.java | 5 +- .../config/PrepareSpawnTask_ReadyMixin.java | 98 ++++++++++++ .../core/server/players/PlayerListMixin.java | 141 +++++++----------- .../level/storage/PlayerDataStorageMixin.java | 21 --- ...erGamePacketListenerImplMixin_Tracker.java | 10 +- src/mixins/resources/mixins.sponge.core.json | 1 + 14 files changed, 187 insertions(+), 129 deletions(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/network/config/PrepareSpawnTask_ReadyMixin.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 48cb727cd6e..816b55f32ef 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1577,6 +1577,9 @@ + + + @@ -3751,6 +3754,11 @@ + + + + + @@ -3759,6 +3767,14 @@ + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java index cead56cb855..d79197232d8 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/network/chat/StyleAccessor.java @@ -29,7 +29,6 @@ import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; -import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java index aa2c98f0a1b..feb0d770768 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SpawnEggItemStackData.java @@ -30,12 +30,10 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.TypedEntityData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.EntityArchetype; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.entity.SpongeEntityArchetypeBuilder; diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java index b11fb94a437..fd2224756c1 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java @@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; -import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java index 5e73ff153f7..a7812e8f384 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/server/IntegratedPlayerListMixin.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.core.client.server; -import com.mojang.authlib.GameProfile; import net.minecraft.client.server.IntegratedPlayerList; import net.minecraft.network.chat.Component; import net.minecraft.server.players.NameAndId; @@ -48,9 +47,10 @@ public abstract class IntegratedPlayerListMixin extends PlayerListMixin implemen @Override public CompletableFuture bridge$canPlayerLoginClient(final SocketAddress param0, final com.mojang.authlib.GameProfile param1) { - final Component component = this.shadow$canPlayerLogin(param0, new NameAndId(param1)); + final var name = new NameAndId(param1); + final Component component = this.shadow$canPlayerLogin(param0, name); if (component == null) { - return this.impl$canPlayerLoginServer(param0, param1); + return this.impl$canPlayerLoginServer(param0, name); } return CompletableFuture.completedFuture(component); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java index ec623d2a55f..3ff191c0f0a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java @@ -28,7 +28,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.server.ServerFunctionLibrary; import net.minecraft.server.packs.resources.PreparableReloadListener; -import net.minecraft.server.packs.resources.ResourceManager; import org.spongepowered.api.Sponge; import org.spongepowered.asm.mixin.Mixin; @@ -39,10 +38,11 @@ public abstract class ServerFunctionLibraryMixin { @WrapMethod(method = "reload") - private CompletableFuture impl$onReload(final PreparableReloadListener.PreparationBarrier barrier, final ResourceManager manager, - final Executor executor1, final Executor executor2, final Operation> original) { + private CompletableFuture impl$onReload( + final PreparableReloadListener.SharedState state, final Executor executor1, + final PreparableReloadListener.PreparationBarrier barrier, Executor executor2, Operation> original) { if (Sponge.isServerAvailable()) { - return original.call(barrier, manager, executor1, executor2); + return original.call(state, executor1, barrier, executor2); } return barrier.wait(null); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java index 992760e055e..08c0700f7d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.core.server.dedicated; -import com.mojang.authlib.GameProfile; import net.minecraft.core.LayeredRegistryAccess; import net.minecraft.server.MinecraftServer; import net.minecraft.server.RegistryLayer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java index a798a21ca54..2b1227d0b9c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java @@ -32,6 +32,7 @@ import net.minecraft.network.protocol.configuration.ServerboundFinishConfigurationPacket; import net.minecraft.server.network.ConfigurationTask; import net.minecraft.server.network.ServerConfigurationPacketListenerImpl; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.SpongeEventFactory; @@ -137,8 +138,8 @@ public abstract class ServerConfigurationPacketListenerImplMixin extends ServerC } @Redirect(method = "handleConfigurationFinished", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;")) - private Component impl$onCanPlayerLogin(final PlayerList instance, final SocketAddress $$0, final GameProfile $$1) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lnet/minecraft/server/players/NameAndId;)Lnet/minecraft/network/chat/Component;")) + private Component impl$onCanPlayerLogin(final PlayerList instance, final SocketAddress $$0, final NameAndId $$1) { //Skip as we check it at the start. return null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java index db5d44ee49e..c4908d7a589 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java @@ -37,6 +37,7 @@ import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginPacketListenerImpl; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import net.minecraft.util.Crypt; import net.minecraft.util.CryptException; @@ -138,8 +139,8 @@ public abstract class ServerLoginPacketListenerImplMixin implements ServerLoginP } @Redirect(method = "verifyLoginAndFinishConnectionSetup", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;")) - private Component impl$onCanPlayerLogin(final PlayerList instance, final SocketAddress $$0, final GameProfile $$1) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lnet/minecraft/server/players/NameAndId;)Lnet/minecraft/network/chat/Component;")) + private Component impl$onCanPlayerLogin(final PlayerList instance, final SocketAddress $$0, final NameAndId $$1) { //We check this as part of auth event. return null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/config/PrepareSpawnTask_ReadyMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/config/PrepareSpawnTask_ReadyMixin.java new file mode 100644 index 00000000000..a5fa9199cd3 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/config/PrepareSpawnTask_ReadyMixin.java @@ -0,0 +1,98 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.server.network.config; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.world.level.storage.ValueInput; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Slice; + +import java.io.IOException; +import java.time.Instant; +import java.util.Optional; +import java.util.function.Consumer; + +@Mixin(targets = "net.minecraft.server.network.config.PrepareSpawnTask$Ready") +public class PrepareSpawnTask_ReadyMixin { + + @WrapOperation( + method = "spawn", // or the mapped method containing the Player.load call + at = @At( + value = "INVOKE", + target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V" + // If your version uses CompoundTag instead, use the proper descriptor + ) + ) + private void impl$afterPlayerLoad( + final Optional instance, final Consumer action, + final Operation original, + @Local net.minecraft.server.level.ServerPlayer player + ) throws IOException { + // Call vanilla first + original.call(instance, action); + + final ServerPlayer sPlayer = (ServerPlayer) player; + if (sPlayer.get(Keys.FIRST_DATE_JOINED).isEmpty()) { + // TODO - 25w32a changed where we have access to the Player and moved access to the data files elsewhere. +// final Path file = new File(this.playerDir, player.getStringUUID() + ".dat").toPath(); +// final Instant creationTime = java.nio.file.Files.exists(file) +// ? java.nio.file.Files.readAttributes(file, java.nio.file.attribute.BasicFileAttributes.class) +// .creationTime().toInstant() +// : null; +// +// ((SpongeServer) SpongeCommon.server()) +// .getPlayerDataManager() +// .readLegacyPlayerData(sPlayer, nbtOrValueInput, creationTime); + } + + sPlayer.offer(Keys.LAST_DATE_JOINED, java.time.Instant.now()); + } + + + @WrapOperation(method = "spawn", + at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V"), + slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;loadPlayerData(Lnet/minecraft/server/players/NameAndId;)Ljava/util/Optional;"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;snapTo(Lnet/minecraft/world/phys/Vec3;FF)V") + ) + ) + private void impl$setPlayerDataForNewPlayers( + final Optional instance, final Consumer action, + final Operation original, + @Local final net.minecraft.server.level.ServerPlayer playerIn + ) { + original.call(instance, action); + if (instance.isEmpty()) { + final Instant now = Instant.now(); + ((ServerPlayer) playerIn).offer(Keys.FIRST_DATE_JOINED, now); + ((ServerPlayer) playerIn).offer(Keys.LAST_DATE_JOINED, now); + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index c92827a40e2..d4c996cfcf0 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.core.server.players; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import io.netty.channel.local.LocalAddress; import net.kyori.adventure.audience.Audience; @@ -47,17 +49,14 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.network.CommonListenerCookie; import net.minecraft.server.players.IpBanList; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import net.minecraft.server.players.UserBanList; import net.minecraft.server.players.UserWhiteList; -import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; import net.minecraft.world.level.border.BorderChangeListener; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.portal.TeleportTransition; -import net.minecraft.world.level.storage.PlayerDataStorage; -import net.minecraft.world.level.storage.ValueInput; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.slf4j.Logger; @@ -130,9 +129,7 @@ import java.util.Collection; import java.util.Date; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.function.Predicate; @@ -149,17 +146,14 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Shadow @Final @Mutable private UserWhiteList whitelist; @Shadow @Final private List players; @Shadow @Final protected int maxPlayers; - @Shadow @Final private Map playersByUUID; - @Shadow @Final private PlayerDataStorage playerIo; - @Shadow public abstract MinecraftServer shadow$getServer(); - @Shadow public abstract Optional shadow$load(final net.minecraft.server.level.ServerPlayer $$0, final ProblemReporter $$1); - @Shadow public abstract boolean shadow$canBypassPlayerLimit(com.mojang.authlib.GameProfile param0); + @Shadow public abstract boolean shadow$canBypassPlayerLimit(NameAndId $$0); @Shadow protected abstract boolean shadow$verifyChatTrusted(final PlayerChatMessage $$0); @Shadow protected abstract void shadow$broadcastChatMessage(final PlayerChatMessage $$0, final Predicate $$1, final net.minecraft.server.level.@Nullable ServerPlayer $$2, final ChatType.Bound $$4); // @formatter:on + private boolean impl$isRespawnWithPosition = false; private boolean impl$isDuringSystemMessageEvent = false; @@ -175,10 +169,10 @@ public abstract class PlayerListMixin implements PlayerListBridge { if (this instanceof IntegratedPlayerListBridge) { return ((IntegratedPlayerListBridge) this).bridge$canPlayerLoginClient(param0, param1); } - return this.impl$canPlayerLoginServer(param0, param1); + return this.impl$canPlayerLoginServer(param0, new NameAndId(param1)); } - protected final CompletableFuture impl$canPlayerLoginServer(final SocketAddress param0, final com.mojang.authlib.GameProfile param1) { + protected final CompletableFuture impl$canPlayerLoginServer(final SocketAddress param0, final NameAndId param1) { final SpongeGameProfile profile = SpongeGameProfile.basicOf(param1); return Sponge.server().serviceProvider().banService().find(profile).thenCompose(profileBanOpt -> { @@ -219,7 +213,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { return CompletableFuture.completedFuture(null); } final PermissionService permissionService = Sponge.server().serviceProvider().permissionService(); - return permissionService.userSubjects().loadSubject(param1.getId().toString()).handle((subject, ex) -> { + return permissionService.userSubjects().loadSubject(param1.id().toString()).handle((subject, ex) -> { if (ex == null) { return subject.hasPermission(LoginPermissions.BYPASS_WHITELIST_PERMISSION); } @@ -248,31 +242,16 @@ public abstract class PlayerListMixin implements PlayerListBridge { }, SpongeCommon.server()); } - @Redirect(method = "placeNewPlayer", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/players/PlayerList;load(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/util/ProblemReporter;)Ljava/util/Optional;" - ) - ) - private Optional impl$setPlayerDataForNewPlayers( - final PlayerList playerList, final net.minecraft.server.level.ServerPlayer playerIn, - final ProblemReporter problemReporter - ) { - final Optional compound = this.shadow$load(playerIn, problemReporter); - if (compound.isEmpty()) { - final Instant now = Instant.now(); - ((ServerPlayer) playerIn).offer(Keys.FIRST_DATE_JOINED, now); - ((ServerPlayer) playerIn).offer(Keys.LAST_DATE_JOINED, now); - } - return compound; - } - @Redirect(method = "placeNewPlayer", + @WrapOperation(method = "placeNewPlayer", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;" + target = "Lnet/minecraft/server/level/ServerPlayer;level()Lnet/minecraft/server/level/ServerLevel;" ) ) - private net.minecraft.server.level.ServerLevel impl$onInitPlayer_getWorld(final MinecraftServer minecraftServer, - final ResourceKey dimension, final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer + private net.minecraft.server.level.ServerLevel impl$onInitPlayer_getWorld( + final net.minecraft.server.level.ServerPlayer instance, final Operation original, + final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer, + final CommonListenerCookie ci ) { final net.minecraft.network.chat.@Nullable Component kickReason = ((ConnectionBridge) networkManager).bridge$getKickReason(); final Component disconnectMessage; @@ -282,12 +261,12 @@ public abstract class PlayerListMixin implements PlayerListBridge { disconnectMessage = Component.text("You are not allowed to log in to this server."); } - net.minecraft.server.level.ServerLevel mcWorld = minecraftServer.getLevel(dimension); + net.minecraft.server.level.ServerLevel mcWorld = original.call(instance); if (mcWorld == null) { SpongeCommon.logger().warn("The player '{}' was located in a world that isn't loaded or doesn't exist. This is not safe so " - + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().getName()); - mcWorld = minecraftServer.overworld(); + + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().getName()); + mcWorld = this.server.overworld(); final BlockPos spawnPoint = mcWorld.getSharedSpawnPos(); mcPlayer.setPos(spawnPoint.getX() + 0.5, spawnPoint.getY() + 0.5, spawnPoint.getZ() + 0.5); } @@ -305,7 +284,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final Cause cause = Cause.of(EventContext.empty(), connection, user); final ServerSideConnectionEvent.Login event = SpongeEventFactory.createServerSideConnectionEventLogin(cause, disconnectMessage, - disconnectMessage, location, location, rotation, rotation, connection, SpongeGameProfile.of(mcPlayer.getGameProfile()), user); + disconnectMessage, location, location, rotation, rotation, connection, SpongeGameProfile.of(mcPlayer.getGameProfile()), user); if (kickReason != null) { event.setCancelled(true); } @@ -317,15 +296,17 @@ public abstract class PlayerListMixin implements PlayerListBridge { final ServerLocation toLocation = event.toLocation(); final Vector3d toRotation = event.toRotation(); mcPlayer.absSnapTo(toLocation.x(), toLocation.y(), toLocation.z(), - (float) toRotation.y(), (float) toRotation.x()); - return (net.minecraft.server.level.ServerLevel) toLocation.world(); + (float) toRotation.y(), (float) toRotation.x()); + final var level = (ServerLevel) toLocation.world(); + instance.setServerLevel(level); + return level; } @Inject(method = "placeNewPlayer", cancellable = true, at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;", + target = "Lnet/minecraft/server/level/ServerPlayer;level()Lnet/minecraft/server/level/ServerLevel;", shift = At.Shift.AFTER ) ) @@ -342,9 +323,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { ) ) private void impl$onInitPlayer_printPlayerWorldInJoinFeedback(final org.slf4j.Logger logger, final String s, final Object[] objects, - final Connection conn, final net.minecraft.server.level.ServerPlayer player) { + final Connection conn, final net.minecraft.server.level.ServerPlayer player) { logger.info("{}[{}] logged in to world '{}' with entity id {} at ({}, {}, {})", player.getName().getString(), player, - ((ServerWorld)player.level()).key(), player.getId(), player.getX(), player.getY(), player.getZ()); + ((ServerWorld) player.level()).key(), player.getId(), player.getX(), player.getY(), player.getZ()); } @Redirect(method = "placeNewPlayer", @@ -378,7 +359,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ) ) private void impl$onInitPlayer_delaySendMessage(final PlayerList instance, final net.minecraft.network.chat.Component message, - final boolean $$1, final Connection manager, final net.minecraft.server.level.ServerPlayer playerIn + final boolean $$1, final Connection manager, final net.minecraft.server.level.ServerPlayer playerIn ) { // Don't send here, will be done later. We cache the expected message. ((ServerPlayerBridge) playerIn).bridge$setConnectionMessageToSend(message); @@ -391,13 +372,13 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getCustomBossEvents()Lnet/minecraft/server/bossevents/CustomBossEvents;")) private CustomBossEvents impl$getPerWorldBossBarManager( - final MinecraftServer minecraftServer, final Connection netManager, final net.minecraft.server.level.ServerPlayer playerIn) { + final MinecraftServer minecraftServer, final Connection netManager, final net.minecraft.server.level.ServerPlayer playerIn) { return ((ServerLevelBridge) playerIn.level()).bridge$getBossBarManager(); } @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;updateEntireScoreboard(Lnet/minecraft/server/ServerScoreboard;Lnet/minecraft/server/level/ServerPlayer;)V")) private void impl$sendScoreboard(final PlayerList playerList, final ServerScoreboard scoreboardIn, final net.minecraft.server.level.ServerPlayer playerIn) { - ((ServerPlayerBridge)playerIn).bridge$initScoreboard(); + ((ServerPlayerBridge) playerIn).bridge$initScoreboard(); } @Redirect( @@ -408,7 +389,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ) ) private void impl$onlySendSelfAddPlayerOnVanished(final PlayerList playerList, final Packet addPlayer, - final Connection playerConnection, final net.minecraft.server.level.ServerPlayer serverPlayer + final Connection playerConnection, final net.minecraft.server.level.ServerPlayer serverPlayer ) { if (((VanishableBridge) serverPlayer).bridge$vanishState().invisible()) { serverPlayer.connection.send(addPlayer); @@ -441,7 +422,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final Component joinComponent = SpongeAdventure.asAdventure(((ServerPlayerBridge) mcPlayer).bridge$getConnectionMessageToSend()); final ServerSideConnectionEvent.Join event = SpongeEventFactory.createServerSideConnectionEventJoin(cause, audience, - Optional.of(audience), joinComponent, joinComponent, connection, player, SpongeGameProfile.of(mcPlayer.getGameProfile()), false); + Optional.of(audience), joinComponent, joinComponent, connection, player, SpongeGameProfile.of(mcPlayer.getGameProfile()), false); SpongeCommon.post(event); if (!event.isMessageCancelled()) { event.audience().ifPresent(audience1 -> audience1.sendMessage(Identity.nil(), event.message())); @@ -481,29 +462,13 @@ public abstract class PlayerListMixin implements PlayerListBridge { worldBorder.addListener(new PerWorldBorderListener(serverWorld)); } - @Redirect(method = "load", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerPlayer;load(Lnet/minecraft/world/level/storage/ValueInput;)V" - ) - ) - private void impl$setSpongePlayerDataForSinglePlayer(final net.minecraft.server.level.ServerPlayer entity, final ValueInput compound) { - entity.load(compound); - - if (((ServerPlayer) entity).get(Keys.FIRST_DATE_JOINED).isEmpty()) { - ((SpongeServer) this.shadow$getServer()).getPlayerDataManager().readLegacyPlayerData((ServerPlayer) entity, compound, null); - } - - ((ServerPlayer) entity).offer(Keys.LAST_DATE_JOINED, Instant.now()); - } - @Inject(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;findRespawnPositionAndUseSpawnBlock(ZLnet/minecraft/world/level/portal/TeleportTransition$PostTeleportTransition;)Lnet/minecraft/world/level/portal/TeleportTransition;" ) ) private void impl$flagIfRespawnPositionIsGameMechanic(final net.minecraft.server.level.ServerPlayer $$0, final boolean $$1, - final Entity.RemovalReason $$2, final CallbackInfoReturnable cir) { + final Entity.RemovalReason $$2, final CallbackInfoReturnable cir) { this.impl$isRespawnWithPosition = $$0.getRespawnConfig() != null; } @@ -516,7 +481,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ) ) private double impl$callRespawnPlayerRecreateEvent(final net.minecraft.server.level.ServerPlayer newPlayer, - final net.minecraft.server.level.ServerPlayer player, final boolean keepAllPlayerData, final @Local TeleportTransition dimensionTransition) { + final net.minecraft.server.level.ServerPlayer player, final boolean keepAllPlayerData, final @Local TeleportTransition dimensionTransition) { final ServerPlayer originalPlayer = (ServerPlayer) player; final ServerPlayer recreatedPlayer = (ServerPlayer) newPlayer; @@ -526,9 +491,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { final ServerWorld destinationWorld = recreatedPlayer.world(); final RespawnPlayerEvent.Recreate event = SpongeEventFactory.createRespawnPlayerEventRecreate(PhaseTracker.getInstance().currentCause(), - destinationPosition, originalWorld, originalPosition, destinationWorld, - (ServerWorld) dimensionTransition.newLevel(), - destinationPosition, originalPlayer, recreatedPlayer, this.impl$isRespawnWithPosition, !keepAllPlayerData); + destinationPosition, originalWorld, originalPosition, destinationWorld, + (ServerWorld) dimensionTransition.newLevel(), + destinationPosition, originalPlayer, recreatedPlayer, this.impl$isRespawnWithPosition, !keepAllPlayerData); SpongeCommon.post(event); this.impl$isRespawnWithPosition = false; @@ -555,18 +520,18 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Inject(method = "respawn", at = @At("RETURN")) private void impl$callRespawnPlayerPostEvent(final net.minecraft.server.level.ServerPlayer player, final boolean $$1, final Entity.RemovalReason $$2, - final CallbackInfoReturnable cir, final @Local TeleportTransition dimensionTransition) { + final CallbackInfoReturnable cir, final @Local TeleportTransition dimensionTransition) { final ServerPlayer recreatedPlayer = (ServerPlayer) cir.getReturnValue(); final ServerWorld originalWorld = (ServerWorld) player.level(); final RespawnPlayerEvent.Post event = SpongeEventFactory.createRespawnPlayerEventPost(PhaseTracker.getInstance().currentCause(), - recreatedPlayer.world(), originalWorld, (ServerWorld) dimensionTransition.newLevel(), recreatedPlayer); + recreatedPlayer.world(), originalWorld, (ServerWorld) dimensionTransition.newLevel(), recreatedPlayer); SpongeCommon.post(event); } @Redirect(method = "sendLevelInfo", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;")) private ServerLevel impl$usePerWorldWorldBorder(final MinecraftServer minecraftServer, final net.minecraft.server.level.ServerPlayer playerIn, - final ServerLevel worldIn) { + final ServerLevel worldIn) { return worldIn; } @@ -574,8 +539,8 @@ public abstract class PlayerListMixin implements PlayerListBridge { final net.minecraft.network.chat.Component reason = SpongeAdventure.asVanilla(disconnectMessage); try { - PlayerListMixin.LOGGER.info("Disconnecting " + (profile != null ? profile.toString() + " (" + netManager.getRemoteAddress().toString() + ")" : - netManager.getRemoteAddress() + ": " + reason.getString())); + PlayerListMixin.LOGGER.info("Disconnecting " + (profile != null ? profile + " (" + netManager.getRemoteAddress() + ")" : + netManager.getRemoteAddress() + ": " + reason.getString())); netManager.send(new ClientboundDisconnectPacket(reason)); netManager.disconnect(reason); } catch (final Exception exception) { @@ -589,9 +554,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { } @Inject(method = "broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Ljava/util/function/Function;Z)V", - at = @At("HEAD"), cancellable = true) + at = @At("HEAD"), cancellable = true) private void impl$onBroadcastSystemMessage(final net.minecraft.network.chat.Component $$0, - final Function $$1, final boolean $$2, final CallbackInfo ci) { + final Function $$1, final boolean $$2, final CallbackInfo ci) { if (this.impl$isDuringSystemMessageEvent) { return; } @@ -600,7 +565,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final Audience originalAudience = (Audience) this.server; final Component originalMessage = SpongeAdventure.asAdventure($$0); final SystemMessageEvent event = SpongeEventFactory.createSystemMessageEvent(PhaseTracker.getInstance().currentCause(), - originalAudience, Optional.of(originalAudience), originalMessage, originalMessage); + originalAudience, Optional.of(originalAudience), originalMessage, originalMessage); if (SpongeCommon.post(event)) { ci.cancel(); return; @@ -612,23 +577,23 @@ public abstract class PlayerListMixin implements PlayerListBridge { } @Redirect(method = "broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Ljava/util/function/Predicate;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Ljava/util/function/Predicate;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V")) private void impl$onBroadcastChatMessage1(final PlayerList instance, final PlayerChatMessage $$0, - final Predicate $$1, final net.minecraft.server.level.ServerPlayer $$2, - final ChatType.Bound $$4) { + final Predicate $$1, final net.minecraft.server.level.ServerPlayer $$2, + final ChatType.Bound $$4) { this.impl$onBroadcastChatMessage($$0, $$1, $$2, $$4); } @Redirect(method = "broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Lnet/minecraft/commands/CommandSourceStack;Lnet/minecraft/network/chat/ChatType$Bound;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Ljava/util/function/Predicate;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Ljava/util/function/Predicate;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/network/chat/ChatType$Bound;)V")) private void impl$onBroadcastChatMessage2(final PlayerList instance, final PlayerChatMessage $$0, - final Predicate $$1, final net.minecraft.server.level.ServerPlayer $$2, - final ChatType.Bound $$4) { + final Predicate $$1, final net.minecraft.server.level.ServerPlayer $$2, + final ChatType.Bound $$4) { this.impl$onBroadcastChatMessage($$0, $$1, $$2, $$4); } private void impl$onBroadcastChatMessage(final PlayerChatMessage $$0, final Predicate $$1, - final net.minecraft.server.level.ServerPlayer $$2, final ChatType.Bound $$4) { + final net.minecraft.server.level.ServerPlayer $$2, final ChatType.Bound $$4) { final boolean isTrusted = this.shadow$verifyChatTrusted($$0); @@ -647,12 +612,12 @@ public abstract class PlayerListMixin implements PlayerListBridge { } final PlayerChatEvent.Submit event = SpongeEventFactory.createPlayerChatEventSubmit(frame.currentCause(), content, content, chatType, - Optional.empty(), Optional.ofNullable((ServerPlayer) $$2), sender, Optional.ofNullable(target), isTrusted); + Optional.empty(), Optional.ofNullable((ServerPlayer) $$2), sender, Optional.ofNullable(target), isTrusted); if (SpongeCommon.post(event)) { return; // Do nothing when canceled or audience removed } boundChatType = ChatType.bind(ResourceKey.create(Registries.CHAT_TYPE, (ResourceLocation) (Object) event.chatType().location()), - this.server.registryAccess(), SpongeAdventure.asVanilla(event.sender())); + this.server.registryAccess(), SpongeAdventure.asVanilla(event.sender())); boundChatType = event.target().map(SpongeAdventure::asVanilla).map(boundChatType::withTargetName).orElse(boundChatType); filter = event.filter().map(f -> $$1.and((Predicate) f)).orElse($$1); @@ -663,7 +628,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { // The value of `isTrusted` will always be `true` when `online-mode=true`. // If `online-mode=false`, then `isTrusted` will also have a value of `false`. // When `online-mode=false`, the player is not shown a notification when the server changes the message. - var modifiedMessage = new PlayerChatMessage($$0.link(), $$0.signature(), $$0.signedBody(), customMessage, $$0.filterMask()); + var modifiedMessage = new PlayerChatMessage($$0.link(), $$0.signature(), $$0.signedBody(), customMessage, $$0.filterMask()); this.shadow$broadcastChatMessage(modifiedMessage, filter, $$2, boundChatType); return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java index b5be3ddb4a3..b695562105d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java @@ -24,14 +24,8 @@ */ package org.spongepowered.common.mixin.core.world.level.storage; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.mojang.datafixers.DataFixer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.storage.PlayerDataStorage; -import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -43,11 +37,6 @@ import org.spongepowered.common.SpongeServer; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.time.Instant; @Mixin(PlayerDataStorage.class) public abstract class PlayerDataStorageMixin { @@ -56,16 +45,6 @@ public abstract class PlayerDataStorageMixin { @Shadow @Final private File playerDir; // @formatter:on - @Redirect(method = "lambda$load$1", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;load(Lnet/minecraft/world/level/storage/ValueInput;)V")) - private void impl$readSpongePlayerData(final Player playerEntity, final ValueInput compound) throws IOException { - playerEntity.load(compound); - if (((ServerPlayer) playerEntity).get(Keys.FIRST_DATE_JOINED).isEmpty()) { - final Path file = new File(this.playerDir, playerEntity.getStringUUID() + ".dat").toPath(); - final Instant creationTime = Files.exists(file) ? Files.readAttributes(file, BasicFileAttributes.class).creationTime().toInstant() : null; - ((SpongeServer) SpongeCommon.server()).getPlayerDataManager().readLegacyPlayerData((ServerPlayer) playerEntity, compound, creationTime); - } - ((ServerPlayer) playerEntity).offer(Keys.LAST_DATE_JOINED, Instant.now()); - } @Inject(method = "save", at = @At(value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java index 1d3906024cb..a4d511670ec 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.tracker.server.network; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; @@ -54,17 +56,17 @@ public abstract class ServerGamePacketListenerImplMixin_Tracker { @Shadow public ServerPlayer player; - @Redirect(method = "tick", + @WrapOperation(method = "tickPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;doTick()V")) - private void tracker$wrapPlayerTickWithPhase(final ServerPlayer player) { + private void tracker$wrapPlayerTickWithPhase(ServerPlayer instance, Operation original) { if (((PlatformEntityBridge) player).bridge$isFakePlayer() || ((LevelBridge) player.level()).bridge$isFake()) { - player.doTick(); + original.call(instance); return; } try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.getWorldInstance(this.player.level())).source(player)) { context.buildAndSwitch(); PhaseTracker.LOGGER.trace(TrackingUtil.PLAYER_TICK, () -> "Wrapping Player Tick: " + player.toString()); - player.doTick(); + original.call(instance); } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 3ef7ba1cc51..d6084a47817 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -95,6 +95,7 @@ "server.network.ServerHandshakePacketListenerImplMixin", "server.network.ServerLoginPacketListenerImplMixin", "server.network.ServerStatusPacketListenerImplMixin", + "server.network.config.PrepareSpawnTask_ReadyMixin", "server.packs.resoruces.MultiPackResourceManagerMixin", "server.players.BanListEntryMixin", "server.players.GameProfileCache_GameProfileInfoMixin", From c96cd45173f22196d0f8265c2b6296d2bf3bf8f4 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 1 Sep 2025 18:03:24 -0700 Subject: [PATCH 313/586] chore(minecraft): update to 25w33a Notes: - Added an implementation shortfall for the new explosion handling, see https://github.com/SpongePowered/SpongeAPI/issues/2599 See: https://minecraft.wiki/w/Java_Edition_25w33a --- SpongeAPI | 2 +- .../world/level/block/BlockRegistries.java | 2 +- gradle.properties | 2 +- .../block/state/BlockStateDataProvider.java | 13 ++++---- .../event/tracking/phase/tick/TickPhase.java | 2 +- .../core/server/level/ServerLevelMixin.java | 5 +-- .../level/ServerLevelMixin_Tracker.java | 32 ++++++++++--------- 7 files changed, 31 insertions(+), 27 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 6252dce257b..b121463d867 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 6252dce257b18be1897b5c07d946ff2886fbf79b +Subproject commit b121463d867d4d0d65b04d77da285fca6beecd37 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java index 59d1f58a69c..1a7e8938a0b 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java @@ -110,7 +110,7 @@ public static List enumRegistries(final Context context) { ), new EnumEntriesValidator<>( "data.type", - "CopperOxidization", + "CopperOxidations", WeatheringCopper.WeatherState.class, "getSerializedName", "sponge" diff --git a/gradle.properties b/gradle.properties index 335000978ef..d81f4121e3f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w32a +minecraftVersion=25w33a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index dd2d82f4c66..d51022054f1 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -49,6 +49,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_4, BlockStateProperties.AGE_4); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_5, BlockStateProperties.AGE_5); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_7, BlockStateProperties.AGE_7); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ALIGN_ITEMS_TO_BOTTOM, BlockStateProperties.ALIGN_ITEMS_TO_BOTTOM); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ATTACHED, BlockStateProperties.ATTACHED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ATTACH_FACE, BlockStateProperties.ATTACH_FACE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AXIS, BlockStateProperties.AXIS); @@ -62,12 +63,6 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CANDLES, BlockStateProperties.CANDLES); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CAN_SUMMON, BlockStateProperties.CAN_SUMMON); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHEST_TYPE, BlockStateProperties.CHEST_TYPE); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_0_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_0_OCCUPIED); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_1_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_1_OCCUPIED); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_2_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_2_OCCUPIED); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_3_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_3_OCCUPIED); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_4_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_4_OCCUPIED); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CHISELED_BOOKSHELF_SLOT_5_OCCUPIED, BlockStateProperties.CHISELED_BOOKSHELF_SLOT_5_OCCUPIED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CONDITIONAL, BlockStateProperties.CONDITIONAL); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.COPPER_GOLEM_POSE, BlockStateProperties.COPPER_GOLEM_POSE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.CRACKED, BlockStateProperties.CRACKED); @@ -143,6 +138,12 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SIDE_CHAIN_PART, BlockStateProperties.SIDE_CHAIN_PART); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SIGNAL_FIRE, BlockStateProperties.SIGNAL_FIRE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLAB_TYPE, BlockStateProperties.SLAB_TYPE); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_0_OCCUPIED, BlockStateProperties.SLOT_0_OCCUPIED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_1_OCCUPIED, BlockStateProperties.SLOT_1_OCCUPIED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_2_OCCUPIED, BlockStateProperties.SLOT_2_OCCUPIED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_3_OCCUPIED, BlockStateProperties.SLOT_3_OCCUPIED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_4_OCCUPIED, BlockStateProperties.SLOT_4_OCCUPIED); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SLOT_5_OCCUPIED, BlockStateProperties.SLOT_5_OCCUPIED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SNOWY, BlockStateProperties.SNOWY); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SOUTH, BlockStateProperties.SOUTH); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SOUTH_REDSTONE, BlockStateProperties.SOUTH_REDSTONE); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/TickPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/TickPhase.java index aee13b8e122..080a96839b6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/TickPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/TickPhase.java @@ -40,7 +40,7 @@ public static final class Tick { public static final IPhaseState TILE_ENTITY = new TileEntityTickPhaseState(); public static final IPhaseState BLOCK_EVENT = new BlockEventTickPhaseState(); public static final IPhaseState PLAYER = new PlayerTickPhaseState(); - public static final IPhaseState WEATHER = new WeatherTickPhaseState(); + public static final IPhaseState WEATHER = new WeatherTickPhaseState(); public static final IPhaseState SERVER_TICK = new ServerTickState(); public static final IPhaseState WORLD_TICK = new WorldTickState(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 9c7f5dde43b..4425ab67848 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -48,6 +48,7 @@ import net.minecraft.server.players.PlayerList; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.RandomSequences; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiManager; @@ -275,7 +276,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel for (ServerPlayer player : this.players) { if (player.distanceToSqr(mcExplosion.center()) < 4096.0) { Optional kb = Optional.ofNullable(mcExplosion.getHitPlayers().get(player)); - final var packet = new ClientboundExplodePacket(mcExplosion.center(), kb, particle, sound); + final var packet = new ClientboundExplodePacket(mcExplosion.center(), explosion.radius(), 1, kb, particle, sound, WeightedList.of()); this.bridge$handleExplosionPacket(player.connection, explosion, packet); player.connection.send(packet); } @@ -292,7 +293,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel var soundEvent = Holder.direct(new SoundEvent(ResourceLocation.parse("sponge:none"), Optional.of(0f))); // "no" sound soundEvent = packet.explosionSound(); // TODO apiExplosion.shouldPlaySmoke() is not initialized correctly - var newPacket = new ClientboundExplodePacket(packet.center(), packet.playerKnockback(), particleData, soundEvent); + var newPacket = new ClientboundExplodePacket(packet.center(), packet.radius(), packet.blockCount(), packet.playerKnockback(), particleData, soundEvent, packet.blockParticles()); instance.send(newPacket); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index e003846fac5..d5867c90ef8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.particles.ExplosionParticleInfo; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketListener; @@ -40,6 +41,7 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; +import net.minecraft.util.random.WeightedList; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; @@ -313,9 +315,9 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem private org.spongepowered.api.world.explosion.Explosion tracker$apiExplosion; - @Redirect(method = "explode", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/ServerExplosion;explode()V")) - private void tracker$onExplode(final ServerExplosion instance) { + @WrapOperation(method = "explode", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/ServerExplosion;explode()I")) + private int tracker$onExplode(ServerExplosion instance, Operation original) { var mcExplosion = instance; final var entity = instance.getDirectSourceEntity(); // TODO entity can be null, what is our API explosive then? @@ -327,21 +329,21 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem if (!(entity instanceof final Explosive apiExplosive)) { mcExplosion.explode(); this.tracker$apiExplosion = explosionBuilder.build(); - return; + return 0; } final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(phaseTracker.currentCause(), explosionBuilder, apiExplosive, (org.spongepowered.api.world.explosion.Explosion) instance); if (Sponge.eventManager().post(detonateEvent)) { this.tracker$cancelExplosionEffects(entity); - return; + return 0; } // Build the explosion from event var apiExplosion = detonateEvent.explosionBuilder().build(); if (apiExplosion.radius() <= 0) { this.tracker$cancelExplosionEffects(entity); - return; + return 0; } if (ShouldFire.EXPLOSION_EVENT_PRE) { @@ -350,7 +352,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem SpongeEventFactory.createExplosionEventPre(phaseTracker.currentCause(), apiExplosion, thisWorld); if (SpongeCommon.post(event)) { this.tracker$cancelExplosionEffects(entity); - return; + return 0; } try { @@ -365,18 +367,17 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem } } + this.tracker$apiExplosion = apiExplosion; try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker).explosion(mcExplosion) .source(((Optional) apiExplosion.sourceExplosive()).orElse(this))) { ctx.buildAndSwitch(); - mcExplosion.explode(); + return original.call(mcExplosion); } - - this.tracker$apiExplosion = apiExplosion; } @Inject(method = "explode", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/ServerExplosion;explode()V", shift = At.Shift.AFTER)) + target = "Lnet/minecraft/world/level/ServerExplosion;explode()I", shift = At.Shift.AFTER)) private void tracker$onCancelled(final CallbackInfo ci) { if (this.tracker$apiExplosion == null) { ci.cancel(); @@ -394,10 +395,11 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem } @Inject(method = "explode", at = @At(value = "RETURN")) - private void tracker$afterExplodeCleanup(final Entity $$0, final DamageSource $$1, - final ExplosionDamageCalculator $$2, final double $$3, final double $$4, final double $$5, final float $$6, - final boolean $$7, final Level.ExplosionInteraction $$8, final ParticleOptions $$9, final ParticleOptions $$10, - final Holder $$11, final CallbackInfo ci) { + private void tracker$afterExplodeCleanup( + final Entity $$0, final DamageSource $$1, final ExplosionDamageCalculator $$2, final double $$3, + final double $$4, final double $$5, final float $$6, final boolean $$7, final Level.ExplosionInteraction $$8, + final ParticleOptions $$9, final ParticleOptions $$10, final WeightedList $$11, + final Holder $$12, final CallbackInfo ci) { this.tracker$apiExplosion = null; } From 231ab0292ee0b55067da96e999da55ddd7e66e21 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 1 Sep 2025 19:12:00 -0700 Subject: [PATCH 314/586] chore(minecraft): update to 25w34a Changes: - property name changes See: https://minecraft.wiki/w/Java_Edition_25w34a --- SpongeAPI | 2 +- gradle.properties | 2 +- .../data/provider/block/state/BlockStateDataProvider.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index b121463d867..e11889e9800 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b121463d867d4d0d65b04d77da285fca6beecd37 +Subproject commit e11889e9800cc3fdb0d4ab0dc7ec1e7b3fc109e2 diff --git a/gradle.properties b/gradle.properties index d81f4121e3f..f55f65bcbd3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w33a +minecraftVersion=25w34a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index d51022054f1..c6bd3fc18a1 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -49,7 +49,6 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_4, BlockStateProperties.AGE_4); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_5, BlockStateProperties.AGE_5); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AGE_7, BlockStateProperties.AGE_7); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ALIGN_ITEMS_TO_BOTTOM, BlockStateProperties.ALIGN_ITEMS_TO_BOTTOM); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ATTACHED, BlockStateProperties.ATTACHED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.ATTACH_FACE, BlockStateProperties.ATTACH_FACE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.AXIS, BlockStateProperties.AXIS); From b8beab8e86c41fbb7cb54ac6e30cc539f6eafca6 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 1 Sep 2025 19:19:42 -0700 Subject: [PATCH 315/586] chore(minecraft): update to 25w35a Additions: - Add formerly server properties as game rules Breaking Change: - Rename CHAIN to IRON_CHAIN See: https://minecraft.wiki/w/Java_Edition_25w35a --- SpongeAPI | 2 +- .../generator/BlockStatePropertiesGenerator.java | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index e11889e9800..687ece5fafa 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit e11889e9800cc3fdb0d4ab0dc7ec1e7b3fc109e2 +Subproject commit 687ece5fafacbdb7f669c0b1118144279e4c760b diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index fbd3387f2e3..2e07feb0af8 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -155,7 +155,7 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(VaultState.class, BlockStatePropertiesGenerator.inDataTypePkg("VaultState")); vanillaEnumTypeMapping.put(CreakingHeartState.class, BlockStatePropertiesGenerator.inDataTypePkg("CreakingHeartState")); vanillaEnumTypeMapping.put(TestBlockMode.class, BlockStatePropertiesGenerator.inDataTypePkg("TestBlockMode")); - vanillaEnumTypeMapping.put(SideChainPart.class, BlockStatePropertiesGenerator.inDataTypePkg("SideChainPart")); + vanillaEnumTypeMapping.put(SideChainPart.class, BlockStatePropertiesGenerator.inDataTypePkg("SideChain")); vanillaEnumTypeMapping.put(CopperGolemStatueBlock.Pose.class, BlockStatePropertiesGenerator.inDataTypePkg("CopperGolemPose")); vanillaEnumTypeMapping.put(WeatheringCopper.WeatherState.class, BlockStatePropertiesGenerator.inDataTypePkg("CopperOxidation")); diff --git a/gradle.properties b/gradle.properties index f55f65bcbd3..c465ff07f25 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json superClassChanges=common.superclasschange -minecraftVersion=25w34a +minecraftVersion=25w35a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 816b55f32ef..6236deaf226 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1499,6 +1499,14 @@ + + + + + + + + @@ -2463,6 +2471,14 @@ + + + + + + + + From b378f1b99c52b8a2565be21996307b94c9a165ec Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 3 Sep 2025 13:56:18 +0200 Subject: [PATCH 316/586] Remove unused bootstrap method --- .../spongepowered/bootstrap/forge/ForgeLikeBootstrap.java | 5 ----- .../src/main/java/org/spongepowered/bootstrap/Bootstrap.java | 2 -- .../spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java | 5 ----- 3 files changed, 12 deletions(-) diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java index df9c6d38c5d..aa9997d8a87 100644 --- a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java @@ -53,11 +53,6 @@ protected String getModuleName(final SecureJar jar) { return jar.name(); } - @Override - protected URL getJarURL(final SecureJar jar) throws Exception { - return jar.getRootPath().toUri().toURL(); - } - @Override protected ModuleFinder createModuleFinder(final Collection jars) { return SecureModuleFinder.of(jars); diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 393503b05d3..9ef04b2a09f 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -48,8 +48,6 @@ public abstract class Bootstrap { protected abstract String getModuleName(Jar jar); - protected abstract URL getJarURL(Jar jar) throws Exception; - protected abstract ModuleFinder createModuleFinder(Collection jars); /** diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java index 88b931ae17b..b39653ca764 100644 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java @@ -58,11 +58,6 @@ protected String getModuleName(final SecureJar jar) { return jar.name(); } - @Override - protected URL getJarURL(final SecureJar jar) throws Exception { - return jar.getRootPath().toUri().toURL(); - } - @Override protected ModuleFinder createModuleFinder(final Collection jars) { return JarModuleFinder.of(jars.toArray(SecureJar[]::new)); From 4c9de76ab9335e4b1a11142f30def06a42f9a5fb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 3 Sep 2025 16:01:23 +0200 Subject: [PATCH 317/586] Fix spotless --- .../org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java | 1 - .../org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java | 1 - 2 files changed, 2 deletions(-) diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java index aa9997d8a87..f7fbd101d01 100644 --- a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java @@ -31,7 +31,6 @@ import java.lang.module.Configuration; import java.lang.module.ModuleFinder; -import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.List; diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java index b39653ca764..84ac0a335ea 100644 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java @@ -31,7 +31,6 @@ import java.lang.module.Configuration; import java.lang.module.ModuleFinder; -import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.List; From 2c8da2a754abd6007e20388170740bc7a55e8f3a Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 20 Jul 2025 17:36:57 +0200 Subject: [PATCH 318/586] Unit tests on all platforms --- .../bootstrap/dev/DevClasspath.java | 2 +- forge/build.gradle.kts | 35 ++++++++- .../forge/lang/locator/DummyModLocator.java | 35 +++++++++ ...necraftforge.forgespi.locating.IModLocator | 1 + .../forge/locator/DummyModLocator.java | 35 +++++++++ ...necraftforge.forgespi.locating.IModLocator | 1 + .../org/spongepowered/forge/ServerTest.java | 36 +++++++++ .../forge/boot/SpongeSessionListener.java | 48 ++++++++++++ .../forge/boot/SpongeTestBoot.java | 40 ++++++++++ ....platform.launcher.LauncherSessionListener | 1 + gradle.properties | 2 +- neoforge/build.gradle.kts | 41 +++++++++- .../resources/mixins.spongeneo.core.json | 4 +- .../spongepowered/neoforge/ServerTest.java | 36 +++++++++ .../neoforge/boot/SpongeSessionListener.java | 48 ++++++++++++ .../neoforge/boot/SpongeTestBoot.java | 46 +++++++++++ ....platform.launcher.LauncherSessionListener | 1 + .../applaunch/test/GameClassLoaderHolder.java | 37 +++++++++ .../spongepowered/common/launch/Launch.java | 2 + .../core/server/MinecraftServerMixin.java | 18 +++-- .../common/mixin/plugin/TestPlugin.java | 38 +++++++++ .../server/MinecraftServerMixin_Test.java | 78 +++++++++++++++++++ .../dedicated/DedicatedServerMixin_Test.java | 46 +++++++++++ .../server/dedicated/SettingsMixin_Test.java | 44 +++++++++++ src/mixins/resources/mixins.sponge.test.json | 10 +++ vanilla/build.gradle.kts | 34 +++++++- .../org/spongepowered/vanilla/ServerTest.java | 36 +++++++++ .../vanilla/boot/SpongeSessionListener.java | 48 ++++++++++++ .../vanilla/boot/SpongeTestBoot.java | 40 ++++++++++ ....platform.launcher.LauncherSessionListener | 1 + 30 files changed, 824 insertions(+), 20 deletions(-) create mode 100644 forge/src/lang/java/org/spongepowered/forge/lang/locator/DummyModLocator.java create mode 100644 forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator create mode 100644 forge/src/main/java/org/spongepowered/forge/locator/DummyModLocator.java create mode 100644 forge/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator create mode 100644 forge/src/test/java/org/spongepowered/forge/ServerTest.java create mode 100644 forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java create mode 100644 forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java create mode 100644 forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener create mode 100644 neoforge/src/test/java/org/spongepowered/neoforge/ServerTest.java create mode 100644 neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java create mode 100644 neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java create mode 100644 neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java create mode 100644 src/mixins/resources/mixins.sponge.test.json create mode 100644 vanilla/src/test/java/org/spongepowered/vanilla/ServerTest.java create mode 100644 vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java create mode 100644 vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java create mode 100644 vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index a2ad50a357b..5b0d65f20c9 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -125,7 +125,7 @@ public static List resolve() { final String fileName = path.getFileName().toString(); - if (false) { + if (fileName.startsWith("junit-")) { if (Bootstrap.DEBUG) { System.out.println("Ignored: " + path); } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index c0212ff9802..605cd138435 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,6 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.common.util.RunConfig -import net.minecraftforge.gradle.userdev.UserDevExtension import org.gradle.api.tasks.JavaExec import org.gradle.internal.DefaultTaskExecutionRequest import org.spongepowered.gradle.impl.AWToAT @@ -167,6 +166,10 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } +sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) +} configurations.configureEach { // Fix that can be found in Forge MDK too @@ -175,6 +178,10 @@ configurations.configureEach { } } +configurations.testRuntimeOnly { + exclude(module = "testplugins") +} + dependencies { "minecraft"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") @@ -213,6 +220,12 @@ dependencies { testPluginsProject?.also { runtimeOnly(project(it.path)) } + + testImplementation(platform(apiLibs.junit.bom)) + testImplementation(apiLibs.junit.api) + testImplementation(apiLibs.junit.params) + testImplementation(apiLibs.junit.launcher) + testRuntimeOnly(apiLibs.junit.engine) } val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files @@ -221,7 +234,7 @@ AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations -extensions.configure(UserDevExtension::class) { +minecraft { mappings("official", "1.21.4") accessTransformers.from(atFile) reobf = false @@ -246,7 +259,7 @@ extensions.configure(UserDevExtension::class) { } afterEvaluate { - extensions.configure(UserDevExtension::class) { + minecraft { // Configure bootstrap dev val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) @@ -399,6 +412,22 @@ tasks { assemble { dependsOn(universalJar) } + + test { + useJUnitPlatform() + + val runServer = minecraft.runs.getByName("server") + jvmArgs(runServer.jvmArgs) + jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) + workingDir = layout.buildDirectory.dir("test-run").get().asFile + + doFirst { + // reset test directory + workingDir.deleteRecursively() + workingDir.mkdirs() + workingDir.resolve("eula.txt").writeText("eula=true") + } + } } if (IdeHelper.isIdeaSync()) { diff --git a/forge/src/lang/java/org/spongepowered/forge/lang/locator/DummyModLocator.java b/forge/src/lang/java/org/spongepowered/forge/lang/locator/DummyModLocator.java new file mode 100644 index 00000000000..4eef306572a --- /dev/null +++ b/forge/src/lang/java/org/spongepowered/forge/lang/locator/DummyModLocator.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.lang.locator; + +import net.minecraftforge.forgespi.locating.IModLocator; + +/** + * Hack. + * FML ClasspathLocator in our test env wants to load the lang/resources directory without a union, causing a conflict. + * Fortunately, when it detects certain services, it just skips the directory. + */ +public abstract class DummyModLocator implements IModLocator { +} diff --git a/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator b/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator new file mode 100644 index 00000000000..1be92fd2bbd --- /dev/null +++ b/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator @@ -0,0 +1 @@ +org.spongepowered.forge.lang.locator.DummyModLocator diff --git a/forge/src/main/java/org/spongepowered/forge/locator/DummyModLocator.java b/forge/src/main/java/org/spongepowered/forge/locator/DummyModLocator.java new file mode 100644 index 00000000000..fc85ba085fe --- /dev/null +++ b/forge/src/main/java/org/spongepowered/forge/locator/DummyModLocator.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.locator; + +import net.minecraftforge.forgespi.locating.IModLocator; + +/** + * Hack. + * FML ClasspathLocator in our test env wants to load the main/resources directory without a union, causing a conflict. + * Fortunately, when it detects certain services, it just skips the directory. + */ +public abstract class DummyModLocator implements IModLocator { +} diff --git a/forge/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator b/forge/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator new file mode 100644 index 00000000000..7884741e014 --- /dev/null +++ b/forge/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator @@ -0,0 +1 @@ +org.spongepowered.forge.locator.DummyModLocator diff --git a/forge/src/test/java/org/spongepowered/forge/ServerTest.java b/forge/src/test/java/org/spongepowered/forge/ServerTest.java new file mode 100644 index 00000000000..792b0832172 --- /dev/null +++ b/forge/src/test/java/org/spongepowered/forge/ServerTest.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge; + +import org.junit.jupiter.api.Test; +import org.spongepowered.api.Sponge; + +public class ServerTest { + + @Test + public void serverAvailable() { + Sponge.server(); + } +} diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java new file mode 100644 index 00000000000..c865f7a68ed --- /dev/null +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java @@ -0,0 +1,48 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.boot; + +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.LauncherSessionListener; + +public class SpongeSessionListener implements LauncherSessionListener { + private ClassLoader previousLoader; + + @Override + public void launcherSessionOpened(final LauncherSession session) { + this.previousLoader = Thread.currentThread().getContextClassLoader(); + + try { + Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void launcherSessionClosed(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.previousLoader); + } +} diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java new file mode 100644 index 00000000000..7b0299df2cb --- /dev/null +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java @@ -0,0 +1,40 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.boot; + +import org.spongepowered.bootstrap.forge.ForgeBootstrap; +import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; + +public class SpongeTestBoot { + + public static ClassLoader getGameClassLoader() throws Exception { + if (GameClassLoaderHolder.loader == null) { + final String[] args = System.getProperty("sponge.test.args").split(" "); + System.setProperty("sponge.test.active", "true"); + new ForgeBootstrap(args).devBoot(false); + } + return GameClassLoaderHolder.loader; + } +} diff --git a/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener b/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener new file mode 100644 index 00000000000..363e6b24c85 --- /dev/null +++ b/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener @@ -0,0 +1 @@ +org.spongepowered.forge.boot.SpongeSessionListener diff --git a/gradle.properties b/gradle.properties index 2f01c48ff1e..948f91c0633 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ projectDescription=The SpongeAPI implementation targeting vanilla Minecraft and mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.concurrent.json,mixins.sponge.core.json,\ mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ - mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json + mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange minecraftVersion=1.21.4 diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index fb6deb72cfc..01b44992e9c 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,6 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.neoforged.moddevgradle.dsl.NeoForgeExtension import net.neoforged.moddevgradle.internal.RunGameTask +import org.gradle.api.tasks.JavaExec import org.spongepowered.gradle.impl.AWToAT buildscript { @@ -158,6 +158,14 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapNeoForge.get(), this) } +sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapNeoForge.get(), this) +} + +configurations.testRuntimeOnly { + exclude(module = "testplugins") +} val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile @@ -165,7 +173,7 @@ AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations -extensions.configure(NeoForgeExtension::class) { +neoForge { version = neoForgeVersion accessTransformers.from(atFile) @@ -189,6 +197,7 @@ extensions.configure(NeoForgeExtension::class) { } bootLibrariesConfig.get().extendsFrom(configurations.getByName("modDevCompileDependencies")) +configurations.testRuntimeOnly.get().extendsFrom(configurations.getByName("modDevRuntimeDependencies")) dependencies { val service = serviceLibrariesConfig.name @@ -217,10 +226,16 @@ dependencies { testPluginsProject?.also { runtimeOnly(project(it.path)) } + + testImplementation(platform(apiLibs.junit.bom)) + testImplementation(apiLibs.junit.api) + testImplementation(apiLibs.junit.params) + testImplementation(apiLibs.junit.launcher) + testRuntimeOnly(apiLibs.junit.engine) } afterEvaluate { - extensions.configure(NeoForgeExtension::class) { + neoForge { // Configure bootstrap dev val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) @@ -370,6 +385,26 @@ tasks { assemble { dependsOn(universalJar) } + + val runServer = named("runServer", JavaExec::class) + val prepareServerRun = named("prepareServerRun") + + test { + useJUnitPlatform() + + jvmArgs(runServer.get().jvmArgs) + jvmArgs("-Dsponge.test.args=" + runServer.get().args!!.joinToString(" ")) + workingDir = layout.buildDirectory.dir("test-run").get().asFile + + doFirst { + // reset test directory + workingDir.deleteRecursively() + workingDir.mkdirs() + workingDir.resolve("eula.txt").writeText("eula=true") + } + + dependsOn(prepareServerRun) + } } publishing { diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index 135ad8490aa..4424652efdd 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -8,9 +8,8 @@ "api.event.block.ChangeBlockEvent_AllMixin_Neo", "api.event.entity.ChangeEntityWorldEvent_PreMixin_Neo", "api.event.entity.ChangeEventWorldEvent_PostMixin_Neo", - "neoforge.event.entity.item.ItemTossEventMixin_Neo", "commands.CommandsMixin_Neo", - "neoforge.NeoForgeMixin_Neo", + "neoforge.event.entity.item.ItemTossEventMixin_Neo", "neoforge.event.entity.EntityTravelToDimensionEventMixin_Neo", "neoforge.event.entity.player.PlayerEvent_PlayerChangedDimensionEventMixin_Neo", "neoforge.event.world.BlockEvent_BreakEventMixin_Neo", @@ -18,6 +17,7 @@ "neoforge.internal.BrandingControlMixin_Neo", "neoforge.registries.GameDataMixin_Neo", "neoforge.registries.RegistryManagerMixin_Neo", + "neoforge.NeoForgeMixin_Neo", "network.ConnectionMixin_Neo", "server.BootstrapMixin_Neo", "server.MinecraftServerMixin_Neo", diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/ServerTest.java b/neoforge/src/test/java/org/spongepowered/neoforge/ServerTest.java new file mode 100644 index 00000000000..a02de5b083a --- /dev/null +++ b/neoforge/src/test/java/org/spongepowered/neoforge/ServerTest.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge; + +import org.junit.jupiter.api.Test; +import org.spongepowered.api.Sponge; + +public class ServerTest { + + @Test + public void serverAvailable() { + Sponge.server(); + } +} diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java new file mode 100644 index 00000000000..07323da67b4 --- /dev/null +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java @@ -0,0 +1,48 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.boot; + +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.LauncherSessionListener; + +public class SpongeSessionListener implements LauncherSessionListener { + private ClassLoader previousLoader; + + @Override + public void launcherSessionOpened(final LauncherSession session) { + this.previousLoader = Thread.currentThread().getContextClassLoader(); + + try { + Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void launcherSessionClosed(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.previousLoader); + } +} diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java new file mode 100644 index 00000000000..e14bea8bbd4 --- /dev/null +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java @@ -0,0 +1,46 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.boot; + +import org.spongepowered.bootstrap.neoforge.NeoForgeBootstrap; +import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class SpongeTestBoot { + + public static ClassLoader getGameClassLoader() throws Exception { + if (GameClassLoaderHolder.loader == null) { + final Path argsFile = Path.of(System.getProperty("sponge.test.args").substring(1)); + final String[] args = Files.lines(argsFile).map(String::trim).filter(line -> !line.startsWith("#") && !line.isEmpty()) + .skip(1) // main class + .toArray(String[]::new); + System.setProperty("sponge.test.active", "true"); + new NeoForgeBootstrap(args).devBoot(false); + } + return GameClassLoaderHolder.loader; + } +} diff --git a/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener b/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener new file mode 100644 index 00000000000..5c360ba009e --- /dev/null +++ b/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener @@ -0,0 +1 @@ +org.spongepowered.neoforge.boot.SpongeSessionListener diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java b/src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java new file mode 100644 index 00000000000..e921b1ed3d7 --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.test; + +public class GameClassLoaderHolder { + public static ClassLoader loader; + + public static void set(final ClassLoader loader) { + try { + ClassLoader.getSystemClassLoader().loadClass(GameClassLoaderHolder.class.getName()).getField("loader").set(null, loader); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/launch/java/org/spongepowered/common/launch/Launch.java b/src/launch/java/org/spongepowered/common/launch/Launch.java index ab1684504c3..169c8364cc4 100644 --- a/src/launch/java/org/spongepowered/common/launch/Launch.java +++ b/src/launch/java/org/spongepowered/common/launch/Launch.java @@ -32,6 +32,7 @@ import org.spongepowered.api.plugin.PluginManager; import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.common.applaunch.plugin.PluginPlatform; +import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; import org.spongepowered.common.launch.plugin.SpongePluginManager; import org.spongepowered.plugin.PluginContainer; @@ -67,6 +68,7 @@ public static void setInstance(final Launch instance) { } Launch.INSTANCE = Objects.requireNonNull(instance); + GameClassLoaderHolder.set(instance.getClass().getClassLoader()); } public final String id() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 138e867ba6d..53a0c966a89 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -28,6 +28,7 @@ import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.datafixers.DataFixer; import net.kyori.adventure.resource.ResourcePackRequest; import net.minecraft.Util; import net.minecraft.commands.CommandSourceStack; @@ -39,9 +40,11 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerFunctionManager; +import net.minecraft.server.Services; import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleReloadInstance; @@ -85,7 +88,6 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; import org.spongepowered.common.accessor.server.ServerFunctionManagerAccessor; @@ -115,14 +117,13 @@ import org.spongepowered.common.world.server.SpongeWorldManager; import java.io.IOException; +import java.net.Proxy; import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin implements SpongeServer, MinecraftServerBridge, CommandSourceProviderBridge, SubjectProxy, @@ -203,11 +204,12 @@ public Subject subject() { return SpongeCommon.game().systemSubject(); } - @Inject(method = "spin", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private static void impl$setThreadOnServerPhaseTracker(final Function p_240784_0_, - final CallbackInfoReturnable cir, - final AtomicReference atomicReference, - final Thread thread) { + @Inject(method = "", at = @At("RETURN")) + private void impl$setThreadOnServerPhaseTracker( + Thread thread, LevelStorageSource.LevelStorageAccess storageAccess, PackRepository packRepo, + WorldStem stem, Proxy proxy, DataFixer fixer, + Services services, ChunkProgressListenerFactory progress, CallbackInfo ci + ) { try { PhaseTracker.getServerInstanceExplicitly().setThread(thread); } catch (final IllegalAccessException e) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java new file mode 100644 index 00000000000..a51d74ab859 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.plugin; + +public final class TestPlugin extends AbstractMixinConfigPlugin { + private final boolean active; + + public TestPlugin() { + this.active = "true".equals(System.getProperty("sponge.test.active")); + } + + @Override + public boolean shouldApplyMixin(final String targetClassName, final String mixinClassName) { + return this.active; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java new file mode 100644 index 00000000000..12eac43294e --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java @@ -0,0 +1,78 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.test.server; + +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.io.IOException; +import java.util.function.Function; + +@Mixin(MinecraftServer.class) +public abstract class MinecraftServerMixin_Test { + + @Shadow + protected abstract boolean initServer() throws IOException; + + @Shadow + private volatile boolean running; + + @Shadow + private boolean stopped; + + @Shadow + public abstract void stopServer(); + + /** + * @author Yeregorix + * @reason Stay on the same thread and do not tick the server. + */ + @Inject(method = "spin", at = @At("HEAD"), cancellable = true) + private static void spin(final Function supplier, CallbackInfoReturnable cir) { + final MinecraftServer server = supplier.apply(Thread.currentThread()); + try { + ((MinecraftServerMixin_Test) (Object) server).initServer(); + } catch (IOException e) { + throw new RuntimeException(e); + } + cir.setReturnValue(server); + } + + /** + * @author Yeregorix + * @reason Stops the server instead of the loop. + */ + @Overwrite + public void halt(final boolean join) { + this.running = false; + this.stopped = true; + this.stopServer(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java new file mode 100644 index 00000000000..24af936e95c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java @@ -0,0 +1,46 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.test.server.dedicated; + +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.network.ServerConnectionListener; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.net.InetAddress; + +@Mixin(DedicatedServer.class) +public class DedicatedServerMixin_Test { + @Shadow @Final static Logger LOGGER; + + @Redirect(method = "initServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerConnectionListener;startTcpServerListener(Ljava/net/InetAddress;I)V")) + private void dontStartTcpServer(final ServerConnectionListener listener, final InetAddress address, final int port) { + DedicatedServerMixin_Test.LOGGER.info("[TEST] TCP server not started."); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java new file mode 100644 index 00000000000..510deef81fa --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java @@ -0,0 +1,44 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.test.server.dedicated; + +import net.minecraft.server.dedicated.Settings; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.nio.file.NoSuchFileException; + +@Mixin(Settings.class) +public class SettingsMixin_Test { + + @Redirect(method = "loadFromFile", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V")) + private static void onLoadFromFileError(final Logger logger, final String message, final Object path, final Object exception) { + if (!(exception instanceof NoSuchFileException)) { + logger.error(message, path, exception); + } + } +} diff --git a/src/mixins/resources/mixins.sponge.test.json b/src/mixins/resources/mixins.sponge.test.json new file mode 100644 index 00000000000..d1d903f4dda --- /dev/null +++ b/src/mixins/resources/mixins.sponge.test.json @@ -0,0 +1,10 @@ +{ + "parent": "mixins.sponge.parent.json", + "package": "org.spongepowered.common.mixin.test", + "plugin": "org.spongepowered.common.mixin.plugin.TestPlugin", + "mixins": [ + "server.MinecraftServerMixin_Test", + "server.dedicated.DedicatedServerMixin_Test", + "server.dedicated.SettingsMixin_Test" + ] +} diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 9a2129e87f6..f0a129baa74 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -138,6 +138,10 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } +sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) +} val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations @@ -154,6 +158,10 @@ configurations.configureEach { } } +configurations.testRuntimeOnly { + exclude(module = "testplugins") +} + dependencies { val installer = installerLibrariesConfig.name installer(libs.securemodules) @@ -242,15 +250,21 @@ dependencies { testPluginsProject?.also { runtimeOnly(project(it.path)) } + + testImplementation(platform(apiLibs.junit.bom)) + testImplementation(apiLibs.junit.api) + testImplementation(apiLibs.junit.params) + testImplementation(apiLibs.junit.launcher) + testRuntimeOnly(apiLibs.junit.engine) } minecraft { runs { // Full development environment - server("runServer") { + server() { args("--nogui", "--launchTarget", "sponge_server_dev") } - client("runClient") { + client() { args("--launchTarget", "sponge_client_dev") } @@ -476,6 +490,22 @@ tasks { assemble { dependsOn(universalJar) } + + test { + useJUnitPlatform() + + val runServer = minecraft.runs.server().get() + jvmArgs(runServer.allJvmArguments()) + jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) + workingDir = layout.buildDirectory.dir("test-run").get().asFile + + doFirst { + // reset test directory + workingDir.deleteRecursively() + workingDir.mkdirs() + workingDir.resolve("eula.txt").writeText("eula=true") + } + } } publishing { diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/ServerTest.java b/vanilla/src/test/java/org/spongepowered/vanilla/ServerTest.java new file mode 100644 index 00000000000..d08e581f7c2 --- /dev/null +++ b/vanilla/src/test/java/org/spongepowered/vanilla/ServerTest.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla; + +import org.junit.jupiter.api.Test; +import org.spongepowered.api.Sponge; + +public class ServerTest { + + @Test + public void serverAvailable() { + Sponge.server(); + } +} diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java new file mode 100644 index 00000000000..b30074b2a1c --- /dev/null +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java @@ -0,0 +1,48 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.boot; + +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.LauncherSessionListener; + +public class SpongeSessionListener implements LauncherSessionListener { + private ClassLoader previousLoader; + + @Override + public void launcherSessionOpened(final LauncherSession session) { + this.previousLoader = Thread.currentThread().getContextClassLoader(); + + try { + Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void launcherSessionClosed(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.previousLoader); + } +} diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java new file mode 100644 index 00000000000..108fa6a7a4f --- /dev/null +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java @@ -0,0 +1,40 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.boot; + +import org.spongepowered.bootstrap.forge.VanillaBootstrap; +import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; + +public class SpongeTestBoot { + + public static ClassLoader getGameClassLoader() throws Exception { + if (GameClassLoaderHolder.loader == null) { + final String[] args = System.getProperty("sponge.test.args").split(" "); + System.setProperty("sponge.test.active", "true"); + new VanillaBootstrap(args).devBoot(false); + } + return GameClassLoaderHolder.loader; + } +} diff --git a/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener b/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener new file mode 100644 index 00000000000..7eb5ad2f411 --- /dev/null +++ b/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener @@ -0,0 +1 @@ +org.spongepowered.vanilla.boot.SpongeSessionListener From f12b974f2fc900cb4be748f64b20b089efad93b4 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 21 Jul 2025 16:28:04 +0200 Subject: [PATCH 319/586] Shutdown test server when junit session is closing --- .../forge/boot/SpongeSessionListener.java | 2 + .../forge/boot/SpongeTestBoot.java | 6 +-- .../neoforge/boot/SpongeSessionListener.java | 2 + .../neoforge/boot/SpongeTestBoot.java | 6 +-- .../applaunch/test/TestGameAccess.java} | 44 ++++++++++++++++--- .../spongepowered/common/launch/Launch.java | 2 - .../server/MinecraftServerMixin_Test.java | 36 +++++++++++++-- .../BlockableEventLoopMixin_Tracker.java | 4 +- .../vanilla/boot/SpongeSessionListener.java | 2 + .../vanilla/boot/SpongeTestBoot.java | 6 +-- 10 files changed, 87 insertions(+), 23 deletions(-) rename src/{applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java => applaunchConfig/java/org/spongepowered/common/applaunch/test/TestGameAccess.java} (51%) diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java index c865f7a68ed..7e93cdd7301 100644 --- a/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java @@ -26,6 +26,7 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; +import org.spongepowered.common.applaunch.test.TestGameAccess; public class SpongeSessionListener implements LauncherSessionListener { private ClassLoader previousLoader; @@ -43,6 +44,7 @@ public void launcherSessionOpened(final LauncherSession session) { @Override public void launcherSessionClosed(final LauncherSession session) { + TestGameAccess.shutdownGame(); Thread.currentThread().setContextClassLoader(this.previousLoader); } } diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java index 7b0299df2cb..e02fdb51ded 100644 --- a/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeTestBoot.java @@ -25,16 +25,16 @@ package org.spongepowered.forge.boot; import org.spongepowered.bootstrap.forge.ForgeBootstrap; -import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; +import org.spongepowered.common.applaunch.test.TestGameAccess; public class SpongeTestBoot { public static ClassLoader getGameClassLoader() throws Exception { - if (GameClassLoaderHolder.loader == null) { + if (TestGameAccess.getGameClassLoader() == null) { final String[] args = System.getProperty("sponge.test.args").split(" "); System.setProperty("sponge.test.active", "true"); new ForgeBootstrap(args).devBoot(false); } - return GameClassLoaderHolder.loader; + return TestGameAccess.getGameClassLoader(); } } diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java index 07323da67b4..53916709244 100644 --- a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java @@ -26,6 +26,7 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; +import org.spongepowered.common.applaunch.test.TestGameAccess; public class SpongeSessionListener implements LauncherSessionListener { private ClassLoader previousLoader; @@ -43,6 +44,7 @@ public void launcherSessionOpened(final LauncherSession session) { @Override public void launcherSessionClosed(final LauncherSession session) { + TestGameAccess.shutdownGame(); Thread.currentThread().setContextClassLoader(this.previousLoader); } } diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java index e14bea8bbd4..416b5317e49 100644 --- a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java @@ -25,7 +25,7 @@ package org.spongepowered.neoforge.boot; import org.spongepowered.bootstrap.neoforge.NeoForgeBootstrap; -import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; +import org.spongepowered.common.applaunch.test.TestGameAccess; import java.nio.file.Files; import java.nio.file.Path; @@ -33,7 +33,7 @@ public class SpongeTestBoot { public static ClassLoader getGameClassLoader() throws Exception { - if (GameClassLoaderHolder.loader == null) { + if (TestGameAccess.getGameClassLoader() == null) { final Path argsFile = Path.of(System.getProperty("sponge.test.args").substring(1)); final String[] args = Files.lines(argsFile).map(String::trim).filter(line -> !line.startsWith("#") && !line.isEmpty()) .skip(1) // main class @@ -41,6 +41,6 @@ public static ClassLoader getGameClassLoader() throws Exception { System.setProperty("sponge.test.active", "true"); new NeoForgeBootstrap(args).devBoot(false); } - return GameClassLoaderHolder.loader; + return TestGameAccess.getGameClassLoader(); } } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java b/src/applaunchConfig/java/org/spongepowered/common/applaunch/test/TestGameAccess.java similarity index 51% rename from src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java rename to src/applaunchConfig/java/org/spongepowered/common/applaunch/test/TestGameAccess.java index e921b1ed3d7..20bfaad482b 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/test/GameClassLoaderHolder.java +++ b/src/applaunchConfig/java/org/spongepowered/common/applaunch/test/TestGameAccess.java @@ -24,14 +24,46 @@ */ package org.spongepowered.common.applaunch.test; -public class GameClassLoaderHolder { - public static ClassLoader loader; +import java.lang.reflect.Field; - public static void set(final ClassLoader loader) { +/** + * Caution: this class exists in multiple classloaders + */ +@SuppressWarnings("unused") +public class TestGameAccess { + private static Runnable shutdownGame; + + public static ClassLoader getGameClassLoader() { + return TestGameAccess.shutdownGame == null ? null : TestGameAccess.shutdownGame.getClass().getClassLoader(); + } + + public static void shutdownGame() { + try { + if (TestGameAccess.shutdownGame != null) { + TestGameAccess.shutdownGame.run(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void set(final String name, final Object value) { + final Class cl; + try { + cl = ClassLoader.getSystemClassLoader().loadClass(TestGameAccess.class.getName()); + } catch (final ClassNotFoundException e) { + return; + } try { - ClassLoader.getSystemClassLoader().loadClass(GameClassLoaderHolder.class.getName()).getField("loader").set(null, loader); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); + final Field field = cl.getDeclaredField(name); + field.setAccessible(true); + field.set(null, value); + } catch (final ReflectiveOperationException e) { + e.printStackTrace(); } } + + public static void setup(final Runnable shutdownGame) { + TestGameAccess.set("shutdownGame", shutdownGame); + } } diff --git a/src/launch/java/org/spongepowered/common/launch/Launch.java b/src/launch/java/org/spongepowered/common/launch/Launch.java index 169c8364cc4..ab1684504c3 100644 --- a/src/launch/java/org/spongepowered/common/launch/Launch.java +++ b/src/launch/java/org/spongepowered/common/launch/Launch.java @@ -32,7 +32,6 @@ import org.spongepowered.api.plugin.PluginManager; import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.common.applaunch.plugin.PluginPlatform; -import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; import org.spongepowered.common.launch.plugin.SpongePluginManager; import org.spongepowered.plugin.PluginContainer; @@ -68,7 +67,6 @@ public static void setInstance(final Launch instance) { } Launch.INSTANCE = Objects.requireNonNull(instance); - GameClassLoaderHolder.set(instance.getClass().getClassLoader()); } public final String id() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java index 12eac43294e..8d191bdfdd8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java @@ -25,18 +25,26 @@ package org.spongepowered.common.mixin.test.server; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.TickTask; +import net.minecraft.util.thread.ReentrantBlockableEventLoop; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.applaunch.test.TestGameAccess; import java.io.IOException; import java.util.function.Function; @Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin_Test { +public abstract class MinecraftServerMixin_Test extends ReentrantBlockableEventLoop { + + public MinecraftServerMixin_Test(String name) { + super(name); + } @Shadow protected abstract boolean initServer() throws IOException; @@ -50,6 +58,11 @@ public abstract class MinecraftServerMixin_Test { @Shadow public abstract void stopServer(); + @Inject(method = "", at = @At("RETURN")) + private void onInit(final CallbackInfo ci) { + TestGameAccess.setup(this::impl$stop); + } + /** * @author Yeregorix * @reason Stay on the same thread and do not tick the server. @@ -65,14 +78,29 @@ private static void spin(final Function suppl cir.setReturnValue(server); } + private void impl$stop() { + if (this.running) { + this.running = false; + this.stopped = true; + this.stopServer(); + } + } + /** * @author Yeregorix * @reason Stops the server instead of the loop. */ @Overwrite public void halt(final boolean join) { - this.running = false; - this.stopped = true; - this.stopServer(); + this.impl$stop(); + } + + /** + * @author Yeregorix + * @reason The server is not ticking. + */ + @Overwrite + public void waitUntilNextTick() { + this.runAllTasks(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java index 7484b626e8c..da8b8c93d59 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java @@ -31,7 +31,6 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.plugin.BasicPluginContext; import org.spongepowered.common.event.tracking.phase.plugin.PluginPhase; -import org.spongepowered.common.hooks.PlatformHooks; @Mixin(BlockableEventLoop.class) public abstract class BlockableEventLoopMixin_Tracker { @@ -43,7 +42,8 @@ public abstract class BlockableEventLoopMixin_Tracker { remap = false)) private void tracker$callOnMainThreadWithPhaseState(final Runnable runnable) { // This method can be called async while server is stopping - if (this.tracker$isServerAndIsServerStopped() && !PlatformHooks.INSTANCE.getGeneralHooks().onServerThread()) { + // TODO find why this cause a runaway phase during shutdown of the test server + if (this.tracker$isServerAndIsServerStopped()/* && !PlatformHooks.INSTANCE.getGeneralHooks().onServerThread() */) { runnable.run(); return; } diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java index b30074b2a1c..df8888cb032 100644 --- a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java @@ -26,6 +26,7 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; +import org.spongepowered.common.applaunch.test.TestGameAccess; public class SpongeSessionListener implements LauncherSessionListener { private ClassLoader previousLoader; @@ -43,6 +44,7 @@ public void launcherSessionOpened(final LauncherSession session) { @Override public void launcherSessionClosed(final LauncherSession session) { + TestGameAccess.shutdownGame(); Thread.currentThread().setContextClassLoader(this.previousLoader); } } diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java index 108fa6a7a4f..308264a6407 100644 --- a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeTestBoot.java @@ -25,16 +25,16 @@ package org.spongepowered.vanilla.boot; import org.spongepowered.bootstrap.forge.VanillaBootstrap; -import org.spongepowered.common.applaunch.test.GameClassLoaderHolder; +import org.spongepowered.common.applaunch.test.TestGameAccess; public class SpongeTestBoot { public static ClassLoader getGameClassLoader() throws Exception { - if (GameClassLoaderHolder.loader == null) { + if (TestGameAccess.getGameClassLoader() == null) { final String[] args = System.getProperty("sponge.test.args").split(" "); System.setProperty("sponge.test.active", "true"); new VanillaBootstrap(args).devBoot(false); } - return GameClassLoaderHolder.loader; + return TestGameAccess.getGameClassLoader(); } } From b3e90021610202a68617d4b58e4b14adefcd2a9f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 23 Jul 2025 11:37:07 +0200 Subject: [PATCH 320/586] Force test server properties --- .../dedicated/DedicatedServerMixin_Test.java | 17 ++++++++----- ...=> DedicatedServerSettingsMixin_Test.java} | 24 +++++++++++-------- src/mixins/resources/mixins.sponge.test.json | 2 +- 3 files changed, 26 insertions(+), 17 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/{SettingsMixin_Test.java => DedicatedServerSettingsMixin_Test.java} (62%) diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java index 24af936e95c..34ed5efd881 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerMixin_Test.java @@ -27,20 +27,25 @@ import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.network.ServerConnectionListener; import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import java.net.InetAddress; @Mixin(DedicatedServer.class) public class DedicatedServerMixin_Test { - @Shadow @Final static Logger LOGGER; - @Redirect(method = "initServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerConnectionListener;startTcpServerListener(Ljava/net/InetAddress;I)V")) - private void dontStartTcpServer(final ServerConnectionListener listener, final InetAddress address, final int port) { - DedicatedServerMixin_Test.LOGGER.info("[TEST] TCP server not started."); + @Redirect(method = "initServer", + at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;info(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V"), + slice = @Slice( + from = @At(value = "INVOKE", target = "net/minecraft/server/dedicated/DedicatedServer.initializeKeyPair()V"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerConnectionListener;startTcpServerListener(Ljava/net/InetAddress;I)V"))) + private void removeAddressInLog(final Logger logger, final String message, final Object arg1, final Object arg2) { + logger.info("Starting Minecraft test server"); } + + @Redirect(method = "initServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerConnectionListener;startTcpServerListener(Ljava/net/InetAddress;I)V")) + private void dontStartTcpServer(final ServerConnectionListener listener, final InetAddress address, final int port) {} } diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java similarity index 62% rename from src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java rename to src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java index 510deef81fa..47385cbc346 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/SettingsMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java @@ -24,21 +24,25 @@ */ package org.spongepowered.common.mixin.test.server.dedicated; -import net.minecraft.server.dedicated.Settings; -import org.slf4j.Logger; +import net.minecraft.server.dedicated.DedicatedServerProperties; +import net.minecraft.server.dedicated.DedicatedServerSettings; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.Properties; -@Mixin(Settings.class) -public class SettingsMixin_Test { +@Mixin(DedicatedServerSettings.class) +public class DedicatedServerSettingsMixin_Test { - @Redirect(method = "loadFromFile", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V")) - private static void onLoadFromFileError(final Logger logger, final String message, final Object path, final Object exception) { - if (!(exception instanceof NoSuchFileException)) { - logger.error(message, path, exception); - } + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/dedicated/DedicatedServerProperties;fromFile(Ljava/nio/file/Path;)Lnet/minecraft/server/dedicated/DedicatedServerProperties;")) + public DedicatedServerProperties forceTestProperties(final Path path) { + final Properties props = new Properties(); + props.setProperty("spawn-protection", "0"); + props.setProperty("level-seed", "0"); + props.setProperty("level-type", "flat"); + props.setProperty("enable-command-block", "true"); + return new DedicatedServerProperties(props); } } diff --git a/src/mixins/resources/mixins.sponge.test.json b/src/mixins/resources/mixins.sponge.test.json index d1d903f4dda..d05a9f81b2e 100644 --- a/src/mixins/resources/mixins.sponge.test.json +++ b/src/mixins/resources/mixins.sponge.test.json @@ -5,6 +5,6 @@ "mixins": [ "server.MinecraftServerMixin_Test", "server.dedicated.DedicatedServerMixin_Test", - "server.dedicated.SettingsMixin_Test" + "server.dedicated.DedicatedServerSettingsMixin_Test" ] } From 1752ed55aa457d7f85903731e30d081da4e042f0 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 23 Jul 2025 14:14:30 +0200 Subject: [PATCH 321/586] Run SpongeCommon tests in submodules --- build.gradle.kts | 3 ++- forge/build.gradle.kts | 12 +++++++++++- neoforge/build.gradle.kts | 12 +++++++++++- vanilla/build.gradle.kts | 12 +++++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index aa8d5c06871..bda3857402b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -437,7 +437,8 @@ tasks { } test { - useJUnitPlatform() + // tests can only be run in subprojects + enabled = false } check { diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 605cd138435..2e893adfe95 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -88,6 +88,7 @@ val commonAppLaunch = commonProject.sourceSets.named("applaunch") val commonAppLaunchConf = commonProject.sourceSets.named("applaunchConfig") val commonMixins = commonProject.sourceSets.named("mixins") val commonMain = commonProject.sourceSets.named("main") +val commonTest = commonProject.sourceSets.named("test") // SpongeForge source sets // Service layer @@ -166,7 +167,9 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } -sourceSets.named("test") { +val testSources = sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(commonTest.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) } @@ -226,6 +229,11 @@ dependencies { testImplementation(apiLibs.junit.params) testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) + + testImplementation(libs.mockito.core) + testImplementation(libs.mockito.junitJupiter) { + exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") + } } val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files @@ -416,6 +424,8 @@ tasks { test { useJUnitPlatform() + testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs + val runServer = minecraft.runs.getByName("server") jvmArgs(runServer.jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 01b44992e9c..a78cc276381 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -80,6 +80,7 @@ val commonAppLaunch = commonProject.sourceSets.named("applaunch") val commonAppLaunchConf = commonProject.sourceSets.named("applaunchConfig") val commonMixins = commonProject.sourceSets.named("mixins") val commonMain = commonProject.sourceSets.named("main") +val commonTest = commonProject.sourceSets.named("test") // SpongeNeo source sets // Service layer @@ -158,7 +159,9 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapNeoForge.get(), this) } -sourceSets.named("test") { +val testSources = sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(commonTest.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) spongeImpl.addDependencyToImplementation(bootstrapNeoForge.get(), this) } @@ -232,6 +235,11 @@ dependencies { testImplementation(apiLibs.junit.params) testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) + + testImplementation(libs.mockito.core) + testImplementation(libs.mockito.junitJupiter) { + exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") + } } afterEvaluate { @@ -392,6 +400,8 @@ tasks { test { useJUnitPlatform() + testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs + jvmArgs(runServer.get().jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.get().args!!.joinToString(" ")) workingDir = layout.buildDirectory.dir("test-run").get().asFile diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index f0a129baa74..4f5a36bca04 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -56,6 +56,7 @@ val commonAppLaunch = commonProject.sourceSets.named("applaunch") val commonAppLaunchConf = commonProject.sourceSets.named("applaunchConfig") val commonMixins = commonProject.sourceSets.named("mixins") val commonMain = commonProject.sourceSets.named("main") +val commonTest = commonProject.sourceSets.named("test") // SpongeVanilla source sets // Prod launch @@ -138,7 +139,9 @@ val main by sourceSets.named("main") { spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) spongeImpl.addDependencyToRuntimeOnly(bootstrapForge.get(), this) } -sourceSets.named("test") { +val testSources = sourceSets.named("test") { + spongeImpl.addDependencyToImplementation(commonTest.get(), this) + spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) } @@ -256,6 +259,11 @@ dependencies { testImplementation(apiLibs.junit.params) testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) + + testImplementation(libs.mockito.core) + testImplementation(libs.mockito.junitJupiter) { + exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") + } } minecraft { @@ -494,6 +502,8 @@ tasks { test { useJUnitPlatform() + testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs + val runServer = minecraft.runs.server().get() jvmArgs(runServer.allJvmArguments()) jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) From d72cdbd720cdc60a71697ee2296fa2b208ad8a9e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 23 Jul 2025 14:14:42 +0200 Subject: [PATCH 322/586] Update existing unit tests --- .../persistence/ConfigurateDataViewTest.java | 20 +- .../common/data/persistence/SimpleData.java | 34 +-- .../tracking/BlockChangeFlagManagerTest.java | 4 +- .../GameTransactionIteratorTest.java | 12 +- .../context/transaction/StubEvent.java | 6 +- .../server/permission/NodeTreeTest.java | 6 +- .../server/permission/package-info.java | 26 --- .../common/test/TestEventManager.java | 12 -- .../spongepowered/common/test/TestLaunch.java | 64 ------ .../common/test/TestPluginPlatform.java | 95 --------- .../common/test/UnitTestExtension.java | 46 ---- .../common/test/block/SpongeBlock.java | 34 --- .../event/EventManagerRegistrationTest.java | 7 +- .../common/test/stub/StubGame.java | 135 ------------ .../common/test/stub/StubKey.java | 72 ------- .../common/test/stub/StubModule.java | 40 ---- .../common/test/stub/block/StubBlock.java | 139 ------------ .../common/test/stub/block/StubState.java | 197 ------------------ .../common/test/stub/block/package-info.java | 29 --- .../common/test/stub/package-info.java | 29 --- .../stub/registry/StubRegistryFactory.java | 47 ----- .../stub/registry/StubRegistryHolder.java | 71 ------- .../test/stub/registry/StubbedRegistry.java | 149 ------------- .../test/stub/registry/package-info.java | 29 --- .../common/test/stub/util/StubMirror.java | 42 ---- .../common/test/stub/util/StubRotations.java | 92 -------- .../common/test/stub/util/package-info.java | 29 --- .../schematic/StubBlockStatePaletteType.java | 46 ---- .../stub/world/schematic/StubPaletteType.java | 53 ----- .../stub/world/schematic/package-info.java | 29 --- .../common/util/ReflectionTest.java | 37 ---- .../common/util/TypeTokenUtilTest.java | 1 - .../VolumeTransformationTest.java | 185 ++++------------ 33 files changed, 64 insertions(+), 1753 deletions(-) delete mode 100644 src/test/java/org/spongepowered/common/service/server/permission/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/test/TestLaunch.java delete mode 100644 src/test/java/org/spongepowered/common/test/TestPluginPlatform.java delete mode 100644 src/test/java/org/spongepowered/common/test/UnitTestExtension.java delete mode 100644 src/test/java/org/spongepowered/common/test/block/SpongeBlock.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/StubGame.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/StubKey.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/StubModule.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/block/StubState.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/block/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryFactory.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/registry/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/util/StubMirror.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/util/StubRotations.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/util/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/world/schematic/StubBlockStatePaletteType.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/world/schematic/StubPaletteType.java delete mode 100644 src/test/java/org/spongepowered/common/test/stub/world/schematic/package-info.java delete mode 100644 src/test/java/org/spongepowered/common/util/ReflectionTest.java diff --git a/src/test/java/org/spongepowered/common/data/persistence/ConfigurateDataViewTest.java b/src/test/java/org/spongepowered/common/data/persistence/ConfigurateDataViewTest.java index 98eb9c236fd..a6d461e3847 100644 --- a/src/test/java/org/spongepowered/common/data/persistence/ConfigurateDataViewTest.java +++ b/src/test/java/org/spongepowered/common/data/persistence/ConfigurateDataViewTest.java @@ -30,7 +30,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Lists; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.persistence.DataContainer; @@ -54,7 +53,6 @@ import java.util.List; import java.util.Map; -@Disabled("Can't run these tests without access to a ResourceKey implementation") public class ConfigurateDataViewTest { private static final HoconDataFormat HOCON = new HoconDataFormat(); @@ -71,7 +69,7 @@ void testNodeToData() { node.node("foo", "stringList").raw(stringList); final List dataList = new ArrayList<>(); for (int i = 0; i < 100; i++) { - dataList.add(new SimpleData(i, 10.0 + i, "String" + i, Collections.emptyList())); + dataList.add(new SimpleData(i, 10.0 + i, "String" + i, new String[0])); } node.node("foo", "nested", "Data").raw(dataList); @@ -141,7 +139,7 @@ void testFireworkEffectData() throws IOException { } @Test - void testRespawnLocationData() throws IOException { + void testRespawnLocationData() { final Map m = new HashMap<>(); for (int i = 0; i < 5; i++) { final ResourceKey key = ResourceKey.sponge("overworld" + i); @@ -159,7 +157,7 @@ void testRespawnLocationData() throws IOException { } @Test - void testNumber() throws IOException { + void testNumber() { final DataContainer container = DataContainer.createNew().set(DataQuery.of("double"), 1.0); final ConfigurationNode node = ConfigurateTranslator.instance().translate(container); @@ -193,18 +191,6 @@ void testNullRootKey() { ConfigurateTranslator.instance().translate(BasicConfigurationNode.root().raw("bar"))); } - @Test - void testNullMapKey() { - final ConfigurationNode node = CommentedConfigurationNode.root(); - final Map map = Collections.singletonMap(null, "v"); - final List list = Arrays.asList("e", map); - - node.node("foo").raw("bar"); - node.node("l").raw(list); - - assertThrows(IllegalArgumentException.class, () -> ConfigurateTranslator.instance().translate(node)); - } - @Test void testNonRootNodeToData() { final ConfigurationNode root = CommentedConfigurationNode.root(n -> { diff --git a/src/test/java/org/spongepowered/common/data/persistence/SimpleData.java b/src/test/java/org/spongepowered/common/data/persistence/SimpleData.java index dcfc57fcb0c..4f71b5fdb27 100644 --- a/src/test/java/org/spongepowered/common/data/persistence/SimpleData.java +++ b/src/test/java/org/spongepowered/common/data/persistence/SimpleData.java @@ -24,44 +24,14 @@ */ package org.spongepowered.common.data.persistence; -import com.google.common.collect.ImmutableList; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.data.persistence.DataSerializable; import java.util.Arrays; -import java.util.List; import java.util.Objects; -final class SimpleData implements DataSerializable { - - private final int testInt; - private final double testDouble; - private final String testString; - private final String[] testList; - - SimpleData(final int testInt, final double testDouble, final String testString, final List testList) { - this.testInt = testInt; - this.testDouble = testDouble; - this.testString = testString; - this.testList = testList.toArray(new String[testList.size()]); - } - - public int getTestInt() { - return this.testInt; - } - - public double getTestDouble() { - return this.testDouble; - } - - public String getTestString() { - return this.testString; - } - - public List getTestList() { - return ImmutableList.copyOf(this.testList); - } +public record SimpleData(int testInt, double testDouble, String testString, String[] testList) implements DataSerializable { @Override public int contentVersion() { @@ -80,7 +50,7 @@ public DataContainer toContainer() { @Override public int hashCode() { - return Objects.hash(this.testInt, this.testDouble, this.testString, this.testList); + return Objects.hash(this.testInt, this.testDouble, this.testString, Arrays.hashCode(this.testList)); } @Override diff --git a/src/test/java/org/spongepowered/common/event/tracking/BlockChangeFlagManagerTest.java b/src/test/java/org/spongepowered/common/event/tracking/BlockChangeFlagManagerTest.java index b2dcc241e94..68d1fce545a 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/BlockChangeFlagManagerTest.java +++ b/src/test/java/org/spongepowered/common/event/tracking/BlockChangeFlagManagerTest.java @@ -34,7 +34,7 @@ import org.spongepowered.common.util.Constants; import org.spongepowered.common.world.SpongeBlockChangeFlag; -class BlockChangeFlagManagerTest { +public class BlockChangeFlagManagerTest { @BeforeAll public static void setupBlockChangeFlagManager() { @@ -280,7 +280,7 @@ void verifyNestedNeighborPhysics() { final SpongeBlockChangeFlag flag = BlockChangeFlagManagerTest.createDefaultFlag(); assertTrue(flag.updateNeighboringShapes()); // 16 assertTrue(flag.getRawFlag() != 0); - assertEquals((flag.getRawFlag() & 32), 0); + assertEquals(0, (flag.getRawFlag() & 32)); assertTrue(flag.neighborDropsAllowed()); final SpongeBlockChangeFlag nestedNeighbor = flag.asNestedNeighborUpdates(); assertFalse(nestedNeighbor.updateNeighbors()); diff --git a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java index 385ea7cd738..25c47a6ad0e 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java +++ b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java @@ -28,7 +28,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -36,14 +35,11 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.StubPhaseState; import org.spongepowered.common.event.tracking.context.transaction.effect.InventoryEffect; -import org.spongepowered.common.test.UnitTestExtension; import java.util.Iterator; import java.util.stream.Stream; @Disabled -@SuppressWarnings("deprecation") -@ExtendWith(UnitTestExtension.class) public class GameTransactionIteratorTest { @Test @@ -56,7 +52,7 @@ public void verifyIterator() { @Test public void verifyNestedIterator() { final StubTransaction stubTransaction = new StubTransaction(); - final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect( + final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( InventoryEffect.getInstance()); stubTransaction.addLast(effect); final StubTransaction child1 = new StubTransaction(); @@ -83,7 +79,7 @@ public void verifyDeeplyNestedIterator(final int effectCount, final int childCou final PhaseContext<@NonNull ?> phaseContext = StubPhaseState.getInstance().createPhaseContext(PhaseTracker.getInstance()); phaseContext.buildAndSwitch(); for (int i = 0; i < effectCount; i++) { - final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect( + final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( InventoryEffect.getInstance()); parent.addLast(effect); for (int j = 0; j < childCount; j++) { @@ -120,6 +116,8 @@ private static Stream validateTransactionalIterator() { Arguments.of(293, 87, 112) ); } + + @SuppressWarnings("deprecation") @ParameterizedTest @MethodSource(value = "validateTransactionalIterator") public void validateTransactionalIterator(final int transactionCount, final int effectCount, final int childCount) { @@ -134,7 +132,7 @@ public void validateTransactionalIterator(final int transactionCount, final int transactions[t] = transaction; transactor.logTransaction(transaction); for (int i = 0; i < effectCount; i++) { - final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect( + final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( InventoryEffect.getInstance()); try (final EffectTransactor ignored = transactor.pushEffect(effect)) { for (int j = 0; j < childCount; j++) { diff --git a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/StubEvent.java b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/StubEvent.java index 57224c7ad40..2c668dcafcf 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/StubEvent.java +++ b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/StubEvent.java @@ -26,13 +26,13 @@ import org.spongepowered.api.event.Cancellable; import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.Event; import org.spongepowered.api.event.EventContext; +import org.spongepowered.api.event.impl.AbstractEvent; import java.util.Collections; -class StubEvent implements Event, Cancellable { - boolean cancelled = false; +public class StubEvent extends AbstractEvent implements Cancellable { + private boolean cancelled = false; @Override public boolean isCancelled() { diff --git a/src/test/java/org/spongepowered/common/service/server/permission/NodeTreeTest.java b/src/test/java/org/spongepowered/common/service/server/permission/NodeTreeTest.java index 12b8fe6342d..4f1d7253c35 100644 --- a/src/test/java/org/spongepowered/common/service/server/permission/NodeTreeTest.java +++ b/src/test/java/org/spongepowered/common/service/server/permission/NodeTreeTest.java @@ -51,7 +51,7 @@ public void testAsMap() { } @Test - public void testWithValue() throws Exception { + public void testWithValue() { final Map testPermissions = new HashMap<>(); testPermissions.put("generate.rainbow", true); testPermissions.put("generate.sunset", false); @@ -66,7 +66,7 @@ public void testWithValue() throws Exception { } @Test - public void testWithAll() throws Exception { + public void testWithAll() { final Map testPermissions = new HashMap<>(); testPermissions.put("generate.rainbow", true); testPermissions.put("generate.sunset", false); @@ -93,7 +93,7 @@ public void testWithAll() throws Exception { } @Test - public void testCreateFromValues() throws Exception { + public void testCreateFromValues() { final Map testPermissions = new HashMap<>(); testPermissions.put("generate.rainbow", true); testPermissions.put("generate.sunset", false); diff --git a/src/test/java/org/spongepowered/common/service/server/permission/package-info.java b/src/test/java/org/spongepowered/common/service/server/permission/package-info.java deleted file mode 100644 index 19060966f56..00000000000 --- a/src/test/java/org/spongepowered/common/service/server/permission/package-info.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@org.checkerframework.framework.qual.DefaultQualifier(org.checkerframework.checker.nullness.qual.NonNull.class) -package org.spongepowered.common.service.server.permission; diff --git a/src/test/java/org/spongepowered/common/test/TestEventManager.java b/src/test/java/org/spongepowered/common/test/TestEventManager.java index 94a37a48fae..7ba12eaca53 100644 --- a/src/test/java/org/spongepowered/common/test/TestEventManager.java +++ b/src/test/java/org/spongepowered/common/test/TestEventManager.java @@ -24,19 +24,7 @@ */ package org.spongepowered.common.test; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.manager.SpongeEventManager; -import org.spongepowered.common.util.DefinableClassLoader; public class TestEventManager extends SpongeEventManager { - - private final @Nullable DefinableClassLoader loader; - - public TestEventManager(final DefinableClassLoader loader) { - this.loader = loader; - } - - public TestEventManager() { - this.loader = null; - } } diff --git a/src/test/java/org/spongepowered/common/test/TestLaunch.java b/src/test/java/org/spongepowered/common/test/TestLaunch.java deleted file mode 100644 index 365f3f774cc..00000000000 --- a/src/test/java/org/spongepowered/common/test/TestLaunch.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import com.google.inject.Injector; -import com.google.inject.Stage; -import org.spongepowered.common.applaunch.plugin.PluginPlatform; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.launch.plugin.SpongePluginManager; -import org.spongepowered.plugin.PluginContainer; - -public class TestLaunch extends Launch { - - protected TestLaunch(final PluginPlatform pluginPlatform) { - super(pluginPlatform); - } - - @Override - public boolean dedicatedServer() { - return false; - } - - @Override - public SpongePluginManager pluginManager() { - return null; - } - - @Override - public Stage injectionStage() { - return null; - } - - @Override - public PluginContainer platformPlugin() { - return null; - } - - @Override - public Injector createInjector() { - return null; - } -} diff --git a/src/test/java/org/spongepowered/common/test/TestPluginPlatform.java b/src/test/java/org/spongepowered/common/test/TestPluginPlatform.java deleted file mode 100644 index 922e8e4a7e4..00000000000 --- a/src/test/java/org/spongepowered/common/test/TestPluginPlatform.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.common.applaunch.config.LaunchConfig; -import org.spongepowered.common.applaunch.config.TokenReplacement; -import org.spongepowered.common.applaunch.plugin.PluginPlatform; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collections; -import java.util.List; - -/** - * The absolute minimum required to have a plugin platform to function - * with regard to SpongeCommon's configurations being usable. Required - * to be used if the {@link org.spongepowered.common.event.tracking.PhaseTracker} - * is being utilized since the configurations are being checked. - */ -public class TestPluginPlatform implements PluginPlatform { - - private static final Logger LOGGER = LogManager.getLogger("UnitTestPlatform"); - - private final Path baseDirectory; - private final Path pluginsDirectory; - - public TestPluginPlatform() { - this.baseDirectory = Paths.get("."); - this.pluginsDirectory = this.baseDirectory.resolve("plugins"); - } - - @Override - public String version() { - return "unit-test"; - } - - @Override - public Logger logger() { - return TestPluginPlatform.LOGGER; - } - - @Override - public boolean vanilla() { - return true; - } - - @Override - public Path baseDirectory() { - return this.baseDirectory; - } - - @Override - public Path configDirectory() { - return this.baseDirectory.resolve("config"); - } - - @Override - public LaunchConfig config() { - return LaunchConfig.DEFAULT; - } - - @Override - public TokenReplacement tokens() { - return new TokenReplacement(); - } - - @Override - public List pluginDirectories() { - return Collections.singletonList(this.pluginsDirectory); - } -} diff --git a/src/test/java/org/spongepowered/common/test/UnitTestExtension.java b/src/test/java/org/spongepowered/common/test/UnitTestExtension.java deleted file mode 100644 index 58c31d5db42..00000000000 --- a/src/test/java/org/spongepowered/common/test/UnitTestExtension.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import net.minecraft.DetectedVersion; -import net.minecraft.SharedConstants; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.launch.config.core.SpongeConfigs; - -public class UnitTestExtension implements BeforeAllCallback { - @Override - public void beforeAll(final ExtensionContext context) throws Exception { - final TestPluginPlatform platform = new TestPluginPlatform(); - if (AppLaunch.pluginPlatform() == null) { - AppLaunch.setPluginPlatform(platform); - Launch.setInstance(new TestLaunch(platform)); - SpongeConfigs.getCommon(); - SharedConstants.setVersion(DetectedVersion.tryDetectVersion()); - } - } -} diff --git a/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java b/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java deleted file mode 100644 index 3fbae6a0c5f..00000000000 --- a/src/test/java/org/spongepowered/common/test/block/SpongeBlock.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.block; - -import net.minecraft.world.level.block.Block; - -public class SpongeBlock extends Block { - public SpongeBlock(Properties param0) { - super(param0); - } - -} diff --git a/src/test/java/org/spongepowered/common/test/event/EventManagerRegistrationTest.java b/src/test/java/org/spongepowered/common/test/event/EventManagerRegistrationTest.java index afe094ba1a4..c920b2173ed 100644 --- a/src/test/java/org/spongepowered/common/test/event/EventManagerRegistrationTest.java +++ b/src/test/java/org/spongepowered/common/test/event/EventManagerRegistrationTest.java @@ -24,9 +24,7 @@ */ package org.spongepowered.common.test.event; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; @@ -46,14 +44,11 @@ import org.spongepowered.api.event.lifecycle.StoppedGameEvent; import org.spongepowered.api.service.economy.EconomyService; import org.spongepowered.common.test.TestEventManager; -import org.spongepowered.common.test.UnitTestExtension; import org.spongepowered.common.util.DefinableClassLoader; import org.spongepowered.plugin.PluginContainer; import java.lang.reflect.InvocationTargetException; -@Disabled -@ExtendWith(UnitTestExtension.class) public class EventManagerRegistrationTest { @Test @@ -77,7 +72,7 @@ public void successfulRegistrationWithAsmDefinedClass() throws InstantiationException, IllegalAccessException { final var loader = new DefinableClassLoader(Thread.currentThread().getContextClassLoader()); - final EventManager eventManager = new TestEventManager(loader); + final EventManager eventManager = new TestEventManager(); final PluginContainer mock = Mockito.mock(PluginContainer.class); final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); writer.visit( diff --git a/src/test/java/org/spongepowered/common/test/stub/StubGame.java b/src/test/java/org/spongepowered/common/test/stub/StubGame.java deleted file mode 100644 index 504500fdc8f..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/StubGame.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.Game; -import org.spongepowered.api.Platform; -import org.spongepowered.api.Server; -import org.spongepowered.api.SystemSubject; -import org.spongepowered.api.config.ConfigManager; -import org.spongepowered.api.data.DataManager; -import org.spongepowered.api.event.EventManager; -import org.spongepowered.api.network.channel.ChannelManager; -import org.spongepowered.api.plugin.PluginManager; -import org.spongepowered.api.scheduler.Scheduler; -import org.spongepowered.api.service.ServiceProvider; -import org.spongepowered.api.util.metric.MetricsConfigManager; -import org.spongepowered.common.registry.SpongeBuilderProvider; -import org.spongepowered.common.registry.SpongeFactoryProvider; -import org.spongepowered.common.test.stub.registry.StubRegistryHolder; - -import java.nio.file.Path; -import java.util.Locale; - -import javax.inject.Singleton; - -@Singleton -public class StubGame extends StubRegistryHolder implements Game { - - private final SpongeFactoryProvider provider = new SpongeFactoryProvider(); - private final SpongeBuilderProvider builder = new SpongeBuilderProvider(); - - @Override - public Scheduler asyncScheduler() { - return null; - } - - @Override - public Path gameDirectory() { - return null; - } - - @Override - public boolean isServerAvailable() { - return false; - } - - @Override - public Server server() { - return null; - } - - @Override - public SystemSubject systemSubject() { - return null; - } - - @Override - public Locale locale(@NonNull String locale) { - return null; - } - - @Override - public Platform platform() { - return null; - } - - @Override - public SpongeBuilderProvider builderProvider() { - return this.builder; - } - - @Override - public SpongeFactoryProvider factoryProvider() { - return this.provider; - } - - @Override - public DataManager dataManager() { - return null; - } - - @Override - public PluginManager pluginManager() { - return null; - } - - @Override - public EventManager eventManager() { - return null; - } - - @Override - public ConfigManager configManager() { - return null; - } - - @Override - public ChannelManager channelManager() { - return null; - } - - @Override - public MetricsConfigManager metricsConfigManager() { - return null; - } - - @Override - public ServiceProvider.GameScoped serviceProvider() { - return null; - } - -} diff --git a/src/test/java/org/spongepowered/common/test/stub/StubKey.java b/src/test/java/org/spongepowered/common/test/stub/StubKey.java deleted file mode 100644 index c67fd9206e5..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/StubKey.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.ResourceKey; - -import java.util.Objects; - -public final class StubKey implements ResourceKey { - public final String namespace; - public final String key; - - public StubKey(final String namespace, final String key) { - this.namespace = namespace; - this.key = key; - } - - @Override - public @NonNull String namespace() { - return this.namespace; - } - - @Override - public @NonNull String value() { - return this.key; - } - - @Override - public String toString() { - return this.asString(); - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || this.getClass() != o.getClass()) { - return false; - } - final StubKey stubKey = (StubKey) o; - return this.namespace.equals(stubKey.namespace) && this.key.equals(stubKey.key); - } - - @Override - public int hashCode() { - return Objects.hash(this.namespace, this.key); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/StubModule.java b/src/test/java/org/spongepowered/common/test/stub/StubModule.java deleted file mode 100644 index 2cee5e30330..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/StubModule.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub; - -import com.google.inject.AbstractModule; -import org.spongepowered.api.Game; -import org.spongepowered.api.Sponge; - -public class StubModule extends AbstractModule { - - @Override - protected void configure() { - this.bind(Game.class).to(StubGame.class); - - this.requestStaticInjection(Sponge.class); - - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java b/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java deleted file mode 100644 index e376dd32df5..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/block/StubBlock.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.block; - -import com.google.common.collect.ImmutableList; -import net.kyori.adventure.text.Component; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.block.BlockSoundGroup; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.registry.DefaultedRegistryType; -import org.spongepowered.api.state.StateProperty; -import org.spongepowered.api.tag.Tag; -import org.spongepowered.common.data.holder.SpongeImmutableDataHolder; -import org.spongepowered.math.vector.Vector3i; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Stream; - -public class StubBlock implements SpongeImmutableDataHolder, BlockType { - - private static final Vector3i INVALID_STUB_POSITION = Vector3i.from( - Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); - private final BlockState air; - public final Vector3i deducedPos; - public StubBlock(final ResourceKey key) { - final Vector3i deducedPos; - final String value = key.value(); - if (value.startsWith("volumetest")) { - final String replace = value.replace("volumetest{", "") - .replace("}", ""); - final String[] split = replace.split(","); - if (split.length == 3) { - final int x = Integer.parseInt(split[0].replace(" ", "")); - final int y = Integer.parseInt(split[1].replace(" ", "")); - final int z = Integer.parseInt(split[2].replace(" ", "")); - deducedPos = new Vector3i(x, y, z); - } else { - deducedPos = StubBlock.INVALID_STUB_POSITION; - } - } else { - deducedPos = StubBlock.INVALID_STUB_POSITION; - } - this.air = new StubState(this, key, deducedPos); - this.deducedPos = deducedPos; - } - - @Override - public Optional item() { - return Optional.empty(); - } - - @Override - public boolean doesUpdateRandomly() { - return false; - } - - @Override - public void setUpdateRandomly(final boolean updateRandomly) { - - } - - @Override - public BlockSoundGroup soundGroup() { - return null; - } - - @Override - public boolean isAnyOf(final Supplier... types) { - return false; - } - - @Override - public boolean isAnyOf(final BlockType... types) { - return false; - } - - @Override - public boolean hasBlockEntity() { - return false; - } - - @Override - public @NonNull Component asComponent() { - return null; - } - - @Override - public ImmutableList validStates() { - return ImmutableList.of(this.air); - } - - @Override - public BlockState defaultState() { - return this.air; - } - - @Override - public Collection> stateProperties() { - return Collections.emptyList(); - } - - @Override - public Optional> findStateProperty(final String name) { - return Optional.empty(); - } - - @Override - public Stream> tags(DefaultedRegistryType registryType) { - return Stream.empty(); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/block/StubState.java b/src/test/java/org/spongepowered/common/test/stub/block/StubState.java deleted file mode 100644 index 70902f9bff4..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/block/StubState.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.block; - -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.block.BlockSnapshot; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataView; -import org.spongepowered.api.data.persistence.InvalidDataException; -import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.fluid.FluidState; -import org.spongepowered.api.state.StateProperty; -import org.spongepowered.api.util.Cycleable; -import org.spongepowered.api.util.Direction; -import org.spongepowered.api.util.mirror.Mirror; -import org.spongepowered.api.util.rotation.Rotation; -import org.spongepowered.api.world.server.ServerLocation; -import org.spongepowered.common.data.holder.SpongeImmutableDataHolder; -import org.spongepowered.math.vector.Vector3i; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.StringJoiner; - -public final class StubState implements BlockState, SpongeImmutableDataHolder { - - private final BlockType mocked; - public final ResourceKey key; - public final Vector3i deducedPos; - - public StubState(final BlockType mocked, final ResourceKey key, final Vector3i deducedPos) { - this.mocked = mocked; - this.key = key; - this.deducedPos = deducedPos; - } - - @Override - public BlockType type() { - return this.type(); - } - - @Override - public FluidState fluidState() { - return null; - } - - @Override - public BlockSnapshot snapshotFor(final ServerLocation location) { - return null; - } - - @Override - public BlockState rotate(final Rotation rotation) { - return this; - } - - @Override - public BlockState mirror(final Mirror mirror) { - return this; - } - - @Override - public String asString() { - return null; - } - - @Override - public Optional get( - final Direction direction, final Key> key - ) { - return Optional.empty(); - } - - @Override - public boolean validateRawData(final DataView container) { - return false; - } - - @Override - public BlockState withRawData(final DataView container) throws InvalidDataException { - return this; - } - - @Override - public BlockState copy() { - return this; - } - - @Override - public int contentVersion() { - return 0; - } - - @Override - public DataContainer toContainer() { - return null; - } - - @Override - public > Optional stateProperty(final StateProperty stateProperty) { - return Optional.empty(); - } - - @Override - public Optional> findStateProperty(final String name) { - return Optional.empty(); - } - - @Override - public , V extends T> Optional withStateProperty( - final StateProperty stateProperty, final V value - ) { - return Optional.empty(); - } - - @Override - public > Optional cycleStateProperty( - final StateProperty stateProperty - ) { - return Optional.empty(); - } - - @Override - public > Optional cycleValue( - final Key> key - ) { - return Optional.empty(); - } - - @Override - public Collection> stateProperties() { - return Collections.emptySet(); - } - - @Override - public Collection statePropertyValues() { - return Collections.emptySet(); - } - - @Override - public Map, ?> statePropertyMap() { - return Collections.emptyMap(); - } - - @Override - public String toString() { - return new StringJoiner(", ", StubState.class.getSimpleName() + "[", "]") - .add("mocked=" + this.mocked) - .add("key=" + this.key) - .toString(); - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || this.getClass() != o.getClass()) { - return false; - } - final StubState stubState = (StubState) o; - return this.mocked.equals(stubState.mocked) && this.key.equals(stubState.key); - } - - @Override - public int hashCode() { - return Objects.hash(this.mocked, this.key); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/block/package-info.java b/src/test/java/org/spongepowered/common/test/stub/block/package-info.java deleted file mode 100644 index 652738343db..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/block/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@DefaultQualifier(NonNull.class) -package org.spongepowered.common.test.stub.block; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; diff --git a/src/test/java/org/spongepowered/common/test/stub/package-info.java b/src/test/java/org/spongepowered/common/test/stub/package-info.java deleted file mode 100644 index c4df1f35dfa..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@DefaultQualifier(NonNull.class) -package org.spongepowered.common.test.stub; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryFactory.java b/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryFactory.java deleted file mode 100644 index 8c2a5f26616..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.registry; - -import org.spongepowered.api.ResourceKey; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.plugin.PluginContainer; - -public class StubRegistryFactory implements ResourceKey.Factory{ - - @Override - public ResourceKey of(final String namespace, final String value) { - return new StubKey(namespace, value); - } - - @Override - public ResourceKey of(final PluginContainer plugin, final String value) { - return new StubKey(plugin.metadata().id(), value); - } - - @Override - public ResourceKey resolve(final String formatted) { - return new StubKey(formatted.split(":")[0], formatted.split(":")[1]); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java b/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java deleted file mode 100644 index 86433b2234d..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/registry/StubRegistryHolder.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.registry; - -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.api.registry.RegistryType; - -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.stream.Stream; - -public class StubRegistryHolder implements RegistryHolder { - - private final Collection> registries = new ConcurrentLinkedDeque<>(); - - public void register(final StubbedRegistry registry) { - this.registries.add(registry); - } - - @SuppressWarnings("unchecked") - @Override - public Registry registry(final RegistryType type) { - return this.registries.stream().filter(r -> r.type() == type).findFirst() - .map(r -> (Registry) r) - .orElseThrow(() -> new IllegalStateException("Registry for type not available:" + type.toString())); - } - - @SuppressWarnings("unchecked") - @Override - public Optional> findRegistry( - final RegistryType type - ) { - return this.registries.stream().filter(r -> r.type() == type).findFirst() - .map(r -> (Registry) r); - } - - @Override - public Stream> streamRegistries() { - return Stream.empty(); - } - - @Override - public Stream> streamRegistries(final ResourceKey root) { - return Stream.of(); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java b/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java deleted file mode 100644 index 59651a29340..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/registry/StubbedRegistry.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.registry; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.api.registry.RegistryEntry; -import org.spongepowered.api.registry.RegistryType; -import org.spongepowered.api.tag.Tag; -import org.spongepowered.common.registry.SpongeRegistryEntry; -import org.spongepowered.common.test.stub.StubKey; - -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; - -public class StubbedRegistry implements Registry { - - private final BiMap stubs = HashBiMap.create(); - private final BiMap> entries = HashBiMap.create(); - private final Supplier> typeSupplier; - private final Function generator; - - public StubbedRegistry(final Supplier> typeSupplier, final Function generator) { - this.typeSupplier = typeSupplier; - this.generator = generator; - } - - public T createEntry(final String namespace, final String desired) { - final ResourceKey key = new StubKey(namespace, desired); - return this.getOrCreate(key); - } - - @Override - public RegistryType type() { - return this.typeSupplier.get(); - } - - @Override - public ResourceKey valueKey(final T value) { - return this.findValueKey(value).orElseThrow(() -> new IllegalArgumentException("Could not find key for value: " + value)); - } - - @Override - public Optional findValueKey(final T value) { - final ResourceKey resourceKey = this.stubs.inverse().get(value); - return Optional.ofNullable(resourceKey); - } - - @SuppressWarnings("unchecked") - @Override - public Optional> findEntry( - final ResourceKey key - ) { - final RegistryEntry entry = this.entries.computeIfAbsent(key, (k) -> { - final T stub = this.getOrCreate(k); - return new SpongeRegistryEntry<>(this.type(), k, stub); - }); - return Optional.of((RegistryEntry) entry); - } - - private T getOrCreate(final ResourceKey key) { - if (this.stubs.containsKey(key)) { - return this.stubs.get(key); - } - // otherwise, set up the blocks - final T type = this.generator.apply(key); - this.stubs.put(key, type); - this.entries.put(key, new SpongeRegistryEntry<>(this.type(), key, type)); - return type; - } - - @SuppressWarnings("unchecked") - @Override - public Optional findValue(final ResourceKey key) { - - return Optional.of((V) this.getOrCreate(key)); - } - - @SuppressWarnings("unchecked") - @Override - public V value(final ResourceKey key) { - return (V) this.getOrCreate(key); - } - - @Override - public Stream taggedValues(final Tag tag) { - return Stream.empty(); - } - - @Override - public Stream> tags() { - return Stream.empty(); - } - - @Override - public Stream> streamEntries() { - return this.entries.values().stream(); - } - - @Override - public Stream stream() { - return this.stubs.values().stream(); - } - - @Override - public boolean isDynamic() { - return false; - } - - @SuppressWarnings("unchecked") - @Override - public Optional> register(final ResourceKey key, final V value) { - final RegistryEntry entry; - if (!this.entries.containsKey(key)) { - entry = new SpongeRegistryEntry<>(this.type(), key, value); - this.entries.put(key, entry); - this.stubs.put(key, value); - } else { - entry = this.entries.get(key); - } - return Optional.of((RegistryEntry) entry); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/registry/package-info.java b/src/test/java/org/spongepowered/common/test/stub/registry/package-info.java deleted file mode 100644 index d1822b80116..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/registry/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@DefaultQualifier(NonNull.class) -package org.spongepowered.common.test.stub.registry; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; diff --git a/src/test/java/org/spongepowered/common/test/stub/util/StubMirror.java b/src/test/java/org/spongepowered/common/test/stub/util/StubMirror.java deleted file mode 100644 index 9e022af2715..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/util/StubMirror.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.util; - -import org.spongepowered.api.util.mirror.Mirror; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.common.test.stub.registry.StubbedRegistry; - -public enum StubMirror implements Mirror { - NONE, - LEFT_RIGHT, - FRONT_BACK; - - public static void registerDefaults(final StubbedRegistry registry) { - registry.register(new StubKey("sponge", "none"), StubMirror.NONE); - registry.register(new StubKey("sponge", "left_right"), StubMirror.LEFT_RIGHT); - registry.register(new StubKey("sponge", "front_back"), StubMirror.FRONT_BACK); - } - -} diff --git a/src/test/java/org/spongepowered/common/test/stub/util/StubRotations.java b/src/test/java/org/spongepowered/common/test/stub/util/StubRotations.java deleted file mode 100644 index ae07d2b3486..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/util/StubRotations.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.util; - -import org.spongepowered.api.util.Angle; -import org.spongepowered.api.util.rotation.Rotation; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.common.test.stub.registry.StubbedRegistry; - -public enum StubRotations implements Rotation { - NONE(0), - CLOCKWISE_90(90), - CLOCKWISE_180(180), - COUNTERCLOCKWISE_90(-90); - - public static void registerDefaults(final StubbedRegistry registry) { - registry.register(new StubKey("sponge", "none"), StubRotations.NONE); - registry.register(new StubKey("sponge", "clockwise_90"), StubRotations.CLOCKWISE_90); - registry.register(new StubKey("sponge", "clockwise_180"), StubRotations.CLOCKWISE_180); - registry.register(new StubKey("sponge", "counterclockwise_90"), StubRotations.COUNTERCLOCKWISE_90); - } - - private final int angle; - - StubRotations(final int angle) { - this.angle = angle; - } - - @Override - public Rotation and(final Rotation rotation) { - if (!(rotation instanceof StubRotations)) { - throw new IllegalStateException("Shouldn't be operating on anything but stubrotations"); - } - if (((StubRotations) rotation).angle == 0) { - return this; - } - final StubRotations stub = (StubRotations) rotation; - switch (this) { - case NONE: return rotation; - case CLOCKWISE_90: { - switch (stub) { - case CLOCKWISE_90: return StubRotations.CLOCKWISE_180; - case CLOCKWISE_180: return StubRotations.COUNTERCLOCKWISE_90; - case COUNTERCLOCKWISE_90: return StubRotations.NONE; - default: return this; - } - } - case CLOCKWISE_180: { - switch (stub) { - case CLOCKWISE_90: return StubRotations.COUNTERCLOCKWISE_90; - case CLOCKWISE_180: return StubRotations.NONE; - case COUNTERCLOCKWISE_90: return StubRotations.CLOCKWISE_90; - } - } - case COUNTERCLOCKWISE_90: { - switch (stub) { - case CLOCKWISE_90: return StubRotations.NONE; - case CLOCKWISE_180: return StubRotations.CLOCKWISE_90; - case COUNTERCLOCKWISE_90: return StubRotations.CLOCKWISE_180; - } - } - } - throw new IllegalStateException("Impossible state"); - } - - @Override - public Angle angle() { - return Angle.fromDegrees(this.angle); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/util/package-info.java b/src/test/java/org/spongepowered/common/test/stub/util/package-info.java deleted file mode 100644 index 5f94753ba74..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/util/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@DefaultQualifier(NonNull.class) -package org.spongepowered.common.test.stub.util; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; diff --git a/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubBlockStatePaletteType.java b/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubBlockStatePaletteType.java deleted file mode 100644 index 119c0f27761..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubBlockStatePaletteType.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.world.schematic; - -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.common.test.stub.block.StubState; -import org.spongepowered.common.world.schematic.SpongePaletteType; - -import java.util.Optional; - -public class StubBlockStatePaletteType extends SpongePaletteType { - public StubBlockStatePaletteType() { - super(StubBlockStatePaletteType::apply, (rRegistry, t) -> ((StubState) t).key.asString()); - } - - private static Optional apply(final String s, final Registry r) { - final String[] split = s.split(":"); - final StubKey key = new StubKey(split[0], split[1]); - return r.findValue(key).map(BlockType::defaultState); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubPaletteType.java b/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubPaletteType.java deleted file mode 100644 index 4d1c11b2c15..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/world/schematic/StubPaletteType.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.stub.world.schematic; - -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.common.test.stub.block.StubState; -import org.spongepowered.common.world.schematic.SpongePaletteType; - -import java.util.Optional; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class StubPaletteType extends SpongePaletteType { - @SuppressWarnings("UnnecessaryLocalVariable") - public StubPaletteType() { - super((s, r) -> { - final String[] split = s.split(":"); - final StubKey key = new StubKey(split[0], split[1]); - if (r.type() == RegistryTypes.BLOCK_TYPE) { - final Optional t = r.findValue(key).map(v -> ((BlockType) v).defaultState()); - return t; - } - final Optional value = r.findValue(key); - return value; - }, ((rRegistry, t) -> (t instanceof StubState) - ? ((StubState) t).key.asString() - : ((Registry) rRegistry).valueKey(t).asString())); - } -} diff --git a/src/test/java/org/spongepowered/common/test/stub/world/schematic/package-info.java b/src/test/java/org/spongepowered/common/test/stub/world/schematic/package-info.java deleted file mode 100644 index 8ff6b259b6b..00000000000 --- a/src/test/java/org/spongepowered/common/test/stub/world/schematic/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -@DefaultQualifier(NonNull.class) -package org.spongepowered.common.test.stub.world.schematic; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; diff --git a/src/test/java/org/spongepowered/common/util/ReflectionTest.java b/src/test/java/org/spongepowered/common/util/ReflectionTest.java deleted file mode 100644 index 6f40b536677..00000000000 --- a/src/test/java/org/spongepowered/common/util/ReflectionTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.util; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.extension.ExtendWith; -import org.spongepowered.common.test.UnitTestExtension; - - -@Disabled -@ExtendWith(UnitTestExtension.class) -public class ReflectionTest { - - -} diff --git a/src/test/java/org/spongepowered/common/util/TypeTokenUtilTest.java b/src/test/java/org/spongepowered/common/util/TypeTokenUtilTest.java index 7ad58972742..19c39bff052 100644 --- a/src/test/java/org/spongepowered/common/util/TypeTokenUtilTest.java +++ b/src/test/java/org/spongepowered/common/util/TypeTokenUtilTest.java @@ -43,7 +43,6 @@ public final class TypeTokenUtilTest { @SuppressWarnings("rawtypes") - @Test @Disabled public void testA() { assertTrue(TypeTokenUtil.isAssignable( diff --git a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java index b78ad302ca2..a8c28ec8297 100644 --- a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java +++ b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java @@ -24,134 +24,44 @@ */ package org.spongepowered.common.util.transformation; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; -import org.spongepowered.api.Game; -import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.event.EventContextKey; +import org.spongepowered.api.block.entity.BlockEntityArchetype; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.data.persistence.DataQuery; import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.api.registry.RegistryKey; -import org.spongepowered.api.registry.RegistryType; -import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.api.util.mirror.Mirror; import org.spongepowered.api.util.rotation.Rotation; import org.spongepowered.api.util.rotation.Rotations; import org.spongepowered.api.util.transformation.Transformation; -import org.spongepowered.api.world.biome.Biome; -import org.spongepowered.api.world.schematic.PaletteReference; -import org.spongepowered.api.world.schematic.PaletteType; import org.spongepowered.api.world.volume.archetype.ArchetypeVolume; import org.spongepowered.api.world.volume.stream.StreamOptions; import org.spongepowered.api.world.volume.stream.VolumePositionTranslators; -import org.spongepowered.common.event.SpongeEventContextKeyBuilder; -import org.spongepowered.common.registry.SpongeBuilderProvider; -import org.spongepowered.common.registry.SpongeFactoryProvider; -import org.spongepowered.common.registry.SpongeRegistryKey; -import org.spongepowered.common.registry.SpongeRegistryType; -import org.spongepowered.common.test.UnitTestExtension; -import org.spongepowered.common.test.stub.StubGame; -import org.spongepowered.common.test.stub.StubKey; -import org.spongepowered.common.test.stub.StubModule; -import org.spongepowered.common.test.stub.block.StubBlock; -import org.spongepowered.common.test.stub.block.StubState; -import org.spongepowered.common.test.stub.registry.StubRegistryFactory; -import org.spongepowered.common.test.stub.registry.StubbedRegistry; -import org.spongepowered.common.test.stub.util.StubMirror; -import org.spongepowered.common.test.stub.util.StubRotations; -import org.spongepowered.common.test.stub.world.schematic.StubBlockStatePaletteType; -import org.spongepowered.common.test.stub.world.schematic.StubPaletteType; -import org.spongepowered.common.world.schematic.SpongePaletteReferenceFactory; import org.spongepowered.common.world.volume.buffer.archetype.AbstractReferentArchetypeVolume; import org.spongepowered.common.world.volume.buffer.archetype.SpongeArchetypeVolume; -import org.spongepowered.common.world.volume.stream.SpongeStreamOptionsBuilder; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3i; -import java.util.stream.IntStream; +import java.util.Optional; import java.util.stream.Stream; @Disabled -@SuppressWarnings("rawtypes") -@ExtendWith({ MockitoExtension.class, UnitTestExtension.class }) +@ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) public final class VolumeTransformationTest { private static final Vector3i INVALID_STUB_POSITION = Vector3i.from( Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); - private static final Injector guice = Guice.createInjector(new StubModule()); + private static final DataQuery POS = DataQuery.of("pos"); - @SuppressWarnings("unused") - static class DummyInjectable { - @Inject Game game; - } - - @BeforeAll - static void setup() { - VolumeTransformationTest.guice.injectMembers(new DummyInjectable()); - final StubGame game = (StubGame) Sponge.game(); - - final SpongeFactoryProvider factoryProvider = game.factoryProvider(); - final SpongeBuilderProvider builderProvider = game.builderProvider(); - // Set up Rotations - final StubbedRegistry rotation = new StubbedRegistry<>( - () -> RegistryTypes.ROTATION, - (k) -> Rotations.NONE.get() - ); - - // Set up Blocks and BlockState - final StubbedRegistry blocktypes = new StubbedRegistry<>( - () -> RegistryTypes.BLOCK_TYPE, - StubBlock::new - ); - // Set up biomes - final StubbedRegistry biomes = new StubbedRegistry<>( - () -> RegistryTypes.BIOME, - (key) -> Mockito.mock(Biome.class) - ); - // Set up palettes - final StubbedRegistry> paletteTypeRegistry = new StubbedRegistry<>( - () -> RegistryTypes.PALETTE_TYPE, - (key) -> new StubPaletteType<>() - ); - factoryProvider.registerFactory(RegistryType.Factory.class, new SpongeRegistryType.FactoryImpl()); - factoryProvider.registerFactory(RegistryKey.Factory.class, new SpongeRegistryKey.FactoryImpl()); - factoryProvider.registerFactory(PaletteReference.Factory.class, new SpongePaletteReferenceFactory()); - // and finally, set up the resourcekey stuff - factoryProvider.registerFactory(ResourceKey.Factory.class, new StubRegistryFactory()); - game.register(rotation); - game.register(blocktypes); - game.register(biomes); - game.register(paletteTypeRegistry); - final StubbedRegistry mirror = new StubbedRegistry<>( - () -> RegistryTypes.MIRROR, (k) -> Mockito.mock(Mirror.class)); - StubMirror.registerDefaults(mirror); - game.register(mirror); - - builderProvider.register(EventContextKey.Builder.class, SpongeEventContextKeyBuilder::new); - builderProvider.register(Transformation.Builder.class, SpongeTransformationBuilder::new); - builderProvider.register(StreamOptions.Builder.class, SpongeStreamOptionsBuilder::new); - StubRotations.registerDefaults(rotation); - - paletteTypeRegistry.register(new StubKey("sponge", "block_state_palette"), new StubBlockStatePaletteType()); - } - - @SuppressWarnings("unused") // IDEA bug not noticing this method is used by junit to populate parameters private static Stream testTransformationsOfPositions() { return Stream.of( Arguments.of( @@ -160,7 +70,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.ZERO, Vector3i.from(1, 1, 1), 0, - StubRotations.NONE + Rotations.NONE.get() ), Arguments.of( Vector3i.ZERO, @@ -168,7 +78,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.UNIT_X, Vector3i.from(1, 1, 1), 1, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ), Arguments.of( Vector3i.ZERO, @@ -176,7 +86,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.from(-1, 1, 4), Vector3i.from(1, 1, 1), 0, - StubRotations.NONE + Rotations.NONE.get() ), Arguments.of( Vector3i.ZERO, @@ -184,7 +94,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.from(-1, 1, 4), Vector3i.from(1, 1, 1), 1, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ), Arguments.of( Vector3i.from(1, -1, -1), @@ -192,7 +102,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.ZERO, Vector3i.from(1, -1, -1), 1, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ), Arguments.of( Vector3i.from(1, -1, -1), @@ -200,7 +110,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.ZERO, Vector3i.from(1, -1, -1), 2, - StubRotations.COUNTERCLOCKWISE_90 + Rotations.COUNTERCLOCKWISE_90.get() ), Arguments.of( Vector3i.from(1, -1, -1), @@ -208,7 +118,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.ZERO, Vector3i.from(1, -1, -1), 4, - StubRotations.CLOCKWISE_180 + Rotations.CLOCKWISE_180.get() ), Arguments.of( Vector3i.from(-4, -1, -5), @@ -216,7 +126,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.ZERO, Vector3i.from(1, -3, -1), 8, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ), Arguments.of( Vector3i.from(-4, -1, -5), @@ -224,7 +134,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.from(-8, 3, -7), Vector3i.from(1, -3, -1), 8, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ), Arguments.of( Vector3i.from(-11, -4, -10), @@ -232,7 +142,7 @@ private static Stream testTransformationsOfPositions() { Vector3i.from(-6, 2, -4), Vector3i.from(1, -3, -1), 8, - StubRotations.CLOCKWISE_90 + Rotations.CLOCKWISE_90.get() ) ); } @@ -245,16 +155,14 @@ private static SpongeArchetypeVolume fillVolume(final Vector3i min, final Vector final RegistryHolder holder = Sponge.game(); final SpongeArchetypeVolume volume = new SpongeArchetypeVolume(relativeMin, size, holder); - final StubbedRegistry blockRegistry = (StubbedRegistry) RegistryTypes.BLOCK_TYPE.get(); final Vector3i volMax = volume.max().add(Vector3i.ONE); - IntStream.range(relativeMin.x(), volMax.x()).forEach(x -> IntStream.range(relativeMin.z(), volMax.z()) - .forEach(z -> IntStream.range(relativeMin.y(), volMax.y()) - .forEach(y -> { - final BlockType block = blockRegistry.createEntry( - "minecraft", String.format("volumetest{%d, %d, %d}", x, y, z)); - final BlockState blockState = block.defaultState(); - volume.setBlock(x, y, z, blockState); - }))); + for (int x = relativeMin.x(); x < volMax.x(); x++) { + for (int z = relativeMin.z(); z < volMax.z(); z++) { + for (int y = relativeMin.y(); y < volMax.y(); y++) { + volume.addBlockEntity(x, y, z, BlockEntityArchetype.builder().blockEntityData(DataContainer.createNew().set(VolumeTransformationTest.POS, new Vector3i(x, y, z))).build()); + } + } + } return volume; } @@ -262,7 +170,7 @@ private static SpongeArchetypeVolume fillVolume(final Vector3i min, final Vector @ParameterizedTest void testTransformationsOfPositions( final Vector3i min, final Vector3i max, final Vector3i origin, final Vector3i testForRoundTrip, - final int rotationCount, final StubRotations wanted + final int rotationCount, final Rotation wanted ) { final SpongeArchetypeVolume volume = VolumeTransformationTest.fillVolume(min, max, origin); final Vector3i size = volume.size(); @@ -303,16 +211,16 @@ void testTransformationsOfPositions( final int relativeY = y + relativeMin.y(); final int relativeZ = z + relativeMin.z(); final Vector3d rawRelativePosition = new Vector3d(relativeX, relativeY, relativeZ); - final BlockState untransformedState = volume.block(relativeX, relativeY, relativeZ); + final Optional untransformedEntity = volume.blockEntityArchetype(relativeX, relativeY, relativeZ); final Vector3i transformedPosition = expectedTransform.transformPosition( rawRelativePosition).toInt(); - final BlockState transformedState = rotated.block( + final Optional transformedEntity = rotated.blockEntityArchetype( transformedPosition.x(), transformedPosition.y(), transformedPosition.z()); - Assertions.assertEquals(untransformedState, transformedState, () -> String.format( - "Block Check Failed!\nOriginal(%d, %d, %d): %s\nTransformed(%d, %d, %d): %s\n", - relativeX, relativeY, relativeZ, untransformedState, + Assertions.assertEquals(untransformedEntity, transformedEntity, () -> String.format( + "Block entity check failed!\nOriginal(%d, %d, %d): %s\nTransformed(%d, %d, %d): %s\n", + relativeX, relativeY, relativeZ, untransformedEntity, transformedPosition.x(), transformedPosition.y(), - transformedPosition.z(), transformedState + transformedPosition.z(), transformedEntity )); } } @@ -322,40 +230,37 @@ void testTransformationsOfPositions( } // At this point, we should have an abstract referent volume at least - rotated.blockStateStream(rotated.min(), rotated.max(), StreamOptions.lazily()) - .forEach((rotatedRef, type, x, y, z) -> { + rotated.blockEntityArchetypeStream(rotated.min(), rotated.max(), StreamOptions.lazily()) + .forEach((rotatedRef, entity, x, y, z) -> { final Vector3d transformedPos = new Vector3d(x, y, z); // We have this offset in the stream, so we have to undo it here. final Vector3d invertedTransformedPos = inverse .transformPosition(transformedPos.add(VolumePositionTranslators.BLOCK_OFFSET)) .sub(VolumePositionTranslators.BLOCK_OFFSET); final Vector3i invertedBlockPos = invertedTransformedPos.toInt(); - final Vector3i expectedPos; - Assertions.assertInstanceOf(StubState.class, type, - () -> String.format("expected state to be a stub state for pos: [%f, %f, %f] but got %s", x, y, z, - type - ) - ); + + final Vector3i expectedPos = (Vector3i) entity.blockEntityData().get(VolumeTransformationTest.POS).get(); + Assertions.assertNotEquals( - ((StubState) type).deducedPos, VolumeTransformationTest.INVALID_STUB_POSITION, - () -> String.format("expected to have a positioned stub state: [%f, %f, %f] but got %s", x, y, z, - type + expectedPos, + () -> String.format("expected to have a positioned block entity: [%f, %f, %f] but got %s", x, y, z, + entity ) ); - expectedPos = ((StubState) type).deducedPos; + Assertions.assertEquals(expectedPos, invertedBlockPos, () -> String.format( - "expected untransformed position %s for state %s does not match reverse transformed position: %s", - expectedPos, type, invertedBlockPos + "expected untransformed position %s for block entity %s does not match reverse transformed position: %s", + expectedPos, entity, invertedBlockPos ) ); - final BlockState block = volume.block(expectedPos.x(), expectedPos.y(), expectedPos.z()); - Assertions.assertEquals(type, block, + final BlockEntityArchetype originalEntity = volume.blockEntityArchetype(expectedPos.x(), expectedPos.y(), expectedPos.z()).orElse(null); + Assertions.assertEquals(entity, originalEntity, () -> String.format( - "Expected deduced state to be equal from the original target volume but had a mismatch: Original target %s does not match %s", - block, type + "Expected deduced block entity to be equal from the original target volume but had a mismatch: Original target %s does not match %s", + originalEntity, entity ) ); }); From c473e6c79e04ac50b924a5a0ba7e7cce8ab7403c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 23 Jul 2025 17:37:04 +0200 Subject: [PATCH 323/586] Update invalid unit tests --- build.gradle.kts | 2 + .../common/data/manipulator/DataTestUtil.java | 80 ---- .../data/manipulator/ManipulatorTest.java | 363 ------------------ .../data/manipulator/SpecialCaseDataTest.java | 45 --- .../data/util/ExperienceHolderUtilsTest.java | 124 ------ .../common/event/CauseStackManagerTest.java | 93 ----- .../invalid/common/event/ShouldFireTest.java | 133 ------- .../common/event/SnapshotGenerationTest.java | 112 ------ .../invalid/common/launch/TestTweaker.java | 57 --- .../common/launch/mixin/ItemMixin_Test.java | 44 --- .../mixin/SchematicTranslatorMixin_Test.java | 47 --- .../mixin/SpongeImplHooksMixin_Test.java | 44 --- .../registry/CatalogTypeClassesTest.java | 72 ---- .../registry/CatalogTypeMethodTest.java | 165 -------- .../common/registry/RegistryModuleTest.java | 74 ---- .../common/registry/RegistryTestUtil.java | 112 ------ .../common/regression/registry/Test1Tile.java | 29 -- .../common/regression/registry/Test2Tile.java | 29 -- .../common/regression/registry/Test3Tile.java | 29 -- .../registry/TileEntityRegistrationTest.java | 93 ----- .../pagination/PaginationCalculatorTest.java | 54 --- .../invalid/common/test/RegressionTest.java | 68 ---- src/test/invalid/common/test/TestGame.java | 59 --- src/test/invalid/common/test/TestMain.java | 48 --- src/test/invalid/common/test/TestServer.java | 262 ------------- .../test/inject/TestImplementationModule.java | 70 ---- .../invalid/common/text/LegacyParserTest.java | 71 ---- .../common/text/LegacySerializerTest.java | 78 ---- .../world/storage/SpongeChunkLayoutTest.java | 170 -------- .../common/config/core}/IpSetTest.java | 25 +- .../common/event/EventFilterTest.java | 239 ++++++------ .../common/event/ShouldFireTest.java | 123 ++++++ .../common/event/SnapshotGenerationTest.java | 83 ++++ .../event/listener/AllCauseListener.java | 4 +- .../listener/BeforeAfterCauseListener.java | 8 +- .../event/listener/CancelledListener.java | 0 .../listener/CovariantGetterListener.java | 0 .../event/listener/DataHasListener.java | 13 +- .../event/listener/DataSupportsListener.java | 13 +- .../common/event/listener/DoubleListener.java | 4 +- .../listener/FirstLastCauseListener.java | 0 .../common/event/listener/GetterListener.java | 0 .../listener/IncludeExcludeListener.java | 4 +- .../InvalidIncludeExcludeListener.java | 0 .../common/event/listener/NonPreListener.java | 2 +- .../common/event/listener}/PreListener.java | 4 +- .../common/event/listener/RootListener.java | 0 .../common/event/listener/SimpleListener.java | 0 .../manager/ListenerClassVisitorHelper.java} | 38 +- .../event/tracking/PhaseTrackerTest.java | 87 +++++ .../common/mixin}/MixinTest.java | 9 +- .../common/registry/RegistryTest.java | 131 +++++++ .../common/util/ExperienceHolderUtilTest.java | 84 ++++ .../util/persistence/data/FakeBuilder.java | 4 +- .../persistence/data/FakeSerializable.java | 12 +- .../persistence/data/NBTTranslationTest.java | 20 +- .../VolumeTransformationTest.java | 2 +- .../world/schematic/SchematicTest.java} | 27 +- .../world/storage/SpongeChunkLayoutTest.java | 168 ++++++++ 59 files changed, 887 insertions(+), 2844 deletions(-) delete mode 100644 src/test/invalid/common/data/manipulator/DataTestUtil.java delete mode 100644 src/test/invalid/common/data/manipulator/ManipulatorTest.java delete mode 100644 src/test/invalid/common/data/manipulator/SpecialCaseDataTest.java delete mode 100644 src/test/invalid/common/data/util/ExperienceHolderUtilsTest.java delete mode 100644 src/test/invalid/common/event/CauseStackManagerTest.java delete mode 100644 src/test/invalid/common/event/ShouldFireTest.java delete mode 100644 src/test/invalid/common/event/SnapshotGenerationTest.java delete mode 100644 src/test/invalid/common/launch/TestTweaker.java delete mode 100644 src/test/invalid/common/launch/mixin/ItemMixin_Test.java delete mode 100644 src/test/invalid/common/launch/mixin/SchematicTranslatorMixin_Test.java delete mode 100644 src/test/invalid/common/launch/mixin/SpongeImplHooksMixin_Test.java delete mode 100644 src/test/invalid/common/registry/CatalogTypeClassesTest.java delete mode 100644 src/test/invalid/common/registry/CatalogTypeMethodTest.java delete mode 100644 src/test/invalid/common/registry/RegistryModuleTest.java delete mode 100644 src/test/invalid/common/registry/RegistryTestUtil.java delete mode 100644 src/test/invalid/common/regression/registry/Test1Tile.java delete mode 100644 src/test/invalid/common/regression/registry/Test2Tile.java delete mode 100644 src/test/invalid/common/regression/registry/Test3Tile.java delete mode 100644 src/test/invalid/common/regression/registry/TileEntityRegistrationTest.java delete mode 100644 src/test/invalid/common/service/pagination/PaginationCalculatorTest.java delete mode 100644 src/test/invalid/common/test/RegressionTest.java delete mode 100644 src/test/invalid/common/test/TestGame.java delete mode 100644 src/test/invalid/common/test/TestMain.java delete mode 100644 src/test/invalid/common/test/TestServer.java delete mode 100644 src/test/invalid/common/test/inject/TestImplementationModule.java delete mode 100644 src/test/invalid/common/text/LegacyParserTest.java delete mode 100644 src/test/invalid/common/text/LegacySerializerTest.java delete mode 100644 src/test/invalid/common/world/storage/SpongeChunkLayoutTest.java rename src/test/{invalid/common/util => java/org/spongepowered/common/config/core}/IpSetTest.java (70%) rename src/test/{invalid => java/org/spongepowered}/common/event/EventFilterTest.java (54%) create mode 100644 src/test/java/org/spongepowered/common/event/ShouldFireTest.java create mode 100644 src/test/java/org/spongepowered/common/event/SnapshotGenerationTest.java rename src/test/{invalid => java/org/spongepowered}/common/event/listener/AllCauseListener.java (94%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/BeforeAfterCauseListener.java (91%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/CancelledListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/CovariantGetterListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/DataHasListener.java (76%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/DataSupportsListener.java (75%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/DoubleListener.java (90%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/FirstLastCauseListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/GetterListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/IncludeExcludeListener.java (96%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/InvalidIncludeExcludeListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/NonPreListener.java (97%) rename src/test/{invalid/common/event => java/org/spongepowered/common/event/listener}/PreListener.java (94%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/RootListener.java (100%) rename src/test/{invalid => java/org/spongepowered}/common/event/listener/SimpleListener.java (100%) rename src/test/{invalid/common/InjectedTest.java => java/org/spongepowered/common/event/manager/ListenerClassVisitorHelper.java} (57%) create mode 100644 src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java rename src/test/{invalid/common => java/org/spongepowered/common/mixin}/MixinTest.java (88%) create mode 100644 src/test/java/org/spongepowered/common/registry/RegistryTest.java create mode 100644 src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java rename src/test/{invalid => java/org/spongepowered}/common/util/persistence/data/FakeBuilder.java (95%) rename src/test/{invalid => java/org/spongepowered}/common/util/persistence/data/FakeSerializable.java (87%) rename src/test/{invalid => java/org/spongepowered}/common/util/persistence/data/NBTTranslationTest.java (80%) rename src/test/{invalid/common/regression/SchematicUpgradeTest.java => java/org/spongepowered/common/world/schematic/SchematicTest.java} (77%) create mode 100644 src/test/java/org/spongepowered/common/world/storage/SpongeChunkLayoutTest.java diff --git a/build.gradle.kts b/build.gradle.kts index bda3857402b..19455e530d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -170,6 +170,8 @@ dependencies { testImplementation(libs.mockito.junitJupiter) { exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") } + + testImplementation(libs.mixin) } minecraft { diff --git a/src/test/invalid/common/data/manipulator/DataTestUtil.java b/src/test/invalid/common/data/manipulator/DataTestUtil.java deleted file mode 100644 index baecf4f6cca..00000000000 --- a/src/test/invalid/common/data/manipulator/DataTestUtil.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.manipulator; - -import org.spongepowered.api.data.manipulator.DataManipulator; -import org.spongepowered.api.data.manipulator.DataManipulatorBuilder; -import org.spongepowered.common.data.SpongeDataManager; -import org.spongepowered.common.data.SpongeManipulatorRegistry; -import org.spongepowered.common.data.util.DataProcessorDelegate; -import org.spongepowered.common.data.util.ImplementationRequiredForTest; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -final class DataTestUtil { - - private DataTestUtil() {} - - static List generateManipulatorTestObjects() throws Exception { - final Map>, DataManipulatorBuilder> manipulatorBuilderMap = getBuilderMap(); - final Map>, DataProcessorDelegate> delegateMap = getDelegateMap(); - return delegateMap.entrySet().stream() - .filter(entry -> isValidForTesting(entry.getKey())) - .flatMap(entry -> { - String name = entry.getKey().getSimpleName(); - Class> key = entry.getKey(); - DataManipulatorBuilder builder = manipulatorBuilderMap.get(key); - - return Stream.of(new Object[]{name, key, builder, false}, new Object[]{name, key, builder, true}); - }) - .collect(Collectors.toList()); - } - - private static boolean isValidForTesting(Class clazz) { - return !Modifier.isInterface(clazz.getModifiers()) && !Modifier.isAbstract(clazz.getModifiers()) - && clazz.getAnnotation(ImplementationRequiredForTest.class) == null; - } - - @SuppressWarnings("unchecked") - private static Map>, DataProcessorDelegate> getDelegateMap() throws Exception { - final Field delegateField = SpongeManipulatorRegistry.class.getDeclaredField("dataProcessorDelegates"); - delegateField.setAccessible(true); - return (Map>, DataProcessorDelegate>) delegateField.get(SpongeManipulatorRegistry.getInstance()); - - } - - @SuppressWarnings("unchecked") - private static Map>, DataManipulatorBuilder> getBuilderMap() throws Exception { - final Field builderMap = SpongeDataManager.class.getDeclaredField("builderMap"); - builderMap.setAccessible(true); - return (Map>, DataManipulatorBuilder>) builderMap.get(SpongeDataManager.getInstance()); - } - -} diff --git a/src/test/invalid/common/data/manipulator/ManipulatorTest.java b/src/test/invalid/common/data/manipulator/ManipulatorTest.java deleted file mode 100644 index c9a39a0e2ba..00000000000 --- a/src/test/invalid/common/data/manipulator/ManipulatorTest.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.manipulator; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -import com.google.common.collect.Lists; -import io.leangen.geantyref.TypeToken; -import org.checkerframework.checker.nullness.Opt; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.data.DataContainer; -import org.spongepowered.api.data.DataQuery; -import org.spongepowered.api.data.DataView; -import org.spongepowered.api.data.key.Key; -import org.spongepowered.api.data.manipulator.DataManipulator; -import org.spongepowered.api.data.manipulator.DataManipulatorBuilder; -import org.spongepowered.api.data.manipulator.ImmutableDataManipulator; -import org.spongepowered.api.data.value.BaseValue; -import org.spongepowered.api.data.value.immutable.ImmutableValue; -import org.spongepowered.api.effect.potion.PotionEffect; -import org.spongepowered.api.entity.EntitySnapshot; -import org.spongepowered.api.event.SpongeEventFactoryTest; -import org.spongepowered.api.item.merchant.TradeOffer; -import org.spongepowered.api.util.PEBKACException; -import org.spongepowered.asm.util.PrettyPrinter; -import org.spongepowered.common.util.TypeTokenHelper; -import org.spongepowered.lwts.runner.LaunchWrapperParameterized; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -@RunWith(LaunchWrapperParameterized.class) -public class ManipulatorTest { - - @Parameterized.Parameters(name = "{index} Data: {0} generateValues: {3}") - public static Iterable data() throws Exception { - return DataTestUtil.generateManipulatorTestObjects(); - } - - private String dataName; - private Class> manipulatorClass; - private DataManipulatorBuilder builder; - private boolean generateValues; - - public ManipulatorTest(String simpleName, Class> manipulatorClass, DataManipulatorBuilder builder, boolean generateValues) { - this.manipulatorClass = manipulatorClass; - this.dataName = simpleName; - this.builder = builder; - this.generateValues = generateValues; - } - - @SuppressWarnings("unchecked") - private DataManipulator createManipulator() { - try { - final Constructor ctor = this.manipulatorClass.getConstructor(); - DataManipulator manipulator = (DataManipulator) ctor.newInstance(); - - if (this.generateValues) { - final Set> keys = manipulator.getKeys(); - - for (Key key: keys) { - Optional value = createValueElement((Key) key); - value.ifPresent(o -> manipulator.set((Key) key, o)); - } - } - return manipulator; - } catch (InstantiationException | InvocationTargetException e) { - throw new IllegalStateException("Failed to construct manipulator: " + this.dataName, e); - } catch (Exception e) { - throw new RuntimeException("There was an unknown exception, probably with validation of the Immutable copy for: " - + this.manipulatorClass.getSimpleName() + ". \n It may be required to use @ImplementationRequiredForTest on " - + "the DataManipulator implementation class to avoid testing a DataManipulator dependent on a CatalogType.", e); - } - } - - @Test - public void testCreateData() { - try { - DataManipulator manipulator = this.createManipulator(); - manipulator.asImmutable(); - } catch (Exception e) { - throw new RuntimeException("There was an unknown exception, probably with validation of the Immutable copy for: " - + this.manipulatorClass.getSimpleName() + ". \n It may be required to use @ImplementationRequiredForTest on " - + "the DataManipulator implementation class to avoid testing a DataManipulator dependent on a CatalogType.", e); - } - } - - @Test - public void testValueEquals() { - final DataManipulator manipulator = this.createManipulator(); - final ImmutableDataManipulator immutable = manipulator.asImmutable(); - final Set> manipulatorValues = manipulator.getValues(); - final Set> immutableValues = immutable.getValues(); - assertThat("The ImmutableDataManipulator is missing values present from the DataManipulator! " + this.dataName, - manipulatorValues.containsAll(immutableValues), is(true)); - assertThat("The DataManipulator is missing values present from the ImmutableDataManipulator! " + this.dataName, - immutableValues.containsAll(manipulatorValues), is(true)); - } - - @Test - public void testMutableImmutable() { - final DataManipulator manipulator = this.createManipulator(); - final ImmutableDataManipulator immutableDataManipulator = manipulator.asImmutable(); - final DataManipulator newManipulator = immutableDataManipulator.asMutable(); - - assertThat("The DataManipulator constructed by ImmutableDataManipulator#asMutable is not " - + "equal to original DataManipulator!\n" - + "This shouldn't be the case, as aDataManipulator constructed from an ImmutableDataManipulator " - + "should store exactly the same keys and values as the original DataManipulator, and therefore " - + "be equal to it.\n" - + "The mutable manipulator in question: " + this.dataName + "\n" - + "The immutable manipulator in question: " + immutableDataManipulator.getClass().getSimpleName(), - manipulator.getValues().equals(newManipulator.getValues()), is(true)); - } - - @Test - public void testSameKeys() { - final DataManipulator manipulator = this.createManipulator(); - final ImmutableDataManipulator immutableDataManipulator = manipulator.asImmutable(); - final Set> mutableKeys = manipulator.getKeys(); - final Set> immutableKeys = immutableDataManipulator.getKeys(); - assertThat("The DataManipulator and ImmutableDataManipulator have differing keys!\n" - + "This shouldn't be the case as a DataManipulator is contractually obliged to store the exact same" - + "key/values as the ImmutableDataManipulator and vice versa.\n" - + "The mutable manipulator in question: " + this.dataName +"\n" - + "The immutable manipulator in question: " + immutableDataManipulator.getClass().getSimpleName(), - immutableKeys, equalTo(mutableKeys)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - @Test - public void testGetValues() { - final DataManipulator manipulator = this.createManipulator(); - final ImmutableDataManipulator immutableDataManipulator = manipulator.asImmutable(); - final Set> keys = manipulator.getKeys(); - for (Key> key : keys) { - Optional mutable = manipulator.get((Key) key); - Optional immutable = immutableDataManipulator.get((Key) key); - assertThat("The DataManipulator failed to retrieve a value that a key was registered for!\n" - + "The manipulator in question: " + this.dataName, mutable.isPresent(), is(true)); - assertThat("The ImmutableDataManipulator failed to retrieve a value that a key was registered for!\n" - + "The manipulator in question: " + immutableDataManipulator.getClass().getSimpleName(), immutable.isPresent(), is(true)); - assertThat("The returned values do not equal eachother!\n" - + "DataManipulator: " + this.dataName + "\nImmutableDataManipulator: " - + immutableDataManipulator.getClass().getSimpleName(), mutable.equals(immutable), is(true)); - } - } - - @SuppressWarnings("unchecked") - private Optional createValueElement(Key type) { - Class elementClass = (Class) type.getElementToken().getRawType(); - if (Optional.class.isAssignableFrom(elementClass)) { - Class wrappedType = TypeTokenHelper.getGenericParam(type.getElementToken(), 0); - // The innermost optional is the actual type of the Key. The outer optional - // indicates to the caller that we were able to create something for this key. - return (Optional) Optional.of(Optional.of(createType(wrappedType))); - } else if (List.class.isAssignableFrom(elementClass)) { - Class wrappedType = TypeTokenHelper.getGenericParam(type.getElementToken(), 0); - - return (Optional) Optional.of(Lists.newArrayList(createType(wrappedType))); - } - return Optional.empty(); - } - - - @SuppressWarnings("unchecked") - private T createType(Class type) { - if (CatalogType.class.isAssignableFrom(type)) { - return (T) Sponge.getRegistry().getAllOf((Class) type).iterator().next(); - } else if (isBuildable(type)) { - return (T) createFromBuilder(type); - } else { - return (T) SpongeEventFactoryTest.mockParam(type); - } - } - - private boolean isBuildable(Class type) { - // The 'child' methods on Text.Builder interact oddly - // with our code, so skip building Text for now - if (type == Text.class) { - return false; - } - // EntitySnapshot can't be built with null values - // We need a dummy EntitySnapshot - // Skip building EntitySnapshot for now - if (type == EntitySnapshot.class) { - return false; - } - try { - type.getMethod("builder"); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - private Object createFromBuilder(Class type) { - try { - Method methodbuilder = type.getMethod("builder"); - Class builderType = methodbuilder.getReturnType(); - Method methodBuild = builderType.getMethod("build"); - Object builderObject = methodbuilder.invoke(nullValue()); - - for (Method builderSetter: builderType.getMethods()) { - if (!this.isBuilderSetter(builderType, type, builderSetter)) { - continue; - } - Class paramType = builderSetter.getParameterTypes()[0]; - Object param = this.createBuilderParam(paramType); - - builderSetter.invoke(builderObject, param); - } - - Object finalType = methodBuild.invoke(builderObject); - return finalType; - - } catch (Exception e) { - throw new RuntimeException("Exception while creating builder for type " + type, e); - } - } - - private Object createBuilderParam(Class paramType) { - // Many builder methods require that that integer parameters be greater than 0 - if (paramType.equals(int.class) || paramType.equals(Integer.class)) { - return 1; - } - return this.createType(paramType); - } - - private boolean isBuilderSetter(Class builderType, Class type, Method method) { - if (method.getReturnType().equals(builderType) && method.getParameterCount() == 1) { - // Don't try to call any methods that take the type we're building - Class paramType = method.getParameterTypes()[0]; - return !paramType.equals(type) - && !paramType.equals(Class.class) - && !paramType.equals(DataManipulator.class) - && !paramType.equals(ImmutableDataManipulator.class) - && !method.getName().startsWith("from"); - } - return false; - } - @SuppressWarnings("unchecked") - @Test - public void testSerialization() { - try { - final DataManipulator manipulator = this.createManipulator(); - - final DataContainer container = manipulator.toContainer(); - if (this.builder != null) { - final Optional> optional; - try { - optional = (Optional>) this.builder.build(container); - } catch (Exception e) { - printExceptionBuildingData(container, e); - throw e; - } - if (!optional.isPresent()) { - printEmptyBuild(container); - throw new IllegalArgumentException("[Serialization]: A builder did not translate the data manipulator: " - + this.dataName + "\n[Serialization]: Providing the DataContainer: " + container.toString()); - } - - final DataManipulator deserialized = this.builder.build(container).get(); - final boolean equals = manipulator.equals(deserialized); - if (!equals) { - printNonEqual(container, manipulator, deserialized); - } - assertThat(manipulator, equalTo(deserialized)); - } - } catch (Exception e) { - throw new RuntimeException("There was an unknown exception trying to test " + this.dataName - + ". Probably because the DataManipulator relies on an implementation class.", e); - } - } - - private void printNonEqual(DataContainer container, DataManipulator original, DataManipulator deserialized) { - final PrettyPrinter printer = new PrettyPrinter(60).centre().add("Unequal Data").hr() - .add("Something something equals....") - .add() - .add("Provided manipulators don't equal eachother."); - printRemaining(container, printer); - - } - - private void printEmptyBuild(DataContainer container) { - final PrettyPrinter printer = new PrettyPrinter(60).centre().add("Did not build data!").hr() - .add("Something something builders....") - .add() - .add("Provided container didn't get built into a manipulator!"); - printRemaining(container, printer); - } - - private void printExceptionBuildingData(DataContainer container, Exception exception) { - final PrettyPrinter printer = new PrettyPrinter(60).centre().add("Could not build data!").hr() - .add(exception) - .add("Something something data....") - .add() - .add("Here's the provided container:"); - printRemaining(container, printer); - } - - private void printRemaining(DataContainer container, PrettyPrinter printer) { - printContainerToPrinter(printer, container, 2); - printer.add() - .add("Manipulator class: " + this.manipulatorClass) - .print(System.err); - } - - - private static void printContainerToPrinter(PrettyPrinter printer, DataView container, int indentation) { - for (DataQuery dataQuery : container.getKeys(false)) { - final Object o = container.get(dataQuery).get(); - final StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < indentation; i++) { - stringBuilder.append(" "); - } - final List parts = dataQuery.getParts(); - - printer.add(stringBuilder.toString() + "- Query: " + parts.get(parts.size() - 1)); - if (o instanceof DataView) { - // Paginate the internal views. - printContainerToPrinter(printer, (DataView) o, indentation * 2); - } else { - printer .add(stringBuilder.toString() + "- Value: " + o); - - } - } - } -} diff --git a/src/test/invalid/common/data/manipulator/SpecialCaseDataTest.java b/src/test/invalid/common/data/manipulator/SpecialCaseDataTest.java deleted file mode 100644 index 5b6e08f316d..00000000000 --- a/src/test/invalid/common/data/manipulator/SpecialCaseDataTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.manipulator; - -public class SpecialCaseDataTest { - - //@RunWith(Parameterized.class) - public static final class CatalogDataTest { - // todo mock a fake catalog - // todo create a test datamanipulator - // todo create a test immutable datamanipulator - // todo write tests for validating the catalog data abstraction layer - } - - //@RunWith(Parameterized.class) - public static final class ItemStackDataTest { - - // todo write a test based on a fake implemented ItemStack - // same as CatalogDataTest - - } - -} diff --git a/src/test/invalid/common/data/util/ExperienceHolderUtilsTest.java b/src/test/invalid/common/data/util/ExperienceHolderUtilsTest.java deleted file mode 100644 index dee670452ef..00000000000 --- a/src/test/invalid/common/data/util/ExperienceHolderUtilsTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.util; - -import com.mojang.authlib.GameProfile; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.profiler.Profiler; -import net.minecraft.world.World; -import net.minecraft.world.WorldProviderSurface; -import net.minecraft.world.chunk.IChunkProvider; -import net.minecraft.world.storage.WorldInfo; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.spongepowered.common.data.provider.entity.player.ExperienceHolderUtils; - -import java.util.Iterator; -import java.util.UUID; - -@RunWith(Parameterized.class) -public final class ExperienceHolderUtilsTest { - - private final int level; - private final int startExp; - private final int expInLevel; - - public ExperienceHolderUtilsTest(int level, int startExp, int expInLevel) { - this.level = level; - this.startExp = startExp; - this.expInLevel = expInLevel; - } - - @Parameterized.Parameters - public static Iterable data() { - World world = new World(null, new WorldInfo(new NBTTagCompound()), new WorldProviderSurface(), new Profiler(), false) { - - @Override - protected IChunkProvider createChunkProvider() { - return null; - } - - @Override - protected boolean isChunkLoaded(int x, int z, boolean allowEmpty) { - return false; - } - }; - //noinspection EntityConstructor - EntityPlayer player = new EntityPlayer(world, new GameProfile(UUID.randomUUID(), "Player")) { - - @Override - public boolean isSpectator() { - return false; - } - - @Override - public boolean isCreative() { - return false; - } - }; - return () -> new Iterator() { - - private int level; - private int startExp; - - @Override - public boolean hasNext() { - return level < 50; - } - - @Override - public Object[] next() { - player.experienceLevel = level; - Object[] data = {level, startExp, player.xpBarCap()}; - startExp += player.xpBarCap(); - level++; - return data; - } - }; - } - - @Test - public void testGetExpBetweenLevels() { - Assert.assertEquals(expInLevel, ExperienceHolderUtils.getExpBetweenLevels(level)); - } - - @Test - public void testXpAtLevel() { - Assert.assertEquals(startExp, ExperienceHolderUtils.xpAtLevel(level)); - } - - @Test - public void testGetLevelForXpStart() { - Assert.assertEquals(level, ExperienceHolderUtils.getLevelForExp(startExp)); - } - - @Test - public void testGetLevelForXpMiddle() { - Assert.assertEquals(level, ExperienceHolderUtils.getLevelForExp(startExp + 1)); - } -} diff --git a/src/test/invalid/common/event/CauseStackManagerTest.java b/src/test/invalid/common/event/CauseStackManagerTest.java deleted file mode 100644 index b9c1dc2bad1..00000000000 --- a/src/test/invalid/common/event/CauseStackManagerTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.spongepowered.api.entity.living.player.User; -import org.spongepowered.api.event.cause.EventContextKeys; -import org.spongepowered.common.SpongeImpl; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; - -@RunWith(LaunchWrapperTestRunner.class) -public class CauseStackManagerTest { - - @Test - public void testPoppingFramePopsCauses() throws Exception { - final SpongeCauseStackManager causeStackManager = SpongeImpl.getCauseStackManager(); - - // We start by pushing a frame... - SpongeCauseStackManager.StackFrame frame1 = causeStackManager.pushCauseFrame(); - causeStackManager.pushCause(1); - causeStackManager.pushCause(2); - - // Then we push another frame - SpongeCauseStackManager.StackFrame frame = causeStackManager.pushCauseFrame(); - causeStackManager.pushCause(3); - - Assert.assertEquals(3, causeStackManager.getCurrentCause().root()); - Assert.assertEquals(3, causeStackManager.getCurrentCause().all().size()); - - // Now pop the frame - causeStackManager.popCauseFrame(frame); - Assert.assertEquals(2, causeStackManager.getCurrentCause().root()); - Assert.assertEquals(2, causeStackManager.getCurrentCause().all().size()); - - // Remove for next tests. - causeStackManager.popCauseFrame(frame1); - } - - @Test - public void testPoppingFrameRemovesFrameContexts() throws Exception { - final SpongeCauseStackManager causeStackManager = SpongeImpl.getCauseStackManager(); - - User user = Mockito.mock(User.class); - Mockito.when(user.getName()).thenReturn("first"); - - User user2 = Mockito.mock(User.class); - Mockito.when(user.getName()).thenReturn("second"); - - // We start by pushing a frame... - SpongeCauseStackManager.StackFrame frame1 = causeStackManager.pushCauseFrame(); - causeStackManager.pushCause(1); - causeStackManager.addContext(EventContextKeys.OWNER, user); - - // Then we push another frame - SpongeCauseStackManager.StackFrame frame = causeStackManager.pushCauseFrame(); - causeStackManager.addContext(EventContextKeys.OWNER, user2); - - Assert.assertEquals(user2, causeStackManager.getContext(EventContextKeys.OWNER).get()); - - // Now pop the frame - causeStackManager.popCauseFrame(frame); - Assert.assertEquals(user, causeStackManager.getContext(EventContextKeys.OWNER).get()); - - causeStackManager.popCauseFrame(frame1); - Assert.assertFalse(causeStackManager.getContext(EventContextKeys.OWNER).isPresent()); - } - -} diff --git a/src/test/invalid/common/event/ShouldFireTest.java b/src/test/invalid/common/event/ShouldFireTest.java deleted file mode 100644 index 7f185e86cbf..00000000000 --- a/src/test/invalid/common/event/ShouldFireTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.spongepowered.api.event.EventManager; -import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.entity.SpawnEntityEvent; -import org.spongepowered.api.plugin.PluginManager; -import org.spongepowered.common.InjectedTest; -import org.spongepowered.plugin.PluginContainer; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Optional; - -public class ShouldFireTest extends InjectedTest { - - private EventManager eventManager; - private Object plugin; - private PluginContainer container; - - @Before - public void init() throws Exception { - PluginManager manager = Mockito.mock(PluginManager.class); - this.eventManager = new SpongeEventManager(this.logger, manager); - - this.plugin = new Object(); - this.container = Mockito.mock(PluginContainer.class); - Mockito.when(manager.fromInstance(this.plugin)).thenReturn(Optional.of(this.container)); - - this.resetStatics(); - } - - private void resetStatics() throws IllegalAccessException { - for (Field field: ShouldFire.class.getDeclaredFields()) { - if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) { - field.set(null, false); - } - } - } - - @Test - public void testSpawn() { - SpawnListener listener = new SpawnListener(); - - Assert.assertFalse("SPAWN_ENTITY_EVENT is not false!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - Assert.assertFalse("DROP_ITEM_EVENT_DISPENSE is not false!", ShouldFire.DROP_ITEM_EVENT_DISPENSE); - - this.eventManager.registerListeners(this.plugin, listener); - Assert.assertTrue("SPAWN_ENTITY_EVENT is not true!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - Assert.assertTrue("DROP_ITEM_EVENT_DISPENSE it not true!", ShouldFire.DROP_ITEM_EVENT_DISPENSE); - - this.eventManager.unregisterListeners(listener); - Assert.assertFalse("SPAWN_ENTITY_EVENT is not false!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - Assert.assertFalse("DROP_ITEM_EVENT_DISPENSE is not false!", ShouldFire.DROP_ITEM_EVENT_DISPENSE); - } - - @Test - public void testMultipleListeners() { - SpawnListener spawnBaseListener = new SpawnListener(); - SubListener spawnCustomListener = new SubListener(); - - Assert.assertFalse("SPAWN_ENTITY_EVENT is not false!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CUSTOM is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - - this.eventManager.registerListeners(this.plugin, spawnCustomListener); - - Assert.assertTrue("SPAWN_ENTITY_EVENT is not true!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CUSTOM is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - - this.eventManager.registerListeners(this.plugin, spawnBaseListener); - - Assert.assertTrue("SPAWN_ENTITY_EVENT is not true!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CUSTOM is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - - this.eventManager.unregisterListeners(spawnCustomListener); - - Assert.assertTrue("SPAWN_ENTITY_EVENT is not true!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CUSTOM is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM); - Assert.assertTrue("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not true!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - - this.eventManager.unregisterListeners(spawnBaseListener); - - Assert.assertFalse("SPAWN_ENTITY_EVENT is not false!", ShouldFire.SPAWN_ENTITY_EVENT); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CUSTOM is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM); - Assert.assertFalse("SPAWN_ENTITY_EVENT_CHUNK_LOAD is not false!", ShouldFire.SPAWN_ENTITY_EVENT_CHUNK_LOAD); - } - - private static class SpawnListener { - - @Listener - public void onSpawn(SpawnEntityEvent event) {} - } - - private static class SubListener { - - @Listener - public void onCustom(SpawnEntityEvent.Custom event) {} - } - -} diff --git a/src/test/invalid/common/event/SnapshotGenerationTest.java b/src/test/invalid/common/event/SnapshotGenerationTest.java deleted file mode 100644 index 8a4c04f4e80..00000000000 --- a/src/test/invalid/common/event/SnapshotGenerationTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.withSettings; - -import co.aikar.timings.Timings; -import co.aikar.timings.TimingsFactory; -import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.spongepowered.api.Game; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.EventManager; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.cause.Cause; -import org.spongepowered.api.event.cause.EventContext; -import org.spongepowered.api.event.entity.SpawnEntityEvent; -import org.spongepowered.api.plugin.PluginManager; -import org.spongepowered.common.InjectedTest; -import org.spongepowered.common.event.listener.NonPreListener; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; -import org.spongepowered.plugin.PluginContainer; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Optional; - -@RunWith(LaunchWrapperTestRunner.class) -public class SnapshotGenerationTest extends InjectedTest { - - private Entity entity; - private SpawnEntityEvent event; - private EventManager eventManager; - private Object plugin; - - @Before - public void init() { - PluginManager manager = Mockito.mock(PluginManager.class); - this.eventManager = new SpongeEventManager(this.logger, manager); - - try { - Field field = Timings.class.getDeclaredField("factory"); - field.setAccessible(true); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - - field.set(null, Mockito.mock(TimingsFactory.class)); - } catch (IllegalAccessException | NoSuchFieldException e) { - e.printStackTrace(); - } - - this.plugin = new Object(); - PluginContainer container = Mockito.mock(PluginContainer.class); - Mockito.when(manager.fromInstance(this.plugin)).thenReturn(Optional.of(container)); - - Cause cause = Cause.of(EventContext.empty(), this); - this.entity = Mockito.mock(Entity.class, withSettings().defaultAnswer(Mockito.RETURNS_MOCKS)); - - this.event = SpongeEventFactory.createSpawnEntityEvent(cause, Lists.newArrayList(this.entity)); - - Game game = mock(Game.class); - CauseStackManager csm = mock(CauseStackManager.class); - Mockito.when(game.getCauseStackManager()).thenReturn(csm); - } - - @Test - public void testPreListener() { - this.eventManager.registerListeners(this.plugin, new PreListener()); - this.eventManager.registerListeners(this.plugin, new NonPreListener()); - this.eventManager.post(this.event); - - verify(this.entity).createSnapshot(); - this.event.getEntitySnapshots(); - } - - @Test(expected = IllegalStateException.class) - public void testNonPreListener() { - this.eventManager.post(this.event); - this.event.getEntitySnapshots(); - } - -} diff --git a/src/test/invalid/common/launch/TestTweaker.java b/src/test/invalid/common/launch/TestTweaker.java deleted file mode 100644 index 15157d70ef9..00000000000 --- a/src/test/invalid/common/launch/TestTweaker.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.launch; - -import static org.spongepowered.asm.mixin.MixinEnvironment.Side.SERVER; - -import net.minecraft.launchwrapper.LaunchClassLoader; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.Mixins; -import org.spongepowered.lwts.AbstractTestTweaker; - -import java.io.File; - -public class TestTweaker extends AbstractTestTweaker { - - @Override - public void injectIntoClassLoader(LaunchClassLoader loader) { - super.injectIntoClassLoader(loader); - loader.addClassLoaderExclusion("org.slf4j."); - - registerAccessTransformer("META-INF/common_at.cfg"); - - SpongeLaunch.initPaths(new File(".")); - - SpongeLaunch.setupMixinEnvironment(); - Mixins.addConfiguration("mixins.common.test.json"); - MixinEnvironment.getDefaultEnvironment().setSide(SERVER); - } - - @Override - public String getLaunchTarget() { - return "org.spongepowered.common.test.TestMain"; - } - -} diff --git a/src/test/invalid/common/launch/mixin/ItemMixin_Test.java b/src/test/invalid/common/launch/mixin/ItemMixin_Test.java deleted file mode 100644 index 55bd87771f8..00000000000 --- a/src/test/invalid/common/launch/mixin/ItemMixin_Test.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.launch.mixin; - -import net.minecraft.item.Item; -import net.minecraft.util.ResourceLocation; -import org.spongepowered.api.item.ItemType; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(value = Item.class, remap = false) -public abstract class ItemMixin_Test { - - // Register items - @Inject(method = "registerItem(ILnet/minecraft/util/ResourceLocation;Lnet/minecraft/item/Item;)V", at = @At("RETURN")) - private static void registerMinecraftItem(final int id, final ResourceLocation name, final Item item, final CallbackInfo ci) { - ItemTypeRegistryModule.getInstance().registerAdditionalCatalog((ItemType) item); - } - -} diff --git a/src/test/invalid/common/launch/mixin/SchematicTranslatorMixin_Test.java b/src/test/invalid/common/launch/mixin/SchematicTranslatorMixin_Test.java deleted file mode 100644 index d7bbf90c2aa..00000000000 --- a/src/test/invalid/common/launch/mixin/SchematicTranslatorMixin_Test.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.launch.mixin; - -import net.minecraft.util.datafix.DataFixer; -import net.minecraft.util.datafix.DataFixesManager; -import org.spongepowered.api.data.DataView; -import org.spongepowered.api.world.schematic.Schematic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.data.persistence.SchematicTranslator; - -@Mixin(value = SchematicTranslator.class, remap = false) -public class SchematicTranslatorMixin_Test { - - @Shadow private static DataFixer VANILLA_FIXER; - - @Inject(method = "translate(Lorg/spongepowered/api/data/DataView;)Lorg/spongepowered/api/world/schematic/Schematic;", at = @At("HEAD")) - private void setDummyDataFixer(final DataView unprocessed, final CallbackInfoReturnable cir) { - VANILLA_FIXER = DataFixesManager.createFixer(); - } -} diff --git a/src/test/invalid/common/launch/mixin/SpongeImplHooksMixin_Test.java b/src/test/invalid/common/launch/mixin/SpongeImplHooksMixin_Test.java deleted file mode 100644 index b2603789bf1..00000000000 --- a/src/test/invalid/common/launch/mixin/SpongeImplHooksMixin_Test.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.launch.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.common.SpongeImplHooks; - -@Mixin(value = SpongeImplHooks.class, remap = false) -public class SpongeImplHooksMixin_Test { - - /** - * @author gabizou - unit test - * @reason unit test. - * - * @return - */ - @Overwrite - public static boolean isMainThread() { - return true; - } -} diff --git a/src/test/invalid/common/registry/CatalogTypeClassesTest.java b/src/test/invalid/common/registry/CatalogTypeClassesTest.java deleted file mode 100644 index 7c06af208a7..00000000000 --- a/src/test/invalid/common/registry/CatalogTypeClassesTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.registry; - -import static org.junit.Assume.assumeFalse; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.spongepowered.api.registry.RegistryException; -import org.spongepowered.lwts.runner.LaunchWrapperParameterized; - -import java.lang.reflect.Field; - -@RunWith(LaunchWrapperParameterized.class) -public class CatalogTypeClassesTest { - - @Parameterized.Parameters(name = "{index} Catalog Type: {1} Field : {0}") - public static Iterable data() throws Exception { - return RegistryTestUtil.generateCatalogContainerTestObjects(); - } - - @Parameterized.Parameter(0) public String fieldName; - @Parameterized.Parameter(1) public Class catalogClass; - @Parameterized.Parameter(2) public Class catalogContainerClass; - @Parameterized.Parameter(3) public CatalogRegistryModule registryModule; - @Parameterized.Parameter(4) public Field targetedField; - - private boolean isDummy = false; - - @Test - public void testCatalogFieldExists() throws Exception { - try { - final CatalogType o = (CatalogType) this.targetedField.get(null); - o.getId(); // Validates that the field is not a dummy object. If it is, it will throw an exception. - } catch (Exception e) { - this.isDummy = true; - throw e; - } - } - - @Test - public void testCatalogCanBeRetrieved() throws Exception { - assumeFalse(this.isDummy); - final CatalogType o = (CatalogType) this.targetedField.get(null); - this.registryModule.getById(o.getId()) - .orElseThrow(() -> new RegistryException("Could not locate " + this.fieldName + " in the registry: " + this.registryModule)); - } - -} diff --git a/src/test/invalid/common/registry/CatalogTypeMethodTest.java b/src/test/invalid/common/registry/CatalogTypeMethodTest.java deleted file mode 100644 index 134f5443c86..00000000000 --- a/src/test/invalid/common/registry/CatalogTypeMethodTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.registry; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.spongepowered.lwts.runner.LaunchWrapperParameterized; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; - -@RunWith(LaunchWrapperParameterized.class) -public class CatalogTypeMethodTest { - - private static final Logger LOG = LoggerFactory.getLogger(CatalogTypeMethodTest.class); - - @Parameterized.Parameters(name = "{index} Catalog Type: {0} Id : {3} Method: {5} ({6})") - public static Iterable data() throws Exception { - return RegistryTestUtil.generateCatalogTypeMethodTestObjects(); - } - - // TODO: Fix this list - private static final Set ignoredFailures = ImmutableSet.builder() - .add("org.spongepowered.common.statistic.SpongeEntityStatistic#getEntityType()") - .add("org.spongepowered.common.world.gen.SpongePopulatorType#getTranslation()") - .add("net.minecraft.util.EnumHand#getTranslation()") - // AbstractMethodErrors - .add("net.minecraft.block.BlockDirt$DirtType#getTranslation()") - .add("net.minecraft.block.BlockPistonExtension$EnumPistonType#getTranslation()") - .add("net.minecraft.block.BlockPrismarine$EnumType#getTranslation()") - .add("net.minecraft.block.BlockQuartz$EnumType#getTranslation()") - .add("net.minecraft.block.BlockSand$EnumType#getTranslation()") - .add("net.minecraft.block.BlockSandStone$EnumType#getTranslation()") - .add("net.minecraft.block.BlockStone$EnumType#getTranslation()") - .add("net.minecraft.block.BlockStoneBrick$EnumType#getTranslation()") - .add("net.minecraft.block.BlockStoneSlab$EnumType#getTranslation()") - .add("net.minecraft.block.BlockStoneSlabNew$EnumType#getTranslation()") - .add("net.minecraft.item.ItemArmor$ArmorMaterial#getRepairItemType()") - .build(); - - // Ignored translation prefixes + whether it was provided by sponge - private static final Map ignoredTranslationPrefixes = ImmutableMap.builder() - .put("sponge.statistic.type.", true) - .put("item.", false) - .put("entity.", false) - .put("stat.", false) - .put("tile.", false) - .put("potion.effect.missing", false) // Needs API changes - .put("gameMode.", false) - .build(); - - @Parameterized.Parameter(0) - public String name; - @Parameterized.Parameter(1) - public Class catalogClass; - @Parameterized.Parameter(2) - public CatalogType catalogType; - @Parameterized.Parameter(3) - public String catalogId; - @Parameterized.Parameter(4) - public Method method; - @Parameterized.Parameter(5) - public String methodName; - @Parameterized.Parameter(6) - public String implementationClass; - - @Test - public void testCatalogMethodImpl() throws Throwable { - try { - try { - testResult(checkNotNull(this.method.invoke(this.catalogType), "return value")); - } catch (InvocationTargetException e) { - // Unwrap exception to avoid useless stacktrace entries - if (e.getCause() != null) { - throw e.getCause(); - } - throw e; - } - } catch (Throwable t) { - if (ignoredFailures.contains(this.implementationClass + "#" + this.method.getName() + "()")) { -// LOG.warn("Catalog Type: {} Id : {} has broken Method: {} ({}): {}", this.name, this.catalogId, this.methodName, this.implementationClass, t); - return; - } - throw t; - } - } - - private void testResult(Object object) { - checkNotNull(object, "contained value"); - if (object instanceof Optional) { - ((Optional) object).ifPresent(this::testResult); - } - if (object instanceof Iterable) { - int index = 0; - for (Object elem : (Iterable) object) { - try { - testResult(elem); - index++; - } catch (Throwable t) { - throw new RuntimeException("Failed on sub-element: " + index, t); - } - } - } - if (object instanceof Translatable) { - testResult(((Translatable) object).getTranslation()); - } - if (object instanceof Translation) { - Translation translation = (Translation) object; - String translationId = checkNotNull(translation.getId(), "translationId"); - String translated = checkNotNull(translation.get(), "translated"); - if (translationId.equals(translated)) { - boolean ignore = false; - boolean silent = false; - for (Entry entry : ignoredTranslationPrefixes.entrySet()) { - if (translationId.startsWith(entry.getKey())) { - ignore = true; - silent = entry.getValue(); - } - } - if (silent) { - // Do nothing - } else if (ignore) { - // Disabling logging for now, until someone ends up fixing the translations and tests. - // LOG.warn("Catalog Type: {} Id : {} fails to provide translation: '{}' in {} ({})", this.name, this.catalogId, translationId, this.methodName, this.implementationClass); - } else { - throw new RuntimeException("No translation present for " + translationId); - } - } - } - } - -} diff --git a/src/test/invalid/common/registry/RegistryModuleTest.java b/src/test/invalid/common/registry/RegistryModuleTest.java deleted file mode 100644 index d0933ac796a..00000000000 --- a/src/test/invalid/common/registry/RegistryModuleTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.registry; - - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.spongepowered.lwts.runner.LaunchWrapperParameterized; - -@RunWith(LaunchWrapperParameterized.class) -public class RegistryModuleTest { - - @Parameterized.Parameters(name = "{index} Catalog Type: {0} Id : {4}") - public static Iterable data() throws Exception { - return RegistryTestUtil.generateRegistryTestObjects(); - } - - @Parameterized.Parameter(0) public String name; - @Parameterized.Parameter(1) public Class catalogClass; - @Parameterized.Parameter(2) public CatalogRegistryModule registryModule; - @Parameterized.Parameter(3) public CatalogType catalogType; - @Parameterized.Parameter(4) public String catalogId; - -// @Test -// @Ignore -// public void testIdValidity() { -// assertThat("The CatalogType " + this.catalogType.getName() + " has an invalid id", this.catalogId.startsWith("minecraft:") || this.catalogId.startsWith("sponge:")); -// assertThat("The CatalogType " + this.catalogType.getName() + " has spaces! It should never be spaced!", !this.catalogId.contains(" ")); -// } - - @Test - public void testGetCatalogTypeFromAll() { - final boolean contains = this.registryModule.getAll().contains(this.catalogType); - assertThat("The CatalogType " + this.catalogType.getId() + " could not be located in the \n" - + "all collection of " + this.registryModule.getClass().getSimpleName() + ".", - contains, is(true)); - } - - @Test - public void testGetCatalogTypeById() { - assertThat("The CatalogType " + this.catalogType.getId() + " could not be retrieved by id \n" - + "from " + this.registryModule.getClass().getSimpleName() + " with the following id: \n" - + this.catalogId, - this.registryModule.getById(this.catalogType.getId()).isPresent(), is(true)); - } - - -} diff --git a/src/test/invalid/common/registry/RegistryTestUtil.java b/src/test/invalid/common/registry/RegistryTestUtil.java deleted file mode 100644 index ed21337f36c..00000000000 --- a/src/test/invalid/common/registry/RegistryTestUtil.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.registry; - -import org.spongepowered.api.util.annotation.CatalogedBy; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -class RegistryTestUtil { - - static Iterable generateRegistryTestObjects() { - - final ArrayList array = new ArrayList<>(); - for (Map.Entry, CatalogRegistryModule> entry : SpongeGameRegistry.REGISTRY_MAP.entrySet()) { - for (CatalogType catalogType : entry.getValue().getAll()) { - array.add(new Object[]{entry.getKey().getSimpleName(), entry.getKey(), entry.getValue(), catalogType, catalogType.getId()}); - } - } - return array; - } - - static Iterable generateCatalogContainerTestObjects() { - - final ArrayList objects = new ArrayList<>(); - for (Map.Entry, CatalogRegistryModule> entry : SpongeGameRegistry.REGISTRY_MAP.entrySet()) { - final Class key = entry.getKey(); - final CatalogedBy catalogedBy = key.getAnnotation(CatalogedBy.class); - if (catalogedBy != null) { - for (Class containerClass : catalogedBy.value()) { - for (Field field : containerClass.getFields()) { - if (Modifier.isStatic(field.getModifiers())) { - objects.add(new Object[] {field.getName(), entry.getKey(), containerClass, entry.getValue(), field}); - } - } - } - } - } - - return objects; - } - - static Iterable generateCatalogTypeMethodTestObjects() { - - final ArrayList array = new ArrayList<>(); - for (Map.Entry, CatalogRegistryModule> entry : SpongeGameRegistry.REGISTRY_MAP.entrySet()) { - for (CatalogType catalogType : entry.getValue().getAll()) { - for (Method method : getTestableApiMethods(getApplicableApiCatalogTypeInterfaces(catalogType))) { - array.add(new Object[] {entry.getKey().getSimpleName(), entry.getKey(), catalogType, catalogType.getId(), method, - method.getDeclaringClass().getSimpleName() + "#" + method.getName() + "()", catalogType.getClass().getName()}); - } - } - } - return array; - } - - static Stream> getApplicableApiInterfaces(Object instance) { - Collection> interfaces = new LinkedHashSet<>(); - Class current = instance.getClass(); - while (current != null) { - interfaces.addAll(Arrays.asList(current.getInterfaces())); - current = current.getSuperclass(); - } - return interfaces.stream() - .filter(clazz -> clazz.getName().startsWith("org.spongepowered.api.")); - } - - static Stream> getApplicableApiCatalogTypeInterfaces(Object instance) { - return getApplicableApiInterfaces(instance) - .filter(CatalogType.class::isAssignableFrom) - .map(clazz -> clazz.asSubclass(CatalogType.class)); - } - - static Set getTestableApiMethods(Stream> clazzes) { - return clazzes.map(Class::getMethods) - .flatMap(Arrays::stream) - .filter(m -> m.getParameters().length == 0) - .collect(Collectors.toSet()); - } - -} diff --git a/src/test/invalid/common/regression/registry/Test1Tile.java b/src/test/invalid/common/regression/registry/Test1Tile.java deleted file mode 100644 index 9e959f85276..00000000000 --- a/src/test/invalid/common/regression/registry/Test1Tile.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.regression.registry; - -import net.minecraft.tileentity.TileEntity; - -public final class Test1Tile extends TileEntity { } diff --git a/src/test/invalid/common/regression/registry/Test2Tile.java b/src/test/invalid/common/regression/registry/Test2Tile.java deleted file mode 100644 index 90faf1c8bc4..00000000000 --- a/src/test/invalid/common/regression/registry/Test2Tile.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.regression.registry; - -import net.minecraft.tileentity.TileEntity; - -public final class Test2Tile extends TileEntity { } diff --git a/src/test/invalid/common/regression/registry/Test3Tile.java b/src/test/invalid/common/regression/registry/Test3Tile.java deleted file mode 100644 index 583dde5cbc0..00000000000 --- a/src/test/invalid/common/regression/registry/Test3Tile.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.regression.registry; - -import net.minecraft.tileentity.TileEntity; - -public final class Test3Tile extends TileEntity { } diff --git a/src/test/invalid/common/regression/registry/TileEntityRegistrationTest.java b/src/test/invalid/common/regression/registry/TileEntityRegistrationTest.java deleted file mode 100644 index 625a3d4824c..00000000000 --- a/src/test/invalid/common/regression/registry/TileEntityRegistrationTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.regression.registry; - -import static org.junit.Assert.assertEquals; - -import com.flowpowered.math.vector.Vector3i; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.chunk.storage.AnvilSaveHandler; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.spongepowered.api.block.tileentity.TileEntityType; -import org.spongepowered.common.registry.type.block.TileEntityTypeRegistryModule; -import org.spongepowered.common.test.RegressionTest; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -@RunWith(LaunchWrapperTestRunner.class) -public class TileEntityRegistrationTest { - - - @RegressionTest(ghIssue = "https://github.com/SpongePowered/SpongeForge/issues/2761", - relatedCommits = "https://github.com/SpongePowered/sponge/commit/2e394dc71f03026f937ad332eab57020eb55e536" - ) - public static final String UNQUALIFIED_TILE_ID = "mod.you.are"; - public static final String CORRECTLY_QUALIFIED_ID = "sponge:myfodo"; - public static final String MINECRAFT_PREFIXED_ID = "minecraft:mod.and.youAreMySamwise"; - - @BeforeClass - public static void setupSchematic() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - // Idea: register a few dummy tile entities with the following: - // 'mod.sponge.herpaderpa' - // 'sponge:herpaderpderp' - // 'minecraft:mod.sponge.herpadpera' - final Method tileRegisterMethod = TileEntity.class.getDeclaredMethod("register", String.class, Class.class); - tileRegisterMethod.setAccessible(true); - tileRegisterMethod.invoke(null, UNQUALIFIED_TILE_ID, Test1Tile.class); - tileRegisterMethod.invoke(null, CORRECTLY_QUALIFIED_ID, Test2Tile.class); - tileRegisterMethod.invoke(null, MINECRAFT_PREFIXED_ID, Test3Tile.class); - } - - /** - * This verifies that our custom tile entity types are being registered, both as sponge mod prefixed, and - * the rare case where a forge mod is being registered as "minecraft:" prefixed. These come into play for the - * required mods section of schematics. - */ - @RegressionTest(ghIssue = "https://github.com/SpongePowered/SpongeForge/issues/2785") - @SuppressWarnings("ConstantConditions") - @Test - public void testGettingTileEntityTypes() { - final TileEntityType test1type = TileEntityTypeRegistryModule.getInstance().getForClass(Test1Tile.class); - final TileEntityType test2type = TileEntityTypeRegistryModule.getInstance().getForClass(Test2Tile.class); - final TileEntityType test3type = TileEntityTypeRegistryModule.getInstance().getForClass(Test3Tile.class); - - @RegressionTest(ghIssue = "https://github.com/SpongePowered/SpongeForge/issues/2785", - comment = "Specifically put, Forge has a weird case where they auto-prefix mod provided" - + "id's " - ) - final String autoPrefixed = "sponge:" + UNQUALIFIED_TILE_ID; - assertEquals(autoPrefixed, test1type.getId()); // Note that SpongeImplHooks by default will prefix based on package, so we're good. - assertEquals(CORRECTLY_QUALIFIED_ID, test2type.getId()); - assertEquals(MINECRAFT_PREFIXED_ID, test3type.getId()); - - assertEquals(((org.spongepowered.api.block.tileentity.TileEntity) (Object) new Test1Tile()).getType(), test1type); - assertEquals(((org.spongepowered.api.block.tileentity.TileEntity) (Object) new Test2Tile()).getType(), test2type); - assertEquals(((org.spongepowered.api.block.tileentity.TileEntity) (Object) new Test3Tile()).getType(), test3type); - } -} diff --git a/src/test/invalid/common/service/pagination/PaginationCalculatorTest.java b/src/test/invalid/common/service/pagination/PaginationCalculatorTest.java deleted file mode 100644 index d3b7a416dd8..00000000000 --- a/src/test/invalid/common/service/pagination/PaginationCalculatorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.service.game.pagination; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; - -import org.junit.Before; -import org.junit.Test; -import org.spongepowered.api.text.channel.MessageReceiver; - -public class PaginationCalculatorTest { - - PaginationCalculator pc; - private MessageReceiver src; - - @Before - public void setUp() throws Exception { - this.pc = new PaginationCalculator(10); - this.src = mock(MessageReceiver.class); - } - - @Test - public void linesTest() throws Exception { - int lines = this.pc.getLinesPerPage(this.src); - assertEquals("Lines per page should be 10", 10, lines); - //Current implementation doesn't use source, update tests once PaginationCalculator is actually source specific. - verifyZeroInteractions(this.src); - } - -} diff --git a/src/test/invalid/common/test/RegressionTest.java b/src/test/invalid/common/test/RegressionTest.java deleted file mode 100644 index 56fedcc69de..00000000000 --- a/src/test/invalid/common/test/RegressionTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * An annotation used to mark tests that ensure that a specific - * Sponge issue has not regressed. These will usually, but not always, - * be written using Mctester. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.LOCAL_VARIABLE}) -public @interface RegressionTest { - - /** - * A fully-qualified link to the GitHub issue being tested by this test. - * - *

Example: 'https://github.com/SpongePowered/Sponge/issues/1945'

- * - * @return The URL of the issue - */ - String ghIssue(); - - /** - * A fully qualified link to a commit related to the issue where possible - * regressions took place as a byproduct to said commits. - * - *

Example: 'https://github.com/SpongePowered/Sponge/commit/2e394dc71f03026f937ad332eab57020eb55e536'

- * - * @return The URL of the related commits - */ - String[] relatedCommits() default {}; - - /** - * Any additional comments about the regresion issue that can be made, maybe outside - * the javadoc comment of the overall test. - * - * @return The comment about the regression to avoid - */ - String comment() default ""; - -} diff --git a/src/test/invalid/common/test/TestGame.java b/src/test/invalid/common/test/TestGame.java deleted file mode 100644 index a526e498a6e..00000000000 --- a/src/test/invalid/common/test/TestGame.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import org.spongepowered.api.Server; -import org.spongepowered.common.SpongeGame; - -import java.nio.file.Path; - -@Singleton -public class TestGame extends SpongeGame { - - private TestServer server; - - @Inject - public TestGame(TestServer server) { - this.server = server; - } - - @Override - public boolean isServerAvailable() { - return false; - } - - @Override - public Server getServer() { - return this.server; - } - - @Override - public Path getSavesDirectory() { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/test/invalid/common/test/TestMain.java b/src/test/invalid/common/test/TestMain.java deleted file mode 100644 index 173584d1e1d..00000000000 --- a/src/test/invalid/common/test/TestMain.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import com.google.inject.Guice; -import net.minecraft.init.Bootstrap; -import org.spongepowered.common.inject.SpongeModule; -import org.spongepowered.common.test.inject.TestImplementationModule; - -public final class TestMain { - - private TestMain() { - } - - public static void main(String[] args) { - Bootstrap.register(); - SpongeGameRegistry registry = Guice.createInjector(new SpongeModule(), new TestImplementationModule()) - .getInstance(SpongeGameRegistry.class); - - registry.preRegistryInit(); - registry.preInit(); - registry.init(); - registry.postInit(); - } - -} diff --git a/src/test/invalid/common/test/TestServer.java b/src/test/invalid/common/test/TestServer.java deleted file mode 100644 index 43b7e3e968c..00000000000 --- a/src/test/invalid/common/test/TestServer.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test; - -import com.google.inject.Singleton; -import org.spongepowered.api.Server; -import org.spongepowered.api.command.source.ConsoleSource; -import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.profile.GameProfileManager; -import org.spongepowered.api.resourcepack.ResourcePack; -import org.spongepowered.api.scoreboard.Scoreboard; -import org.spongepowered.api.world.ChunkTicketManager; -import org.spongepowered.api.world.World; -import org.spongepowered.api.world.WorldArchetype; -import org.spongepowered.api.world.storage.ChunkLayout; -import org.spongepowered.api.world.storage.WorldProperties; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.Collections; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -@Singleton -public class TestServer implements Server { - - @Override - public Collection getOnlinePlayers() { - return Collections.emptyList(); - } - - @Override - public int getMaxPlayers() { - return 0; - } - - @Override - public Optional getPlayer(UUID uniqueId) { - return Optional.empty(); - } - - @Override - public Optional getPlayer(String name) { - return Optional.empty(); - } - - @Override - public Collection getWorlds() { - return Collections.emptyList(); - } - - @Override - public Collection getUnloadedWorlds() { - return Collections.emptyList(); - } - - @Override - public Collection getAllWorldProperties() { - return Collections.emptyList(); - } - - @Override - public Optional getWorld(UUID uniqueId) { - return Optional.empty(); - } - - @Override - public Optional getWorld(String worldName) { - return Optional.empty(); - } - - @Override - public Optional getDefaultWorld() { - return Optional.empty(); - } - - @Override - public String getDefaultWorldName() { - return "test"; - } - - @Override - public Optional loadWorld(String worldName) { - return Optional.empty(); - } - - @Override - public Optional loadWorld(UUID uniqueId) { - return Optional.empty(); - } - - @Override - public Optional loadWorld(WorldProperties properties) { - return Optional.empty(); - } - - @Override - public Optional getWorldProperties(String worldName) { - return Optional.empty(); - } - - @Override - public Optional getWorldProperties(UUID uniqueId) { - return Optional.empty(); - } - - @Override - public boolean unloadWorld(World world) { - return false; - } - - @Override - public WorldProperties createWorldProperties(String folderName, WorldArchetype archetype) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture> copyWorld(WorldProperties worldProperties, String copyName) { - throw new UnsupportedOperationException(); - } - - @Override - public Optional renameWorld(WorldProperties worldProperties, String newName) { - return Optional.empty(); - } - - @Override - public CompletableFuture deleteWorld(WorldProperties worldProperties) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean saveWorldProperties(WorldProperties properties) { - return false; - } - - @Override - public Optional getServerScoreboard() { - return Optional.empty(); - } - - @Override - public ChunkLayout getChunkLayout() { - throw new UnsupportedOperationException(); - } - - @Override - public int getRunningTimeTicks() { - return 0; - } - - @Override - public MessageChannel getBroadcastChannel() { - throw new UnsupportedOperationException(); - } - - @Override - public void setBroadcastChannel(MessageChannel channel) { - throw new UnsupportedOperationException(); - - } - - @Override - public Optional getBoundAddress() { - return Optional.empty(); - } - - @Override - public boolean hasWhitelist() { - return false; - } - - @Override - public void setHasWhitelist(boolean enabled) { - throw new NoSuchElementException(); - } - - @Override - public boolean getOnlineMode() { - return false; - } - - @Override - public Text getMotd() { - throw new UnsupportedOperationException(); - } - - @Override - public void shutdown() { - throw new UnsupportedOperationException(); - } - - @Override - public void shutdown(Text kickMessage) { - throw new UnsupportedOperationException(); - } - - @Override - public ConsoleSource getConsole() { - throw new NoSuchElementException(); - } - - @Override - public ChunkTicketManager getChunkTicketManager() { - throw new NoSuchElementException(); - } - - @Override - public GameProfileManager getGameProfileManager() { - throw new NoSuchElementException(); - } - - @Override - public double getTicksPerSecond() { - return 0; - } - - @Override - public Optional getDefaultResourcePack() { - return Optional.empty(); - } - - @Override - public int getPlayerIdleTimeout() { - return 0; - } - - @Override - public void setPlayerIdleTimeout(int timeout) { - - } - - @Override - public boolean isMainThread() { - return true; - } -} diff --git a/src/test/invalid/common/test/inject/TestImplementationModule.java b/src/test/invalid/common/test/inject/TestImplementationModule.java deleted file mode 100644 index 997e6ea6cfe..00000000000 --- a/src/test/invalid/common/test/inject/TestImplementationModule.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.test.inject; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.spongepowered.api.Platform; -import org.spongepowered.api.Server; -import org.spongepowered.api.event.EventManager; -import org.spongepowered.api.network.ChannelRegistrar; -import org.spongepowered.api.plugin.PluginManager; -import org.spongepowered.common.SpongeGame; -import org.spongepowered.common.SpongeImpl; -import org.spongepowered.common.inject.SpongeImplementationModule; -import org.spongepowered.common.test.TestGame; -import org.spongepowered.common.test.TestServer; -import org.spongepowered.plugin.PluginContainer; - -import java.util.Optional; - -public class TestImplementationModule extends SpongeImplementationModule { - - @Override - protected void configure() { - super.configure(); - - this.bind(Server.class).to(TestServer.class); - this.bind(SpongeGame.class).to(TestGame.class); - Platform platform = mock(Platform.class); - when(platform.getExecutionType()).thenReturn(Platform.Type.SERVER); - PluginContainer mock = mock(PluginContainer.class); - when(platform.getContainer(any())).thenReturn(mock); - this.bind(Platform.class).toInstance(platform); - - PluginManager manager = mock(PluginManager.class); - when(mock.getId()).thenReturn("sponge"); - when(manager.getPlugin(anyString())).thenReturn(Optional.of(mock)); - when(manager.fromInstance(any())).thenReturn(Optional.of(mock)); - this.bind(PluginManager.class).toInstance(manager); - PluginContainer common = mock(PluginContainer.class); - SpongeImpl.setSpongePlugin(common); - this.bind(EventManager.class).toInstance(mock(EventManager.class)); - this.bind(ChannelRegistrar.class).toInstance(mock(ChannelRegistrar.class)); - } -} diff --git a/src/test/invalid/common/text/LegacyParserTest.java b/src/test/invalid/common/text/LegacyParserTest.java deleted file mode 100644 index acef8be771d..00000000000 --- a/src/test/invalid/common/text/LegacyParserTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.text; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; - -@RunWith(LaunchWrapperTestRunner.class) -public class LegacyParserTest { - - private static Text parse(String input) { - return TextSerializers.FORMATTING_CODE.deserialize(input); - } - - @Test - public void testPlain() { - assertEquals(Text.EMPTY, parse("")); - assertEquals(Text.of("&&"), parse("&&")); - assertEquals(Text.of("Sponge"), parse("Sponge")); - assertEquals(Text.of("Sponge & Water"), parse("Sponge & Water")); - } - - @Test - public void testSimple() { - assertEquals(Text.builder("Sponge").color(TextColors.GOLD).build(), parse("&6Sponge")); - } - - @Test - public void testMany() { - assertEquals(Text.builder("Hello ").append(Text.builder("Sponge").color(TextColors.YELLOW).build()).build(), - parse("Hello &eSponge")); - assertEquals(Text.builder().append( - Text.builder("Sponge").color(TextColors.YELLOW).style(TextStyles.BOLD).build(), - Text.builder(" & ").color(TextColors.RESET).build(), - Text.builder("Water").color(TextColors.AQUA).style(TextStyles.ITALIC).build()).build(), - parse("&e&lSponge&r & &b&oWater")); - } - - @Test - public void testRedundantFormattingCodes() { - assertEquals(Text.EMPTY, parse("&c&e&l&f")); - assertEquals(Text.builder("Hello ").append(Text.builder("Sponge").color(TextColors.YELLOW).build()).build(), - parse("Hello &a&f&e&eSponge")); - } - -} diff --git a/src/test/invalid/common/text/LegacySerializerTest.java b/src/test/invalid/common/text/LegacySerializerTest.java deleted file mode 100644 index cd192d8fe1b..00000000000 --- a/src/test/invalid/common/text/LegacySerializerTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.text; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.spongepowered.common.text.SpongeTexts.COLOR_CHAR; - -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.TextFormatting; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; - -@RunWith(LaunchWrapperTestRunner.class) -public class LegacySerializerTest { - - @Test - public void testPlainText() { - assertThat(SpongeTexts.toLegacy(new TextComponentString("test")), is("test")); - } - - @Test - public void testTranslatableText() { - assertThat(SpongeTexts.toLegacy(new TextComponentTranslation("test")), is("test")); - } - - @Test - public void testColoredText() { - ITextComponent component = new TextComponentString("test"); - component.getStyle().setColor(TextFormatting.RED); - assertThat(SpongeTexts.toLegacy(component), is(COLOR_CHAR + "ctest")); - } - - @Test - public void testNestedText() { - ITextComponent component = new TextComponentString("first"); - component.getStyle().setColor(TextFormatting.RED); - - component.appendSibling(new TextComponentString("second")); - - TextComponentString component2 = new TextComponentString("third"); - component2.getStyle().setColor(TextFormatting.BLUE); - component.appendSibling(component2); - - assertThat(SpongeTexts.toLegacy(component), is(COLOR_CHAR + "cfirstsecond" + COLOR_CHAR + "9third")); - } - - @Test - public void testEmptyTranslatableText() { - assertThat(SpongeTexts.toLegacy(new TextComponentString("blah").appendSibling(new TextComponentTranslation(""))), is("blah")); - } - -} diff --git a/src/test/invalid/common/world/storage/SpongeChunkLayoutTest.java b/src/test/invalid/common/world/storage/SpongeChunkLayoutTest.java deleted file mode 100644 index 0ef2a22cbbd..00000000000 --- a/src/test/invalid/common/world/storage/SpongeChunkLayoutTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.world.storage; - -import com.flowpowered.math.vector.Vector3i; -import org.junit.Assert; -import org.junit.Test; -import org.spongepowered.api.util.Direction; - -public class SpongeChunkLayoutTest { - - @Test - public void testConstants() { - Assert.assertEquals(new Vector3i(16, 256, 16), SpongeChunkLayout.instance.getChunkSize()); - Assert.assertEquals(new Vector3i(1874999, 0, 1874999), SpongeChunkLayout.instance.getSpaceMax()); - Assert.assertEquals(new Vector3i(-1875000, 0, -1875000), SpongeChunkLayout.instance.getSpaceMin()); - Assert.assertEquals(new Vector3i(3750000, 1, 3750000), SpongeChunkLayout.instance.getSpaceSize()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.getSpaceOrigin()); - } - - @Test - public void testCoordValidation() { - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(new Vector3i(0, 0, 0))); - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(0, 0, 0)); - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(new Vector3i(1874999, 0, 1874999))); - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(1874999, 0, 1874999)); - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(new Vector3i(-1875000, 0, -1875000))); - Assert.assertTrue(SpongeChunkLayout.instance.isValidChunk(-1875000, 0, -1875000)); - - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(1875000, 0, 1874999)); - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(1874999, 1, 1874999)); - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(1874999, 0, 1875000)); - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(-1875001, 0, -1875000)); - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(-1875000, -1, -1875000)); - Assert.assertFalse(SpongeChunkLayout.instance.isValidChunk(-1875000, 0, -1875001)); - - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(0, 0, 0)); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(new Vector3i(14, 125, 9))); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(14, 125, 9)); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(15, 255, 15)); - - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(-1, 0, 0))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(0, -1, 0))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(0, 0, -1))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(-1, 0, 0)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(0, -1, 0)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(0, 0, -1)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(16, 255, 15)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(15, 256, 15)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(15, 255, 16)); - - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(0, 0, 0, 0, 0, 0)); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(new Vector3i(30, 125, -7), new Vector3i(1, 0, -1))); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(30, 125, -7, 1, 0, -1)); - Assert.assertTrue(SpongeChunkLayout.instance.isInChunk(65, 255, -33, 4, 0, -3)); - - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(-17, 0, 0), new Vector3i(-1, 0, 0))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(0, -257, 0), new Vector3i(0, -1, 0))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(new Vector3i(0, 0, -17), new Vector3i(0, 0, -1))); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(-17, 0, 0, -1, 0, 0)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(0, -257, 0, 0, -1, 0)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(0, 0, -17, 0, 0, -1)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(32, 255, 31, 1, 0, 1)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(31, 256, 31, 1, 0, 1)); - Assert.assertFalse(SpongeChunkLayout.instance.isInChunk(31, 255, 32, 1, 0, 1)); - } - - @Test - public void testCoordConversion() { - // chunk to world - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toChunk(Vector3i.ZERO).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toChunk(0, 0, 0).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toChunk(new Vector3i(15, 255, 15)).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toChunk(15, 255, 15).get()); - - Assert.assertEquals(new Vector3i(2, 0, 4), SpongeChunkLayout.instance.toChunk(new Vector3i(34, 121, 72)).get()); - Assert.assertEquals(new Vector3i(2, 0, 4), SpongeChunkLayout.instance.toChunk(34, 121, 72).get()); - - Assert.assertEquals(new Vector3i(-6, 0, -13), SpongeChunkLayout.instance.toChunk(new Vector3i(-83, 62, -203)).get()); - Assert.assertEquals(new Vector3i(-6, 0, -13), SpongeChunkLayout.instance.toChunk(-83, 62, -203).get()); - - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(30000000, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(-30000001, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(0, 256, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(0, -1, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(0, 0, 30000000).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toChunk(0, 0, -30000001).isPresent()); - - // world to chunk - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toWorld(Vector3i.ZERO).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.toWorld(0, 0, 0).get()); - - Assert.assertEquals(new Vector3i(32, 0, 64), SpongeChunkLayout.instance.toWorld(new Vector3i(2, 0, 4)).get()); - Assert.assertEquals(new Vector3i(32, 0, 64), SpongeChunkLayout.instance.toWorld(2, 0, 4).get()); - - Assert.assertEquals(new Vector3i(-96, 0, -208), SpongeChunkLayout.instance.toWorld(new Vector3i(-6, 0, -13)).get()); - Assert.assertEquals(new Vector3i(-96, 0, -208), SpongeChunkLayout.instance.toWorld(-6, 0, -13).get()); - - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(1875000, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(-1875001, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(0, 1, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(0, -1, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(0, 0, 1875000).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.toWorld(0, 0, -1875001).isPresent()); - } - - @Test - public void testCoordAdd() { - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.addToChunk(Vector3i.ZERO, Vector3i.ZERO).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.addToChunk(0, 0, 0, 0, 0, 0).get()); - - Assert.assertEquals(new Vector3i(7, 0, 5), SpongeChunkLayout.instance.addToChunk(3, 0, 5, 4, 0, 0).get()); - Assert.assertEquals(new Vector3i(7, 0, 9), SpongeChunkLayout.instance.addToChunk(3, 0, 5, 4, 0, 4).get()); - - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(1874999, 0, 0, 1, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(0, 0, 0, 0, 1, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(0, 0, 1874999, 0, 0, 1).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(-1875000, 0, 0, -1, 0, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(0, 0, 0, 0, -1, 0).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.addToChunk(0, 0, -1875000, 0, 0, -1).isPresent()); - } - - @Test - public void testCoordMove() { - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.moveToChunk(Vector3i.ZERO, Direction.NONE).get()); - Assert.assertEquals(Vector3i.ZERO, SpongeChunkLayout.instance.moveToChunk(0, 0, 0, Direction.NONE).get()); - - Assert.assertEquals(new Vector3i(4, 0, 5), SpongeChunkLayout.instance.moveToChunk(3, 0, 5, Direction.EAST).get()); - Assert.assertEquals(new Vector3i(7, 0, 5), SpongeChunkLayout.instance.moveToChunk(3, 0, 5, Direction.EAST, 4).get()); - Assert.assertEquals(new Vector3i(4, 0, 6), SpongeChunkLayout.instance.moveToChunk(3, 0, 5, Direction.SOUTHEAST).get()); - Assert.assertEquals(new Vector3i(7, 0, 9), SpongeChunkLayout.instance.moveToChunk(3, 0, 5, Direction.SOUTHEAST, 4).get()); - - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(1874999, 0, 0, Direction.EAST).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(0, 0, 0, Direction.UP).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(0, 0, 1874999, Direction.SOUTH).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(-1875000, 0, 0, Direction.WEST).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(0, 0, 0, Direction.DOWN).isPresent()); - Assert.assertFalse(SpongeChunkLayout.instance.moveToChunk(0, 0, -1875000, Direction.NORTH).isPresent()); - - try { - SpongeChunkLayout.instance.moveToChunk(0, 0, 0, Direction.SOUTH_SOUTHEAST); - Assert.fail(); - } catch (IllegalArgumentException ignored) { - // we expect this exception - } - } - -} diff --git a/src/test/invalid/common/util/IpSetTest.java b/src/test/java/org/spongepowered/common/config/core/IpSetTest.java similarity index 70% rename from src/test/invalid/common/util/IpSetTest.java rename to src/test/java/org/spongepowered/common/config/core/IpSetTest.java index 0c4381f3aff..e13decb39d8 100644 --- a/src/test/invalid/common/util/IpSetTest.java +++ b/src/test/java/org/spongepowered/common/config/core/IpSetTest.java @@ -22,12 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.util; +package org.spongepowered.common.config.core; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.spongepowered.common.launch.config.core.IpSet; import java.net.InetAddress; import java.net.UnknownHostException; @@ -36,29 +37,29 @@ public class IpSetTest { @Test public void testIpv4Set() throws UnknownHostException { IpSet spec = IpSet.fromCidr("10.42.0.0/16"); - assertTrue(spec.apply(InetAddress.getByName("10.42.2.5"))); - assertFalse(spec.apply(InetAddress.getByName("10.43.2.5"))); + assertTrue(spec.test(InetAddress.getByName("10.42.2.5"))); + assertFalse(spec.test(InetAddress.getByName("10.43.2.5"))); } @Test public void testIpv6Set() throws UnknownHostException { IpSet spec = IpSet.fromCidr("[fc00::]/8"); - assertTrue(spec.apply(InetAddress.getByName("fcc0:c0b2:2a14:7afc:5216:1854:1a2f:2c13"))); + assertTrue(spec.test(InetAddress.getByName("fcc0:c0b2:2a14:7afc:5216:1854:1a2f:2c13"))); spec = IpSet.fromCidr("::/0"); - assertTrue(spec.apply(InetAddress.getByName("::dead:beef"))); + assertTrue(spec.test(InetAddress.getByName("::dead:beef"))); } @Test public void testNonByteAlignedSets() throws UnknownHostException { IpSet spec = IpSet.fromCidr("[2064:45:300::]/40"); - assertTrue(spec.apply(InetAddress.getByName("2064:45:310::cafe"))); - assertFalse(spec.apply(InetAddress.getByName("2064:45:410::cafe"))); + assertTrue(spec.test(InetAddress.getByName("2064:45:310::cafe"))); + assertFalse(spec.test(InetAddress.getByName("2064:45:410::cafe"))); } @Test public void testFullLengthSets() throws UnknownHostException { IpSet specv4 = IpSet.fromCidr("10.0.0.1/32"); - assertTrue(specv4.apply(InetAddress.getByName("10.0.0.1"))); - assertFalse(specv4.apply(InetAddress.getByName("10.0.0.2"))); + assertTrue(specv4.test(InetAddress.getByName("10.0.0.1"))); + assertFalse(specv4.test(InetAddress.getByName("10.0.0.2"))); } } diff --git a/src/test/invalid/common/event/EventFilterTest.java b/src/test/java/org/spongepowered/common/event/EventFilterTest.java similarity index 54% rename from src/test/invalid/common/event/EventFilterTest.java rename to src/test/java/org/spongepowered/common/event/EventFilterTest.java index 7d06ee6b8ff..35e3344274f 100644 --- a/src/test/invalid/common/event/EventFilterTest.java +++ b/src/test/java/org/spongepowered/common/event/EventFilterTest.java @@ -24,65 +24,57 @@ */ package org.spongepowered.common.event; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.junit.Assert; -import org.junit.Test; +import net.kyori.adventure.text.Component; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.data.manipulator.mutable.entity.SkinData; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Cancellable; +import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.Event; -import org.spongepowered.api.event.block.ChangeBlockEvent; -import org.spongepowered.api.event.cause.Cause; -import org.spongepowered.api.event.cause.EventContext; +import org.spongepowered.api.event.EventContext; +import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.world.biome.BiomeTypes; -import org.spongepowered.api.world.extent.Extent; -import org.spongepowered.common.event.filter.FilterFactory; -import org.spongepowered.common.event.listener.AllCauseListener; -import org.spongepowered.common.event.listener.BeforeAfterCauseListener; -import org.spongepowered.common.event.listener.CancelledListener; -import org.spongepowered.common.event.listener.CovariantGetterListener; -import org.spongepowered.common.event.listener.DataHasListener; -import org.spongepowered.common.event.listener.DataSupportsListener; -import org.spongepowered.common.event.listener.DoubleListener; -import org.spongepowered.common.event.listener.FirstLastCauseListener; -import org.spongepowered.common.event.listener.GetterListener; -import org.spongepowered.common.event.listener.IncludeExcludeListener; -import org.spongepowered.common.event.listener.InvalidIncludeExcludeListener; -import org.spongepowered.common.event.listener.RootListener; -import org.spongepowered.common.event.listener.SimpleListener; +import org.spongepowered.api.world.World; +import org.spongepowered.common.event.filter.FilterGenerator; +import org.spongepowered.common.event.listener.*; +import org.spongepowered.common.event.manager.AnnotatedEventListener; +import org.spongepowered.common.event.manager.ClassEventListenerFactory; +import org.spongepowered.common.event.manager.ListenerClassVisitorHelper; import java.lang.invoke.MethodHandles; import java.util.Optional; public class EventFilterTest { - + public static final Cause TEST_CAUSE = Cause.of(EventContext.empty(), EventFilterTest.class); private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - private final AnnotatedEventListener.Factory handlerFactory = new ClassEventListenerFactory(new FilterFactory(LOOKUP), LOOKUP); + private final AnnotatedEventListener.Factory handlerFactory = new ClassEventListenerFactory(FilterGenerator::create); @Test - public void testSimpleEvent() throws Exception { + public void testSimpleEvent() throws Throwable { SimpleListener listener = new SimpleListener(); AnnotatedEventListener annotatedEventListener = this.getListener(listener, "onEvent"); annotatedEventListener.handle(new SubEvent(TEST_CAUSE)); - Assert.assertTrue("Simple listener was not called!", listener.called); + assertTrue(listener.called, "Simple listener was not called!"); } @Test - public void testDoubleListener() throws Exception { + public void testDoubleListener() throws Throwable { DoubleListener listener = new DoubleListener(); - this.getListener(listener, "onEvent", ChangeBlockEvent.Break.class, Player.class, ItemStack.class); + this.getListener(listener, "onEvent", InteractBlockEvent.Primary.class, Player.class, ItemStack.class); } @Test - public void testCancelledEvent() throws Exception { + public void testCancelledEvent() throws Throwable { CancelledListener listener = new CancelledListener(); SubEvent event = new SubEvent(TEST_CAUSE); @@ -92,31 +84,29 @@ public void testCancelledEvent() throws Exception { AnnotatedEventListener alwaysCalledListener = this.getListener(listener, "alwaysCalledListener"); normalListener.handle(event); - Assert.assertTrue("Un-annotated listener was not called when event was not cancelled!", listener.normalListenerWasCalled); + assertTrue(listener.normalListenerWasCalled, "Un-annotated listener was not called when event was not cancelled!"); alwaysCalledListener.handle(event); - Assert.assertTrue("Listener annotated with @IsCancelled(Tristate.UNDEFINED) was not called when event was not cancelled!", listener.alwaysCalledWasCalled); + assertTrue(listener.alwaysCalledWasCalled, "Listener annotated with @IsCancelled(Tristate.UNDEFINED) was not called when event was not cancelled!"); event.setCancelled(true); listener.normalListenerWasCalled = false; - /* - * normalListener.handle(event); Assert.assertFalse( - * "Un-annotated listener was called when event was cancelled!", listener.normalListenerWasCalled); - */ + normalListener.handle(event); + assertFalse(listener.normalListenerWasCalled, "Un-annotated listener was called when event was cancelled!"); uncalledListener.handle(event); - Assert.assertFalse("Listener annotated with @IsCancelled(Tristate.FALSE) was called!", listener.uncalledWasCalled); + assertFalse(listener.uncalledWasCalled, "Listener annotated with @IsCancelled(Tristate.FALSE) was called!"); afterCancelledListener.handle(event); - Assert.assertTrue("Listener annotated with @IsCancelled was not called!", listener.afterCancelledWasCalled); + assertTrue(listener.afterCancelledWasCalled, "Listener annotated with @IsCancelled was not called!"); alwaysCalledListener.handle(event); - Assert.assertTrue("Listener annotated with @IsCancelled(Tristate.UNDEFINED) was not called!", listener.alwaysCalledWasCalled); + assertTrue(listener.alwaysCalledWasCalled, "Listener annotated with @IsCancelled(Tristate.UNDEFINED) was not called!"); } @Test - public void testIncludeExcludeListener() throws Exception { + public void testIncludeExcludeListener() throws Throwable { IncludeExcludeListener listener = new IncludeExcludeListener(); AnnotatedEventListener includeListener = this.getListener(listener, "includeListener", TestEvent.class); @@ -129,37 +119,38 @@ public void testIncludeExcludeListener() throws Exception { SubEvent subEvent = new SubEvent(TEST_CAUSE); includeListener.handle(testEvent); - Assert.assertFalse("Listener annotated with @Include was called!", listener.includeListenerCalled); + assertFalse(listener.includeListenerCalled, "Listener annotated with @Include was called!"); includeListener.handle(subEvent); - Assert.assertTrue("Listener annotated with @Include was not called!", listener.includeListenerCalled); + assertTrue(listener.includeListenerCalled, "Listener annotated with @Include was not called!"); excludeListener.handle(subEvent); - Assert.assertFalse("Listener annotated with @Exclude was called!", listener.exlcudeListenerCalled); + assertFalse(listener.excludeListenerCalled, "Listener annotated with @Exclude was called!"); excludeListener.handle(testEvent); - Assert.assertTrue("Listener annotated with @Exclude was not called!", listener.exlcudeListenerCalled); + assertTrue(listener.excludeListenerCalled, "Listener annotated with @Exclude was not called!"); multiIncludeListener.handle(testEvent); - Assert.assertFalse("Listener annotated with multi-target @Include was called!", listener.multiIncludeListenerCalled); + assertFalse(listener.multiIncludeListenerCalled, "Listener annotated with multi-target @Include was called!"); multiIncludeListener.handle(subEvent); - Assert.assertTrue("Listener annotated with multi-target @Include was not called!", listener.multiIncludeListenerCalled); + assertTrue(listener.multiIncludeListenerCalled, "Listener annotated with multi-target @Include was not called!"); multiExcludeListener.handle(subEvent); - Assert.assertFalse("Listener annotated with multi-target @Exclude was called!", listener.multiExcludeListenerCalled); + assertFalse(listener.multiExcludeListenerCalled, "Listener annotated with multi-target @Exclude was called!"); multiExcludeListener.handle(testEvent); - Assert.assertTrue("Listener annotated with multi-target @Exclude was not called!", listener.multiExcludeListenerCalled); + assertTrue(listener.multiExcludeListenerCalled, "Listener annotated with multi-target @Exclude was not called!"); } - @Test(expected = RuntimeException.class) - public void testIncludeExcludeListener_InvalidListener() throws Exception { - this.getListener(new InvalidIncludeExcludeListener(), "invalidListener", TestEvent.class); + @Test + public void testIncludeExcludeListener_InvalidListener() { + assertThrows(RuntimeException.class, () -> this.getListener(new InvalidIncludeExcludeListener(), "invalidListener", TestEvent.class)); } + @Disabled @Test - public void testFirstLastCauseListener() throws Exception { + public void testFirstLastCauseListener() throws Throwable { FirstLastCauseListener listener = new FirstLastCauseListener(); AnnotatedEventListener firstCauseListener = this.getListener(listener, "firstCauseListener", SubEvent.class, Player.class); AnnotatedEventListener lastCauseListener = this.getListener(listener, "lastCauseListener", SubEvent.class, Player.class); @@ -175,34 +166,34 @@ public void testFirstLastCauseListener() throws Exception { SubEvent event2 = new SubEvent(cause2); firstCauseListener.handle(event1); - Assert.assertFalse("Listener was called with improper @First parameter!", listener.firstCauseCalled); + assertFalse(listener.firstCauseCalled, "Listener was called with improper @First parameter!"); firstCauseListener.handle(event2); - Assert.assertTrue("Listener with @First parameter was not called when proper Cause was provided!", listener.firstCauseCalled); + assertTrue(listener.firstCauseCalled, "Listener with @First parameter was not called when proper Cause was provided!"); lastCauseListener.handle(event1); - Assert.assertFalse("Listener was called with improper @Last parameter!", listener.lastCauseCalled); + assertFalse(listener.lastCauseCalled, "Listener was called with improper @Last parameter!"); lastCauseListener.handle(event2); - Assert.assertTrue("Listener with @Last parameter was not called when proper Cause was provided!", listener.lastCauseCalled); + assertTrue(listener.lastCauseCalled, "Listener with @Last parameter was not called when proper Cause was provided!"); firstCauseListenerInc.handle(event2); - Assert.assertTrue("Listener with @First with inclusions was not called when proper Cause was provided!", listener.firstCauseCalledInc); + assertTrue(listener.firstCauseCalledInc, "Listener with @First with inclusions was not called when proper Cause was provided!"); firstCauseListenerEx.handle(event2); - Assert.assertFalse("Listener with @First with exclusions was called when an improper Cause was provided!", listener.firstCauseCalledEx); + assertFalse(listener.firstCauseCalledEx, "Listener with @First with exclusions was called when an improper Cause was provided!"); lastCauseListenerInc.handle(event2); - Assert.assertTrue("Listener with @Last with inclusions was not called when proper Cause was provided!", listener.lastCauseCalledInc); + assertTrue(listener.lastCauseCalledInc, "Listener with @Last with inclusions was not called when proper Cause was provided!"); lastCauseListenerEx.handle(event2); - Assert.assertFalse("Listener with @Last with exclusions was called when an improper Cause was provided!", listener.lastCauseCalledEx); + assertFalse(listener.lastCauseCalledEx, "Listener with @Last with exclusions was called when an improper Cause was provided!"); } @Test - public void testAllCauseListener() throws Exception { + public void testAllCauseListener() throws Throwable { AllCauseListener listener = new AllCauseListener(); - AnnotatedEventListener emptyListener = this.getListener(listener, "emptyListener", SubEvent.class, BiomeTypes[].class); + AnnotatedEventListener emptyListener = this.getListener(listener, "emptyListener", SubEvent.class, Component[].class); AnnotatedEventListener allCauseListener = this.getListener(listener, "allCauseListener", SubEvent.class, Player[].class); Cause cause1 = TEST_CAUSE; @@ -212,31 +203,31 @@ public void testAllCauseListener() throws Exception { SubEvent event2 = new SubEvent(cause2); emptyListener.handle(event1); - Assert.assertTrue("Listener with @All(ignoreEmpty = false) was not called!", listener.emptyListenerCalled); + assertTrue(listener.emptyListenerCalled, "Listener with @All(ignoreEmpty = false) was not called!"); listener.emptyListenerCalled = false; emptyListener.handle(event2); - Assert.assertTrue("Listener with @All(ignoreEmpty = false) was not called!", listener.emptyListenerCalled); + assertTrue(listener.emptyListenerCalled, "Listener with @All(ignoreEmpty = false) was not called!"); allCauseListener.handle(event1); - Assert.assertFalse("Listener with @All was called with improper array parameter!", listener.allCauseListenerCalled); + assertFalse(listener.allCauseListenerCalled, "Listener with @All was called with improper array parameter!"); allCauseListener.handle(event2); - Assert.assertTrue("Listener with @All was not called when proper Cause was provided!", listener.allCauseListenerCalled); + assertTrue(listener.allCauseListenerCalled, "Listener with @All was not called when proper Cause was provided!"); } @Test - public void testDataSupportsListener() throws Exception { + public void testDataSupportsListener() throws Throwable { DataSupportsListener listener = new DataSupportsListener(); - AnnotatedEventListener supportsSkinListener = this.getListener(listener, "supportsSkinListener", SubEvent.class, Player.class); - AnnotatedEventListener inverseSupportsSkinListener = this.getListener(listener, "inverseSupportsSkinListener", SubEvent.class, Player.class); + AnnotatedEventListener supportsDisplayNameListener = this.getListener(listener, "supportsDisplayNameListener", SubEvent.class, Player.class); + AnnotatedEventListener inverseSupportsDisplayNameListener = this.getListener(listener, "inverseSupportsDisplayNameListener", SubEvent.class, Player.class); Player player1 = mock(Player.class); - when(player1.supports(SkinData.class)).thenReturn(false); + when(player1.supports(Keys.DISPLAY_NAME)).thenReturn(false); Player player2 = mock(Player.class); - when(player2.supports(SkinData.class)).thenReturn(true); + when(player2.supports(Keys.DISPLAY_NAME)).thenReturn(true); Cause cause1 = Cause.of(EventContext.empty(), player1); Cause cause2 = Cause.of(EventContext.empty(), player2); @@ -244,30 +235,30 @@ public void testDataSupportsListener() throws Exception { SubEvent event1 = new SubEvent(cause1); SubEvent event2 = new SubEvent(cause2); - supportsSkinListener.handle(event1); - Assert.assertFalse("Listener with @Supports was called!", listener.supportsSkinListenerCalled); + supportsDisplayNameListener.handle(event1); + assertFalse(listener.supportsDisplayNameListenerCalled, "Listener with @Supports was called!"); - supportsSkinListener.handle(event2); - Assert.assertTrue("Listener with @Supports was not called!", listener.supportsSkinListenerCalled); + supportsDisplayNameListener.handle(event2); + assertTrue(listener.supportsDisplayNameListenerCalled, "Listener with @Supports was not called!"); - inverseSupportsSkinListener.handle(event2); - Assert.assertFalse("Inverse listener with @Supports was called!", listener.inverseSupportsSkinListenerCalled); + inverseSupportsDisplayNameListener.handle(event2); + assertFalse(listener.inverseSupportsDisplayNameListenerCalled, "Inverse listener with @Supports was called!"); - inverseSupportsSkinListener.handle(event1); - Assert.assertTrue("Inverse listener with @Supports was not called!", listener.inverseSupportsSkinListenerCalled); + inverseSupportsDisplayNameListener.handle(event1); + assertTrue(listener.inverseSupportsDisplayNameListenerCalled, "Inverse listener with @Supports was not called!"); } @Test - public void testDataHasListener() throws Exception { + public void testDataHasListener() throws Throwable { DataHasListener listener = new DataHasListener(); - AnnotatedEventListener hasSkinListener = this.getListener(listener, "hasSkinListener", SubEvent.class, Player.class); - AnnotatedEventListener inversehasSkinListener = this.getListener(listener, "inverseHasSkinListener", SubEvent.class, Player.class); + AnnotatedEventListener hasDisplayNameListener = this.getListener(listener, "hasDisplayNameListener", SubEvent.class, Player.class); + AnnotatedEventListener inverseHasDisplayNameListener = this.getListener(listener, "inverseHasDisplayNameListener", SubEvent.class, Player.class); Player player1 = mock(Player.class); - when(player1.get(SkinData.class)).thenReturn(Optional.empty()); + when(player1.get(Keys.DISPLAY_NAME)).thenReturn(Optional.empty()); Player player2 = mock(Player.class); - when(player2.get(SkinData.class)).thenReturn(Optional.of(mock(SkinData.class))); + when(player2.get(Keys.DISPLAY_NAME)).thenReturn(Optional.of(Component.text("name"))); Cause cause1 = Cause.of(EventContext.empty(), player1); Cause cause2 = Cause.of(EventContext.empty(), player2); @@ -275,21 +266,22 @@ public void testDataHasListener() throws Exception { SubEvent event1 = new SubEvent(cause1); SubEvent event2 = new SubEvent(cause2); - hasSkinListener.handle(event1); - Assert.assertFalse("Listener with @Has was called!", listener.hasSkinListenerCalled); + hasDisplayNameListener.handle(event1); + assertFalse(listener.hasDisplayNameListenerCalled, "Listener with @Has was called!"); - hasSkinListener.handle(event2); - Assert.assertTrue("Listener with @Has was not called!", listener.hasSkinListenerCalled); + hasDisplayNameListener.handle(event2); + assertTrue(listener.hasDisplayNameListenerCalled, "Listener with @Has was not called!"); - inversehasSkinListener.handle(event2); - Assert.assertFalse("Inverse listener with @Has was called!", listener.inverseHasSkinListenerCalled); + inverseHasDisplayNameListener.handle(event2); + assertFalse(listener.inverseDisplayNameListenerCalled, "Inverse listener with @Has was called!"); - inversehasSkinListener.handle(event1); - Assert.assertTrue("Inverse listener with @Has was not called!", listener.inverseHasSkinListenerCalled); + inverseHasDisplayNameListener.handle(event1); + assertTrue(listener.inverseDisplayNameListenerCalled, "Inverse listener with @Has was not called!"); } + @Disabled @Test - public void testRootListener() throws Exception { + public void testRootListener() throws Throwable { RootListener listener = new RootListener(); AnnotatedEventListener rootListener = this.getListener(listener, "rootListener", SubEvent.class, Player.class); AnnotatedEventListener rootListenerInc = this.getListener(listener, "rootListenerInclude", SubEvent.class, Object.class); @@ -302,26 +294,27 @@ public void testRootListener() throws Exception { SubEvent event2 = new SubEvent(cause2); rootListener.handle(event1); - Assert.assertFalse("Listener with @Root was called with improper parameter!", listener.rootListenerCalled); + assertFalse(listener.rootListenerCalled, "Listener with @Root was called with improper parameter!"); rootListener.handle(event2); - Assert.assertTrue("Listener with @Root was not called when proper Cause was provided!", listener.rootListenerCalled); + assertTrue(listener.rootListenerCalled, "Listener with @Root was not called when proper Cause was provided!"); rootListenerInc.handle(event1); - Assert.assertFalse("Listener with @Root with include was called with improper parameter!", listener.rootListenerCalledInc); + assertFalse(listener.rootListenerCalledInc, "Listener with @Root with include was called with improper parameter!"); rootListenerInc.handle(event2); - Assert.assertTrue("Listener with @Root with include was not called when proper Cause was provided!", listener.rootListenerCalledInc); + assertTrue(listener.rootListenerCalledInc, "Listener with @Root with include was not called when proper Cause was provided!"); rootListenerEx.handle(event2); - Assert.assertFalse("Listener with @Root with exclude was called with improper parameter!", listener.rootListenerCalledEx); + assertFalse(listener.rootListenerCalledEx, "Listener with @Root with exclude was called with improper parameter!"); rootListenerEx.handle(event1); - Assert.assertTrue("Listener with @Root with exclude was not called when proper Cause was provided!", listener.rootListenerCalledEx); + assertTrue(listener.rootListenerCalledEx, "Listener with @Root with exclude was not called when proper Cause was provided!"); } + @Disabled @Test - public void testBeforeCauseListener() throws Exception { + public void testBeforeCauseListener() throws Throwable { BeforeAfterCauseListener listener = new BeforeAfterCauseListener(); AnnotatedEventListener beforeCauseListener = this.getListener(listener, "beforeCauseListener", SubEvent.class, Player.class); AnnotatedEventListener afterCauseListener = this.getListener(listener, "afterCauseListener", SubEvent.class, Entity.class); @@ -330,73 +323,75 @@ public void testBeforeCauseListener() throws Exception { AnnotatedEventListener afterCauseListenerInc = this.getListener(listener, "afterCauseListenerInclude", SubEvent.class, Entity.class); AnnotatedEventListener afterCauseListenerEx = this.getListener(listener, "afterCauseListenerExclude", SubEvent.class, Entity.class); - Cause cause1 = Cause.of(EventContext.empty(), "Foo", mock(Player.class), mock(Extent.class)); + Cause cause1 = Cause.of(EventContext.empty(), "Foo", mock(Player.class), mock(World.class)); Cause cause2 = Cause.of(EventContext.empty(), "Me", mock(BlockState.class), mock(Entity.class)); SubEvent event1 = new SubEvent(cause1); SubEvent event2 = new SubEvent(cause2); beforeCauseListener.handle(event2); - Assert.assertFalse("Listener with @Before was called with improper parameter!", listener.beforeCauseCalled); + assertFalse(listener.beforeCauseCalled, "Listener with @Before was called with improper parameter!"); beforeCauseListener.handle(event1); - Assert.assertTrue("Listener with @Before was not called when proper Cause was provided!", listener.beforeCauseCalled); + assertTrue(listener.beforeCauseCalled, "Listener with @Before was not called when proper Cause was provided!"); afterCauseListener.handle(event1); - Assert.assertFalse("Listener with @After was called with improper parameter!", listener.afterCauseCalled); + assertFalse(listener.afterCauseCalled, "Listener with @After was called with improper parameter!"); afterCauseListener.handle(event2); - Assert.assertTrue("Listener with @After was not called when proper Cause was provided!", listener.afterCauseCalled); + assertTrue(listener.afterCauseCalled, "Listener with @After was not called when proper Cause was provided!"); beforeCauseListenerInc.handle(event1); - Assert.assertTrue("Listener with @Before with inclusions was not called when proper Cause was provided!", listener.beforeCauseCalledInc); + assertTrue(listener.beforeCauseCalledInc, "Listener with @Before with inclusions was not called when proper Cause was provided!"); beforeCauseListenerEx.handle(event1); - Assert.assertFalse("Listener with @Before with exclusions was called when an improper Cause was provided!", listener.beforeCauseCalledEx); + assertFalse(listener.beforeCauseCalledEx, "Listener with @Before with exclusions was called when an improper Cause was provided!"); afterCauseListenerInc.handle(event2); - Assert.assertFalse("Listener with @After with inclusions was called when an improper Cause was provided!", listener.afterCauseCalledInc); + assertFalse(listener.afterCauseCalledInc, "Listener with @After with inclusions was called when an improper Cause was provided!"); afterCauseListenerEx.handle(event2); - Assert.assertTrue("Listener with @After with exclusions was not called when proper Cause was provided!", listener.afterCauseCalledEx); + assertTrue(listener.afterCauseCalledEx, "Listener with @After with exclusions was not called when proper Cause was provided!"); } @Test - public void testGetter() throws Exception { + public void testGetter() throws Throwable { GetterListener listener = new GetterListener(); AnnotatedEventListener normalListener = this.getListener(listener, "normalListener", GetterEvent.class, TestObject.class); AnnotatedEventListener subClassListener = this.getListener(listener, "subClassListener", GetterEvent.class, SubObject.class); - Cause cause = Cause.of(EventContext.empty(), Text.of()); + Cause cause = Cause.of(EventContext.empty(), Component.text()); GetterEvent normalEvent = new GetterEvent(cause, new TestObject()); GetterEvent subClassEvent = new GetterEvent(cause, new SubObject()); normalListener.handle(normalEvent); - Assert.assertTrue("Listener with @Getter was not called when the targeted getter returned the same type!", listener.normalCalled); + assertTrue(listener.normalCalled, "Listener with @Getter was not called when the targeted getter returned the same type!"); listener.normalCalled = false; normalListener.handle(subClassEvent); - Assert.assertTrue("Listener with @Getter was not called when the targeted getter returned a subtype of the expected type!", listener.normalCalled); + assertTrue(listener.normalCalled, "Listener with @Getter was not called when the targeted getter returned a subtype of the expected type!"); subClassListener.handle(normalEvent); - Assert.assertFalse("Listener with @Getter was called when the targeted getter returned a supertype! How is this even possible???", listener.subClassCalled); + assertFalse(listener.subClassCalled, + "Listener with @Getter was called when the targeted getter returned a supertype! How is this even possible???"); listener.subClassCalled = false; subClassListener.handle(subClassEvent); - Assert.assertTrue("Listener with @Getter was not called when the targeted getter returned a subtype of the expected type, which matched the parameter type!", listener.normalCalled); + assertTrue(listener.normalCalled, + "Listener with @Getter was not called when the targeted getter returned a subtype of the expected type, which matched the parameter type!"); } @Test - public void testCovariantGetter() throws Exception { + public void testCovariantGetter() throws Throwable { CovariantGetterListener listener = new CovariantGetterListener(); AnnotatedEventListener covariantListener = this.getListener(listener, "covariantListener", CovariantEvent.OverloadedEvent.class, SubObject.class); - covariantListener.handle(new CovariantEvent.OverloadedEvent(Cause.of(EventContext.empty(), Text.of()), new SubObject())); - Assert.assertTrue("Listener with @Getter targeting a method with a covariant return type was not called!", listener.covariantListenerCalled); + covariantListener.handle(new CovariantEvent.OverloadedEvent(Cause.of(EventContext.empty(), Component.text()), new SubObject())); + assertTrue(listener.covariantListenerCalled, "Listener with @Getter targeting a method with a covariant return type was not called!"); } @@ -410,7 +405,7 @@ public TestEvent(Cause cause) { } @Override - public Cause getCause() { + public Cause cause() { return this.cause; } @@ -473,7 +468,7 @@ public CovariantEvent(Cause cause, TestObject testObject) { } @Override - public Cause getCause() { + public Cause cause() { return this.cause; } @@ -494,11 +489,11 @@ public SubObject getTestObject() { } } - private AnnotatedEventListener getListener(Object listener, String method) throws Exception { + private AnnotatedEventListener getListener(Object listener, String method) throws Throwable { return this.getListener(listener, method, SubEvent.class); } - private AnnotatedEventListener getListener(Object listener, String method, Class... classes) throws Exception { - return this.handlerFactory.create(listener, listener.getClass().getMethod(method, classes)); + private AnnotatedEventListener getListener(Object listener, String methodName, Class... parameterTypes) throws Throwable { + return this.handlerFactory.create(listener, ListenerClassVisitorHelper.getMethod(listener.getClass(), methodName, parameterTypes), LOOKUP); } } diff --git a/src/test/java/org/spongepowered/common/event/ShouldFireTest.java b/src/test/java/org/spongepowered/common/event/ShouldFireTest.java new file mode 100644 index 00000000000..0e2053f629b --- /dev/null +++ b/src/test/java/org/spongepowered/common/event/ShouldFireTest.java @@ -0,0 +1,123 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.event.EventManager; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.entity.SpawnEntityEvent; +import org.spongepowered.plugin.PluginContainer; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class ShouldFireTest { + + @BeforeEach + public void resetShouldFireFields() throws IllegalAccessException { + for (Field field : ShouldFire.class.getDeclaredFields()) { + if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) { + field.set(null, false); + } + } + } + + @Test + public void testSpawn() { + final EventManager eventManager = Sponge.eventManager(); + final PluginContainer plugin = Mockito.mock(PluginContainer.class); + + final SpawnListener listener = new SpawnListener(); + + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not false!"); + assertFalse(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not false!"); + + eventManager.registerListeners(plugin, listener); + + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not true!"); + assertTrue(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE it not true!"); + + eventManager.unregisterListeners(listener); + + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not false!"); + assertFalse(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not false!"); + } + + @Test + public void testMultipleListeners() { + final EventManager eventManager = Sponge.eventManager(); + final PluginContainer plugin = Mockito.mock(PluginContainer.class); + + SpawnListener spawnListener = new SpawnListener(); + SpawnCustomListener spawnCustomListener = new SpawnCustomListener(); + + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not false!"); + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM, "SPAWN_ENTITY_EVENT_CUSTOM is not false!"); + assertFalse(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not false!"); + + eventManager.registerListeners(plugin, spawnCustomListener); + + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not true!"); + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM, "SPAWN_ENTITY_EVENT_CUSTOM is not true!"); + assertFalse(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not false!"); + + eventManager.registerListeners(plugin, spawnListener); + + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not true!"); + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM, "SPAWN_ENTITY_EVENT_CUSTOM is not true!"); + assertTrue(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not true!"); + + eventManager.unregisterListeners(spawnCustomListener); + + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not true!"); + assertTrue(ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM, "SPAWN_ENTITY_EVENT_CUSTOM is not true!"); + assertTrue(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not true!"); + + eventManager.unregisterListeners(spawnListener); + + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT, "SPAWN_ENTITY_EVENT is not false!"); + assertFalse(ShouldFire.SPAWN_ENTITY_EVENT_CUSTOM, "SPAWN_ENTITY_EVENT_CUSTOM is not false!"); + assertFalse(ShouldFire.DROP_ITEM_EVENT_DISPENSE, "DROP_ITEM_EVENT_DISPENSE is not false!"); + } + + private static class SpawnListener { + + @Listener + public void onSpawn(SpawnEntityEvent event) {} + } + + private static class SpawnCustomListener { + + @Listener + public void onCustom(SpawnEntityEvent.Custom event) {} + } + +} diff --git a/src/test/java/org/spongepowered/common/event/SnapshotGenerationTest.java b/src/test/java/org/spongepowered/common/event/SnapshotGenerationTest.java new file mode 100644 index 00000000000..8f292b75155 --- /dev/null +++ b/src/test/java/org/spongepowered/common/event/SnapshotGenerationTest.java @@ -0,0 +1,83 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +import com.google.common.collect.Lists; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.event.*; +import org.spongepowered.api.event.cause.entity.SpawnTypes; +import org.spongepowered.api.event.entity.SpawnEntityEvent; +import org.spongepowered.common.event.listener.NonPreListener; +import org.spongepowered.common.event.listener.PreListener; +import org.spongepowered.plugin.PluginContainer; + +public class SnapshotGenerationTest { + private Entity entity; + private SpawnEntityEvent event; + + @BeforeEach + public void prepare() { + this.entity = Mockito.mock(Entity.class, withSettings().defaultAnswer(Mockito.RETURNS_MOCKS)); + final Cause cause = Cause.of(EventContext.builder().add(EventContextKeys.SPAWN_TYPE, SpawnTypes.PLUGIN.get()).build(), this); + this.event = SpongeEventFactory.createSpawnEntityEvent(cause, Lists.newArrayList(this.entity)); + } + + @Test + public void testPreListener() { + final EventManager eventManager = Sponge.game().eventManager(); + final PluginContainer plugin = mock(PluginContainer.class); + final Object[] listeners = {new PreListener(), new NonPreListener()}; + + for (Object listener : listeners) { + eventManager.registerListeners(plugin, listener); + } + + eventManager.post(this.event); + + verify(this.entity).createSnapshot(); + this.event.entitySnapshots(); + + // Cleanup registered listeners to not interfere with other tests + for (Object listener : listeners) { + eventManager.unregisterListeners(listener); + } + } + + @Test + public void testNonPreListener() { + final EventManager eventManager = Sponge.game().eventManager(); + eventManager.post(this.event); + + assertThrows(IllegalStateException.class, () -> this.event.entitySnapshots()); + } + +} diff --git a/src/test/invalid/common/event/listener/AllCauseListener.java b/src/test/java/org/spongepowered/common/event/listener/AllCauseListener.java similarity index 94% rename from src/test/invalid/common/event/listener/AllCauseListener.java rename to src/test/java/org/spongepowered/common/event/listener/AllCauseListener.java index 448058cfb7a..91915bc195c 100644 --- a/src/test/invalid/common/event/listener/AllCauseListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/AllCauseListener.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.event.listener; +import net.kyori.adventure.text.Component; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.filter.cause.All; -import org.spongepowered.api.world.biome.BiomeTypes; import org.spongepowered.common.event.EventFilterTest; public class AllCauseListener { @@ -36,7 +36,7 @@ public class AllCauseListener { public boolean allCauseListenerCalled; @Listener - public void emptyListener(EventFilterTest.SubEvent event, @All(ignoreEmpty = false) BiomeTypes[] players) { + public void emptyListener(EventFilterTest.SubEvent event, @All(ignoreEmpty = false) Component[] components) { this.emptyListenerCalled = true; } diff --git a/src/test/invalid/common/event/listener/BeforeAfterCauseListener.java b/src/test/java/org/spongepowered/common/event/listener/BeforeAfterCauseListener.java similarity index 91% rename from src/test/invalid/common/event/listener/BeforeAfterCauseListener.java rename to src/test/java/org/spongepowered/common/event/listener/BeforeAfterCauseListener.java index a2e81afb4ba..9adcc5c7a76 100644 --- a/src/test/invalid/common/event/listener/BeforeAfterCauseListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/BeforeAfterCauseListener.java @@ -30,7 +30,7 @@ import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.filter.cause.After; import org.spongepowered.api.event.filter.cause.Before; -import org.spongepowered.api.world.extent.Extent; +import org.spongepowered.api.world.World; import org.spongepowered.common.event.EventFilterTest; public class BeforeAfterCauseListener { @@ -44,7 +44,7 @@ public class BeforeAfterCauseListener { public boolean afterCauseCalledEx; @Listener - public void beforeCauseListener(EventFilterTest.SubEvent event, @Before(Extent.class) Player player) { + public void beforeCauseListener(EventFilterTest.SubEvent event, @Before(World.class) Player player) { this.beforeCauseCalled = true; } @@ -54,12 +54,12 @@ public void afterCauseListener(EventFilterTest.SubEvent event, @After(BlockState } @Listener - public void beforeCauseListenerInclude(EventFilterTest.SubEvent event, @Before(value = Extent.class, typeFilter = Player.class) Player player) { + public void beforeCauseListenerInclude(EventFilterTest.SubEvent event, @Before(value = World.class, typeFilter = Player.class) Player player) { this.beforeCauseCalledInc = true; } @Listener - public void beforeCauseListenerExclude(EventFilterTest.SubEvent event, @Before(value = Extent.class, typeFilter = Player.class, inverse = true) Player player) { + public void beforeCauseListenerExclude(EventFilterTest.SubEvent event, @Before(value = World.class, typeFilter = Player.class, inverse = true) Player player) { this.beforeCauseCalledEx = true; } diff --git a/src/test/invalid/common/event/listener/CancelledListener.java b/src/test/java/org/spongepowered/common/event/listener/CancelledListener.java similarity index 100% rename from src/test/invalid/common/event/listener/CancelledListener.java rename to src/test/java/org/spongepowered/common/event/listener/CancelledListener.java diff --git a/src/test/invalid/common/event/listener/CovariantGetterListener.java b/src/test/java/org/spongepowered/common/event/listener/CovariantGetterListener.java similarity index 100% rename from src/test/invalid/common/event/listener/CovariantGetterListener.java rename to src/test/java/org/spongepowered/common/event/listener/CovariantGetterListener.java diff --git a/src/test/invalid/common/event/listener/DataHasListener.java b/src/test/java/org/spongepowered/common/event/listener/DataHasListener.java similarity index 76% rename from src/test/invalid/common/event/listener/DataHasListener.java rename to src/test/java/org/spongepowered/common/event/listener/DataHasListener.java index 58ead5e800c..0e1ad09dd6b 100644 --- a/src/test/invalid/common/event/listener/DataHasListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/DataHasListener.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.event.listener; -import org.spongepowered.api.data.manipulator.mutable.entity.SkinData; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.filter.cause.First; @@ -33,17 +32,17 @@ public class DataHasListener { - public boolean hasSkinListenerCalled; - public boolean inverseHasSkinListenerCalled; + public boolean hasDisplayNameListenerCalled; + public boolean inverseDisplayNameListenerCalled; @Listener - public void hasSkinListener(EventFilterTest.SubEvent event, @First @Has(SkinData.class) Player player) { - this.hasSkinListenerCalled = true; + public void hasDisplayNameListener(EventFilterTest.SubEvent event, @First @Has("DISPLAY_NAME") Player player) { + this.hasDisplayNameListenerCalled = true; } @Listener - public void inverseHasSkinListener(EventFilterTest.SubEvent event, @First @Has(value = SkinData.class, inverse = true) Player player) { - this.inverseHasSkinListenerCalled = true; + public void inverseHasDisplayNameListener(EventFilterTest.SubEvent event, @First @Has(value = "DISPLAY_NAME", inverse = true) Player player) { + this.inverseDisplayNameListenerCalled = true; } } diff --git a/src/test/invalid/common/event/listener/DataSupportsListener.java b/src/test/java/org/spongepowered/common/event/listener/DataSupportsListener.java similarity index 75% rename from src/test/invalid/common/event/listener/DataSupportsListener.java rename to src/test/java/org/spongepowered/common/event/listener/DataSupportsListener.java index dd8acb703be..1efc509760b 100644 --- a/src/test/invalid/common/event/listener/DataSupportsListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/DataSupportsListener.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.event.listener; -import org.spongepowered.api.data.manipulator.mutable.entity.SkinData; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.filter.cause.First; @@ -33,16 +32,16 @@ public class DataSupportsListener { - public boolean supportsSkinListenerCalled; - public boolean inverseSupportsSkinListenerCalled; + public boolean supportsDisplayNameListenerCalled; + public boolean inverseSupportsDisplayNameListenerCalled; @Listener - public void supportsSkinListener(EventFilterTest.SubEvent event, @First @Supports(SkinData.class) Player player) { - this.supportsSkinListenerCalled = true; + public void supportsDisplayNameListener(EventFilterTest.SubEvent event, @First @Supports("DISPLAY_NAME") Player player) { + this.supportsDisplayNameListenerCalled = true; } @Listener - public void inverseSupportsSkinListener(EventFilterTest.SubEvent event, @First @Supports(value = SkinData.class, inverse = true) Player player) { - this.inverseSupportsSkinListenerCalled = true; + public void inverseSupportsDisplayNameListener(EventFilterTest.SubEvent event, @First @Supports(value = "DISPLAY_NAME", inverse = true) Player player) { + this.inverseSupportsDisplayNameListenerCalled = true; } } diff --git a/src/test/invalid/common/event/listener/DoubleListener.java b/src/test/java/org/spongepowered/common/event/listener/DoubleListener.java similarity index 90% rename from src/test/invalid/common/event/listener/DoubleListener.java rename to src/test/java/org/spongepowered/common/event/listener/DoubleListener.java index f174b75963d..8ca6114fc0c 100644 --- a/src/test/invalid/common/event/listener/DoubleListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/DoubleListener.java @@ -26,14 +26,14 @@ import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.block.ChangeBlockEvent; +import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.filter.cause.First; import org.spongepowered.api.item.inventory.ItemStack; public class DoubleListener { @Listener - public void onEvent(ChangeBlockEvent.Break e, @First Player p, @First ItemStack stack) { + public void onEvent(InteractBlockEvent.Primary e, @First Player p, @First ItemStack stack) { e.getClass(); } diff --git a/src/test/invalid/common/event/listener/FirstLastCauseListener.java b/src/test/java/org/spongepowered/common/event/listener/FirstLastCauseListener.java similarity index 100% rename from src/test/invalid/common/event/listener/FirstLastCauseListener.java rename to src/test/java/org/spongepowered/common/event/listener/FirstLastCauseListener.java diff --git a/src/test/invalid/common/event/listener/GetterListener.java b/src/test/java/org/spongepowered/common/event/listener/GetterListener.java similarity index 100% rename from src/test/invalid/common/event/listener/GetterListener.java rename to src/test/java/org/spongepowered/common/event/listener/GetterListener.java diff --git a/src/test/invalid/common/event/listener/IncludeExcludeListener.java b/src/test/java/org/spongepowered/common/event/listener/IncludeExcludeListener.java similarity index 96% rename from src/test/invalid/common/event/listener/IncludeExcludeListener.java rename to src/test/java/org/spongepowered/common/event/listener/IncludeExcludeListener.java index 589fb1bb4fc..535708dcb44 100644 --- a/src/test/invalid/common/event/listener/IncludeExcludeListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/IncludeExcludeListener.java @@ -34,7 +34,7 @@ public class IncludeExcludeListener { public boolean includeListenerCalled; public boolean multiIncludeListenerCalled; - public boolean exlcudeListenerCalled; + public boolean excludeListenerCalled; public boolean multiExcludeListenerCalled; @Listener @@ -52,7 +52,7 @@ public void multiIncludeListener(EventFilterTest.TestEvent event) { @Listener @Exclude(EventFilterTest.SubEvent.class) public void excludeListener(EventFilterTest.TestEvent event) { - this.exlcudeListenerCalled = true; + this.excludeListenerCalled = true; } @Listener diff --git a/src/test/invalid/common/event/listener/InvalidIncludeExcludeListener.java b/src/test/java/org/spongepowered/common/event/listener/InvalidIncludeExcludeListener.java similarity index 100% rename from src/test/invalid/common/event/listener/InvalidIncludeExcludeListener.java rename to src/test/java/org/spongepowered/common/event/listener/InvalidIncludeExcludeListener.java diff --git a/src/test/invalid/common/event/listener/NonPreListener.java b/src/test/java/org/spongepowered/common/event/listener/NonPreListener.java similarity index 97% rename from src/test/invalid/common/event/listener/NonPreListener.java rename to src/test/java/org/spongepowered/common/event/listener/NonPreListener.java index 92428a233f4..610a3b43c14 100644 --- a/src/test/invalid/common/event/listener/NonPreListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/NonPreListener.java @@ -31,7 +31,7 @@ public class NonPreListener { @Listener public void onSpawnEntity(SpawnEntityEvent event) { - event.getEntitySnapshots(); + event.entitySnapshots(); } } diff --git a/src/test/invalid/common/event/PreListener.java b/src/test/java/org/spongepowered/common/event/listener/PreListener.java similarity index 94% rename from src/test/invalid/common/event/PreListener.java rename to src/test/java/org/spongepowered/common/event/listener/PreListener.java index c04126e5945..6b10e7aead5 100644 --- a/src/test/invalid/common/event/PreListener.java +++ b/src/test/java/org/spongepowered/common/event/listener/PreListener.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.event; +package org.spongepowered.common.event.listener; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.Order; @@ -32,7 +32,7 @@ public class PreListener { @Listener(order = Order.PRE) public void onSpawn(SpawnEntityEvent event) { - event.getEntitySnapshots(); + event.entitySnapshots(); } } diff --git a/src/test/invalid/common/event/listener/RootListener.java b/src/test/java/org/spongepowered/common/event/listener/RootListener.java similarity index 100% rename from src/test/invalid/common/event/listener/RootListener.java rename to src/test/java/org/spongepowered/common/event/listener/RootListener.java diff --git a/src/test/invalid/common/event/listener/SimpleListener.java b/src/test/java/org/spongepowered/common/event/listener/SimpleListener.java similarity index 100% rename from src/test/invalid/common/event/listener/SimpleListener.java rename to src/test/java/org/spongepowered/common/event/listener/SimpleListener.java diff --git a/src/test/invalid/common/InjectedTest.java b/src/test/java/org/spongepowered/common/event/manager/ListenerClassVisitorHelper.java similarity index 57% rename from src/test/invalid/common/InjectedTest.java rename to src/test/java/org/spongepowered/common/event/manager/ListenerClassVisitorHelper.java index f12c3863626..dda50291de5 100644 --- a/src/test/invalid/common/InjectedTest.java +++ b/src/test/java/org/spongepowered/common/event/manager/ListenerClassVisitorHelper.java @@ -22,32 +22,28 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common; +package org.spongepowered.common.event.manager; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Inject; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.Before; +import org.objectweb.asm.Type; -public class InjectedTest { +import java.io.IOException; +import java.util.Arrays; - @Inject protected Logger logger; +public class ListenerClassVisitorHelper { - @Before - public void before() { - Guice.createInjector(new TestModule()); - } - - public class TestModule extends AbstractModule { + public static ListenerClassVisitor.DiscoveredMethod getMethod(Class clazz, String name, Class... parameterTypes) + throws IOException, NoSuchMethodException { + final Object[] expectedParameterTypeNames = Arrays.stream(parameterTypes).map(Type::getInternalName).toArray(); - @Override - protected void configure() { - this.bind(org.slf4j.Logger.class).toInstance(org.slf4j.LoggerFactory.getLogger("sponge")); - this.bind(Logger.class).toInstance(LogManager.getLogger("sponge")); - - this.requestInjection(InjectedTest.this); + for (ListenerClassVisitor.DiscoveredMethod m : ListenerClassVisitor.getEventListenerMethods(clazz)) { + if (m.methodName().equals(name)) { + final Object[] parameterTypeNames = Arrays.stream(m.parameterTypes()).map(p -> p.type().getInternalName()).toArray(); + if (Arrays.equals(parameterTypeNames, expectedParameterTypeNames)) { + return m; + } + } } + + throw new NoSuchMethodException(name); } } diff --git a/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java b/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java new file mode 100644 index 00000000000..1555dfc1cdb --- /dev/null +++ b/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java @@ -0,0 +1,87 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; + +public class PhaseTrackerTest { + + @Test + public void testPoppingFramePopsCauses() { + final PhaseTracker phaseTracker = PhaseTracker.getInstance(); + + // We start by pushing a frame... + CauseStackManager.StackFrame frame1 = phaseTracker.pushCauseFrame(); + phaseTracker.pushCause(1); + phaseTracker.pushCause(2); + + // Then we push another frame + CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame(); + phaseTracker.pushCause(3); + + assertEquals(3, phaseTracker.currentCause().root()); + assertEquals(3, phaseTracker.currentCause().all().size()); + + // Now pop the frame + phaseTracker.popCauseFrame(frame); + assertEquals(2, phaseTracker.currentCause().root()); + assertEquals(2, phaseTracker.currentCause().all().size()); + + // Remove for next tests. + phaseTracker.popCauseFrame(frame1); + } + + @Test + public void testPoppingFrameRemovesFrameContexts() { + final PhaseTracker phaseTracker = PhaseTracker.getInstance(); + + String cmd1 = "one"; + String cmd2 = "two"; + + // We start by pushing a frame... + CauseStackManager.StackFrame frame1 = phaseTracker.pushCauseFrame(); + phaseTracker.pushCause(1); + phaseTracker.addContext(EventContextKeys.COMMAND, cmd1); + + // Then we push another frame + CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame(); + phaseTracker.addContext(EventContextKeys.COMMAND, cmd2); + + assertEquals(cmd2, phaseTracker.context(EventContextKeys.COMMAND).get()); + + // Now pop the frame + phaseTracker.popCauseFrame(frame); + assertEquals(cmd1, phaseTracker.context(EventContextKeys.COMMAND).get()); + + phaseTracker.popCauseFrame(frame1); + assertFalse(phaseTracker.context(EventContextKeys.COMMAND).isPresent()); + } + +} diff --git a/src/test/invalid/common/MixinTest.java b/src/test/java/org/spongepowered/common/mixin/MixinTest.java similarity index 88% rename from src/test/invalid/common/MixinTest.java rename to src/test/java/org/spongepowered/common/mixin/MixinTest.java index d6e1a2ce63a..d7b0811f417 100644 --- a/src/test/invalid/common/MixinTest.java +++ b/src/test/java/org/spongepowered/common/mixin/MixinTest.java @@ -22,16 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common; +package org.spongepowered.common.mixin; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; -@RunWith(LaunchWrapperTestRunner.class) public class MixinTest { + @Disabled @Test public void auditMixins() { // Ensure all Mixins apply without error diff --git a/src/test/java/org/spongepowered/common/registry/RegistryTest.java b/src/test/java/org/spongepowered/common/registry/RegistryTest.java new file mode 100644 index 00000000000..7622087b8ff --- /dev/null +++ b/src/test/java/org/spongepowered/common/registry/RegistryTest.java @@ -0,0 +1,131 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.registry; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +import com.google.common.reflect.TypeToken; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.registry.*; +import org.spongepowered.api.util.annotation.CatalogedBy; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.stream.Stream; + +public class RegistryTest { + + private static Stream> streamRegistries(final ResourceKey root) { + return Stream.concat(Sponge.game().streamRegistries(root), Sponge.server().streamRegistries(root)).distinct(); + } + + private static Stream> streamRegistries() { + return Stream.concat(RegistryTest.streamRegistries(RegistryRoots.MINECRAFT), RegistryTest.streamRegistries(RegistryRoots.SPONGE)); + } + + @TestFactory + public Stream generateRegistryFindTests() { + return RegistryTest.streamRegistries().flatMap((Registry registry) -> registry.streamEntries().map((RegistryEntry entry) -> { + final String name = "Find key " + entry.key() + " in registry " + registry.type().location() + " in " + registry.type().root(); + return dynamicTest(name, () -> { + final Optional> entryByKey = registry.findEntry(entry.key()); + assertTrue(entryByKey.isPresent()); + assertEquals(entryByKey.get().value(), registry.value(entry.key())); // same key -> same value + }); + })); + } + + private static boolean isPublicStatic(Field field) { + return Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()); + } + + private static Stream streamDefaultedReferenceFields() { + return Arrays.stream(RegistryTypes.class.getDeclaredFields()) + .filter(RegistryTest::isPublicStatic) + .flatMap(registryField -> { + final Class valueType = TypeToken.of(((ParameterizedType) registryField.getGenericType()).getActualTypeArguments()[0]).getRawType(); + + final CatalogedBy catalogedBy = valueType.getAnnotation(CatalogedBy.class); + if (catalogedBy == null) { + return Stream.empty(); + } + + return Arrays.stream(catalogedBy.value()); + }) + .flatMap(container -> Arrays.stream(container.getDeclaredFields())) + .filter(field -> isPublicStatic(field) && DefaultedRegistryReference.class.isAssignableFrom(field.getType())); + } + + @Disabled + @TestFactory + public Stream generateDefaultedReferenceTests() { + return RegistryTest.streamDefaultedReferenceFields().map(field -> { + final String name = "Field " + field.getDeclaringClass().getSimpleName() + "#" + field.getName(); + return dynamicTest(name, () -> { + final DefaultedRegistryReference ref = (DefaultedRegistryReference) field.get(null); + assertNotNull(ref.get()); + }); + }); + } + + private static Stream> streamApiInterfaces(final Object instance) { + final Collection> interfaces = new LinkedHashSet<>(); + Class current = instance.getClass(); + while (current != null) { + interfaces.addAll(Arrays.asList(current.getInterfaces())); + current = current.getSuperclass(); + } + return interfaces.stream() + .filter(clazz -> clazz.getName().startsWith("org.spongepowered.api.")); + } + + @Disabled + @TestFactory + public Stream generateMethodTests() { + return RegistryTest.streamRegistries().flatMap(Registry::streamEntries) + .flatMap((RegistryEntry entry) -> { + final Object value = entry.value(); + return streamApiInterfaces(value).flatMap(c -> Arrays.stream(c.getDeclaredMethods())) + .filter(m -> !Modifier.isStatic(m.getModifiers()) && m.getParameterCount() == 0) + .map(m -> { + final String name = "Invoke " + m.getDeclaringClass().getSimpleName() + "#" + m.getName() + " on " + entry.key(); + return dynamicTest(name, () -> { + final Object result = m.invoke(value); + assertNotNull(result); + }); + }); + }); + } +} diff --git a/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java b/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java new file mode 100644 index 00000000000..e0e20b4ed5c --- /dev/null +++ b/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java @@ -0,0 +1,84 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.mojang.authlib.GameProfile; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public final class ExperienceHolderUtilTest { + + public static List testExp() { + final Level world = mock(Level.class); + when(world.getLevelData()).thenReturn(mock(PrimaryLevelData.class)); + + final Player player = new Player(world, BlockPos.ZERO, 0, new GameProfile(UUID.randomUUID(), "Player")) { + @Override + public boolean isSpectator() { + return false; + } + + @Override + public boolean isCreative() { + return false; + } + }; + + final List list = new ArrayList<>(); + + int level = 0; + int startExp = 0; + while (level < 50) { + player.experienceLevel = level; + list.add(Arguments.of(level, startExp, player.getXpNeededForNextLevel())); + startExp += player.getXpNeededForNextLevel(); + level++; + } + + return list; + } + + @MethodSource + @ParameterizedTest + public void testExp(final int level, final int startExp, final int expInLevel) { + assertEquals(expInLevel, ExperienceHolderUtil.getExpBetweenLevels(level)); + assertEquals(startExp, ExperienceHolderUtil.xpAtLevel(level)); + assertEquals(level, ExperienceHolderUtil.getLevelForExp(startExp)); + assertEquals(level, ExperienceHolderUtil.getLevelForExp(startExp + 1)); + } +} diff --git a/src/test/invalid/common/util/persistence/data/FakeBuilder.java b/src/test/java/org/spongepowered/common/util/persistence/data/FakeBuilder.java similarity index 95% rename from src/test/invalid/common/util/persistence/data/FakeBuilder.java rename to src/test/java/org/spongepowered/common/util/persistence/data/FakeBuilder.java index ad94c43f53d..e133826f154 100644 --- a/src/test/invalid/common/util/persistence/data/FakeBuilder.java +++ b/src/test/java/org/spongepowered/common/util/persistence/data/FakeBuilder.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.util.persistence.data; -import org.spongepowered.api.data.DataQuery; -import org.spongepowered.api.data.DataView; import org.spongepowered.api.data.persistence.DataBuilder; +import org.spongepowered.api.data.persistence.DataQuery; +import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.data.persistence.InvalidDataException; import java.util.Optional; diff --git a/src/test/invalid/common/util/persistence/data/FakeSerializable.java b/src/test/java/org/spongepowered/common/util/persistence/data/FakeSerializable.java similarity index 87% rename from src/test/invalid/common/util/persistence/data/FakeSerializable.java rename to src/test/java/org/spongepowered/common/util/persistence/data/FakeSerializable.java index 0a696b4ef3d..3f293abcd9f 100644 --- a/src/test/invalid/common/util/persistence/data/FakeSerializable.java +++ b/src/test/java/org/spongepowered/common/util/persistence/data/FakeSerializable.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.util.persistence.data; -import org.spongepowered.api.data.DataContainer; -import org.spongepowered.api.data.DataQuery; -import org.spongepowered.api.data.DataSerializable; -import org.spongepowered.api.data.Queries; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.data.persistence.DataQuery; +import org.spongepowered.api.data.persistence.DataSerializable; +import org.spongepowered.api.data.persistence.Queries; public class FakeSerializable implements DataSerializable { @@ -46,14 +46,14 @@ public FakeSerializable(String foo, int myInt, double theDouble, String nestedCo } @Override - public int getContentVersion() { + public int contentVersion() { return 1; } @Override public DataContainer toContainer() { DataContainer container = DataContainer.createNew(); - container.set(Queries.CONTENT_VERSION, getContentVersion()); + container.set(Queries.CONTENT_VERSION, contentVersion()); container.set(DataQuery.of("foo"), this.foo); container.set(DataQuery.of("myInt"), this.myInt); container.set(DataQuery.of("theDouble"), this.theDouble); diff --git a/src/test/invalid/common/util/persistence/data/NBTTranslationTest.java b/src/test/java/org/spongepowered/common/util/persistence/data/NBTTranslationTest.java similarity index 80% rename from src/test/invalid/common/util/persistence/data/NBTTranslationTest.java rename to src/test/java/org/spongepowered/common/util/persistence/data/NBTTranslationTest.java index 653ae66ce91..804b2038c3c 100644 --- a/src/test/invalid/common/util/persistence/data/NBTTranslationTest.java +++ b/src/test/java/org/spongepowered/common/util/persistence/data/NBTTranslationTest.java @@ -24,18 +24,18 @@ */ package org.spongepowered.common.util.persistence.data; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; -import net.minecraft.nbt.NBTTagCompound; -import org.junit.Test; +import net.minecraft.nbt.CompoundTag; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.spongepowered.api.data.DataContainer; import org.spongepowered.api.data.DataManager; -import org.spongepowered.api.data.DataQuery; -import org.spongepowered.api.data.DataView; import org.spongepowered.api.data.persistence.DataBuilder; -import org.spongepowered.common.data.persistence.NbtTranslator; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.data.persistence.DataQuery; +import org.spongepowered.api.data.persistence.DataView; +import org.spongepowered.common.data.persistence.NBTTranslator; import java.util.Optional; @@ -45,12 +45,12 @@ public class NBTTranslationTest { public void testContainerToNBT() { DataManager service = Mockito.mock(DataManager.class); DataBuilder builder = new FakeBuilder(); - when(service.getBuilder(FakeSerializable.class)).thenReturn(Optional.of(builder)); + when(service.builder(FakeSerializable.class)).thenReturn(Optional.of(builder)); DataContainer container = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED); container.set(DataQuery.of("foo"), "bar"); FakeSerializable temp = new FakeSerializable("bar", 7, 10.0D, "nested"); container.set(DataQuery.of("myFake"), temp); - NBTTagCompound compound = NBTTranslator.INSTANCE.translateData(container); + CompoundTag compound = NBTTranslator.INSTANCE.translate(container); DataView translatedContainer = NBTTranslator.INSTANCE.translateFrom(compound); assertEquals(container, translatedContainer); } @@ -58,7 +58,7 @@ public void testContainerToNBT() { @Test public void testDotContainerKeys() { final DataContainer container = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED).set(DataQuery.of("my.key.to.data"), 1); - NBTTagCompound compound = NBTTranslator.INSTANCE.translateData(container); + CompoundTag compound = NBTTranslator.INSTANCE.translate(container); DataView translatedContainer = NBTTranslator.INSTANCE.translateFrom(compound); assertEquals(container, translatedContainer); } diff --git a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java index a8c28ec8297..8853e8fb264 100644 --- a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java +++ b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java @@ -166,7 +166,7 @@ private static SpongeArchetypeVolume fillVolume(final Vector3i min, final Vector return volume; } - @MethodSource("testTransformationsOfPositions") + @MethodSource @ParameterizedTest void testTransformationsOfPositions( final Vector3i min, final Vector3i max, final Vector3i origin, final Vector3i testForRoundTrip, diff --git a/src/test/invalid/common/regression/SchematicUpgradeTest.java b/src/test/java/org/spongepowered/common/world/schematic/SchematicTest.java similarity index 77% rename from src/test/invalid/common/regression/SchematicUpgradeTest.java rename to src/test/java/org/spongepowered/common/world/schematic/SchematicTest.java index fbdaa959fc5..07454b75d52 100644 --- a/src/test/invalid/common/regression/SchematicUpgradeTest.java +++ b/src/test/java/org/spongepowered/common/world/schematic/SchematicTest.java @@ -22,35 +22,36 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.regression; +package org.spongepowered.common.world.schematic; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.spongepowered.api.data.DataContainer; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataFormats; import org.spongepowered.api.world.schematic.Schematic; -import org.spongepowered.lwts.runner.LaunchWrapperTestRunner; import java.io.IOException; import java.io.InputStream; import java.util.zip.GZIPInputStream; -@RunWith(LaunchWrapperTestRunner.class) -public class SchematicUpgradeTest { +@Disabled +public class SchematicTest { @Test public void testUpgradingv1Tov2() throws IOException { final ClassLoader classLoader = this.getClass().getClassLoader(); + final SchematicTranslator translator = SchematicTranslator.get(); + try (final InputStream v1InputStream = classLoader.getResource("loadv1.schematic").openStream(); final InputStream v2InputStream = classLoader.getResource("loadv2.schematic").openStream(); final GZIPInputStream v1GzipInputStream = new GZIPInputStream(v1InputStream); - final GZIPInputStream v2GzipInputStream = new GZIPInputStream(v2InputStream)){ - final DataContainer v1Container = DataFormats.NBT.readFrom(v1GzipInputStream); - final Schematic v1Schem = DataTranslators.SCHEMATIC.translate(v1Container); - final DataContainer v2Container = DataFormats.NBT.readFrom(v2GzipInputStream); - final Schematic v2Schem = DataTranslators.SCHEMATIC.translate(v2Container); + final GZIPInputStream v2GzipInputStream = new GZIPInputStream(v2InputStream)) { + final DataContainer v1Container = DataFormats.NBT.get().readFrom(v1GzipInputStream); + final Schematic v1Schem = translator.translate(v1Container); + final DataContainer v2Container = DataFormats.NBT.get().readFrom(v2GzipInputStream); + final Schematic v2Schem = translator.translate(v2Container); assertEquals(v1Schem, v2Schem); } } diff --git a/src/test/java/org/spongepowered/common/world/storage/SpongeChunkLayoutTest.java b/src/test/java/org/spongepowered/common/world/storage/SpongeChunkLayoutTest.java new file mode 100644 index 00000000000..ad94566499b --- /dev/null +++ b/src/test/java/org/spongepowered/common/world/storage/SpongeChunkLayoutTest.java @@ -0,0 +1,168 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.storage; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.spongepowered.api.util.Direction; +import org.spongepowered.math.vector.Vector3i; + +@Disabled +public class SpongeChunkLayoutTest { + + @Test + public void testConstants() { + assertEquals(new Vector3i(16, 256, 16), SpongeChunkLayout.INSTANCE.chunkSize()); + assertEquals(new Vector3i(1874999, 0, 1874999), SpongeChunkLayout.INSTANCE.spaceMax()); + assertEquals(new Vector3i(-1875000, 0, -1875000), SpongeChunkLayout.INSTANCE.spaceMin()); + assertEquals(new Vector3i(3750000, 1, 3750000), SpongeChunkLayout.INSTANCE.spaceSize()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.spaceOrigin()); + } + + @Test + public void testCoordValidation() { + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(new Vector3i(0, 0, 0))); + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(0, 0, 0)); + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(new Vector3i(1874999, 0, 1874999))); + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(1874999, 0, 1874999)); + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(new Vector3i(-1875000, 0, -1875000))); + assertTrue(SpongeChunkLayout.INSTANCE.isValidChunk(-1875000, 0, -1875000)); + + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(1875000, 0, 1874999)); + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(1874999, 1, 1874999)); + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(1874999, 0, 1875000)); + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(-1875001, 0, -1875000)); + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(-1875000, -1, -1875000)); + assertFalse(SpongeChunkLayout.INSTANCE.isValidChunk(-1875000, 0, -1875001)); + + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(0, 0, 0)); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(14, 125, 9))); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(14, 125, 9)); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(15, 255, 15)); + + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(-1, 0, 0))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(0, -1, 0))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(0, 0, -1))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(-1, 0, 0)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(0, -1, 0)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(0, 0, -1)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(16, 255, 15)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(15, 256, 15)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(15, 255, 16)); + + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(0, 0, 0, 0, 0, 0)); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(30, 125, -7), new Vector3i(1, 0, -1))); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(30, 125, -7, 1, 0, -1)); + assertTrue(SpongeChunkLayout.INSTANCE.isInChunk(65, 255, -33, 4, 0, -3)); + + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(-17, 0, 0), new Vector3i(-1, 0, 0))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(0, -257, 0), new Vector3i(0, -1, 0))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(new Vector3i(0, 0, -17), new Vector3i(0, 0, -1))); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(-17, 0, 0, -1, 0, 0)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(0, -257, 0, 0, -1, 0)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(0, 0, -17, 0, 0, -1)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(32, 255, 31, 1, 0, 1)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(31, 256, 31, 1, 0, 1)); + assertFalse(SpongeChunkLayout.INSTANCE.isInChunk(31, 255, 32, 1, 0, 1)); + } + + @Test + public void testCoordConversion() { + // chunk to world + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toChunk(Vector3i.ZERO).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toChunk(0, 0, 0).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toChunk(new Vector3i(15, 255, 15)).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toChunk(15, 255, 15).get()); + + assertEquals(new Vector3i(2, 0, 4), SpongeChunkLayout.INSTANCE.toChunk(new Vector3i(34, 121, 72)).get()); + assertEquals(new Vector3i(2, 0, 4), SpongeChunkLayout.INSTANCE.toChunk(34, 121, 72).get()); + + assertEquals(new Vector3i(-6, 0, -13), SpongeChunkLayout.INSTANCE.toChunk(new Vector3i(-83, 62, -203)).get()); + assertEquals(new Vector3i(-6, 0, -13), SpongeChunkLayout.INSTANCE.toChunk(-83, 62, -203).get()); + + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(30000000, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(-30000001, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(0, 256, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(0, -1, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(0, 0, 30000000).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toChunk(0, 0, -30000001).isPresent()); + + // world to chunk + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toWorld(Vector3i.ZERO).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.toWorld(0, 0, 0).get()); + + assertEquals(new Vector3i(32, 0, 64), SpongeChunkLayout.INSTANCE.toWorld(new Vector3i(2, 0, 4)).get()); + assertEquals(new Vector3i(32, 0, 64), SpongeChunkLayout.INSTANCE.toWorld(2, 0, 4).get()); + + assertEquals(new Vector3i(-96, 0, -208), SpongeChunkLayout.INSTANCE.toWorld(new Vector3i(-6, 0, -13)).get()); + assertEquals(new Vector3i(-96, 0, -208), SpongeChunkLayout.INSTANCE.toWorld(-6, 0, -13).get()); + + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(1875000, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(-1875001, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(0, 1, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(0, -1, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(0, 0, 1875000).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.toWorld(0, 0, -1875001).isPresent()); + } + + @Test + public void testCoordAdd() { + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.addToChunk(Vector3i.ZERO, Vector3i.ZERO).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.addToChunk(0, 0, 0, 0, 0, 0).get()); + + assertEquals(new Vector3i(7, 0, 5), SpongeChunkLayout.INSTANCE.addToChunk(3, 0, 5, 4, 0, 0).get()); + assertEquals(new Vector3i(7, 0, 9), SpongeChunkLayout.INSTANCE.addToChunk(3, 0, 5, 4, 0, 4).get()); + + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(1874999, 0, 0, 1, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(0, 0, 0, 0, 1, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(0, 0, 1874999, 0, 0, 1).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(-1875000, 0, 0, -1, 0, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(0, 0, 0, 0, -1, 0).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.addToChunk(0, 0, -1875000, 0, 0, -1).isPresent()); + } + + @Test + public void testCoordMove() { + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.moveToChunk(Vector3i.ZERO, Direction.NONE).get()); + assertEquals(Vector3i.ZERO, SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, 0, Direction.NONE).get()); + + assertEquals(new Vector3i(4, 0, 5), SpongeChunkLayout.INSTANCE.moveToChunk(3, 0, 5, Direction.EAST).get()); + assertEquals(new Vector3i(7, 0, 5), SpongeChunkLayout.INSTANCE.moveToChunk(3, 0, 5, Direction.EAST, 4).get()); + assertEquals(new Vector3i(4, 0, 6), SpongeChunkLayout.INSTANCE.moveToChunk(3, 0, 5, Direction.SOUTHEAST).get()); + assertEquals(new Vector3i(7, 0, 9), SpongeChunkLayout.INSTANCE.moveToChunk(3, 0, 5, Direction.SOUTHEAST, 4).get()); + + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(1874999, 0, 0, Direction.EAST).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, 0, Direction.UP).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, 1874999, Direction.SOUTH).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(-1875000, 0, 0, Direction.WEST).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, 0, Direction.DOWN).isPresent()); + assertFalse(SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, -1875000, Direction.NORTH).isPresent()); + + assertThrows(IllegalArgumentException.class, () -> SpongeChunkLayout.INSTANCE.moveToChunk(0, 0, 0, Direction.SOUTH_SOUTHEAST)); + } + +} From 1f3d550c92a59dad60b403174a61f023752f07df Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 7 Aug 2025 18:14:10 +0200 Subject: [PATCH 324/586] Add code coverage via JaCoCo and a specialized class transformer --- .../bootstrap/dev/DevClasspath.java | 2 +- forge/build.gradle.kts | 17 ++ gradle/libs.versions.toml | 2 + gradle/verification-metadata.xml | 42 +++++ modlauncher-transformers/build.gradle.kts | 9 +- .../jacoco/AgentAccessGenerator.java | 39 +++++ .../modlauncher/jacoco/Instrumenter.java | 72 ++++++++ .../jacoco/JacocoPluginService.java | 155 ++++++++++++++++++ .../PrefixedCondyProbeArrayStrategy.java | 63 +++++++ ...odlauncher.serviceapi.ILaunchPluginService | 1 + neoforge/build.gradle.kts | 17 ++ vanilla/build.gradle.kts | 18 +- 12 files changed, 430 insertions(+), 7 deletions(-) create mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java create mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java create mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java create mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java create mode 100644 modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 5b0d65f20c9..3e1b3c97e1d 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -132,7 +132,7 @@ public static List resolve() { continue; } - if (bootNames.contains(fileName)) { + if (bootNames.contains(fileName) || fileName.startsWith("org.jacoco.core-")) { if (Bootstrap.DEBUG) { System.out.println("Boot: " + path); } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 2e893adfe95..fea72eeca39 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -21,6 +21,7 @@ plugins { id("implementation-structure") alias(libs.plugins.blossom) alias(libs.plugins.forgeGradle) + jacoco } val commonProject = parent!! @@ -234,6 +235,10 @@ dependencies { testImplementation(libs.mockito.junitJupiter) { exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") } + + testRuntimeOnly(libs.jacoco.core) { + exclude(group = "org.ow2.asm") + } } val awFiles: Set = files(commonMain.get().resources, main.resources).filter { it.name.endsWith(".accesswidener") }.files @@ -437,6 +442,18 @@ tasks { workingDir.mkdirs() workingDir.resolve("eula.txt").writeText("eula=true") } + + extensions.configure(JacocoTaskExtension::class) { + excludeClassLoaders = listOf("cpw.mods.modlauncher.TransformingClassLoader") + } + + finalizedBy(jacocoTestReport) + } + + jacocoTestReport { + sourceSets(commonAppLaunchConf.get(), commonAppLaunch.get(), commonLaunch.get(), commonAccessors.get(), commonMixins.get(), commonMain.get()) + sourceSets(appLaunch, launch, lang, accessors, mixins, main) + dependsOn(test) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6aefb1ff35..82ea5a9ce16 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,6 +19,7 @@ mockito = "5.11.0" jline = "3.25.1" tinylog = "2.7.0" vineflower = "1.11.1" +jacoco = "0.8.13" [libraries] # common @@ -57,6 +58,7 @@ mixinextras-common = { module = "io.github.llamalad7:mixinextras-common", versio mixinextras-forge = { module = "io.github.llamalad7:mixinextras-forge", version.ref = "mixinextras" } mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } mockito-junitJupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } +jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "jacoco" } # vanilla forgeAutoRenamingTool = { module = "net.minecraftforge:ForgeAutoRenamingTool", version.ref = "forgeAutoRenamingTool" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a614c5b28c6..74d474718c2 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -7069,6 +7069,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8366,6 +8403,11 @@ + + + + + diff --git a/modlauncher-transformers/build.gradle.kts b/modlauncher-transformers/build.gradle.kts index 2f1192b3500..5ddf331a743 100644 --- a/modlauncher-transformers/build.gradle.kts +++ b/modlauncher-transformers/build.gradle.kts @@ -1,10 +1,8 @@ dependencies { - // AccessWidener transformer implementation(libs.accessWidener) { exclude(group="org.apache.logging.log4j") } - // ModLauncher inherited dependencies - strictly should be provided by - // the platform making use of this project + compileOnly(libs.log4j.api) compileOnly(libs.neo.modlauncher) { exclude(group = "org.ow2.asm") @@ -13,9 +11,10 @@ dependencies { compileOnly(libs.joptSimple) compileOnly(libs.asm.commons) - - // And finally, compile only annotations compileOnly(apiLibs.checkerQual) + + // Optional + compileOnly(libs.jacoco.core) } tasks { diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java new file mode 100644 index 00000000000..d4b2c8a9698 --- /dev/null +++ b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.transformers.modlauncher.jacoco; + +import org.jacoco.core.runtime.IExecutionDataAccessorGenerator; +import org.jacoco.core.runtime.RuntimeData; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class AgentAccessGenerator implements IExecutionDataAccessorGenerator { + @Override + public int generateDataAccessor(final long classId, final String className, final int probeCount, final MethodVisitor mv) { + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/$JaCoCo", "data", "Ljava/lang/Object;"); + RuntimeData.generateAccessCall(classId, className, probeCount, mv); + return 6; + } +} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java new file mode 100644 index 00000000000..3c9457f54bc --- /dev/null +++ b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java @@ -0,0 +1,72 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.transformers.modlauncher.jacoco; + +import org.jacoco.core.internal.data.CRC64; +import org.jacoco.core.internal.flow.ClassProbesAdapter; +import org.jacoco.core.internal.instr.ClassInstrumenter; +import org.jacoco.core.internal.instr.IProbeArrayStrategy; +import org.jacoco.core.internal.instr.InstrSupport; +import org.jacoco.core.runtime.IExecutionDataAccessorGenerator; +import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; + +public class Instrumenter { + // Incompatible with Mixin (ClassMetadataNotFoundException: java.lang.$JaCoCo) + private static final IExecutionDataAccessorGenerator agentAccessGenerator = new AgentAccessGenerator(); + + // Module must read org.jacoco.agent.rt + private static final IExecutionDataAccessorGenerator offlineAccessGenerator = new OfflineInstrumentationAccessGenerator(); + + public static byte[] instrument(final byte[] originalBytes, final boolean mixin) { + final ClassReader reader = InstrSupport.classReaderFor(originalBytes); + final int version = InstrSupport.getMajorVersion(reader); + if (version < Opcodes.V11) { + // not supported + return originalBytes; + } + + final long classId = CRC64.classId(originalBytes); + final String prefix = mixin ? Long.toHexString(classId) : ""; + final String className = reader.getClassName(); + final boolean isInterfaceOrModule = (reader.getAccess() & (Opcodes.ACC_INTERFACE | Opcodes.ACC_MODULE)) != 0; + + final IProbeArrayStrategy strategy = new PrefixedCondyProbeArrayStrategy(className, isInterfaceOrModule, classId, prefix, + mixin ? Instrumenter.offlineAccessGenerator : Instrumenter.agentAccessGenerator); + + final ClassWriter writer = new ClassWriter(reader, 0) { + @Override + protected String getCommonSuperClass(final String type1, final String type2) { + throw new IllegalStateException(); + } + }; + final ClassVisitor visitor = new ClassProbesAdapter(new ClassInstrumenter(strategy, writer), InstrSupport.needsFrames(version)); + reader.accept(visitor, ClassReader.EXPAND_FRAMES); + return writer.toByteArray(); + } +} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java new file mode 100644 index 00000000000..d87aaaeea58 --- /dev/null +++ b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java @@ -0,0 +1,155 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.transformers.modlauncher.jacoco; + +import cpw.mods.modlauncher.TransformingClassLoader; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +public class JacocoPluginService implements ILaunchPluginService { + private static final Logger logger = LogManager.getLogger(); + + private static final String MIXIN_DESC = "Lorg/spongepowered/asm/mixin/Mixin;"; + + private static final EnumSet YAY = EnumSet.of(Phase.BEFORE); + private static final EnumSet NAY = EnumSet.noneOf(Phase.class); + + private boolean disabled; + private ClassLoader loader; + + public JacocoPluginService() { + try { + getClass().getClassLoader().loadClass("org.jacoco.core.JaCoCo"); + } catch (final ClassNotFoundException e) { + this.disabled = true; + } + } + + @Override + public String name() { + return "jacoco"; + } + + @Override + public EnumSet handlesClass(Type classType, boolean isEmpty) { + return this.disabled || isEmpty ? NAY : YAY; + } + + @Override + public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { + if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) { + return ComputeFlags.NO_REWRITE; + } + + // Capture a reference to the transforming class loader + if (this.loader == null) { + // First transformed class context, aka game entrypoint is supposed to be the transforming class loader + final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + if (!((Object) contextLoader instanceof TransformingClassLoader)) { // Ignore IDE warning + throw new IllegalStateException("Context class loader of the first transformed class is not a transforming class loader"); + } + // Context class loader may change for next classes, so capture it + this.loader = contextLoader; + } + + // Only apply JaCoCo to our sources + if (!classNode.name.startsWith("org/spongepowered/")) { + return ComputeFlags.NO_REWRITE; + } + + // We need the original bytes for two reasons: + // - JaCoCo computes a checksum from the bytes + // - JaCoCo requires expanded frames, which the current ClassNode doesn't have + byte[] originalBytes; + try (final InputStream in = this.loader.getResourceAsStream(classNode.name + ".class")) { + if (in == null) { + logger.warn("Failed to find original class bytes for class {}", classNode.name); + return ComputeFlags.NO_REWRITE; + } + + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + in.transferTo(buffer); + originalBytes = buffer.toByteArray(); + } catch (IOException e) { + logger.warn("Failed to read original class bytes for class {}", classNode.name, e); + return ComputeFlags.NO_REWRITE; + } + + // Detect the mixin annotation + boolean mixin = false; + if (classNode.invisibleAnnotations != null) { + for (final AnnotationNode annotation : classNode.invisibleAnnotations) { + if (MIXIN_DESC.equals(annotation.desc)) { + mixin = true; + break; + } + } + } + + final byte[] instrumentedBytes = Instrumenter.instrument(originalBytes, mixin); + final ClassReader classReader = new ClassReader(instrumentedBytes); + final ClassNode instrumentedClassNode = new ClassNode(); + classReader.accept(instrumentedClassNode, 0); + + // Completely overwrite any previous transformation, luckily we are in phase BEFORE and all other transformers we use are in phase AFTER + classNode.fields = instrumentedClassNode.fields; + if (mixin) { + // Mixin doesn't like JaCoCo instructions in but mixin constructors are never called anyway + List methods = new ArrayList<>(); + for (final MethodNode method : classNode.methods) { + if (method.name.equals("")) { + methods.add(method); + } + } + for (final MethodNode method : instrumentedClassNode.methods) { + if (!method.name.equals("")) { + methods.add(method); + } + } + classNode.methods = methods; + } else { + classNode.methods = instrumentedClassNode.methods; + } + + // JaCoCo has already updated the frames + return ComputeFlags.SIMPLE_REWRITE; + } + + +} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java new file mode 100644 index 00000000000..3d38c30951a --- /dev/null +++ b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java @@ -0,0 +1,63 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.transformers.modlauncher.jacoco; + +import org.jacoco.core.internal.instr.CondyProbeArrayStrategy; +import org.jacoco.core.internal.instr.IProbeArrayStrategy; +import org.jacoco.core.internal.instr.InstrSupport; +import org.jacoco.core.runtime.IExecutionDataAccessorGenerator; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ConstantDynamic; +import org.objectweb.asm.Handle; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public record PrefixedCondyProbeArrayStrategy( + String className, boolean isInterface, long classId, String prefix, + IExecutionDataAccessorGenerator accessorGenerator +) implements IProbeArrayStrategy { + + @Override + public int storeInstance(final MethodVisitor mv, final boolean clinit, final int variable) { + final Handle bootstrapMethod = new Handle(Opcodes.H_INVOKESTATIC, this.className, this.prefix + InstrSupport.INITMETHOD_NAME, CondyProbeArrayStrategy.B_DESC, this.isInterface); + mv.visitLdcInsn(new ConstantDynamic(this.prefix + InstrSupport.DATAFIELD_NAME, "Ljava/lang/Object;", bootstrapMethod)); + mv.visitTypeInsn(Opcodes.CHECKCAST, "[Z"); + mv.visitVarInsn(Opcodes.ASTORE, variable); + return 1; + } + + @Override + public void addMembers(final ClassVisitor cv, final int probeCount) { + if (probeCount == 0) { + return; + } + + final MethodVisitor mv = cv.visitMethod(InstrSupport.INITMETHOD_ACC, this.prefix + InstrSupport.INITMETHOD_NAME, CondyProbeArrayStrategy.B_DESC, null, null); + final int maxStack = this.accessorGenerator.generateDataAccessor(this.classId, this.className, probeCount, mv); + mv.visitInsn(Opcodes.ARETURN); + mv.visitMaxs(maxStack, 3); + mv.visitEnd(); + } +} diff --git a/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService new file mode 100644 index 00000000000..f95865eabf0 --- /dev/null +++ b/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService @@ -0,0 +1 @@ +org.spongepowered.transformers.modlauncher.jacoco.JacocoPluginService diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index a78cc276381..a23611351a3 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -19,6 +19,7 @@ plugins { id("implementation-structure") alias(libs.plugins.blossom) alias(libs.plugins.modDevGradle) + jacoco } val commonProject = parent!! @@ -240,6 +241,10 @@ dependencies { testImplementation(libs.mockito.junitJupiter) { exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") } + + testRuntimeOnly(libs.jacoco.core) { + exclude(group = "org.ow2.asm") + } } afterEvaluate { @@ -414,6 +419,18 @@ tasks { } dependsOn(prepareServerRun) + + extensions.configure(JacocoTaskExtension::class) { + excludeClassLoaders = listOf("cpw.mods.modlauncher.TransformingClassLoader") + } + + finalizedBy(jacocoTestReport) + } + + jacocoTestReport { + sourceSets(commonAppLaunchConf.get(), commonAppLaunch.get(), commonLaunch.get(), commonAccessors.get(), commonMixins.get(), commonMain.get()) + sourceSets(appLaunch, launch, lang, accessors, mixins, main) + dependsOn(test) } } diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 4f5a36bca04..24bdceca781 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -6,7 +6,7 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - eclipse + jacoco } val commonProject = parent!! @@ -264,6 +264,10 @@ dependencies { testImplementation(libs.mockito.junitJupiter) { exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") } + + testRuntimeOnly(libs.jacoco.core) { + exclude(group = "org.ow2.asm") + } } minecraft { @@ -515,6 +519,18 @@ tasks { workingDir.mkdirs() workingDir.resolve("eula.txt").writeText("eula=true") } + + extensions.configure(JacocoTaskExtension::class) { + excludeClassLoaders = listOf("cpw.mods.modlauncher.TransformingClassLoader") + } + + finalizedBy(jacocoTestReport) + } + + jacocoTestReport { + sourceSets(commonAppLaunchConf.get(), commonAppLaunch.get(), commonLaunch.get(), commonAccessors.get(), commonMixins.get(), commonMain.get()) + sourceSets(appLaunch, launch, accessors, mixins, main) + dependsOn(test) } } From 457e7b49608c104cccc68dcaaa0554d609ed4350 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 9 Aug 2025 16:33:19 +0200 Subject: [PATCH 325/586] Support unit tests via SpongeVanilla production jar --- vanilla/build.gradle.kts | 4 ++ .../vanilla/installer/InstallerMain.java | 20 ++++---- .../installer/test/SpongeSessionListener.java | 50 +++++++++++++++++++ .../installer/test/SpongeTestBoot.java | 40 +++++++++++++++ ....platform.launcher.LauncherSessionListener | 1 + 5 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java create mode 100644 vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeTestBoot.java create mode 100644 vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 24bdceca781..8b6659b1ba6 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -185,6 +185,10 @@ dependencies { installer(project(libraryManagerProject.path)) + // optional at runtime + "installerCompileOnly"(platform(apiLibs.junit.bom)) + "installerCompileOnly"(apiLibs.junit.launcher) + val boot = bootLibrariesConfig.name boot(libs.securemodules) boot(libs.asm.commons) diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index d1ae9561381..4dcb08aa7fb 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -81,28 +81,30 @@ public final class InstallerMain { private static final int MAX_TRIES = 2; private final Installer installer; + private final boolean isolated; - public InstallerMain(final String[] args) throws Exception { + public InstallerMain(final String[] args, final boolean isolated) throws Exception { LauncherCommandLine.configure(args); this.installer = new Installer(LauncherCommandLine.installerDirectory); + this.isolated = isolated; } public static void main(final String[] args) throws Exception { - new InstallerMain(args).run(); + new InstallerMain(args, true).run(); } - public void run() { + public void run() throws Exception { try { this.downloadAndRun(); } catch (final Exception ex) { Logger.error(ex, "Failed to download Sponge libraries and/or Minecraft"); - System.exit(2); + throw ex; } finally { this.installer.getLibraryManager().finishedProcessing(); } } - public void downloadAndRun() throws Exception { + private void downloadAndRun() throws Exception { ServerAndLibraries remappedMinecraftJar = null; Version mcVersion = null; try { @@ -188,7 +190,7 @@ public void downloadAndRun() throws Exception { gameArgs.add(launchTarget); Collections.addAll(gameArgs, this.installer.getConfig().args().split(" ")); - InstallerMain.bootstrap(bootLibs, spongeBoot, gameArgs.toArray(new String[0])); + this.bootstrap(bootLibs, spongeBoot, gameArgs.toArray(new String[0])); } private static Path newJarInJar(final Path jar) { @@ -214,7 +216,7 @@ private ServerAndLibraries recoverFromMinecraftDownloadErr } } - private static void bootstrap(final Path[] bootLibs, final Path spongeBoot, final String[] args) throws Exception { + private void bootstrap(final Path[] bootLibs, final Path spongeBoot, final String[] args) throws Exception { final List classpath = new ArrayList<>(); for (final Path lib : bootLibs) { classpath.add(new Path[] { lib }); @@ -222,10 +224,10 @@ private static void bootstrap(final Path[] bootLibs, final Path spongeBoot, fina classpath.add(new Path[] { spongeBoot }); try { - new VanillaBootstrap(args).boot(classpath, true); + new VanillaBootstrap(args).boot(classpath, this.isolated); } catch (final Exception ex) { Logger.error(ex, "Failed to invoke bootstrap due to an error"); - System.exit(1); + throw ex; } } diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java new file mode 100644 index 00000000000..1c7252550ab --- /dev/null +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.installer.test; + +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.LauncherSessionListener; +import org.spongepowered.common.applaunch.test.TestGameAccess; + +public class SpongeSessionListener implements LauncherSessionListener { + private ClassLoader previousLoader; + + @Override + public void launcherSessionOpened(final LauncherSession session) { + this.previousLoader = Thread.currentThread().getContextClassLoader(); + + try { + Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void launcherSessionClosed(final LauncherSession session) { + TestGameAccess.shutdownGame(); + Thread.currentThread().setContextClassLoader(this.previousLoader); + } +} diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeTestBoot.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeTestBoot.java new file mode 100644 index 00000000000..6260808514e --- /dev/null +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeTestBoot.java @@ -0,0 +1,40 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.installer.test; + +import org.spongepowered.common.applaunch.test.TestGameAccess; +import org.spongepowered.vanilla.installer.InstallerMain; + +public class SpongeTestBoot { + + public static ClassLoader getGameClassLoader() throws Exception { + if (TestGameAccess.getGameClassLoader() == null) { + final String[] args = System.getProperty("sponge.test.args", "").split(" "); + System.setProperty("sponge.test.active", "true"); + new InstallerMain(args, false).run(); + } + return TestGameAccess.getGameClassLoader(); + } +} diff --git a/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener b/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener new file mode 100644 index 00000000000..b9f17c0d2bb --- /dev/null +++ b/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener @@ -0,0 +1 @@ +org.spongepowered.vanilla.installer.test.SpongeSessionListener From abf8d23d1b60f04a970e378653c464c1172963da Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 9 Aug 2025 22:39:58 +0200 Subject: [PATCH 326/586] Support JaCoCo via SpongeVanilla production jar --- forge/build.gradle.kts | 1 + .../jacoco/JacocoPluginService.java | 25 +++++++++++++++++-- neoforge/build.gradle.kts | 1 + vanilla/build.gradle.kts | 1 + .../vanilla/installer/InstallerMain.java | 24 ++++++++++++++---- 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index fea72eeca39..5b6369a6709 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -434,6 +434,7 @@ tasks { val runServer = minecraft.runs.getByName("server") jvmArgs(runServer.jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) + jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java index d87aaaeea58..e8c176b047b 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java +++ b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java @@ -51,6 +51,7 @@ public class JacocoPluginService implements ILaunchPluginService { private static final EnumSet NAY = EnumSet.noneOf(Phase.class); private boolean disabled; + private String[] packages; private ClassLoader loader; public JacocoPluginService() { @@ -58,6 +59,15 @@ public JacocoPluginService() { getClass().getClassLoader().loadClass("org.jacoco.core.JaCoCo"); } catch (final ClassNotFoundException e) { this.disabled = true; + return; + } + + this.packages = System.getProperty("sponge.jacoco.packages", "").split(","); + for (int i = 0; i < this.packages.length; i++) { + final String pkg = this.packages[i].replace('.', '/'); + if (!pkg.endsWith("/")) { + this.packages[i] = pkg + "/"; + } } } @@ -71,6 +81,15 @@ public EnumSet handlesClass(Type classType, boolean isEmpty) { return this.disabled || isEmpty ? NAY : YAY; } + private boolean testClassName(final String name) { + for (final String pkg : this.packages) { + if (name.startsWith(pkg)) { + return true; + } + } + return false; + } + @Override public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) { @@ -88,8 +107,10 @@ public int processClassWithFlags(final Phase phase, final ClassNode classNode, f this.loader = contextLoader; } - // Only apply JaCoCo to our sources - if (!classNode.name.startsWith("org/spongepowered/")) { + // Do not instrument every class for two reasons: + // - Performance + // - JaCoCo changes the LVT which can cause mixins targeting the current class to fail + if (!this.testClassName(classNode.name)) { return ComputeFlags.NO_REWRITE; } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index a23611351a3..7af530fe46b 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -409,6 +409,7 @@ tasks { jvmArgs(runServer.get().jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.get().args!!.joinToString(" ")) + jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 8b6659b1ba6..86742047026 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -515,6 +515,7 @@ tasks { val runServer = minecraft.runs.server().get() jvmArgs(runServer.allJvmArguments()) jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) + jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index 4dcb08aa7fb..3a4cd688cfc 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -111,7 +111,6 @@ private void downloadAndRun() throws Exception { mcVersion = this.downloadMinecraftManifest(); } catch (final IOException ex) { remappedMinecraftJar = this.recoverFromMinecraftDownloadError(ex); - this.installer.getLibraryManager().validate(); } final LibraryManager libraryManager = this.installer.getLibraryManager(); @@ -128,7 +127,6 @@ private void downloadAndRun() throws Exception { throw new UncheckedIOException(ex); } }, libraryManager.preparationWorker()); - libraryManager.validate(); remappedMinecraftJar = remappedMinecraftJarFuture.get(); } } catch (final ExecutionException ex) { @@ -137,6 +135,8 @@ private void downloadAndRun() throws Exception { } assert remappedMinecraftJar != null; // always assigned or thrown + libraryManager.validate(); + // Minecraft itself is on the main layer libraryManager.addLibrary(InstallerMain.COLLECTION_MAIN, new LibraryManager.Library("minecraft", remappedMinecraftJar.server())); @@ -148,17 +148,31 @@ private void downloadAndRun() throws Exception { libraryManager.addLibrary(InstallerMain.COLLECTION_BOOTSTRAP, new LibraryManager.Library(artifact.toString(), path)); } - this.installer.getLibraryManager().finishedProcessing(); + if (!this.isolated) { + // JaCoCo core is provided by the user because its version must match the version of the JaCoCo agent + Path jacocoJar = null; + try { + final Class jacocoClass = getClass().getClassLoader().loadClass("org.jacoco.core.JaCoCo"); + jacocoJar = Path.of(jacocoClass.getProtectionDomain().getCodeSource().getLocation().toURI()); + } catch (final Exception ignored) {} + + if (jacocoJar != null && jacocoJar.getFileName().toString().endsWith(".jar")) { + Logger.info("JaCoCo core has been detected. Custom instrumentation will be enabled."); + libraryManager.addLibrary(InstallerMain.COLLECTION_BOOTSTRAP, new LibraryManager.Library("jacoco-core", jacocoJar)); + } + } + + libraryManager.finishedProcessing(); Logger.info("Environment has been verified."); final Set seenLibs = new HashSet<>(); - final Path[] bootLibs = this.installer.getLibraryManager().getAll(InstallerMain.COLLECTION_BOOTSTRAP).stream() + final Path[] bootLibs = libraryManager.getAll(InstallerMain.COLLECTION_BOOTSTRAP).stream() .peek(lib -> seenLibs.add(lib.name())) .map(LibraryManager.Library::file) .toArray(Path[]::new); - final Path[] gameLibs = this.installer.getLibraryManager().getAll(InstallerMain.COLLECTION_MAIN).stream() + final Path[] gameLibs = libraryManager.getAll(InstallerMain.COLLECTION_MAIN).stream() .filter(lib -> !seenLibs.contains(lib.name())) .map(LibraryManager.Library::file) .toArray(Path[]::new); From 3810b54d06b0293e16e2f0a728f1b2bde8227417 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 10 Aug 2025 21:12:08 +0200 Subject: [PATCH 327/586] Ability to trigger ticks during tests --- .../bootstrap/dev/DevClasspath.java | 2 +- .../bridge/server/MinecraftServerBridge.java | 4 ++ .../server/MinecraftServerMixin_Test.java | 48 ++++++++----- .../DedicatedServerSettingsMixin_Test.java | 1 + .../common/scheduler/SchedulerTest.java | 70 +++++++++++++++++++ src/test/resources/mixins.common.test.json | 11 --- 6 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java delete mode 100644 src/test/resources/mixins.common.test.json diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 3e1b3c97e1d..8dfc98cb24e 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -125,7 +125,7 @@ public static List resolve() { final String fileName = path.getFileName().toString(); - if (fileName.startsWith("junit-")) { + if (fileName.startsWith("junit-") || fileName.startsWith("mockito-")) { if (Bootstrap.DEBUG) { System.out.println("Ignored: " + path); } diff --git a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java index 9d4e6a54def..a3a3a31a5ac 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java @@ -53,4 +53,8 @@ public interface MinecraftServerBridge { void bridge$reloadedServerRegistries(RegistryHolderLogic holder); RegistryHolderLogic bridge$registryHolder(); + + default void bridge$tickServer(int ticks) { + throw new UnsupportedOperationException("Cannot trigger manual server tick outside test environment"); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java index 8d191bdfdd8..8d92a0c9168 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java @@ -35,28 +35,27 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.applaunch.test.TestGameAccess; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; import java.io.IOException; +import java.util.function.BooleanSupplier; import java.util.function.Function; @Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin_Test extends ReentrantBlockableEventLoop { +public abstract class MinecraftServerMixin_Test extends ReentrantBlockableEventLoop implements MinecraftServerBridge { - public MinecraftServerMixin_Test(String name) { - super(name); - } - - @Shadow - protected abstract boolean initServer() throws IOException; - - @Shadow - private volatile boolean running; + // @formatter:off + @Shadow private volatile boolean running; + @Shadow private boolean stopped; - @Shadow - private boolean stopped; + @Shadow protected abstract boolean shadow$initServer() throws IOException; + @Shadow public abstract void shadow$stopServer(); + @Shadow public abstract void shadow$tickServer(BooleanSupplier haveTime); + // @formatter:on - @Shadow - public abstract void stopServer(); + public MinecraftServerMixin_Test(final String name) { + super(name); + } @Inject(method = "", at = @At("RETURN")) private void onInit(final CallbackInfo ci) { @@ -71,7 +70,7 @@ private void onInit(final CallbackInfo ci) { private static void spin(final Function supplier, CallbackInfoReturnable cir) { final MinecraftServer server = supplier.apply(Thread.currentThread()); try { - ((MinecraftServerMixin_Test) (Object) server).initServer(); + ((MinecraftServerMixin_Test) (Object) server).shadow$initServer(); } catch (IOException e) { throw new RuntimeException(e); } @@ -82,7 +81,7 @@ private static void spin(final Function suppl if (this.running) { this.running = false; this.stopped = true; - this.stopServer(); + this.shadow$stopServer(); } } @@ -103,4 +102,21 @@ public void halt(final boolean join) { public void waitUntilNextTick() { this.runAllTasks(); } + + /** + * @author Yeregorix + * @reason We have time to run all optional tasks. + */ + @Overwrite + private boolean haveTime() { + return true; + } + + @Override + public void bridge$tickServer(final int ticks) { + for (int i = 0; i < ticks; i++) { + this.shadow$tickServer(this::haveTime); + this.waitUntilNextTick(); + } + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java index 47385cbc346..dd95cb3ad80 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/dedicated/DedicatedServerSettingsMixin_Test.java @@ -43,6 +43,7 @@ public DedicatedServerProperties forceTestProperties(final Path path) { props.setProperty("level-seed", "0"); props.setProperty("level-type", "flat"); props.setProperty("enable-command-block", "true"); + props.setProperty("pause-when-empty-seconds", "0"); return new DedicatedServerProperties(props); } } diff --git a/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java b/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java new file mode 100644 index 00000000000..1ac7b72f764 --- /dev/null +++ b/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java @@ -0,0 +1,70 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.scheduler; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.scheduler.Task; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.metadata.PluginMetadata; + +import java.util.concurrent.atomic.AtomicBoolean; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class SchedulerTest { + + @Test + public void testScheduleSync() { + final PluginContainer plugin = Mockito.mock(PluginContainer.class); + final PluginMetadata metadata = Mockito.mock(PluginMetadata.class); + when(plugin.metadata()).thenReturn(metadata); + when(metadata.id()).thenReturn("test"); + + final AtomicBoolean done = new AtomicBoolean(false); + final Server server = Sponge.server(); + + server.scheduler().submit(Task.builder().execute(() -> done.set(true)).plugin(plugin).delay(Ticks.of(2)).build()); + assertFalse(done.get()); + + ((MinecraftServerBridge) server).bridge$tickServer(1); + assertFalse(done.get()); + + ((MinecraftServerBridge) server).bridge$tickServer(1); + assertTrue(done.get()); + } +} diff --git a/src/test/resources/mixins.common.test.json b/src/test/resources/mixins.common.test.json deleted file mode 100644 index 5fb635730bb..00000000000 --- a/src/test/resources/mixins.common.test.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "required": true, - "parent": "mixins.sponge.parent.json", - "package": "org.spongepowered.common.launch.mixin", - "mixinPriority": 11111, - "mixins": [ - "ItemMixin_Test", - "SchematicTranslatorMixin_Test", - "SpongeImplHooksMixin_Test" - ] -} From 64d7d46ec930f2e1ef98bb7b6975e9fc0580658e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 11 Aug 2025 14:57:27 +0200 Subject: [PATCH 328/586] Cleanup Idea-Ext plugin configuration --- build.gradle.kts | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 19455e530d5..905da3c316d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.gradle.ext.compiler +import org.jetbrains.gradle.ext.delegateActions +import org.jetbrains.gradle.ext.settings import org.spongepowered.gradle.vanilla.task.DecompileJarTask import java.util.Locale @@ -178,6 +181,20 @@ minecraft { accessWideners(main.resources.filter { it.name.endsWith(".accesswidener") }) } +idea { + project.settings { + delegateActions { + delegateBuildRunToGradle = false + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE + } + compiler { + addNotNullAssertions = false + useReleaseOption = true + parallelCompilation = true + } + } +} + allprojects { configurations.configureEach { resolutionStrategy.dependencySubstitution { @@ -188,7 +205,6 @@ allprojects { } } - apply(plugin = "org.jetbrains.gradle.plugin.idea-ext") apply(plugin = "java-library") apply(plugin = "maven-publish") apply(plugin = "net.kyori.indra.licenser.spotless") @@ -212,22 +228,6 @@ allprojects { } } - idea { - if (project != null) { - (project as ExtensionAware).extensions["settings"].run { - (this as ExtensionAware).extensions.getByType(org.jetbrains.gradle.ext.ActionDelegationConfig::class).run { - delegateBuildRunToGradle = false - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM - } - extensions.getByType(org.jetbrains.gradle.ext.IdeaCompilerConfiguration::class).run { - addNotNullAssertions = false - useReleaseOption = JavaVersion.current().isJava10Compatible - parallelCompilation = true - } - } - } - } - java { val targetJavaVersion = JavaVersion.toVersion(apiJavaTarget.toInt()) sourceCompatibility = targetJavaVersion @@ -272,14 +272,10 @@ allprojects { val spongeSnapshotRepo: String? by project val spongeReleaseRepo: String? by project tasks { - val emptyAnnotationProcessors = objects.fileCollection() withType(JavaCompile::class).configureEach { options.compilerArgs.addAll(listOf("-Xmaxerrs", "1000")) options.encoding = "UTF-8" options.release.set(apiJavaTarget.toInt()) - if (project.name != "testplugins" && System.getProperty("idea.sync.active") != null) { - options.annotationProcessorPath = emptyAnnotationProcessors // hack so IntelliJ doesn't try to run Mixin AP - } } withType(PublishToMavenRepository::class).configureEach { From 01a21b2ec566d6468db75c0a317d5afffec04b1d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 4 Sep 2025 20:35:47 +0200 Subject: [PATCH 329/586] Fix experience test --- .../common/util/ExperienceHolderUtilTest.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java b/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java index e0e20b4ed5c..4ac3ca6aee0 100644 --- a/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java +++ b/src/test/java/org/spongepowered/common/util/ExperienceHolderUtilTest.java @@ -25,17 +25,18 @@ package org.spongepowered.common.util; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.PrimaryLevelData; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.world.DefaultWorldKeys; import java.util.ArrayList; import java.util.List; @@ -44,10 +45,14 @@ public final class ExperienceHolderUtilTest { public static List testExp() { - final Level world = mock(Level.class); - when(world.getLevelData()).thenReturn(mock(PrimaryLevelData.class)); + final Level world = (Level) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); final Player player = new Player(world, BlockPos.ZERO, 0, new GameProfile(UUID.randomUUID(), "Player")) { + @Override + public @Nullable GameType gameMode() { + return null; + } + @Override public boolean isSpectator() { return false; From 54f71334415f120ce6970ce87676c87738b9d052 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 4 Sep 2025 21:17:32 +0200 Subject: [PATCH 330/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 8cb3594abc5..b06229f7846 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8cb3594abc5bab0ba3854b3b7a5ea3366253af8a +Subproject commit b06229f78460f09c9f06679d2332bab784d94fa4 From f834112bddcebb1bd47186599edad2972a237f76 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 4 Sep 2025 21:01:31 +0200 Subject: [PATCH 331/586] Bump SpongeAPI --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 087461105d9..62832193efb 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 087461105d92b122aac9a5e968eed8a2a9f24582 +Subproject commit 62832193efb6b49e4e9a7967ed95d3251ad2409a diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e569dac6921..c0377e1e13e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -8184,6 +8184,9 @@ + + + From 7b347f6713ce4a3d4ef157a853d7e63e7544619f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 4 Sep 2025 22:26:42 +0200 Subject: [PATCH 332/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 6f5f4d6747d..c5911e4c3c7 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 6f5f4d6747d397db0dc906349e39beea132fda91 +Subproject commit c5911e4c3c7c5289b8b6c7cac9893bfcba6e9cc6 From 26e534007c9051215a3774756c7471305404295b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 4 Sep 2025 23:14:19 +0200 Subject: [PATCH 333/586] Fix human spawn packet injection on Neo --- .../mixins.spongeforge.core.shared.json | 1 - .../server/level/ServerEntityMixin_Neo.java | 75 ------------------ .../resources/mixins.spongeneo.core.json | 1 - .../core/server/level/ServerEntityMixin.java | 32 ++++++++ .../level/ServerEntityMixin_Shared.java | 76 ------------------- .../mixins.spongevanilla.core.shared.json | 1 - 6 files changed, 32 insertions(+), 154 deletions(-) delete mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerEntityMixin_Neo.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin_Shared.java diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json index e23ba17fbba..5afc6cf65b6 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json @@ -4,7 +4,6 @@ "package": "org.spongepowered.common.mixin.core", "priority": 1301, "mixins": [ - "server.level.ServerEntityMixin_Shared", "world.entity.LivingEntityMixin_Shared_Damage", "world.entity.player.PlayerMixin_Shared_Damage", "world.entity.projectile.FishingHookMixin_Shared" diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerEntityMixin_Neo.java deleted file mode 100644 index bd1c9dafd96..00000000000 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/level/ServerEntityMixin_Neo.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.mixin.core.server.level; - -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; -import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; -import net.minecraft.server.level.ServerEntity; -import net.minecraft.world.entity.Entity; -import net.neoforged.neoforge.network.bundle.PacketAndPayloadAcceptor; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.entity.living.human.HumanEntity; - -import java.util.EnumSet; -import java.util.List; - -@Mixin(ServerEntity.class) -public class ServerEntityMixin_Neo { - @Shadow @Final private Entity entity; - - /** - * @author gabizou - * @reason Because the entity spawn packet is just a lone packet, we have to actually - * do some hackery to create the player list packet first, then the spawn packet, - * then perform the remove packet. - */ - @Redirect( - method = "sendPairingData", - at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor;accept(Lnet/minecraft/network/protocol/Packet;)Lnet/neoforged/neoforge/network/bundle/PacketAndPayloadAcceptor;", ordinal = 0) - ) - public PacketAndPayloadAcceptor impl$sendHumanSpawnPacket(PacketAndPayloadAcceptor consumer, Packet spawnPacket) { - if (!(this.entity instanceof final HumanEntity human)) { - return consumer.accept(spawnPacket); - } - // Adds the GameProfile to the client - consumer.accept(human.createPlayerListPacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER))); - // Actually spawn the human (a player) - consumer.accept(spawnPacket); - // Remove from the player map - final ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(List.of(human.getUUID())); - if (human.canRemoveFromListImmediately()) { - consumer.accept(removePacket); - } else { - // Human is a Player entity on the client and needs to tick once for the skin to render - human.removeFromTabListDelayed(null, removePacket); - } - return consumer; - } -} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index f61741a8226..7ca65c158da 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -23,7 +23,6 @@ "server.BootstrapMixin_Neo", "server.MinecraftServerMixin_Neo", "server.commands.SpreadPlayersCommandMixin_Neo", - "server.level.ServerEntityMixin_Neo", "server.level.ServerPlayerMixin_Neo", "server.network.ServerGamePacketListenerImplMixin_Neo", "tags.TagLoaderMixin_NeoForge", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java index 06ce9970562..f1a98074f9d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java @@ -27,6 +27,8 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerLevel; @@ -48,6 +50,7 @@ import org.spongepowered.common.entity.living.human.HumanEntity; import java.util.Collection; +import java.util.EnumSet; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -102,6 +105,35 @@ public abstract class ServerEntityMixin { } } + /** + * @author gabizou + * @reason Because the entity spawn packet is just a lone packet, we have to actually + * do some hackery to create the player list packet first, then the spawn packet, + * then perform the remove packet. + */ + @Redirect( + method = "sendPairingData", + at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V", ordinal = 0) + ) + public void impl$sendHumanSpawnPacket(final Consumer> consumer, final Object spawnPacket) { + if (!(this.entity instanceof final HumanEntity human)) { + consumer.accept((Packet) spawnPacket); + return; + } + // Adds the GameProfile to the client + consumer.accept(human.createPlayerListPacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER))); + // Actually spawn the human (a player) + consumer.accept((Packet) spawnPacket); + // Remove from the player map + final ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(List.of(human.getUUID())); + if (human.canRemoveFromListImmediately()) { + consumer.accept(removePacket); + } else { + // Human is a Player entity on the client and needs to tick once for the skin to render + human.removeFromTabListDelayed(null, removePacket); + } + } + @Inject(method = "sendDirtyEntityData", at = @At("HEAD")) public void impl$sendHumanMetadata(final CallbackInfo ci) { if (!(this.entity instanceof final HumanEntity human)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin_Shared.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin_Shared.java deleted file mode 100644 index c7785b5bfa7..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin_Shared.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server.level; - -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; -import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; -import net.minecraft.server.level.ServerEntity; -import net.minecraft.world.entity.Entity; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.entity.living.human.HumanEntity; - -import java.util.EnumSet; -import java.util.List; -import java.util.function.Consumer; - -// Forge and Vanilla -@Mixin(ServerEntity.class) -public class ServerEntityMixin_Shared { - @Shadow @Final private Entity entity; - - /** - * @author gabizou - * @reason Because the entity spawn packet is just a lone packet, we have to actually - * do some hackery to create the player list packet first, then the spawn packet, - * then perform the remove packet. - */ - @Redirect( - method = "sendPairingData", - at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V", ordinal = 0) - ) - public void impl$sendHumanSpawnPacket(final Consumer> consumer, final Object spawnPacket) { - if (!(this.entity instanceof final HumanEntity human)) { - consumer.accept((Packet) spawnPacket); - return; - } - // Adds the GameProfile to the client - consumer.accept(human.createPlayerListPacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER))); - // Actually spawn the human (a player) - consumer.accept((Packet) spawnPacket); - // Remove from the player map - final ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(List.of(human.getUUID())); - if (human.canRemoveFromListImmediately()) { - consumer.accept(removePacket); - } else { - // Human is a Player entity on the client and needs to tick once for the skin to render - human.removeFromTabListDelayed(null, removePacket); - } - } -} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json index e23ba17fbba..5afc6cf65b6 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json @@ -4,7 +4,6 @@ "package": "org.spongepowered.common.mixin.core", "priority": 1301, "mixins": [ - "server.level.ServerEntityMixin_Shared", "world.entity.LivingEntityMixin_Shared_Damage", "world.entity.player.PlayerMixin_Shared_Damage", "world.entity.projectile.FishingHookMixin_Shared" From 26284a5ab55394f2a9de03731cf0b953a7048581 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 5 Sep 2025 00:40:08 +0200 Subject: [PATCH 334/586] Neo ModLauncher and SJH have been moved to FancyModLoader --- bootstrap/build.gradle.kts | 2 +- .../bootstrap/neoforge/NeoForgeBootstrap.java | 2 +- forge/build.gradle.kts | 2 +- gradle/libs.versions.toml | 9 ++-- gradle/verification-metadata.xml | 53 +++++++++++++++++++ modlauncher-transformers/build.gradle.kts | 2 +- neoforge/build.gradle.kts | 2 +- vanilla/build.gradle.kts | 2 +- 8 files changed, 63 insertions(+), 11 deletions(-) diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts index beea2d28538..0372e14307b 100644 --- a/bootstrap/build.gradle.kts +++ b/bootstrap/build.gradle.kts @@ -17,5 +17,5 @@ dependencies { forgeLib(libs.securemodules) val neoforgeLib = neoforge.implementationConfigurationName - neoforgeLib(libs.securejarhandler) + neoforgeLib(libs.fancymodloader.securejarhandler) } diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java index 84ac0a335ea..852e88e448e 100644 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java @@ -69,7 +69,7 @@ protected ClassLoader createApplicationClassLoader(final Configuration config, f @Override protected void runApplication(final ModuleLayer layer) throws Exception { - final Class appClass = layer.findModule("cpw.mods.modlauncher").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); + final Class appClass = layer.findModule("fml_loader").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 33cd716fb56..e8fedc5749e 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -195,7 +195,7 @@ dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) service(project(transformersProject.path)) { - exclude(group = "cpw.mods", module = "modlauncher") + exclude(group = "net.neoforged.fancymodloader", module = "loader") } service(project(libraryManagerProject.path)) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 82ea5a9ce16..a4510edfba6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,9 +10,8 @@ forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" mixinextras = "0.4.1" modlauncher = "10.2.2" -neo-modlauncher = "11.0.3" securemodules = "2.2.22" -securejarhandler = "3.0.8" +fancymodloader = "9.0.16" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" @@ -34,9 +33,9 @@ log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "lo log4j-jpl = { module = "org.apache.logging.log4j:log4j-jpl", version.ref = "log4j" } log4j-slf4j2 = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" } modlauncher = { module = "net.minecraftforge:modlauncher", version.ref = "modlauncher" } -neo-modlauncher = { module = "cpw.mods:modlauncher", version.ref = "neo-modlauncher" } securemodules = { module = "net.minecraftforge:securemodules", version.ref = "securemodules" } -securejarhandler = { module = "cpw.mods:securejarhandler", version.ref = "securejarhandler" } +fancymodloader-loader = { module = "net.neoforged.fancymodloader:loader", version.ref = "fancymodloader" } +fancymodloader-securejarhandler = { module = "net.neoforged.fancymodloader:securejarhandler", version.ref = "fancymodloader" } tinylog-api = { module = "org.tinylog:tinylog-api", version.ref = "tinylog" } tinylog-impl = { module = "org.tinylog:tinylog-impl", version.ref = "tinylog" } tinylog-slf4j = { module = "org.tinylog:slf4j-tinylog", version.ref = "tinylog" } @@ -79,4 +78,4 @@ indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = " shadow = { id = "com.gradleup.shadow", version = "8.3.8" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } -modDevGradle = { id = "net.neoforged.moddev", version = "2.0.78" } +modDevGradle = { id = "net.neoforged.moddev", version = "2.0.107" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index fa93484231a..1dae8da85de 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2248,6 +2248,14 @@ + + + + + + + + @@ -5274,6 +5282,14 @@ + + + + + + + + @@ -5614,6 +5630,14 @@ + + + + + + + + @@ -5765,6 +5789,14 @@ + + + + + + + + @@ -6050,6 +6082,14 @@ + + + + + + + + @@ -6330,6 +6370,19 @@ + + + + + + + + + + + + + diff --git a/modlauncher-transformers/build.gradle.kts b/modlauncher-transformers/build.gradle.kts index 5ddf331a743..bc80591a4c3 100644 --- a/modlauncher-transformers/build.gradle.kts +++ b/modlauncher-transformers/build.gradle.kts @@ -4,7 +4,7 @@ dependencies { } compileOnly(libs.log4j.api) - compileOnly(libs.neo.modlauncher) { + compileOnly(libs.fancymodloader.loader) { exclude(group = "org.ow2.asm") exclude(group = "org.apache.logging.log4j") } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 7af530fe46b..b18c6cd3430 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -207,7 +207,7 @@ dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) service(project(transformersProject.path)) { - exclude(group = "cpw.mods", module = "modlauncher") + exclude(group = "net.neoforged.fancymodloader", module = "loader") } service(project(libraryManagerProject.path)) diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 86742047026..d5517daaa2c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -229,7 +229,7 @@ dependencies { spongeImpl.copyModulesExcludingPrefix(configurations.minecraft.get(), "net.minecraft", "joined", bootLibrariesConfig.get()) boot(project(transformersProject.path)) { - exclude(group = "cpw.mods", module = "modlauncher") + exclude(group = "net.neoforged.fancymodloader", module = "loader") } val game = gameLibrariesConfig.name From c7738c23210777b9b7675efa33e494705f6d21a0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 4 Sep 2025 17:49:22 -0700 Subject: [PATCH 335/586] chore(minecraft): update to 25w35a Updated entity, block, and profile-related API usages for library updates. See: https://minecraft.wiki/w/Java_Edition_25w35a --- .../world/level/BaseCommandBlockAccessor.java | 3 + .../entity/SkullBlockEntityAccessor.java | 1 - .../common/adventure/SpongeAdventure.java | 6 +- .../block/entity/CommandBlockData.java | 2 +- .../provider/block/entity/ConduitData.java | 2 +- .../data/provider/block/entity/SkullData.java | 16 ++++- .../provider/entity/AbstractHorseData.java | 2 +- .../data/provider/entity/AnimalData.java | 2 +- .../common/data/provider/entity/FoxData.java | 4 +- .../provider/entity/ServerPlayerData.java | 4 +- .../provider/entity/ShulkerBulletData.java | 2 +- .../common/data/provider/entity/TNTData.java | 2 +- .../data/provider/entity/TameableData.java | 2 +- .../item/stack/SkullItemStackData.java | 4 +- .../entity/living/human/HumanEntity.java | 33 +++++----- .../common/entity/player/SpongeUserData.java | 16 ++--- .../velocity/VelocityForwardingInfo.java | 2 +- .../network/packet/SpongePacketHandler.java | 4 +- .../network/status/SpongeStatusResponse.java | 2 +- .../common/profile/SpongeGameProfile.java | 12 ++-- .../profile/SpongeGameProfileManager.java | 2 +- .../profile/UncachedGameProfileProvider.java | 19 +++--- .../service/server/ban/SpongeIPBanList.java | 40 ++++++------ .../service/server/ban/SpongeUserBanList.java | 9 ++- .../permission/SpongePermissionService.java | 2 +- .../server/permission/UserSubject.java | 8 +-- .../server/whitelist/SpongeUserWhiteList.java | 11 ++-- .../common/user/SpongeUserManager.java | 10 +-- src/main/resources/common.accesswidener | 1 + .../server/MinecraftServerMixin_API.java | 14 +++-- .../server/level/ServerPlayerMixin_API.java | 3 +- .../entity/CommandBlockEntityMixin_API.java | 12 +++- .../chat/ComponentSerializationMixin.java | 2 +- .../chat/Component_SerializerMixin.java | 2 +- .../core/server/MinecraftServerMixin.java | 17 ++---- .../dedicated/DedicatedPlayerListMixin.java | 5 +- .../core/server/level/ServerPlayerMixin.java | 2 +- ...rConfigurationPacketListenerImplMixin.java | 6 +- .../ServerLoginPacketListenerImplMixin.java | 8 +-- .../server/players/GameProfileCacheMixin.java | 8 +-- .../core/server/players/PlayerListMixin.java | 9 +-- .../core/world/BaseCommandBlockMixin.java | 18 ++++-- .../vehicle/MinecartCommandBlockMixin.java | 3 +- .../block/entity/CommandBlockEntityMixin.java | 3 +- ...oginPacketListenerImplMixin_IpForward.java | 6 +- ...TamableAnimalMixin_Optimization_Owner.java | 2 +- .../DedicatedServerMixin_Tracker.java | 4 +- .../gui/widget/list/FilterableList.java | 61 +++++++++---------- .../gui/widget/list/PluginSelectionList.java | 23 ++++--- 49 files changed, 237 insertions(+), 194 deletions(-) diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java index d9db6bd2d9e..0ac83b2a8c0 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java @@ -28,6 +28,7 @@ import net.minecraft.world.level.BaseCommandBlock; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(BaseCommandBlock.class) public interface BaseCommandBlockAccessor { @@ -40,4 +41,6 @@ public interface BaseCommandBlockAccessor { @Accessor("command") void accessor$command(final String command); + @Invoker("createSource") BaseCommandBlock.CloseableCommandBlockSource invoker$createSource(); + } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java index e38e9af68a4..28f76ba8277 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java @@ -35,5 +35,4 @@ public interface SkullBlockEntityAccessor { @Accessor("noteBlockSound") void accessor$noteBlockSound(final ResourceLocation location); @Accessor("noteBlockSound") ResourceLocation accessor$noteBlockSound(); - } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 2478f2342f3..65b58fc2651 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -75,15 +75,15 @@ import net.minecraft.network.chat.FontDescription; import net.minecraft.network.chat.HoverEvent.Action; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.contents.BlockDataSource; -import net.minecraft.network.chat.contents.EntityDataSource; import net.minecraft.network.chat.contents.KeybindContents; import net.minecraft.network.chat.contents.NbtContents; import net.minecraft.network.chat.contents.PlainTextContents; import net.minecraft.network.chat.contents.ScoreContents; import net.minecraft.network.chat.contents.SelectorContents; -import net.minecraft.network.chat.contents.StorageDataSource; import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.network.chat.contents.data.BlockDataSource; +import net.minecraft.network.chat.contents.data.EntityDataSource; +import net.minecraft.network.chat.contents.data.StorageDataSource; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerBossEvent; diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/CommandBlockData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/CommandBlockData.java index 0d9edff6663..c5f787d725d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/CommandBlockData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/CommandBlockData.java @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.getCommandBlock().getSuccessCount()) .set((h, v) -> ((BaseCommandBlockAccessor) h.getCommandBlock()).accessor$successCount(v)) .create(Keys.TRACKS_OUTPUT) - .get(h -> h.getCommandBlock().acceptsFailure()) + .get(h -> h.getCommandBlock().isTrackOutput()) .set((h, v) -> h.getCommandBlock().setTrackOutput(v)); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java index ac5b47ea0ac..e97bccf092a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/ConduitData.java @@ -66,7 +66,7 @@ public static void register(final DataProviderRegistrator registrator) { if (!(e instanceof LivingEntity le)) { return false; } - c.accessor$setDestroyTarget(new EntityReference<>(le)); + c.accessor$setDestroyTarget(EntityReference.of(le)); return true; }); //@formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java index a1736b556c5..813eb4c98af 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.data.provider.block.entity; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.level.block.entity.SkullBlockEntity; @@ -33,6 +35,8 @@ import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.profile.SpongeGameProfile; +import java.util.UUID; + public final class SkullData { private SkullData() { @@ -45,12 +49,18 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.GAME_PROFILE) .get(h -> { if (h.getOwnerProfile() != null) { - return SpongeGameProfile.of(h.getOwnerProfile().gameProfile()); + return SpongeGameProfile.of(h.getOwnerProfile().partialProfile()); } return null; }) - .set((h, v) -> h.setOwner(new ResolvableProfile(SpongeGameProfile.toMcProfile(v)))) - .delete(h -> h.setOwner(null)) + .set((h, v) -> { + h.applyComponents(h.components(), DataComponentPatch.builder() + .set(DataComponents.PROFILE, ResolvableProfile.createResolved(SpongeGameProfile.toMcProfile(v))) + .build()); + }) + .delete(h -> h.applyComponents(h.components(), DataComponentPatch.builder() + .set(DataComponents.PROFILE, ResolvableProfile.createUnresolved(new UUID(0, 0))) + .build())) .asMutable(SkullBlockEntityAccessor.class) .create(Keys.NOTE_BLOCK_SOUND) .get(h -> (ResourceKey) (Object) h.accessor$noteBlockSound()) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java index 7c172711475..4576e7471f5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java @@ -52,7 +52,7 @@ public static void register(final DataProviderRegistrator registrator) { return owner.getUUID(); }) .set((h, v) -> { - ((AbstractHorseAccessor) h).accessor$setOwner(new EntityReference<>(v)); + ((AbstractHorseAccessor) h).accessor$setOwner(EntityReference.of(v)); }) .delete(h -> { h.setOwner(null); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java index 62866334dcc..d086ec3b5af 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AnimalData.java @@ -40,7 +40,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(AnimalAccessor.class) .create(Keys.BREEDER) .get(a -> a.accessor$loveCause().getUUID()) - .set(((animalAccessor, uuid) -> animalAccessor.accessor$loveCause(new EntityReference<>(uuid)))); + .set(((animalAccessor, uuid) -> animalAccessor.accessor$loveCause(EntityReference.of(uuid)))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java index 7ee1a7afe41..1325ffea14b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java @@ -44,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Fox.class) .create(Keys.FIRST_TRUSTED) .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_0()).map(EntityReference::getUUID).orElse(null)) - .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v).map(EntityReference::new))) + .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_0(), Optional.ofNullable(v).map(EntityReference::of))) .create(Keys.FOX_TYPE) .get(h -> (FoxType) (Object) h.getVariant()) .set((h, v) -> ((FoxAccessor) h ).invoker$setVariant((Fox.Variant) (Object) v)) @@ -68,7 +68,7 @@ public static void register(final DataProviderRegistrator registrator) { .set((h, v) -> ((FoxAccessor) h).invoker$setSleeping(v)) .create(Keys.SECOND_TRUSTED) .get(h -> h.getEntityData().get(FoxAccessor.accessor$DATA_TRUSTED_ID_1()).map(EntityReference::getUUID).orElse(null)) - .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_1(), Optional.ofNullable(v).map(EntityReference::new))); + .set((h, v) -> h.getEntityData().set(FoxAccessor.accessor$DATA_TRUSTED_ID_1(), Optional.ofNullable(v).map(EntityReference::of))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 5263916c19f..88bdbcfb6f4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -74,14 +74,14 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (GameMode) (Object) h.gameMode.getPreviousGameModeForPlayer()) .create(Keys.SKIN_PROFILE_PROPERTY) .get(h -> { - final Collection properties = h.getGameProfile().getProperties().get(ProfileProperty.TEXTURES); + final Collection properties = h.getGameProfile().properties().get(ProfileProperty.TEXTURES); if (properties.isEmpty()) { return null; } return new SpongeProfileProperty(properties.iterator().next()); }) .set((h ,v) -> { - h.getGameProfile().getProperties().replaceValues(ProfileProperty.TEXTURES, Collections.singletonList(((SpongeProfileProperty)v).asProperty())); + h.getGameProfile().properties().replaceValues(ProfileProperty.TEXTURES, Collections.singletonList(((SpongeProfileProperty)v).asProperty())); ServerPlayerData.resendProfile(h); }) .create(Keys.SPECTATOR_TARGET) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java index 1f4fedc565a..63bdc810717 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ShulkerBulletData.java @@ -53,7 +53,7 @@ public static void register(final DataProviderRegistrator registrator) { } return (Entity) target.getEntity(((ShulkerBullet) h).level(), net.minecraft.world.entity.Entity.class); }) - .set((h, v) -> h.accessor$finalTarget(new EntityReference<>((net.minecraft.world.entity.Entity) v))); + .set((h, v) -> h.accessor$finalTarget(EntityReference.of((net.minecraft.world.entity.Entity) v))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java index 3136f6d8903..157e4f912ee 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TNTData.java @@ -44,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(PrimedTnt.class) .create(Keys.DETONATOR) .get(h -> (Living) h.getOwner()) - .set((h, v) -> ((PrimedTntAccessor) h).accessor$owner(new EntityReference<>((LivingEntity) v))) + .set((h, v) -> ((PrimedTntAccessor) h).accessor$owner(EntityReference.of((LivingEntity) v))) .create(Keys.BLOCK_STATE) .get(h -> (BlockState) h.getBlockState()) .set((h, v) -> h.setBlockState((net.minecraft.world.level.block.state.BlockState) v)); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java index 3216f124da9..e245c0b2f83 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TameableData.java @@ -52,7 +52,7 @@ public static void register(final DataProviderRegistrator registrator) { return t.getOwnerReference().getUUID(); }) .set((h, v) -> { - h.setOwnerReference(new EntityReference<>(v)); + h.setOwnerReference(EntityReference.of(v)); h.setTame(v != null, true); }); } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java index 77af4878013..78059b24ce8 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java @@ -46,11 +46,11 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.GAME_PROFILE) .get(h -> { final ResolvableProfile resolvableProfile = h.get(DataComponents.PROFILE); - return resolvableProfile == null ? null : SpongeGameProfile.of(resolvableProfile.gameProfile()); + return resolvableProfile == null ? null : SpongeGameProfile.of(resolvableProfile.partialProfile()); }) .set((h, v) -> { final com.mojang.authlib.GameProfile mcProfile = SpongeGameProfile.toMcProfile(v); - h.set(DataComponents.PROFILE, new ResolvableProfile(mcProfile)); + h.set(DataComponents.PROFILE, ResolvableProfile.createResolved(mcProfile)); }) .delete(h -> h.remove(DataComponents.PROFILE)) .supports(h -> h.getItem() instanceof PlayerHeadItem) diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 28ee38978fc..c09b7f5e3a2 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -123,7 +123,7 @@ public static AttributeSupplier createAttributes() { public HumanEntity(final EntityType type, final Level world) { super(type, world); - this.fakeProfile = new ResolvableProfile(new GameProfile(this.uuid, "")); + this.fakeProfile = ResolvableProfile.createUnresolved(this.uuid); this.setCanPickUpLoot(true); this.entityData.set(PlayerAccessor.accessor$DATA_PLAYER_MODE_CUSTOMISATION(), Constants.Sponge.Entity.Human.PLAYER_MODEL_FLAG_ALL); } @@ -196,7 +196,7 @@ public void readAdditionalSaveData(final ValueInput tag) { tag.read("profile", ResolvableProfile.CODEC) .ifPresent(profile -> { this.fakeProfile = profile; - this.setUUID(this.fakeProfile.id().get()); + this.setUUID(this.fakeProfile.partialProfile().id()); }); } @@ -307,26 +307,27 @@ protected HoverEvent createHoverEvent() { private void setProfileName(final net.minecraft.network.chat.@Nullable Component newName) { final Optional optName = Optional.ofNullable(newName).map(net.minecraft.network.chat.Component::getString); - this.fakeProfile = new ResolvableProfile(optName, this.fakeProfile.id(), this.fakeProfile.properties()); + final var profile = new GameProfile(this.fakeProfile.partialProfile().id(), optName.orElse(this.fakeProfile.name().orElse("")), this.fakeProfile.partialProfile().properties()); + this.fakeProfile = ResolvableProfile.createResolved(profile); } public boolean getOrLoadSkin(final UUID minecraftAccount) { final var server = SpongeCommon.server(); - final @Nullable GameProfile profile = server.nameToIdCache().get(minecraftAccount).flatMap(name -> - server.getProfileRepository().findProfileByName(name.name()) + final @Nullable GameProfile profile = server.services().nameToIdCache().get(minecraftAccount).flatMap(name -> + server.services().profileResolver().fetchByName(name.name()) ).orElseGet(() -> { - final @Nullable ProfileResult result = server.getSessionService().fetchProfile(minecraftAccount, true); + final @Nullable ProfileResult result = server.services().sessionService().fetchProfile(minecraftAccount, true); if (result == null) { return null; } - server.nameToIdCache().add(new NameAndId(result.profile())); + server.services().nameToIdCache().add(new NameAndId(result.profile())); return result.profile(); }); if (profile == null) { return false; } - this.fakeProfile.properties().replaceValues(ProfileProperty.TEXTURES, profile.getProperties().get(ProfileProperty.TEXTURES)); + this.fakeProfile.partialProfile().properties().replaceValues(ProfileProperty.TEXTURES, profile.properties().get(ProfileProperty.TEXTURES)); if (this.isAliveAndInWorld()) { this.respawnOnClient(); } @@ -337,15 +338,15 @@ public boolean getOrLoadSkin(final UUID minecraftAccount) { public boolean getOrLoadSkin(final String minecraftAccount) { Objects.requireNonNull(minecraftAccount); final var server = SpongeCommon.server(); - final @Nullable GameProfile profile = server.nameToIdCache().get(minecraftAccount).flatMap(name -> - server.getProfileRepository().findProfileByName(name.name()) + final @Nullable GameProfile profile = server.services().nameToIdCache().get(minecraftAccount).flatMap(name -> + server.services().profileResolver().fetchByName(name.name()) ).orElse(null); if (profile == null) { return false; } - this.fakeProfile.properties().clear(); - this.fakeProfile.properties().putAll(profile.getProperties()); + this.fakeProfile.partialProfile().properties().clear(); + this.fakeProfile.partialProfile().properties().putAll(profile.properties()); if (this.isAliveAndInWorld()) { this.respawnOnClient(); } @@ -368,7 +369,7 @@ public void removeFromTabListDelayed(final @Nullable ServerPlayer player, final } public SpongeProfileProperty getSkinProperty() { - final Collection properties = this.fakeProfile.properties().get(ProfileProperty.TEXTURES); + final Collection properties = this.fakeProfile.partialProfile().properties().get(ProfileProperty.TEXTURES); if (properties.isEmpty()) { return null; } @@ -376,7 +377,7 @@ public SpongeProfileProperty getSkinProperty() { } public void setSkinProperty(final ProfileProperty property) { - this.fakeProfile.properties() + this.fakeProfile.partialProfile().properties() .replaceValues( ProfileProperty.TEXTURES, Collections.singletonList(((SpongeProfileProperty) property).asProperty())); @@ -406,7 +407,7 @@ private void respawnOnClient() { * @return Whether it can be removed with 0 ticks delay */ public boolean canRemoveFromListImmediately() { - return !this.fakeProfile.properties().containsKey(ProfileProperty.TEXTURES); + return !this.fakeProfile.partialProfile().properties().containsKey(ProfileProperty.TEXTURES); } /** @@ -432,7 +433,7 @@ public ClientboundPlayerInfoUpdatePacket createPlayerListPacket(final EnumSet player() { - return Optional.ofNullable((ServerPlayer) SpongeCommon.server().getPlayerList().getPlayer(this.profile.getId())); + return Optional.ofNullable((ServerPlayer) SpongeCommon.server().getPlayerList().getPlayer(this.profile.id())); } @Override @@ -601,12 +601,12 @@ public boolean equals(final Object obj) { return false; } final SpongeUserData other = (SpongeUserData) obj; - return this.profile.getId().equals(other.profile.getId()); + return this.profile.id().equals(other.profile.id()); } @Override public int hashCode() { - return this.profile.getId().hashCode(); + return this.profile.id().hashCode(); } @Override diff --git a/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java b/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java index 24e61dbee81..c79a5096e42 100644 --- a/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java +++ b/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java @@ -146,7 +146,7 @@ private static void readProperties(final ChannelBuf buf, final GameProfile profi final String name = buf.readString(); final String value = buf.readString(); final String signature = buf.readBoolean() ? buf.readString() : null; - profile.getProperties().put(name, new Property(name, value, signature)); + profile.properties().put(name, new Property(name, value, signature)); } } } diff --git a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java index d8798e4b23f..98aa8a2a3c9 100644 --- a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java +++ b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java @@ -110,10 +110,10 @@ private static TrackerDataResponsePacket createTrackerDataResponse( final Optional owner, final Optional notifier ) { - final String ownerName = owner.flatMap(SpongeCommon.server().nameToIdCache()::get) + final String ownerName = owner.flatMap(SpongeCommon.server().services().nameToIdCache()::get) .map(NameAndId::name) .orElse(""); - final String notifierName = notifier.flatMap(SpongeCommon.server().nameToIdCache()::get) + final String notifierName = notifier.flatMap(SpongeCommon.server().services().nameToIdCache()::get) .map(NameAndId::name) .orElse(""); return new TrackerDataResponsePacket(ownerName, notifierName); diff --git a/src/main/java/org/spongepowered/common/network/status/SpongeStatusResponse.java b/src/main/java/org/spongepowered/common/network/status/SpongeStatusResponse.java index 043383b8615..93fecddd0e0 100644 --- a/src/main/java/org/spongepowered/common/network/status/SpongeStatusResponse.java +++ b/src/main/java/org/spongepowered/common/network/status/SpongeStatusResponse.java @@ -121,7 +121,7 @@ public ServerStatus.Players toVanilla() { // Make sure profiles are sent with non-null UUIDs and names because everything else // will make the response invalid on the client. Some plugins use empty UUIDs to create // custom lines in the player list that do not refer to a specific player. - .map(SpongeGameProfile::toMcProfile) + .map(SpongeGameProfile::toNameAndId) .toList()); } } diff --git a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java index 7c75e137602..49264d46148 100644 --- a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java +++ b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java @@ -62,9 +62,9 @@ public static SpongeGameProfile of(NameAndId mcProfile) { } public static SpongeGameProfile of(final com.mojang.authlib.GameProfile mcProfile) { - final UUID uniqueId = mcProfile.getId(); - final String name = mcProfile.getName().isEmpty() ? null : mcProfile.getName(); - final List properties = mcProfile.getProperties().values().stream() + final UUID uniqueId = mcProfile.id(); + final String name = mcProfile.name().isEmpty() ? null : mcProfile.name(); + final List properties = mcProfile.properties().values().stream() .map(SpongeProfileProperty::new) .collect(Collectors.toList()); return new SpongeGameProfile(uniqueId, name, properties); @@ -76,8 +76,8 @@ public static SpongeGameProfile basicOf(final NameAndId mcProfile) { } public static SpongeGameProfile basicOf(final com.mojang.authlib.GameProfile mcProfile) { - final UUID uniqueId = mcProfile.getId(); - final String name = mcProfile.getName().isEmpty() ? null : mcProfile.getName(); + final UUID uniqueId = mcProfile.id(); + final String name = mcProfile.name().isEmpty() ? null : mcProfile.name(); return new SpongeGameProfile(uniqueId, name); } @@ -150,7 +150,7 @@ public com.mojang.authlib.GameProfile toMcProfile() { final String name = (this.name == null) ? "" : this.name; final com.mojang.authlib.GameProfile mcProfile = new com.mojang.authlib.GameProfile(uniqueId, name); for (final SpongeProfileProperty property : this.properties) { - mcProfile.getProperties().put(property.name(), property.asProperty()); + mcProfile.properties().put(property.name(), property.asProperty()); } return mcProfile; } diff --git a/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java b/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java index 49fbc37b122..8bd5b7c5846 100644 --- a/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java +++ b/src/main/java/org/spongepowered/common/profile/SpongeGameProfileManager.java @@ -67,7 +67,7 @@ public final class SpongeGameProfileManager implements GameProfileManager { public SpongeGameProfileManager(final Server server) { this.usernameCache = ((SpongeServer) server).getUsernameCache(); - this.cache = (GameProfileCacheBridge) ((MinecraftServer) server).nameToIdCache(); + this.cache = (GameProfileCacheBridge) ((MinecraftServer) server).services().nameToIdCache(); this.gameLookupExecutorService = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() .setNameFormat("Sponge - Async User Lookup Thread").build()); } diff --git a/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java b/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java index a682289cdf0..31d6c3770b3 100644 --- a/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java +++ b/src/main/java/org/spongepowered/common/profile/UncachedGameProfileProvider.java @@ -36,6 +36,7 @@ import com.mojang.authlib.ProfileLookupCallback; import com.mojang.authlib.yggdrasil.ProfileResult; import com.mojang.util.UndashedUuid; +import net.minecraft.server.players.NameAndId; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.core.util.Throwables; import org.checkerframework.checker.nullness.qual.Nullable; @@ -92,7 +93,7 @@ private void submit(final Runnable runnable) { final com.mojang.authlib.GameProfile mcProfile; if (SpongeGameProfileManager.canLookup(uniqueId)) { // only attempt to resolve profiles for online mode clients - ProfileResult result = SpongeCommon.server().getSessionService().fetchProfile(uniqueId, true); + ProfileResult result = SpongeCommon.server().services().sessionService().fetchProfile(uniqueId, true); if (result != null) { mcProfile = result.profile(); } else { @@ -105,7 +106,7 @@ private void submit(final Runnable runnable) { return null; } final CachedProfile cachedProfile = new CachedProfile(SpongeGameProfile.of(mcProfile)); - this.profileByNameCache.put(mcProfile.getName().toLowerCase(Locale.ROOT), cachedProfile); + this.profileByNameCache.put(mcProfile.name().toLowerCase(Locale.ROOT), cachedProfile); return cachedProfile; }); } @@ -185,7 +186,7 @@ public CompletableFuture basicProfile(final String name, final @Nul }); } final CompletableFuture result = new CompletableFuture<>(); - this.submit(() -> SpongeCommon.server().getProfileRepository().findProfilesByNames(new String[]{name}, + this.submit(() -> SpongeCommon.server().services().profileRepository().findProfilesByNames(new String[]{name}, new SingleProfileLookupCallback(result))); return result; } @@ -213,7 +214,7 @@ public CompletableFuture> basicProfiles(final Iterable< } final List nameList = Lists.newArrayList(names); final String[] namesArray = nameList.toArray(new String[0]); - this.submit(() -> SpongeCommon.server().getProfileRepository().findProfilesByNames(namesArray, + this.submit(() -> SpongeCommon.server().services().profileRepository().findProfilesByNames(namesArray, new MapProfileLookupCallback(result, nameList))); return result; } @@ -288,8 +289,8 @@ private SingleProfileLookupCallback(final CompletableFuture result) } @Override - public void onProfileLookupSucceeded(final com.mojang.authlib.GameProfile profile) { - this.result.complete(SpongeGameProfile.of(profile)); + public void onProfileLookupSucceeded(String profileName, UUID profileId) { + this.result.complete(SpongeGameProfile.of(new NameAndId(profileId, profileName))); } @Override @@ -321,11 +322,11 @@ public void complete() { } @Override - public void onProfileLookupSucceeded(final com.mojang.authlib.GameProfile profile) { + public void onProfileLookupSucceeded(String profileName, UUID profileId) { String originalName = null; while (originalName == null && !this.nameQueue.isEmpty()) { final String name = this.nameQueue.remove(0); - if (name.equalsIgnoreCase(profile.getName())) { + if (name.equalsIgnoreCase(profileName)) { originalName = name; } } @@ -333,7 +334,7 @@ public void onProfileLookupSucceeded(final com.mojang.authlib.GameProfile profil throw new IllegalStateException(); } if (this.resultMap != null) { - this.resultMap.put(originalName, SpongeGameProfile.of(profile)); + this.resultMap.put(originalName, SpongeGameProfile.of(new NameAndId(profileId, profileName))); } } diff --git a/src/main/java/org/spongepowered/common/service/server/ban/SpongeIPBanList.java b/src/main/java/org/spongepowered/common/service/server/ban/SpongeIPBanList.java index 6ee8716ff4a..32cb8edf41c 100644 --- a/src/main/java/org/spongepowered/common/service/server/ban/SpongeIPBanList.java +++ b/src/main/java/org/spongepowered/common/service/server/ban/SpongeIPBanList.java @@ -27,6 +27,7 @@ import static org.spongepowered.common.util.NetworkUtil.LOCAL_ADDRESS; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.server.notifications.EmptyNotificationService; import net.minecraft.server.players.IpBanList; import net.minecraft.server.players.IpBanListEntry; import org.checkerframework.checker.nullness.qual.Nullable; @@ -44,6 +45,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Optional; /** * Redirects all calls to the {@link BanService}. @@ -51,7 +53,7 @@ public final class SpongeIPBanList extends IpBanList { public SpongeIPBanList(final File file) { - super(file); + super(file, new EmptyNotificationService()); } @Override @@ -75,31 +77,31 @@ protected boolean contains(final String entry) { try { return Sponge.server().serviceProvider().banService().find(InetAddress.getByName(obj)).join() - .map(ban -> { - if (ban instanceof IpBanListEntry) { - return (IpBanListEntry) ban; - } - final LegacyComponentSerializer lcs = LegacyComponentSerializer.legacySection(); - return new IpBanListEntry(BanUtil.addressToBanCompatibleString(ban.address()), - Date.from(ban.creationDate()), - ban.banSource().map(lcs::serialize).orElse(null), - ban.expirationDate().map(Date::from).orElse(null), - ban.reason().map(lcs::serialize).orElse(null)); - }) - .orElse(null); + .map(ban -> { + if (ban instanceof IpBanListEntry) { + return (IpBanListEntry) ban; + } + final LegacyComponentSerializer lcs = LegacyComponentSerializer.legacySection(); + return new IpBanListEntry(BanUtil.addressToBanCompatibleString(ban.address()), + Date.from(ban.creationDate()), + ban.banSource().map(lcs::serialize).orElse(null), + ban.expirationDate().map(Date::from).orElse(null), + ban.reason().map(lcs::serialize).orElse(null)); + }) + .orElse(null); } catch (final UnknownHostException e) { throw new IllegalArgumentException("Error parsing Ban IP address!", e); } } @Override - public void remove(final String entry) { + public boolean remove(final String entry) { if (entry.equals(LOCAL_ADDRESS)) { // Check for single player - return; + return false; } try { - Sponge.server().serviceProvider().banService().pardon(InetAddress.getByName(entry)).join(); + return Sponge.server().serviceProvider().banService().pardon(InetAddress.getByName(entry)).join(); } catch (final UnknownHostException e) { throw new IllegalArgumentException("Error parsing Ban IP address!", e); } @@ -115,8 +117,8 @@ public String[] getUserList() { } @Override - public void add(final IpBanListEntry entry) { - Sponge.server().serviceProvider().banService().add((Ban) entry).join(); + public boolean add(final IpBanListEntry entry) { + return Sponge.server().serviceProvider().banService().add((Ban) entry).thenApply(Optional::isPresent).join(); } @Override @@ -127,7 +129,7 @@ public boolean isEmpty() { /** * @author Minecrell - August 22nd, 2016 * @reason Use InetSocketAddress#getHostString() where possible (instead of - * inspecting SocketAddress#toString()) to support IPv6 addresses + * inspecting SocketAddress#toString()) to support IPv6 addresses */ @Override public String getIpFromAddress(final SocketAddress address) { diff --git a/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java b/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java index 35ca1c9575a..e020e63cef9 100644 --- a/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java +++ b/src/main/java/org/spongepowered/common/service/server/ban/SpongeUserBanList.java @@ -25,6 +25,7 @@ package org.spongepowered.common.service.server.ban; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.server.notifications.EmptyNotificationService; import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserBanList; import net.minecraft.server.players.UserBanListEntry; @@ -48,7 +49,7 @@ public class SpongeUserBanList extends UserBanList { public SpongeUserBanList(final File file) { - super(file); + super(file, new EmptyNotificationService()); } @Override @@ -84,9 +85,10 @@ public String[] getUserList() { } @Override - public void add(final UserBanListEntry entry) { + public boolean add(final UserBanListEntry entry) { final CompletableFuture> completableFuture = Sponge.server().serviceProvider().banService().add((Ban) entry); ((MinecraftServerBridge) SpongeCommon.server()).bridge$spongeMainThreadExecutor().managedBlock(completableFuture::isDone); + return true; } @Override @@ -95,9 +97,10 @@ public boolean isEmpty() { } @Override - public void remove(final NameAndId entry) { + public boolean remove(final NameAndId entry) { final CompletableFuture completableFuture = Sponge.server().serviceProvider().banService().pardon(SpongeGameProfile.of(entry)); ((MinecraftServerBridge) SpongeCommon.server()).bridge$spongeMainThreadExecutor().managedBlock(completableFuture::isDone); + return true; } } diff --git a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java index 819721fc656..f895f30c097 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java @@ -100,7 +100,7 @@ static ServerOpList getOps() { } static int getServerOpLevel() { - return SpongeCommon.server().getOperatorUserPermissionLevel(); + return SpongeCommon.server().operatorUserPermissionLevel(); } public Subject getGroupForOpLevel(final int level) { diff --git a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java index df90e34cd52..6dc24539697 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java @@ -81,12 +81,12 @@ public void setParent(final SubjectReference parent) { @Override public String identifier() { - return this.player.getId().toString(); + return this.player.id().toString(); } @Override public Optional friendlyIdentifier() { - final String name = this.player.getName(); + final String name = this.player.name(); return name.isEmpty() ? Optional.empty() : Optional.of(name); } @@ -96,7 +96,7 @@ public Optional associatedObject() { return Optional.empty(); } - return Sponge.server().player(this.player.getId()); + return Sponge.server().player(this.player.id()); } int getOpLevel() { @@ -106,7 +106,7 @@ int getOpLevel() { final ServerOpListEntry entry = SpongePermissionService.getOps().get(this.nameAndId); if (entry == null) { // Take care of singleplayer commands -- unless an op level is specified, this player follows global rules - return SpongeCommon.server().getPlayerList().isOp(this.nameAndId) ? SpongeCommon.server().getOperatorUserPermissionLevel() : 0; + return SpongeCommon.server().getPlayerList().isOp(this.nameAndId) ? SpongeCommon.server().operatorUserPermissionLevel() : 0; } else { return entry.getLevel(); } diff --git a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java index 694aacc02c8..760b7d297dc 100644 --- a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java +++ b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.service.server.whitelist; +import net.minecraft.server.notifications.EmptyNotificationService; import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserWhiteList; import net.minecraft.server.players.UserWhiteListEntry; @@ -43,7 +44,7 @@ public class SpongeUserWhiteList extends UserWhiteList { public SpongeUserWhiteList(final File file) { - super(file); + super(file, new EmptyNotificationService()); } @Override @@ -62,13 +63,13 @@ public String[] getUserList() { @SuppressWarnings("unchecked") @Override - public void add(final UserWhiteListEntry entry) { - Sponge.server().serviceProvider().whitelistService().addProfile(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())).join(); + public boolean add(final UserWhiteListEntry entry) { + return Sponge.server().serviceProvider().whitelistService().addProfile(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())).join(); } @Override - public void remove(final NameAndId entry) { - Sponge.server().serviceProvider().whitelistService().removeProfile(SpongeGameProfile.of(entry)).join(); + public boolean remove(final NameAndId entry) { + return Sponge.server().serviceProvider().whitelistService().removeProfile(SpongeGameProfile.of(entry)).join(); } @Override diff --git a/src/main/java/org/spongepowered/common/user/SpongeUserManager.java b/src/main/java/org/spongepowered/common/user/SpongeUserManager.java index 08445d2b1ff..09a24729dd9 100644 --- a/src/main/java/org/spongepowered/common/user/SpongeUserManager.java +++ b/src/main/java/org/spongepowered/common/user/SpongeUserManager.java @@ -112,7 +112,7 @@ public CompletableFuture loadOrCreate(final UUID uuid) { return CompletableFuture.completedFuture(null); } return CompletableFuture.supplyAsync(() -> { - final com.mojang.authlib.GameProfile profile = this.server.nameToIdCache().get(uuidToUse) + final com.mojang.authlib.GameProfile profile = this.server.services().nameToIdCache().get(uuidToUse) .map(nameAndId -> new com.mojang.authlib.GameProfile(nameAndId.id(), nameAndId.name())) .orElseGet(() -> new com.mojang.authlib.GameProfile(uuidToUse, "")); try { @@ -135,7 +135,7 @@ public CompletableFuture> load(final String lastKnownName) { .map(SpongeGameProfile::toMcProfile) .orElse(null); if (mcProfile != null) { - return this.load(mcProfile.getId()); + return this.load(mcProfile.id()); } return CompletableFuture.completedFuture(Optional.empty()); } @@ -234,7 +234,7 @@ private UUID ensureNonEmptyUUID(final UUID uuid) { // public void handlePlayerLogin(final com.mojang.authlib.GameProfile mcProfile) throws IOException { - final @Nullable SpongeUserData currentUser = this.userCache.getIfPresent(mcProfile.getId()); + final @Nullable SpongeUserData currentUser = this.userCache.getIfPresent(mcProfile.id()); if (currentUser != null) { // If currentUser have this then we know that the user has changed. if (this.dirtyUsers.contains(currentUser)) { @@ -247,8 +247,8 @@ public void handlePlayerLogin(final com.mojang.authlib.GameProfile mcProfile) th private void createUser(final com.mojang.authlib.GameProfile profile) throws IOException { final @Nullable SpongeUserData user = SpongeUserData.create(profile); - this.userCache.put(profile.getId(), user); - this.userFileCache.userCreated(profile.getId()); + this.userCache.put(profile.id(), user); + this.userFileCache.userCreated(profile.id()); } public void markDirty(final SpongeUserData user) { diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index 9003fe0764a..ab0f0901043 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -19,3 +19,4 @@ accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$A accessible class net/minecraft/world/entity/monster/SpellcasterIllager$IllagerSpell accessible class net/minecraft/world/level/biome/Biome$ClimateSettings accessible class net/minecraft/core/MappedRegistry$TagSet +accessible class net/minecraft/world/level/BaseCommandBlock$CloseableCommandBlockSource \ No newline at end of file diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index 6ce7054e45e..b56db122407 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -41,6 +41,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.PlayerList; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.levelgen.WorldDimensions; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.storage.LevelResource; @@ -122,12 +123,11 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe @Shadow public abstract String shadow$getMotd(); @Shadow public abstract int shadow$getTickCount(); @Shadow public abstract void shadow$halt(boolean p_71263_1_); - @Shadow public abstract int shadow$getPlayerIdleTimeout(); @Shadow public abstract void shadow$setPlayerIdleTimeout(int p_143006_1_); @Shadow public abstract boolean shadow$isHardcore(); @Shadow public abstract boolean shadow$isPvpAllowed(); @Shadow public abstract boolean shadow$isCommandBlockEnabled(); - @Shadow public abstract boolean shadow$isSpawningMonsters(); + @Shadow protected abstract boolean shadow$isSpawningMonsters(); @Shadow public abstract Commands shadow$getCommands(); @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract net.minecraft.server.packs.resources.ResourceManager shadow$getResourceManager(); @@ -143,6 +143,10 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe @Shadow public abstract boolean isSingleplayer(); + @Shadow public abstract void shadow$setUsingWhitelist(boolean $$0); + + @Shadow public abstract int shadow$playerIdleTimeout(); + private Iterable audiences; private ServerScheduler api$scheduler; private SpongeWorldManager api$worldManager; @@ -217,7 +221,7 @@ public boolean isWhitelistEnabled() { @Override public void setHasWhitelist(final boolean enabled) { - this.shadow$getPlayerList().setUsingWhiteList(enabled); + this.shadow$setUsingWhitelist(enabled); } @Override @@ -270,7 +274,7 @@ public boolean isAnimalSpawnsEnabled() { */ @Override public boolean isMultiWorldEnabled() { - return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getProperties().allowNether; + return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER); } @Override @@ -419,7 +423,7 @@ public Optional serverScoreboard() { @Intrinsic public int server$playerIdleTimeout() { - return this.shadow$getPlayerIdleTimeout(); + return this.shadow$playerIdleTimeout(); } @Intrinsic diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java index 926dea4c5ef..07fa31df462 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java @@ -326,7 +326,7 @@ public Optional setWorldBorder(final @Nullable WorldBorder border) synchronized (this) { if (this.api$pointers == null) { this.api$pointers = pointers = Pointers.builder() - .withDynamic(Identity.NAME, () -> ((net.minecraft.server.level.ServerPlayer) (Object) this).getGameProfile().getName()) + .withDynamic(Identity.NAME, () -> ((net.minecraft.server.level.ServerPlayer) (Object) this).getGameProfile().name()) .withDynamic(Identity.DISPLAY_NAME, () -> this.displayName().get()) .withDynamic(Identity.UUID, ((Entity) (Object) this)::getUUID) .withDynamic(Identity.LOCALE, this::locale) @@ -342,6 +342,7 @@ public Optional setWorldBorder(final @Nullable WorldBorder border) @Override @Deprecated + @SuppressWarnings("deprecation") public void sendMessage(final Identity identity, final Component message, final MessageType type) { if (this.impl$isFake) { return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java index 119aece2369..367285e8f68 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java @@ -36,6 +36,7 @@ import org.spongepowered.api.data.value.Value; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.world.level.BaseCommandBlockAccessor; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.util.Constants; @@ -64,8 +65,8 @@ public DataContainer toContainer() { container.set(Constants.TileEntity.CommandBlock.STORED_COMMAND, this.shadow$getCommandBlock().getCommand()); container.set(Constants.TileEntity.CommandBlock.SUCCESS_COUNT, this.shadow$getCommandBlock().getSuccessCount()); container.set(Constants.TileEntity.CUSTOM_NAME, this.shadow$getCommandBlock().getName()); - container.set(Constants.TileEntity.CommandBlock.DOES_TRACK_OUTPUT, this.shadow$getCommandBlock().shouldInformAdmins()); - if (this.shadow$getCommandBlock().shouldInformAdmins()) { + container.set(Constants.TileEntity.CommandBlock.DOES_TRACK_OUTPUT, this.shadow$getCommandBlock().isTrackOutput()); + if (this.shadow$getCommandBlock().isTrackOutput()) { container.set(Constants.TileEntity.CommandBlock.TRACKED_OUTPUT, LegacyComponentSerializer.legacySection().serialize(SpongeAdventure.asAdventure(this.shadow$getCommandBlock().getLastOutput()))); } return container; @@ -89,8 +90,13 @@ public String identifier() { return this.shadow$getCommandBlock().getName().getString(); } + @SuppressWarnings({"UnstableApiUsage", "deprecation"}) @Override public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { - this.shadow$getCommandBlock().sendSystemMessage(SpongeAdventure.asVanilla(message)); + final var source = ((BaseCommandBlockAccessor) this.shadow$getCommandBlock()).invoker$createSource(); + if (source == null) { + return; + } + source.sendSystemMessage(SpongeAdventure.asVanilla(message)); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java index 4039d41a694..8b71cb7920e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java @@ -39,7 +39,7 @@ @Mixin(ComponentSerialization.class) public abstract class ComponentSerializationMixin { - @ModifyVariable(method = "lambda$createCodec$6", at = @At(value = "HEAD"), argsOnly = true) + @ModifyVariable(method = "lambda$createCodec$5", at = @At(value = "HEAD"), argsOnly = true) private static Component impl$localizeComponent(final Component input) { final Locale locale = SpongeAdventure.ENCODING_LOCALE.get(); final ServerPlayer player = SpongeAdventure.ENCODING_PLAYER.get(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java index 01ce68a2357..97824574f4a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/Component_SerializerMixin.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(targets = "net/minecraft/network/codec/ByteBufCodecs$35") +@Mixin(targets = "net/minecraft/network/codec/ByteBufCodecs$34") public abstract class Component_SerializerMixin { // inject into the anonymous function to build a gson instance diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index c4c1efd11f3..7e43945f3bf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -39,14 +39,13 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerFunctionManager; +import net.minecraft.server.Services; import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.LevelLoadListener; -import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleReloadInstance; import net.minecraft.server.players.PlayerList; -import net.minecraft.server.players.UserNameToIdResolver; import net.minecraft.util.Unit; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Difficulty; @@ -55,7 +54,6 @@ import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; -import net.minecraft.world.level.storage.WorldData; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; @@ -111,7 +109,6 @@ import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import java.io.IOException; -import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; @@ -130,23 +127,19 @@ public abstract class MinecraftServerMixin implements SpongeServer, MinecraftSer @Shadow private int tickCount; @Shadow @Final private Thread serverThread; @Shadow @Final private ServerFunctionManager functionManager; + @Shadow private volatile boolean isSaving; @Shadow public abstract CommandSourceStack shadow$createCommandSourceStack(); @Shadow public abstract Iterable shadow$getAllLevels(); @Shadow public abstract boolean shadow$isDedicatedServer(); @Shadow public abstract boolean shadow$isRunning(); @Shadow public abstract PlayerList shadow$getPlayerList(); - @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract RegistryAccess.Frozen shadow$registryAccess(); - @Shadow public abstract UserNameToIdResolver shadow$nameToIdCache(); - @Shadow public abstract CompletableFuture shadow$reloadResources(final Collection $$0); - @Shadow public abstract WorldData shadow$getWorldData(); - @Shadow public abstract boolean shadow$haveTime(); - @Shadow private volatile boolean isSaving; + @Shadow protected abstract boolean shadow$haveTime(); @Shadow public abstract ResourceManager shadow$getResourceManager(); + @Shadow public abstract Services shadow$services(); // @formatter:on - private final ChatDecorator impl$spongeDecorator = new SpongeChatDecorator(); private @Nullable SpongeServerScopedServiceProvider impl$serviceProvider; protected @Nullable ResourcePackRequest impl$resourcePack; @@ -394,7 +387,7 @@ public boolean saveAllChunks(final boolean suppressLog, final boolean flush, fin // Save the usercache.json file every 10 minutes or if forced to if (isForced || this.tickCount % 6000 == 0) { // We want to save the username cache json, as we normally bypass it. - final var profileCache = this.shadow$nameToIdCache(); + final var profileCache = this.shadow$services().nameToIdCache(); ((GameProfileCacheBridge) profileCache).bridge$setCanSave(true); profileCache.save(); ((GameProfileCacheBridge) profileCache).bridge$setCanSave(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java index 08c0700f7d5..631d228d7b3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedPlayerListMixin.java @@ -28,6 +28,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.RegistryLayer; import net.minecraft.server.dedicated.DedicatedPlayerList; +import net.minecraft.server.notifications.EmptyNotificationService; import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.PlayerList; import net.minecraft.world.level.storage.PlayerDataStorage; @@ -46,8 +47,8 @@ public abstract class DedicatedPlayerListMixin extends PlayerList { public DedicatedPlayerListMixin(final MinecraftServer server, final LayeredRegistryAccess registryAccess, - final PlayerDataStorage playerIo, final int maxPlayers) { - super(server, registryAccess, playerIo, maxPlayers); + final PlayerDataStorage playerIo) { + super(server, registryAccess, playerIo, new EmptyNotificationService()); } @Inject(method = "isWhiteListed", at = @At("HEAD"), cancellable = true) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 6e754a253ee..7dd67e5f6aa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -986,7 +986,7 @@ private boolean isPvpAllowed() { var playerRespawnDestination = this.server.getLevel(defaulted); if (playerRespawnDestination == null) { SpongeCommon.logger().warn("The player '{}' respawn location was located in a world that isn't loaded or doesn't exist. This is not safe so " - + "the player will be moved to the spawn of the default world.", player.getGameProfile().getName()); + + "the player will be moved to the spawn of the default world.", player.getGameProfile().name()); playerRespawnDestination = player.getServer().overworld(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java index 2b1227d0b9c..9d90350a929 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java @@ -95,7 +95,7 @@ public abstract class ServerConfigurationPacketListenerImplMixin extends ServerC if (throwable != null) { // An error occurred during login checks so we ask to abort. ((ConnectionBridge) this.connection).bridge$setKickReason(Component.literal("An error occurred checking ban/whitelist status.")); - SpongeCommon.logger().error("An error occurred when checking the ban/whitelist status of {}.", this.gameProfile.getId().toString()); + SpongeCommon.logger().error("An error occurred when checking the ban/whitelist status of {}.", this.gameProfile.id().toString()); SpongeCommon.logger().error(throwable); } else if (componentOpt != null) { // We handle this later @@ -122,7 +122,7 @@ public abstract class ServerConfigurationPacketListenerImplMixin extends ServerC this.impl$skipBanService = true; this.shadow$handleConfigurationFinished($$0); // invalidate just to be sure there is no user cached for the online player anymore - ((SpongeServer) SpongeCommon.server()).userManager().removeFromCache(this.gameProfile.getId()); + ((SpongeServer) SpongeCommon.server()).userManager().removeFromCache(this.gameProfile.id()); } catch (final Exception e) { throw new RuntimeException(e); } finally { @@ -131,7 +131,7 @@ public abstract class ServerConfigurationPacketListenerImplMixin extends ServerC return null; }, SpongeCommon.server()).exceptionally(throwable -> { - SpongeCommon.logger().error("Forcibly disconnecting user {}({}) due to an error during login.", this.gameProfile.getName(), this.gameProfile.getId(), throwable); + SpongeCommon.logger().error("Forcibly disconnecting user {}({}) due to an error during login.", this.gameProfile.name(), this.gameProfile.id(), throwable); this.shadow$disconnect(Component.literal("Internal Server Error: unable to complete login.")); return null; }); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java index c4908d7a589..9c20ea7084e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerLoginPacketListenerImplMixin.java @@ -174,7 +174,7 @@ public abstract class ServerLoginPacketListenerImplMixin implements ServerLoginP if (throwable != null) { // An error occurred during login checks so we ask to abort. ((ConnectionBridge) this.connection).bridge$setKickReason(Component.literal("An error occurred checking ban/whitelist status.")); - SpongeCommon.logger().error("An error occurred when checking the ban/whitelist status of {}.", this.authenticatedProfile.getId().toString()); + SpongeCommon.logger().error("An error occurred when checking the ban/whitelist status of {}.", this.authenticatedProfile.id().toString()); SpongeCommon.logger().error(throwable); } else if (componentOpt != null) { // We handle this later @@ -193,7 +193,7 @@ public abstract class ServerLoginPacketListenerImplMixin implements ServerLoginP this.impl$fireAuthEvent(); return null; }, ServerLoginPacketListenerImplMixin.impl$EXECUTOR).exceptionally(throwable -> { - SpongeCommon.logger().error("Forcibly disconnecting user {}({}) due to an error during login.", this.authenticatedProfile.getName(), this.authenticatedProfile.getId(), throwable); + SpongeCommon.logger().error("Forcibly disconnecting user {}({}) due to an error during login.", this.authenticatedProfile.name(), this.authenticatedProfile.id(), throwable); this.shadow$disconnect(Component.literal("Internal Server Error: unable to complete login.")); return null; }); @@ -256,10 +256,10 @@ public void handleKey(final ServerboundKeyPacket packet) { final String username = Objects.requireNonNull(this.requestedUsername, "Player name not initialized"); try { - final ProfileResult $$1 = ServerLoginPacketListenerImplMixin.this.server.getSessionService().hasJoinedServer(username, $$5, this.impl$getAddress()); + final ProfileResult $$1 = ServerLoginPacketListenerImplMixin.this.server.services().sessionService().hasJoinedServer(username, $$5, this.impl$getAddress()); if ($$1 != null) { final GameProfile $$2 = $$1.profile(); - ServerLoginPacketListenerImplMixin.LOGGER.info("UUID of player {} is {}", $$2.getName(), $$2.getId()); + ServerLoginPacketListenerImplMixin.LOGGER.info("UUID of player {} is {}", $$2.name(), $$2.id()); ServerLoginPacketListenerImplMixin.this.shadow$startClientVerification($$2); } else if (ServerLoginPacketListenerImplMixin.this.server.isSingleplayer()) { ServerLoginPacketListenerImplMixin.LOGGER.warn("Failed to verify username but will let them in anyway!"); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index a3708770f1c..740e1a72059 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -92,18 +92,18 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { @Override public void bridge$add(final com.mojang.authlib.GameProfile profile, final boolean full, final boolean signed) { - GameProfileCache_GameProfileInfoAccessor accessor = this.profilesByUUID.get(Objects.requireNonNull(profile, "profile").getId()); + GameProfileCache_GameProfileInfoAccessor accessor = this.profilesByUUID.get(Objects.requireNonNull(profile, "profile").id()); final NameAndId current = accessor == null ? null : accessor.invoker$nameAndId(); // Don't allow basic game profiles to overwrite the contents if already // an entry exists that is full. - if (current != null && Objects.equals(current.id(), profile.getId()) && - Objects.equals(current.name(), profile.getName()) && !full) { + if (current != null && Objects.equals(current.id(), profile.id()) && + Objects.equals(current.name(), profile.name()) && !full) { return; } final var nameAndIDToAdd = new NameAndId(profile); this.shadow$add(nameAndIDToAdd); - accessor = this.profilesByUUID.get(profile.getId()); + accessor = this.profilesByUUID.get(profile.id()); if (accessor == null || accessor.invoker$nameAndId() != nameAndIDToAdd) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index d4c996cfcf0..b853e3ba933 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -145,15 +145,16 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Shadow @Final @Mutable private IpBanList ipBans; @Shadow @Final @Mutable private UserWhiteList whitelist; @Shadow @Final private List players; - @Shadow @Final protected int maxPlayers; @Shadow public abstract boolean shadow$canBypassPlayerLimit(NameAndId $$0); @Shadow protected abstract boolean shadow$verifyChatTrusted(final PlayerChatMessage $$0); @Shadow protected abstract void shadow$broadcastChatMessage(final PlayerChatMessage $$0, final Predicate $$1, final net.minecraft.server.level.@Nullable ServerPlayer $$2, final ChatType.Bound $$4); + @Shadow public abstract int shadow$getMaxPlayers(); // @formatter:on + private boolean impl$isRespawnWithPosition = false; private boolean impl$isDuringSystemMessageEvent = false; @@ -235,7 +236,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { if (component != null) { return component; } - if (this.players.size() >= this.maxPlayers && !this.shadow$canBypassPlayerLimit(param1)) { + if (this.players.size() >= this.shadow$getMaxPlayers() && !this.shadow$canBypassPlayerLimit(param1)) { return net.minecraft.network.chat.Component.translatable("multiplayer.disconnect.server_full"); } return null; @@ -265,7 +266,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { if (mcWorld == null) { SpongeCommon.logger().warn("The player '{}' was located in a world that isn't loaded or doesn't exist. This is not safe so " - + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().getName()); + + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().name()); mcWorld = this.server.overworld(); final BlockPos spawnPoint = mcWorld.getSharedSpawnPos(); mcPlayer.setPos(spawnPoint.getX() + 0.5, spawnPoint.getY() + 0.5, spawnPoint.getZ() + 0.5); @@ -365,7 +366,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { ((ServerPlayerBridge) playerIn).bridge$setConnectionMessageToSend(message); } - @Redirect(method = "placeNewPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/server/players/PlayerList;viewDistance:I")) + @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;getViewDistance()I")) private int impl$usePerWorldViewDistance(final PlayerList self, final Connection co, final net.minecraft.server.level.ServerPlayer player, final CommonListenerCookie cookie) { return ((ServerLevelDataBridge) player.level().getLevelData()).bridge$viewDistance().orElse(self.getViewDistance()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java index da95a861ee5..bc577d37306 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java @@ -28,6 +28,7 @@ import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; +import net.minecraft.commands.CommandSource; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.level.BaseCommandBlock; import org.checkerframework.checker.nullness.qual.NonNull; @@ -37,21 +38,30 @@ import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; +import javax.annotation.Nullable; + @Mixin(BaseCommandBlock.class) public abstract class BaseCommandBlockMixin implements CommandSourceProviderBridge, Audience { // @formatter:off - @Shadow public abstract CommandSourceStack shadow$createCommandSourceStack(); - @Shadow public abstract void shadow$sendSystemMessage(net.minecraft.network.chat.Component $$0); + @Shadow public abstract CommandSourceStack createCommandSourceStack(CommandSource var1); + @Shadow @Nullable protected abstract BaseCommandBlock.CloseableCommandBlockSource shadow$createSource(); // @formatter:on + + @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.shadow$createCommandSourceStack(); + return this.createCommandSourceStack(this.shadow$createSource()); } @Override + @SuppressWarnings({"deprecation", "UnstableApiUsage"}) public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { - this.shadow$sendSystemMessage(SpongeAdventure.asVanilla(message)); + final var source = this.shadow$createSource(); + if (source == null) { + return; + } + source.sendSystemMessage(SpongeAdventure.asVanilla(message)); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java index 0a34add990e..1ad89d9829b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java @@ -33,6 +33,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.permissions.SubjectBridge; @@ -55,6 +56,6 @@ public abstract class MinecartCommandBlockMixin extends AbstractMinecartMixin im @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.commandBlock.createCommandSourceStack(); + return this.commandBlock.createCommandSourceStack(SpongeCommon.server()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java index d9b9b9b3e83..549e45c8cb1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java @@ -33,6 +33,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.accessor.world.level.BaseCommandBlockAccessor; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.permissions.SubjectBridge; @@ -54,7 +55,7 @@ public abstract class CommandBlockEntityMixin implements SubjectBridge, CommandS @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.commandBlock.createCommandSourceStack(); + return this.commandBlock.createCommandSourceStack((((BaseCommandBlockAccessor) this.commandBlock).invoker$createSource())); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java index 2943887bfa1..4d63df41972 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java +++ b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java @@ -86,14 +86,14 @@ public abstract class ServerLoginPacketListenerImplMixin_IpForward { if (((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedUUID() != null) { uuid = ((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedUUID(); } else { - uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + $$0.getName()).getBytes(StandardCharsets.UTF_8)); + uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + $$0.name()).getBytes(StandardCharsets.UTF_8)); } - $$0 = new GameProfile(uuid, $$0.getName()); + $$0 = new GameProfile(uuid, $$0.name()); if (((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedProfile() != null) { for (final Property property : ((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedProfile()) { - $$0.getProperties().put(property.name(), property); + $$0.properties().put(property.name(), property); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java b/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java index 314fc868ffc..ef76807c09b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java +++ b/src/mixins/java/org/spongepowered/common/mixin/optimization/world/entity/TamableAnimalMixin_Optimization_Owner.java @@ -67,7 +67,7 @@ public EntityReference getOwnerReference() { */ @Overwrite public void setOwner(final @javax.annotation.Nullable LivingEntity entity) { - final var reference = Optional.ofNullable(entity).map(EntityReference::new); + final var reference = Optional.ofNullable(entity).map(EntityReference::of); this.cachedOwner$OwnerId = reference.orElse(null); this.entityData.set(DATA_OWNERUUID_ID, reference); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java index bc9d975b68a..0ae3cea6ea8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java @@ -49,7 +49,7 @@ @Mixin(DedicatedServer.class) public abstract class DedicatedServerMixin_Tracker { - @Shadow public abstract int shadow$getSpawnProtectionRadius(); + @Shadow public abstract int shadow$spawnProtectionRadius(); /** * @author zml - March 9th, 2016 @@ -71,7 +71,7 @@ public boolean isUnderSpawnProtection(final ServerLevel worldIn, final BlockPos } final BlockPos spawnPoint = worldIn.getSharedSpawnPos(); - final int protectionRadius = this.shadow$getSpawnProtectionRadius(); + final int protectionRadius = this.shadow$spawnProtectionRadius(); return protectionRadius > 0 && Math.max(Math.abs(pos.getX() - spawnPoint.getX()), Math.abs(pos.getZ() - spawnPoint.getZ())) <= protectionRadius diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java index 313026a015f..3cfba5eb7ab 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java @@ -39,7 +39,6 @@ import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.function.Consumer; import java.util.function.Supplier; @@ -67,7 +66,7 @@ public Screen getScreen() { } public int getBottom() { - return this.getY() + this.headerHeight; + return this.getY() + this.getHeight(); } public E getCurrentHoveredEntry() { @@ -107,10 +106,10 @@ public P setFilterSupplier(final Supplier> filterSupplier) { this.filterSupplier = filterSupplier; return (P) this; } - - public int getRowHeight() { - return this.itemHeight; - } +// +// public int getRowHeight() { +// return this.itemHeight; +// } @Override public int getRowWidth() { @@ -171,27 +170,27 @@ protected void renderListItems(final GuiGraphics $$0, final int $$1, final int $ final int $$4 = this.getRowLeft(); final int $$5 = this.getRowWidth(); - final int $$6 = this.itemHeight - 4; +// final int $$6 = this.itemHeight - 4; final int $$7 = filteredList.size(); - for (int $$8 = 0; $$8 < $$7; ++$$8) { - final int $$9 = this.getRowTop($$8); - final int $$10 = this.getRowBottom($$8); - if ($$10 >= this.getY() && $$9 <= this.getBottom()) { - this.renderItemFromList(filteredList, $$0, $$1, $$2, $$3, $$8, $$4, $$9, $$5, $$6); - } - } +// for (int $$8 = 0; $$8 < $$7; ++$$8) { +// final int $$9 = this.getRowTop($$8); +// final int $$10 = this.getRowBottom($$8); +// if ($$10 >= this.getY() && $$9 <= this.getBottom()) { +// this.renderItemFromList(filteredList, $$0, $$1, $$2, $$3, $$8, $$4, $$9, $$5, $$6); +// } +// } } private void renderItemFromList(final List list, final GuiGraphics $$0, final int $$1, final int $$2, final float $$3, final int $$4, final int $$5, final int $$6, final int $$7, final int $$8) { final E $$9 = list.get($$4); - $$9.renderBack($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); - if (this.isSelectedItem($$4)) { - final int $$10 = this.isFocused() ? -1 : -8355712; - this.renderSelection($$0, $$6, $$7, $$8, $$10, -16777216); - } +// $$9.render($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); +// if (this.($$4)) { +// final int $$10 = this.isFocused() ? -1 : -8355712; +// this.renderSelection($$0, $$6, $$7, $$8, $$10, -16777216); +// } - $$9.render($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); +// $$9.render($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); } @Override @@ -227,16 +226,16 @@ public P getParentList() { public abstract Bounds getInteractBounds(); - @SuppressWarnings("unchecked") - @Override - public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, - final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, - final float p_render_9_) { - if (this.getInteractBounds().isInBounds(mouseX, mouseY, renderX, renderY)) { - this.parentList.currentHoveredEntry = (E) this; - } else if (this.parentList.getCurrentHoveredEntry() == this) { - this.parentList.currentHoveredEntry = null; - } - } +// @SuppressWarnings("unchecked") +// @Override +// public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, +// final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, +// final float p_render_9_) { +// if (this.getInteractBounds().isInBounds(mouseX, mouseY, renderX, renderY)) { +// this.parentList.currentHoveredEntry = (E) this; +// } else if (this.parentList.getCurrentHoveredEntry() == this) { +// this.parentList.currentHoveredEntry = null; +// } +// } } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java index e1bb2371155..72a84876bd6 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java @@ -50,21 +50,26 @@ public Entry(final PluginSelectionList list, final PluginMetadata metadata) { @Override public Bounds getInteractBounds() { - return new Bounds(0, this.getParentList().getRowWidth(), 0, this.getParentList().getRowHeight()); + return new Bounds(0, this.getParentList().getRowWidth(), 0, this.getParentList().scrollerHeight()); } @Override - public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, - final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, final float p_render_9_) { - // Draw the name, or ID if name is not present - stack.drawString(this.list.fontRenderer, this.metadata.name().orElse(this.metadata.id()), renderX + 2, renderY + 1, 16777215); + public void renderContent(GuiGraphics var1, int var2, int var3, boolean var4, float var5) { - // Draw the ID if the name is present - if (this.metadata.name().isPresent()) { - stack.drawString(this.list.fontRenderer, this.metadata.id(), renderX + 2, renderY + 12, 8421504); - } } + // @Override +// public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, +// final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, final float p_render_9_) { +// // Draw the name, or ID if name is not present +// stack.drawString(this.list.fontRenderer, this.metadata.name().orElse(this.metadata.id()), renderX + 2, renderY + 1, 16777215); +// +// // Draw the ID if the name is present +// if (this.metadata.name().isPresent()) { +// stack.drawString(this.list.fontRenderer, this.metadata.id(), renderX + 2, renderY + 12, 8421504); +// } +// } + @Override public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_, final boolean repeated) { this.getParentList().setSelected(this); From e4c0f7ee484929cd97bae9cc7c6234d50f05808f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 4 Sep 2025 23:59:50 -0700 Subject: [PATCH 336/586] feat(minecraft): update to 25w36b Additions: - Added Mannequin entity representation Implementation Notes: - Several changes to accommodate Avatar split from Player - WorldBorder is now per-world it appears - Weather is still "global" - WorldBorder.Settings are a pain to work with and appear to be deprecated in some way... See: https://minecraft.wiki/w/Java_Edition_25w36a See: https://minecraft.wiki/w/Java_Edition_25w36b --- SpongeAPI | 2 +- gradle.properties | 2 +- .../server/level/ServerPlayerAccessor.java | 3 + .../accessor/world/entity/AvatarAccessor.java | 44 +++++++++++ .../world/entity/player/PlayerAccessor.java | 15 +--- .../resources/mixins.sponge.accessors.json | 3 +- .../provider/entity/EntityDataProviders.java | 1 + .../data/provider/entity/MannequinData.java | 45 +++++++++++ .../provider/entity/ServerPlayerData.java | 8 +- .../provider/world/WorldPropertiesData.java | 2 +- .../entity/living/human/HumanEntity.java | 15 ++-- .../phase/packet/PacketPhaseUtil.java | 13 ++-- .../common/server/PerWorldBorderListener.java | 14 ++-- .../world/border/PlayerOwnBorderListener.java | 16 ++-- .../border/SpongeWorldBorderBuilder.java | 4 +- .../world/server/SpongeWorldManager.java | 2 +- .../world/teleport/SpongeTeleportHelper.java | 12 +-- .../EntitySelectorParserMixin_API.java | 78 ++++++++++++------- .../server/level/ServerLevelMixin_API.java | 4 +- .../world/level/LevelReaderMixin_API.java | 2 +- .../border/WorldBorderMixin_Settings_API.java | 50 ++++++------ .../level/chunk/EmptyLevelChunkMixin_API.java | 7 +- .../level/chunk/LevelChunkMixin_API.java | 5 +- .../level/chunk/ProtoChunkMixin_API.java | 6 +- .../server/commands/WeatherCommandMixin.java | 25 ++++-- .../core/server/level/ServerLevelMixin.java | 6 +- .../core/server/level/ServerPlayerMixin.java | 40 ++++++++-- .../ServerCommonPacketListenerImplMixin.java | 2 +- ...rConfigurationPacketListenerImplMixin.java | 2 +- .../core/server/players/PlayerListMixin.java | 6 -- .../mixin/core/world/entity/AvatarMixin.java} | 21 +++-- .../entity/decoration/MannequinMixin.java} | 17 ++-- .../entity/npc/WanderingTraderMixin.java | 2 +- .../core/world/entity/player/PlayerMixin.java | 24 +----- .../mixin/core/world/level/LevelMixin.java | 2 - .../world/level/border/WorldBorderMixin.java | 69 ++++++++-------- .../world/level/chunk/LevelChunkMixin.java | 15 +--- .../chunk/SerializableChunkDataMixin.java | 7 +- ...essor_ListenerAndPacketMixin_Tracker.java} | 31 +++----- .../protocol/PacketUtilsMixin_Tracker.java | 58 -------------- .../level/ServerChunkCacheMixin_Tracker.java | 16 +--- src/mixins/resources/mixins.sponge.core.json | 3 +- .../resources/mixins.sponge.tracker.json | 2 +- .../client/gui/widget/MetadataPanel.java | 7 +- .../client/gui/widget/ScrollPanel.java | 14 ++-- .../gui/widget/list/FilterableList.java | 18 +++-- .../gui/widget/list/PluginSelectionList.java | 3 +- 47 files changed, 401 insertions(+), 342 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/AvatarAccessor.java create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/MannequinData.java rename src/{accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_IntsAccessor.java => mixins/java/org/spongepowered/common/mixin/core/world/entity/AvatarMixin.java} (71%) rename src/{accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_DoublesAccessor.java => mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/MannequinMixin.java} (71%) rename src/mixins/java/org/spongepowered/common/mixin/{core/server/commands/WorldBorderCommandMixin.java => tracker/network/PacketProcessor_ListenerAndPacketMixin_Tracker.java} (59%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/tracker/network/protocol/PacketUtilsMixin_Tracker.java diff --git a/SpongeAPI b/SpongeAPI index 42b3bf65c4e..9e38f062da8 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 42b3bf65c4e499bfd99b8796f1db7b6c7a3b4e95 +Subproject commit 9e38f062da88ff1e866393c569392fb5d9ed54b1 diff --git a/gradle.properties b/gradle.properties index 7c3ff5be982..fed374b10f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=25w35a +minecraftVersion=25w36b recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerPlayerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerPlayerAccessor.java index d99f6209cce..a2153f86dba 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerPlayerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerPlayerAccessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.accessor.server.level; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; @@ -48,4 +49,6 @@ public interface ServerPlayerAccessor { @Invoker("triggerDimensionChangeTriggers") void invoker$triggerDimensionChangeTriggers(final ServerLevel world); @Accessor("containerCounter") int accessor$containerCounter(); + + @Accessor("server") MinecraftServer accessor$server(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/AvatarAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/AvatarAccessor.java new file mode 100644 index 00000000000..783a850d405 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/AvatarAccessor.java @@ -0,0 +1,44 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity; + +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.Avatar; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.common.UntransformedAccessorError; + +@Mixin(Avatar.class) +public interface AvatarAccessor { + + @Accessor("DATA_PLAYER_MODE_CUSTOMISATION") static EntityDataAccessor accessor$DATA_PLAYER_MODE_CUSTOMISATION() { + throw new UntransformedAccessorError(); + } + + @Accessor("DATA_PLAYER_MAIN_HAND") static EntityDataAccessor accessor$DATA_PLAYER_MAIN_HAND() { + throw new UntransformedAccessorError(); + } + +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java index 1a91a66d7ad..b865b4bcd36 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.accessor.world.entity.player; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; @@ -32,6 +31,8 @@ import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedAccessorError; +import java.util.OptionalInt; + @Mixin(Player.class) public interface PlayerAccessor { @@ -43,19 +44,11 @@ public interface PlayerAccessor { throw new UntransformedAccessorError(); } - @Accessor("DATA_PLAYER_MODE_CUSTOMISATION") static EntityDataAccessor accessor$DATA_PLAYER_MODE_CUSTOMISATION() { - throw new UntransformedAccessorError(); - } - - @Accessor("DATA_PLAYER_MAIN_HAND") static EntityDataAccessor accessor$DATA_PLAYER_MAIN_HAND() { - throw new UntransformedAccessorError(); - } - - @Accessor("DATA_SHOULDER_LEFT") static EntityDataAccessor accessor$DATA_SHOULDER_LEFT() { + @Accessor("DATA_SHOULDER_PARROT_LEFT") static EntityDataAccessor accessor$DATA_SHOULDER_LEFT() { throw new UntransformedAccessorError(); } - @Accessor("DATA_SHOULDER_RIGHT") static EntityDataAccessor accessor$DATA_SHOULDER_RIGHT() { + @Accessor("DATA_SHOULDER_PARROT_RIGHT") static EntityDataAccessor accessor$DATA_SHOULDER_RIGHT() { throw new UntransformedAccessorError(); } @Invoker("getPermissionLevel") int invoker$getPermissionLevel(); diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 77fd528804f..e9406b20aa8 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -10,8 +10,6 @@ "mixins": [ "ChatFormattingAccessor", "advancements.CriteriaTriggersAccessor", - "advancements.critereon.MinMaxBounds_DoublesAccessor", - "advancements.critereon.MinMaxBounds_IntsAccessor", "commands.CommandSourceStackAccessor", "commands.arguments.DimensionArgumentAccessor", "commands.arguments.OperationArgumentAccessor", @@ -63,6 +61,7 @@ "world.damagesource.CombatTrackerAccessor", "world.entity.AgableMobAccessor", "world.entity.AreaEffectCloudAccessor", + "world.entity.AvatarAccessor", "world.entity.Display_BlockDisplayAccessor", "world.entity.Display_ItemDisplayAccessor", "world.entity.Display_TextDisplayAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 49351a84bee..316257cea65 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -154,6 +154,7 @@ public void registerProviders() { LivingData.register(this.registrator); LlamaData.register(this.registrator); LocationTargetingData.register(this.registrator); + MannequinData.register(this.registrator); MobData.register(this.registrator); MooshroomData.register(this.registrator); OcelotData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/MannequinData.java b/src/main/java/org/spongepowered/common/data/provider/entity/MannequinData.java new file mode 100644 index 00000000000..0f63c58994f --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/MannequinData.java @@ -0,0 +1,45 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.decoration.Mannequin; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.HandPreference; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public final class MannequinData { + private MannequinData() { + } + + public static void register(DataProviderRegistrator registrator) { + registrator + .asMutable(Mannequin.class) + .create(Keys.DOMINANT_HAND) + .get(h -> (HandPreference) (Object) h.getMainArm()) + .set((h, v) -> h.setMainArm((HumanoidArm) (Object) v)) + ; + } +} diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 88bdbcfb6f4..80048ed5607 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -135,9 +135,9 @@ private static void resendProfile(final ServerPlayer h) { // Remove Entity h.level().getChunkSource().removeEntity(h); // Remove from TabList - h.getServer().getPlayerList().broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(h.getUUID()))); + ((ServerPlayerAccessor) h).accessor$server().getPlayerList().broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(h.getUUID()))); // Add back to TabList - h.getServer().getPlayerList().broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(h))); + ((ServerPlayerAccessor) h).accessor$server().getPlayerList().broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(h))); // Add Entity h.level().getChunkSource().addEntity(h); // Reconnect local player @@ -148,10 +148,10 @@ private static void resendProfile(final ServerPlayer h) { // resend remaining player data... (see ServerPlayer#changeDimension) h.connection.send(new ClientboundChangeDifficultyPacket(h.level().getLevelData().getDifficulty(), h.level().getLevelData().isDifficultyLocked())); h.connection.send(new ClientboundPlayerAbilitiesPacket(h.getAbilities())); - final PlayerList playerList = h.getServer().getPlayerList(); + final PlayerList playerList = ((ServerPlayerAccessor) h).accessor$server().getPlayerList(); playerList.sendAllPlayerInfo(h); playerList.sendPlayerPermissionLevel(h); - for(MobEffectInstance $$6 : h.getActiveEffects()) { + for (MobEffectInstance $$6 : h.getActiveEffects()) { h.connection.send(new ClientboundUpdateMobEffectPacket(h.getId(), $$6, false)); } h.connection.send(new ClientboundSetExperiencePacket(h.experienceProgress, h.totalExperience, h.experienceLevel)); diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index 73b96f28960..fde1474eb0a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -74,7 +74,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.INITIALIZED) .get(ServerLevelData::isInitialized) .create(Keys.WORLD_BORDER) - .get(h -> (WorldBorder) h.getWorldBorder()) + .get(h -> (WorldBorder) (Object) h.getLegacyWorldBorderSettings().orElse(null)) .create(Keys.WEATHER) .get(SpongeWeather::of) .set(SpongeWeather::apply) diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index c09b7f5e3a2..84fcf7fa112 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -30,7 +30,6 @@ import com.mojang.serialization.DataResult; import net.kyori.adventure.text.Component; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.HoverEvent; @@ -83,6 +82,7 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.network.protocol.game.ClientboundAddEntityPacketAccessor; import org.spongepowered.common.accessor.network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor; +import org.spongepowered.common.accessor.world.entity.AvatarAccessor; import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor; import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor; import org.spongepowered.common.config.SpongeGameConfigs; @@ -100,6 +100,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.OptionalInt; import java.util.UUID; import java.util.stream.Stream; @@ -125,7 +126,7 @@ public HumanEntity(final EntityType type, final Level wor super(type, world); this.fakeProfile = ResolvableProfile.createUnresolved(this.uuid); this.setCanPickUpLoot(true); - this.entityData.set(PlayerAccessor.accessor$DATA_PLAYER_MODE_CUSTOMISATION(), Constants.Sponge.Entity.Human.PLAYER_MODEL_FLAG_ALL); + this.entityData.set(AvatarAccessor.accessor$DATA_PLAYER_MODE_CUSTOMISATION(), Constants.Sponge.Entity.Human.PLAYER_MODEL_FLAG_ALL); } @Override @@ -139,13 +140,15 @@ protected void defineSynchedData(SynchedEntityData.Builder $$0) { $$0.define(LivingEntityAccessor.accessor$DATA_STINGER_COUNT_ID(), 0); $$0.define(LivingEntityAccessor.accessor$SLEEPING_POS_ID(), Optional.empty()); + // Avatar + $$0.define(AvatarAccessor.accessor$DATA_PLAYER_MODE_CUSTOMISATION(), (byte) 0); + $$0.define(AvatarAccessor.accessor$DATA_PLAYER_MAIN_HAND(), (byte) 1); + // Player $$0.define(PlayerAccessor.accessor$DATA_PLAYER_ABSORPTION_ID(), 0.0F); $$0.define(PlayerAccessor.accessor$DATA_SCORE_ID(), 0); - $$0.define(PlayerAccessor.accessor$DATA_PLAYER_MODE_CUSTOMISATION(), (byte) 0); - $$0.define(PlayerAccessor.accessor$DATA_PLAYER_MAIN_HAND(), (byte) 1); - $$0.define(PlayerAccessor.accessor$DATA_SHOULDER_LEFT(), new CompoundTag()); - $$0.define(PlayerAccessor.accessor$DATA_SHOULDER_RIGHT(), new CompoundTag()); + $$0.define(PlayerAccessor.accessor$DATA_SHOULDER_LEFT(), OptionalInt.empty()); + $$0.define(PlayerAccessor.accessor$DATA_SHOULDER_RIGHT(), OptionalInt.empty()); } @Override diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 7c1cc7b4af0..9013c2e40b7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -206,9 +206,9 @@ public static boolean allTransactionsInvalid(final List slotTra } @SuppressWarnings({"rawtypes", "unchecked", "deprecation"}) - public static void onProcessPacket(final Packet packetIn, final PacketListener netHandler) { - if (netHandler instanceof ServerGamePacketListenerImpl) { - net.minecraft.server.level.ServerPlayer packetPlayer = ((ServerGamePacketListenerImpl) netHandler).player; + public static void onProcessPacket(final Packet packetIn, final PacketListener netHandler,final Runnable call) { + if (netHandler instanceof ServerGamePacketListenerImpl serverGameImpl) { + net.minecraft.server.level.ServerPlayer packetPlayer = serverGameImpl.player; // Only process the CustomPayload, Respawn & ChunkBatchReceived packets from players if they are dead. if (!packetPlayer.isAlive() && !((PacketBridge) packetIn).bridge$canProcessWhenDead()) { return; @@ -218,8 +218,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n // Don't process movement capture logic if player hasn't moved boolean ignoreMovementCapture; - if (packetIn instanceof ServerboundMovePlayerPacket) { - final ServerboundMovePlayerPacket movingPacket = ((ServerboundMovePlayerPacket) packetIn); + if (packetIn instanceof ServerboundMovePlayerPacket movingPacket) { if (movingPacket instanceof ServerboundMovePlayerPacket.Rot) { ignoreMovementCapture = true; } else if (packetPlayer.getX() == ((ServerboundMovePlayerPacketAccessor) movingPacket).accessor$x() && packetPlayer.getY() == ((ServerboundMovePlayerPacketAccessor) movingPacket).accessor$y() && packetPlayer.getZ() == ((ServerboundMovePlayerPacketAccessor) movingPacket).accessor$z()) { @@ -271,12 +270,12 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n try (final PhaseContext packetContext = context) { packetContext.buildAndSwitch(); - packetIn.handle(netHandler); + call.run(); } } } } else { // client - packetIn.handle(netHandler); + call.run(); } } diff --git a/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java b/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java index b9998a6e979..b9d555897f8 100644 --- a/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java +++ b/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java @@ -44,36 +44,36 @@ public PerWorldBorderListener(final ServerLevel world) { } @Override - public void onBorderSizeSet(final WorldBorder border, final double newSize) { + public void onSetSize(final WorldBorder border, final double newSize) { this.sendWorldBorderActionPacket(new ClientboundSetBorderSizePacket(border)); } @Override - public void onBorderSizeLerping(final WorldBorder border, final double oldSize, final double newSize, final long time) { + public void onLerpSize(final WorldBorder border, final double oldSize, final double newSize, final long time) { this.sendWorldBorderActionPacket(new ClientboundSetBorderLerpSizePacket(border)); } @Override - public void onBorderCenterSet(final WorldBorder border, final double x, final double z) { + public void onSetCenter(final WorldBorder border, final double x, final double z) { this.sendWorldBorderActionPacket(new ClientboundSetBorderCenterPacket(border)); } @Override - public void onBorderSetWarningTime(final WorldBorder border, final int newTime) { + public void onSetWarningTime(final WorldBorder border, final int newTime) { this.sendWorldBorderActionPacket(new ClientboundSetBorderWarningDelayPacket(border)); } @Override - public void onBorderSetWarningBlocks(final WorldBorder border, final int newDistance) { + public void onSetWarningBlocks(final WorldBorder border, final int newDistance) { this.sendWorldBorderActionPacket(new ClientboundSetBorderWarningDistancePacket(border)); } @Override - public void onBorderSetDamagePerBlock(final WorldBorder border, final double newAmount) { + public void onSetDamagePerBlock(final WorldBorder border, final double newAmount) { } @Override - public void onBorderSetDamageSafeZOne(final WorldBorder border, final double newSize) { + public void onSetSafeZone(final WorldBorder border, final double newSize) { } private void sendWorldBorderActionPacket(final Packet packet) { diff --git a/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java b/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java index 52d95011a16..2f80ec9259c 100644 --- a/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java +++ b/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java @@ -46,38 +46,39 @@ public PlayerOwnBorderListener(final net.minecraft.server.level.ServerPlayer pla } @Override - public void onBorderSizeSet(final WorldBorder border, final double newSize) { + public void onSetSize(final WorldBorder border, final double newSize) { this.sendBorderPacket(new ClientboundSetBorderSizePacket(border)); } @Override - public void onBorderSizeLerping(final WorldBorder border, final double oldSize, final double newSize, final long time) { + public void onLerpSize(final WorldBorder border, final double oldSize, final double newSize, final long time) { this.sendBorderPacket(new ClientboundSetBorderLerpSizePacket(border)); } @Override - public void onBorderCenterSet(final WorldBorder border, final double x, final double z) { + public void onSetCenter(final WorldBorder border, final double x, final double z) { this.sendBorderPacket(new ClientboundSetBorderCenterPacket(border)); } @Override - public void onBorderSetWarningTime(final WorldBorder border, final int newTime) { + public void onSetWarningTime(final WorldBorder border, final int newTime) { this.sendBorderPacket(new ClientboundSetBorderWarningDelayPacket(border)); } @Override - public void onBorderSetWarningBlocks(final WorldBorder border, final int newDistance) { + public void onSetWarningBlocks(final WorldBorder border, final int newDistance) { this.sendBorderPacket(new ClientboundSetBorderWarningDistancePacket(border)); } @Override - public void onBorderSetDamagePerBlock(final WorldBorder border, final double newAmount) { + public void onSetDamagePerBlock(final WorldBorder border, final double newAmount) { } @Override - public void onBorderSetDamageSafeZOne(final WorldBorder border, final double newSize) { + public void onSetSafeZone(final WorldBorder border, final double newSize) { } + /** * This method is for cleaning up the player reference once they disconnect. */ @@ -91,4 +92,5 @@ public void onPlayerDisconnect() { private void sendBorderPacket(final Packet packet) { this.player.connection.send(packet); } + } diff --git a/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java b/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java index 550cb0c61f6..80e3318f7eb 100644 --- a/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java +++ b/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java @@ -61,7 +61,7 @@ public WorldBorder.Builder from(final WorldBorder border) { @Override public WorldBorder.Builder overworldDefaults() { - return this.from((WorldBorder) net.minecraft.world.level.border.WorldBorder.DEFAULT_SETTINGS); + return this.from((WorldBorder) (Object) net.minecraft.world.level.border.WorldBorder.Settings.DEFAULT); } @Override @@ -145,7 +145,7 @@ public WorldBorder build() throws IllegalStateException { if (this.diameter == -1) { throw new IllegalStateException("The diameter or initial diameter has not been set!"); } - return (WorldBorder) WorldBorder_SettingsAccessor.invoker$new( + return (WorldBorder) (Object) WorldBorder_SettingsAccessor.invoker$new( this.center.x(), this.center.y(), this.damagePerBlock, diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 427e2f20f1e..3e431f0ef9c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -905,7 +905,7 @@ private ServerLevel createLevel( this.worlds.put(registryKey, world); // Ensure that the world border is registered. - world.getWorldBorder().applySettings(levelData.getWorldBorder()); + levelData.getLegacyWorldBorderSettings().ifPresent(world.getWorldBorder()::applySettings); PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); return world; } diff --git a/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java b/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java index bfac0f8b7cd..4b8a5ce5fd3 100644 --- a/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java +++ b/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java @@ -73,12 +73,12 @@ public Optional findSafeLocation(ServerLocation location, int he private Stream getBlockLocations(ServerLocation worldLocation, int height, int width) { // We don't want to warp outside of the world border, so we want to check that we're within it. - final WorldBorder.Settings worldBorder = (WorldBorder.Settings) worldLocation.world().properties().worldBorder(); - final double radius = worldBorder.getSize() / 2.0D; - int worldBorderMinX = GenericMath.floor(worldBorder.getCenterX() - radius); - int worldBorderMinZ = GenericMath.floor(worldBorder.getCenterZ() - radius); - int worldBorderMaxX = GenericMath.floor(worldBorder.getCenterX() + radius); - int worldBorderMaxZ = GenericMath.floor(worldBorder.getCenterZ() + radius); + final WorldBorder.Settings worldBorder = (WorldBorder.Settings) (Object) worldLocation.world().properties().worldBorder(); + final double radius = worldBorder.size() / 2.0D; + int worldBorderMinX = GenericMath.floor(worldBorder.centerX() - radius); + int worldBorderMinZ = GenericMath.floor(worldBorder.centerZ() - radius); + int worldBorderMaxX = GenericMath.floor(worldBorder.centerX() + radius); + int worldBorderMaxZ = GenericMath.floor(worldBorder.centerZ() + radius); // Get the World and get the maximum Y value. int worldMaxY = worldLocation.world().max().y(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java index 2de473599c8..da4b71e6e5f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java @@ -30,7 +30,6 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.advancements.critereon.WrappedMinMaxBounds; import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.commands.arguments.selector.EntitySelectorParser; import net.minecraft.core.registries.Registries; @@ -58,8 +57,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.advancements.critereon.MinMaxBounds_DoublesAccessor; -import org.spongepowered.common.accessor.advancements.critereon.MinMaxBounds_IntsAccessor; import org.spongepowered.common.bridge.commands.arguments.selector.EntitySelectorParserBridge; import org.spongepowered.common.command.selector.SpongeSelectorSortAlgorithm; import org.spongepowered.common.util.Preconditions; @@ -69,7 +66,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; @@ -96,8 +92,8 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Shadow @Nullable private Double deltaX; @Shadow @Nullable private Double deltaY; @Shadow @Nullable private Double deltaZ; - @Shadow private WrappedMinMaxBounds rotX = WrappedMinMaxBounds.ANY; - @Shadow private WrappedMinMaxBounds rotY = WrappedMinMaxBounds.ANY; + @Shadow private MinMaxBounds.FloatDegrees rotX = MinMaxBounds.FloatDegrees.ANY; + @Shadow private MinMaxBounds.FloatDegrees rotY = MinMaxBounds.FloatDegrees.ANY; @Shadow @Final private List> predicates; @Shadow private boolean currentEntity; @Shadow @Nullable private String playerName; @@ -131,9 +127,12 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Shadow public abstract void shadow$addPredicate(Predicate p_197401_1_); // @formatter:on - @Nullable private Map> api$scores; - @Nullable private Object2BooleanOpenHashMap api$advancement; - @Nullable private Map> api$criterion; + @Nullable + private Map> api$scores; + @Nullable + private Object2BooleanOpenHashMap api$advancement; + @Nullable + private Map> api$criterion; private boolean api$forceSelf; @Override @@ -172,13 +171,26 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder if (range.max() != null && range.max() < 0) { throw new IllegalArgumentException("max must be non-negative"); } - this.distance = MinMaxBounds_DoublesAccessor.invoker$new(Optional.ofNullable(range.min()), Optional.ofNullable(range.max())); + + final Double min = range.min(); + final Double max = range.max(); + if (min == null && max == null) { + this.distance = MinMaxBounds.Doubles.ANY; + } else if (min == null) { + this.distance = MinMaxBounds.Doubles.atMost(max); + } else if (max == null) { + this.distance = MinMaxBounds.Doubles.atLeast(min); + } else if (min <= max) { + this.distance = MinMaxBounds.Doubles.between(min, max); + } else { + this.distance = MinMaxBounds.Doubles.between(max, min); + } return this; } @Override public Selector.@NonNull Builder volume(final org.spongepowered.math.vector.@NonNull Vector3d corner1, - final org.spongepowered.math.vector.@NonNull Vector3d corner2) { + final org.spongepowered.math.vector.@NonNull Vector3d corner2) { final org.spongepowered.math.vector.Vector3d minPoint = corner1.min(corner2); final org.spongepowered.math.vector.Vector3d distance = corner1.max(corner2).sub(minPoint); this.shadow$setX(minPoint.x()); @@ -220,7 +232,7 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Override public Selector.@NonNull Builder addNotAdvancementCriterion(final @NonNull ResourceKey advancement, - final @NonNull AdvancementCriterion criterion) { + final @NonNull AdvancementCriterion criterion) { return this.api$advancementCriterion(advancement, criterion, true); } @@ -265,7 +277,19 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder public Selector.@NonNull Builder experienceLevel(final @NonNull Range<@NonNull Integer> range) { Preconditions.checkArgument(range.min() == null || range.min() >= 0, "min must be non-negative"); Preconditions.checkArgument(range.max() == null || range.max() >= 0, "max must be non-negative"); - this.level = MinMaxBounds_IntsAccessor.invoker$new(Optional.of(range.min()), Optional.of(range.max())); + final Integer min = range.min(); + final Integer max = range.max(); + if (min == null && max == null) { + this.level = MinMaxBounds.Ints.ANY; + } else if (min == null) { + this.level = MinMaxBounds.Ints.atMost(max); + } else if (max == null) { + this.level = MinMaxBounds.Ints.atLeast(min); + } else if (min <= max) { + this.level = MinMaxBounds.Ints.between(min, max); + } else { + this.level = MinMaxBounds.Ints.between(max, min); + } this.shadow$setIncludesEntities(false); return this; } @@ -379,7 +403,7 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder } if (this.api$criterion != null) { this.api$criterion.forEach((key, value) -> - value.object2BooleanEntrySet().fastForEach(x -> entries.add(key + "={" + x.getKey() + "=" + x.getBooleanValue() + "}"))); + value.object2BooleanEntrySet().fastForEach(x -> entries.add(key + "={" + x.getKey() + "=" + x.getBooleanValue() + "}"))); } this.api$handle("advancements", "{" + String.join(",", entries) + "}"); this.api$advancement = null; @@ -413,8 +437,8 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder this.deltaX = null; this.deltaY = null; this.deltaZ = null; - this.rotX = WrappedMinMaxBounds.ANY; - this.rotY = WrappedMinMaxBounds.ANY; + this.rotX = MinMaxBounds.FloatDegrees.ANY; + this.rotY = MinMaxBounds.FloatDegrees.ANY; this.predicates.clear(); this.currentEntity = false; this.playerName = null; @@ -448,7 +472,7 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder } private Selector.@NonNull Builder api$advancementCriterion(final @NonNull ResourceKey advancement, final @NonNull AdvancementCriterion criterion, - final boolean inverted) { + final boolean inverted) { if (this.api$criterion == null) { this.api$criterion = new HashMap<>(); } @@ -465,9 +489,9 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder ((EntitySelectorParserBridge) this).bridge$handleValue(name, value, invert); } catch (final CommandSyntaxException ex) { throw new IllegalArgumentException( - String.format("Could not create selector criteria based on input (name = '%s', value = '%s', invert = %s)", name, value, - invert.name()), - ex); + String.format("Could not create selector criteria based on input (name = '%s', value = '%s', invert = %s)", name, value, + invert.name()), + ex); } } @@ -480,19 +504,19 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder } - private WrappedMinMaxBounds api$getWrappedBounds(final Range<@NonNull Double> range) { + private MinMaxBounds.FloatDegrees api$getWrappedBounds(final Range<@NonNull Double> range) { final Float a = this.api$floatFromDouble(range.min(), Mth::wrapDegrees); final Float b = this.api$floatFromDouble(range.max(), Mth::wrapDegrees); if (a == null) { - return new WrappedMinMaxBounds(null, b); + return new MinMaxBounds.FloatDegrees(MinMaxBounds.Bounds.atMost(b)); } if (b == null) { - return new WrappedMinMaxBounds(a, null); + return new MinMaxBounds.FloatDegrees(MinMaxBounds.Bounds.atLeast(a)); } if (a <= b) { - return new WrappedMinMaxBounds(a, b); + return new MinMaxBounds.FloatDegrees(MinMaxBounds.Bounds.between(a, b)); } - return new WrappedMinMaxBounds(b, a); + return new MinMaxBounds.FloatDegrees(MinMaxBounds.Bounds.between(b, a)); } private String api$intRangeToStringRepresentation(final @NonNull Range<@NonNull Integer> range) { @@ -501,8 +525,8 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder } return String.format("%s..%s", - range.min() == null ? "" : String.valueOf(range.min().intValue()), - range.max() == null ? "" : String.valueOf(range.max().intValue())); + range.min() == null ? "" : String.valueOf(range.min().intValue()), + range.max() == null ? "" : String.valueOf(range.max().intValue())); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 635d1e85e59..9adc9c0b625 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -343,9 +343,9 @@ public WorldBorder setBorder(final WorldBorder border) { borderBridge.bridge$setAssociatedWorld(this.key()); final WorldBorder worldBorder = borderBridge.bridge$applyFrom(border); if (worldBorder == null) { - return (WorldBorder) net.minecraft.world.level.border.WorldBorder.DEFAULT_SETTINGS; + return (WorldBorder) (Object) net.minecraft.world.level.border.WorldBorder.Settings.DEFAULT; } - this.serverLevelData.setWorldBorder((net.minecraft.world.level.border.WorldBorder.Settings) border); + this.serverLevelData.setLegacyWorldBorderSettings(Optional.of((net.minecraft.world.level.border.WorldBorder.Settings) (Object) border)); return worldBorder; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java index 05edacf69d2..0e65824c30c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java @@ -110,7 +110,7 @@ default WorldBorder border() { default WorldBorder setBorder(final WorldBorder border) { final WorldBorder worldBorder = ((WorldBorderBridge) ((CollisionGetter) this).getWorldBorder()).bridge$applyFrom(border); if (worldBorder == null) { - return (WorldBorder) net.minecraft.world.level.border.WorldBorder.DEFAULT_SETTINGS; + return (WorldBorder) (Object) net.minecraft.world.level.border.WorldBorder.Settings.DEFAULT; } return worldBorder; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java index 8e4dd5558ec..68985d69c1d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java @@ -25,6 +25,9 @@ package org.spongepowered.common.mixin.api.minecraft.world.level.border; import net.minecraft.world.level.border.WorldBorder; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.math.vector.Vector2d; @@ -32,57 +35,58 @@ import java.time.Duration; @Mixin(WorldBorder.Settings.class) +@Implements(@Interface(iface = org.spongepowered.api.world.border.WorldBorder.class, prefix = "api$")) public abstract class WorldBorderMixin_Settings_API implements org.spongepowered.api.world.border.WorldBorder { //@formatter:off - @Shadow public abstract double shadow$getCenterX(); - @Shadow public abstract double shadow$getCenterZ(); - @Shadow public abstract double shadow$getDamagePerBlock(); - @Shadow public abstract double shadow$getSafeZone(); - @Shadow public abstract int shadow$getWarningBlocks(); - @Shadow public abstract int shadow$getWarningTime(); - @Shadow public abstract double shadow$getSize(); - @Shadow public abstract long shadow$getSizeLerpTime(); - @Shadow public abstract double shadow$getSizeLerpTarget(); + @Shadow public abstract double shadow$centerX(); + @Shadow public abstract double shadow$centerZ(); + @Shadow public abstract double shadow$damagePerBlock(); + @Shadow public abstract double shadow$safeZone(); + @Shadow public abstract int shadow$warningBlocks(); + @Shadow public abstract int shadow$warningTime(); + @Shadow public abstract double shadow$size(); + @Shadow public abstract long shadow$lerpTime(); + @Shadow public abstract double shadow$lerpTarget(); //@formatter:on @Override public Vector2d center() { - return new Vector2d(this.shadow$getCenterX(), this.shadow$getCenterZ()); + return new Vector2d(this.shadow$centerX(), this.shadow$centerZ()); } @Override public double targetDiameter() { - return this.shadow$getSizeLerpTarget(); + return this.shadow$lerpTarget(); } @Override public Duration timeUntilTargetDiameter() { - return Duration.ofMillis(this.shadow$getSizeLerpTime()); + return Duration.ofMillis(this.shadow$lerpTime()); } @Override public double diameter() { - return this.shadow$getSize(); + return this.shadow$size(); } - @Override - public double safeZone() { - return this.shadow$getSafeZone(); + @Intrinsic + public double api$safeZone() { + return this.shadow$safeZone(); } - @Override - public double damagePerBlock() { - return this.shadow$getDamagePerBlock(); + @Intrinsic + public double api$damagePerBlock() { + return this.shadow$damagePerBlock(); } - @Override - public Duration warningTime() { - return Duration.ofMillis(this.shadow$getWarningTime()); + @Intrinsic + public Duration api$warningTime() { + return Duration.ofMillis(this.shadow$warningTime()); } @Override public int warningDistance() { - return this.shadow$getWarningBlocks(); + return this.shadow$warningBlocks(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/EmptyLevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/EmptyLevelChunkMixin_API.java index 3c2c72817b3..6d8553e12a7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/EmptyLevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/EmptyLevelChunkMixin_API.java @@ -24,13 +24,14 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.chunk; -import net.minecraft.core.Registry; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.chunk.EmptyLevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.blending.BlendingData; +import org.jetbrains.annotations.Nullable; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.asm.mixin.Mixin; @@ -38,8 +39,8 @@ public abstract class EmptyLevelChunkMixin_API extends LevelChunkMixin_API { public EmptyLevelChunkMixin_API( - final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final Registry $$3, final long $$4, - final LevelChunkSection[] $$5, final BlendingData $$6 + final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final PalettedContainerFactory $$3, + final long $$4, final @Nullable LevelChunkSection[] $$5, final @Nullable BlendingData $$6 ) { super($$0, $$1, $$2, $$3, $$4, $$5, $$6); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index e8bb8cbfce8..96fae23ca05 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -38,6 +38,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.entity.EntitySection; import net.minecraft.world.level.entity.EntitySectionStorage; @@ -121,8 +122,8 @@ public abstract class LevelChunkMixin_API extends ChunkAccess implements WorldCh private @Nullable SpongeChunkLayout api$chunkLayout; public LevelChunkMixin_API( - final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final Registry $$3, final long $$4, - final LevelChunkSection[] $$5, final BlendingData $$6 + final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final PalettedContainerFactory $$3, final long $$4, + final @Nullable LevelChunkSection[] $$5, final @Nullable BlendingData $$6 ) { super($$0, $$1, $$2, $$3, $$4, $$5, $$6); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ProtoChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ProtoChunkMixin_API.java index 128c8e825f3..3561bd4e241 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ProtoChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ProtoChunkMixin_API.java @@ -26,13 +26,13 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.chunk.status.ChunkStatus; @@ -86,8 +86,8 @@ public abstract class ProtoChunkMixin_API extends ChunkAccess implements Generat private @Nullable Vector3i api$blockMax; public ProtoChunkMixin_API( - final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final Registry $$3, final long $$4, - final LevelChunkSection[] $$5, final BlendingData $$6 + final ChunkPos $$0, final UpgradeData $$1, final LevelHeightAccessor $$2, final PalettedContainerFactory $$3, + final long $$4, final LevelChunkSection[] $$5, final BlendingData $$6 ) { super($$0, $$1, $$2, $$3, $$4, $$5, $$6); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java index 834ff15da6e..e4014c116cf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java @@ -24,24 +24,35 @@ */ package org.spongepowered.common.mixin.core.server.commands; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.commands.WeatherCommand; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(WeatherCommand.class) public abstract class WeatherCommandMixin { - @Redirect(method = { - "getDuration", + @WrapOperation( + method = "getDuration", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getRandom()Lnet/minecraft/util/RandomSource;") + ) + private static RandomSource impl$useCurrentWorld(final ServerLevel instance, final Operation original, final CommandSourceStack source) { + return original.call(source.getLevel()); + } + + @WrapOperation(method = { "setClear", "setRain", "setThunder" - }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;")) - private static ServerLevel impl$useCurrentWorld(final MinecraftServer instance, final CommandSourceStack $$0) { - return $$0.getLevel(); + }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setWeatherParameters(IIZZ)V")) + private static void impl$useCurrentWorld( + ServerLevel instance, int delay, int duration, boolean rain, boolean thunder, Operation original, + final CommandSourceStack source + ) { + original.call(source.getLevel(), delay, duration, rain, thunder); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 4425ab67848..9ea5a5c4718 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -62,6 +62,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity; +import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.end.EndDragonFight; @@ -368,7 +369,8 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel original.call(self, flush); // per-world WorldInfo/WorldBorder/BossBars - levelData.setWorldBorder(this.getWorldBorder().createSettings()); + final var border = this.getWorldBorder(); + levelData.setLegacyWorldBorderSettings(Optional.of(new WorldBorder.Settings(border))); if (levelData instanceof WorldData worldData) { worldData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), worldData, this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null); @@ -458,7 +460,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } private void impl$setWorldOnBorder() { - ((WorldBorderBridge) this.shadow$getWorldBorder()).bridge$setAssociatedWorld(((ServerWorld) this).key()); + ((WorldBorderBridge) this.getWorldBorder()).bridge$setAssociatedWorld(((ServerWorld) this).key()); } @Inject(method = "globalLevelEvent", at = @At("HEAD"), cancellable = true) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 7dd67e5f6aa..45ed29153b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -47,6 +47,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerScoreboard; import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayerGameMode; @@ -127,6 +128,7 @@ import org.spongepowered.common.accessor.network.ConnectionAccessor; import org.spongepowered.common.accessor.server.level.ChunkMapAccessor; import org.spongepowered.common.accessor.server.level.ChunkMap_TrackedEntityAccessor; +import org.spongepowered.common.accessor.server.level.ServerPlayerAccessor; import org.spongepowered.common.accessor.server.network.ServerCommonPacketListenerImplAccessor; import org.spongepowered.common.accessor.world.level.portal.TeleportTransitionAccessor; import org.spongepowered.common.adventure.SpongeAdventure; @@ -167,7 +169,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr // @formatter:off @Shadow public ServerGamePacketListenerImpl connection; @Shadow @Final public ServerPlayerGameMode gameMode; - @Shadow @Final public MinecraftServer server; + @Shadow @Final private MinecraftServer server; @Shadow private int lastRecordedExperience; @Shadow private boolean isChangingDimension; @Shadow private net.minecraft.world.phys.Vec3 enteredNetherPosition; @@ -224,6 +226,23 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr return Tristate.FALSE; } + + @WrapOperation( + method = "handleShoulderEntities", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerPlayer;playShoulderEntityAmbientSound(Lnet/minecraft/nbt/CompoundTag;)V" + ) + ) + private void impl$ignoreShoulderSoundsWhileVanished( + final net.minecraft.server.level.ServerPlayer thisPlayer, final CompoundTag tag, final Operation original + ) { + if (!this.bridge$vanishState().createsSounds()) { + return; + } + original.call(thisPlayer, tag); + } + @Override protected final boolean impl$setLocation(final boolean isChangeOfWorld, final ServerLevel level, final Vector3d pos) { if (this.shadow$isRemoved()) { @@ -295,7 +314,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Override public void bridge$initScoreboard() { - ((ServerScoreboardBridge) this.shadow$getScoreboard()).bridge$addPlayer((net.minecraft.server.level.ServerPlayer) (Object) this, true); + ((ServerScoreboardBridge) this.shadow$level().getScoreboard()).bridge$addPlayer((net.minecraft.server.level.ServerPlayer) (Object) this, true); } @Override @@ -836,9 +855,18 @@ public void sendMessage(final OutgoingChatMessage $$0, final boolean $$1, final } } - @Override - public net.minecraft.world.scores.Scoreboard shadow$getScoreboard() { - return (net.minecraft.world.scores.Scoreboard) this.impl$scoreboard; + @WrapOperation(method = { + "updateScoreForCriteria", + "die", + "awardKillScore", + "handleTeamKill", + "awardStat", + "resetStat", + }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getScoreboard()Lnet/minecraft/server/ServerScoreboard;")) + private ServerScoreboard impl$usePerPlayerScoreboard( + final ServerLevel instance, final Operation original + ) { + return (ServerScoreboard) this.impl$scoreboard; } @Override @@ -987,7 +1015,7 @@ private boolean isPvpAllowed() { if (playerRespawnDestination == null) { SpongeCommon.logger().warn("The player '{}' respawn location was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", player.getGameProfile().name()); - playerRespawnDestination = player.getServer().overworld(); + playerRespawnDestination = ((ServerPlayerAccessor) player).accessor$server().overworld(); } final RespawnPlayerEvent.SelectWorld event = SpongeEventFactory.createRespawnPlayerEventSelectWorld(PhaseTracker.getInstance().currentCause(), diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java index 99aaa23b71f..4a84163cd65 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerCommonPacketListenerImplMixin.java @@ -108,7 +108,7 @@ public abstract class ServerCommonPacketListenerImplMixin implements ServerCommo @Inject(method = "handleResourcePackResponse", at = @At( value = "INVOKE", - target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V", + target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", shift = At.Shift.AFTER)) private void impl$onHandleResourcePackResponse(final ServerboundResourcePackPacket $$0, final CallbackInfo ci) { final @Nullable ResourcePackInfo pack = this.impl$resourcePackInfos.get($$0.id()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java index 9d90350a929..d215ceecc97 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerConfigurationPacketListenerImplMixin.java @@ -82,7 +82,7 @@ public abstract class ServerConfigurationPacketListenerImplMixin extends ServerC private boolean impl$skipBanService; @Inject(method = "handleConfigurationFinished", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V")) private void impl$onHandleConfigurationFinished(final ServerboundFinishConfigurationPacket $$0, final CallbackInfo ci) { if (this.impl$skipBanService) { return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 3fe9ee1f050..42f7b7b5b6b 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -540,12 +540,6 @@ public abstract class PlayerListMixin implements PlayerListBridge { SpongeCommon.post(event); } - @Redirect(method = "sendLevelInfo", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;")) - private ServerLevel impl$usePerWorldWorldBorder(final MinecraftServer minecraftServer, final net.minecraft.server.level.ServerPlayer playerIn, - final ServerLevel worldIn) { - return worldIn; - } - private void impl$disconnectClient(final Connection netManager, final Component disconnectMessage, final @Nullable GameProfile profile) { final net.minecraft.network.chat.Component reason = SpongeAdventure.asVanilla(disconnectMessage); diff --git a/src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_IntsAccessor.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/AvatarMixin.java similarity index 71% rename from src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_IntsAccessor.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/AvatarMixin.java index a931c5acca8..3ab7f182324 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_IntsAccessor.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/AvatarMixin.java @@ -22,20 +22,19 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.advancements.critereon; +package org.spongepowered.common.mixin.core.world.entity; -import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.Avatar; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; +import org.spongepowered.asm.mixin.Shadow; -import java.util.Optional; +@Mixin(Avatar.class) +public abstract class AvatarMixin extends LivingEntityMixin { -@Mixin(MinMaxBounds.Ints.class) -public interface MinMaxBounds_IntsAccessor { - - @Invoker("") static MinMaxBounds.Ints invoker$new(final Optional min, final Optional max) { - throw new UntransformedInvokerError(); - } + //@formatter:off + @Shadow @Final protected static EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION; + //@formatter:on } diff --git a/src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_DoublesAccessor.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/MannequinMixin.java similarity index 71% rename from src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_DoublesAccessor.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/MannequinMixin.java index 09e8543900a..10b5feed971 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/advancements/critereon/MinMaxBounds_DoublesAccessor.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/MannequinMixin.java @@ -22,20 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.advancements.critereon; +package org.spongepowered.common.mixin.core.world.entity.decoration; -import net.minecraft.advancements.critereon.MinMaxBounds; +import org.spongepowered.api.entity.Mannequin; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; +import org.spongepowered.common.mixin.core.world.entity.AvatarMixin; -import java.util.Optional; - -@Mixin(MinMaxBounds.Doubles.class) -public interface MinMaxBounds_DoublesAccessor { - - @Invoker("") static MinMaxBounds.Doubles invoker$new(final Optional min, final Optional max) { - throw new UntransformedInvokerError(); - } +@Mixin(net.minecraft.world.entity.decoration.Mannequin.class) +public abstract class MannequinMixin extends AvatarMixin implements Mannequin { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java index e29a9d7bf5a..251de521ef6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java @@ -42,7 +42,7 @@ public abstract class WanderingTraderMixin { @Inject(method = "tick", at = @At("HEAD"), cancellable = true) private void impl$checkInfiniteTickDelay( - final ServerLevel $$0, final boolean $$1, final boolean $$2, final CallbackInfo cir + final ServerLevel $$0, final boolean $$1, final CallbackInfo cir ) { if (this.tickDelay == Constants.TickConversions.INFINITE_TICKS) { cir.cancel(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 8a4507c47af..04a0e4f4ba8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -28,9 +28,7 @@ import com.mojang.datafixers.util.Either; import net.kyori.adventure.bossbar.BossBar; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; @@ -48,7 +46,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.pattern.BlockInWorld; import net.minecraft.world.phys.AABB; -import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Team; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.entity.living.Living; @@ -77,7 +74,7 @@ import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.item.util.ItemStackUtil; -import org.spongepowered.common.mixin.core.world.entity.LivingEntityMixin; +import org.spongepowered.common.mixin.core.world.entity.AvatarMixin; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.ExperienceHolderUtil; @@ -87,10 +84,9 @@ import java.util.Set; @Mixin(net.minecraft.world.entity.player.Player.class) -public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBridge, GameProfileHolderBridge, ViewerBridge { +public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, GameProfileHolderBridge, ViewerBridge { // @formatter: off - @Shadow @Final protected static EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION; @Shadow public int experienceLevel; @Shadow public int totalExperience; @Shadow public float experienceProgress; @@ -101,7 +97,6 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract int shadow$getXpNeededForNextLevel(); @Shadow public abstract FoodData shadow$getFoodData(); - @Shadow public abstract Scoreboard shadow$getScoreboard(); @Shadow public abstract boolean shadow$isCreative(); @Shadow public abstract String shadow$getScoreboardName(); @Shadow public abstract void shadow$awardStat(ResourceLocation stat); @@ -109,7 +104,6 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri @Shadow public Either shadow$startSleepInBed(final BlockPos param0) { return null; // Shadowed } - @Shadow protected abstract void shadow$playShoulderEntityAmbientSound(CompoundTag p_192028_1_); // @formatter: on private boolean impl$affectsSpawning = true; @@ -202,20 +196,6 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerBri return playerEntity.getName(); } - @Redirect( - method = "aiStep", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/entity/player/Player;playShoulderEntityAmbientSound(Lnet/minecraft/nbt/CompoundTag;)V" - ) - ) - private void impl$ignoreShoulderSoundsWhileVanished(final net.minecraft.world.entity.player.Player thisPlayer, final CompoundTag tag) { - if (!this.bridge$vanishState().createsSounds()) { - return; - } - this.shadow$playShoulderEntityAmbientSound(tag); - } - @Redirect( method = { "playSound(Lnet/minecraft/sounds/SoundEvent;FF)V", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index 48764abb719..09eebab75b2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -50,7 +50,6 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.TickingBlockEntity; -import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.storage.LevelData; @@ -109,7 +108,6 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { @Shadow public abstract DifficultyInstance shadow$getCurrentDifficultyAt(BlockPos p_175649_1_); @Shadow public abstract boolean shadow$isRaining(); @Shadow public abstract net.minecraft.world.level.block.entity.@Nullable BlockEntity shadow$getBlockEntity(BlockPos p_175625_1_); - @Shadow public abstract WorldBorder shadow$getWorldBorder(); @Shadow public abstract RegistryAccess shadow$registryAccess(); //@Shadow protected abstract void shadow$postGameEventInRadius(@javax.annotation.Nullable net.minecraft.world.entity.Entity $$0, GameEvent $$1, BlockPos $$2, int $$3); // @formatter on diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java index b8c50cba2e8..451758d8dba 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java @@ -59,9 +59,9 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onSetCenter(final double x, final double z, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .center(x, z) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .center(x, z) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -72,9 +72,9 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onSetSize(final double size, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .initialDiameter(size) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .initialDiameter(size) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -85,11 +85,11 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onLerping(final double initial, final double target, final long milliseconds, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .initialDiameter(initial) - .targetDiameter(target) - .timeToTargetDiameter(Duration.ofMillis(milliseconds)) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .initialDiameter(initial) + .targetDiameter(target) + .timeToTargetDiameter(Duration.ofMillis(milliseconds)) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -100,22 +100,22 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onSetWarningBlocks(final int distance, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .warningDistance(distance) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .warningDistance(distance) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } } } - @Inject(method = "setDamageSafeZone", at = @At(value = "HEAD"), cancellable = true) + @Inject(method = "setSafeZone", at = @At(value = "HEAD"), cancellable = true) private void impl$onSetDamageSafeZone(final double size, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .safeZone(size) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .safeZone(size) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -126,9 +126,9 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onSetDamagePerBlock(final double damagePerBlock, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .damagePerBlock(damagePerBlock) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .damagePerBlock(damagePerBlock) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -139,9 +139,9 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { private void impl$onSetWarningTime(final int warningTime, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = - () -> new SpongeWorldBorderBuilder().from(this) - .warningTime(Duration.ofSeconds(warningTime)) - .build(); + () -> new SpongeWorldBorderBuilder().from(this) + .warningTime(Duration.ofSeconds(warningTime)) + .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); } @@ -159,16 +159,16 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { if (world.isPresent()) { final org.spongepowered.api.world.border.WorldBorder originalNewBorder = supplier.get(); final ChangeWorldBorderEvent.World event = SpongeEventFactory.createChangeWorldBorderEventWorld( - PhaseTracker.getInstance().currentCause(), - Optional.of(originalNewBorder), - Optional.of(originalNewBorder), - Optional.of(this.bridge$asImmutable()), - world.get() + PhaseTracker.getInstance().currentCause(), + Optional.of(originalNewBorder), + Optional.of(originalNewBorder), + Optional.of(this.bridge$asImmutable()), + world.get() ); final boolean isCancelled = Sponge.eventManager().post(event); if (!isCancelled) { final org.spongepowered.api.world.border.WorldBorder toSet = - event.newBorder().orElse((org.spongepowered.api.world.border.WorldBorder) WorldBorder.DEFAULT_SETTINGS); + event.newBorder().orElse((org.spongepowered.api.world.border.WorldBorder) (Object) WorldBorder.Settings.DEFAULT); if (originalNewBorder != toSet) { // set the values, suppress this call. this.impl$fireEvent = false; @@ -184,13 +184,13 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { @Override public org.spongepowered.api.world.border.WorldBorder bridge$asImmutable() { - return (org.spongepowered.api.world.border.WorldBorder) ((WorldBorder) (Object) this).createSettings(); + return (org.spongepowered.api.world.border.WorldBorder) (Object) new WorldBorder.Settings(((WorldBorder) (Object) this)); } @Override public org.spongepowered.api.world.border.@Nullable WorldBorder bridge$applyFrom(final org.spongepowered.api.world.border.WorldBorder worldBorder) { if (!this.impl$fireEvent) { - ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) worldBorder); + ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) (Object) worldBorder); return worldBorder; } @@ -201,15 +201,14 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { return this.bridge$asImmutable(); } - final org.spongepowered.api.world.border.WorldBorder defaultSettings = - (org.spongepowered.api.world.border.WorldBorder) WorldBorder.DEFAULT_SETTINGS; + final var defaultSettings = (org.spongepowered.api.world.border.WorldBorder) (Object) WorldBorder.Settings.DEFAULT; toSet = event.newBorder().orElse(defaultSettings); } else { toSet = worldBorder; } this.impl$fireEvent = false; - ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) toSet); + ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) (Object) toSet); this.impl$fireEvent = true; return toSet; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java index ee2bce6b001..57beb5d15f5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java @@ -25,19 +25,18 @@ package org.spongepowered.common.mixin.core.world.level.chunk; import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.ticks.LevelChunkTicks; @@ -86,7 +85,7 @@ public abstract class LevelChunkMixin extends ChunkAccess implements LevelChunkBridge, CacheKeyBridge, SpongeMutableDataHolder, SpongeDataHolderBridge, DataCompoundHolder, BlockChunk { // @formatter:off - @Shadow @Final private Level level; + @Shadow @Final Level level; @Shadow private boolean loaded; @Shadow @Nullable public abstract BlockEntity shadow$getBlockEntity(BlockPos pos, net.minecraft.world.level.chunk.LevelChunk.EntityCreationType p_177424_2_); @@ -105,15 +104,7 @@ public abstract class LevelChunkMixin extends ChunkAccess implements LevelChunkB private Map impl$trackedShortBlockPositions = new HashMap<>(); private @Nullable CompoundTag impl$compound; - public LevelChunkMixin( - final ChunkPos $$0, - final UpgradeData $$1, - final LevelHeightAccessor $$2, - final Registry $$3, - final long $$4, - final LevelChunkSection[] $$5, - final BlendingData $$6 - ) { + public LevelChunkMixin(ChunkPos $$0, UpgradeData $$1, LevelHeightAccessor $$2, PalettedContainerFactory $$3, long $$4, @org.jetbrains.annotations.Nullable LevelChunkSection[] $$5, @org.jetbrains.annotations.Nullable BlendingData $$6, Level level) { super($$0, $$1, $$2, $$3, $$4, $$5, $$6); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java index 247e4c46a97..d4b215e36af 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/SerializableChunkDataMixin.java @@ -24,12 +24,12 @@ */ package org.spongepowered.common.mixin.core.world.level.chunk; -import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.storage.SerializableChunkData; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.world.SerializationBehavior; @@ -103,7 +103,10 @@ public abstract class SerializableChunkDataMixin implements SerializableChunkDat } @Inject(method = "parse", at = @At(value = "TAIL")) - private static void tracker$parseSpongeData(final LevelHeightAccessor $$0, final RegistryAccess $$1, final CompoundTag tag, final CallbackInfoReturnable cir) { + private static void tracker$parseSpongeData( + final LevelHeightAccessor ha, final PalettedContainerFactory pcf, final CompoundTag tag, + final CallbackInfoReturnable cir + ) { final var bridge = (SerializableChunkDataBridge) (Object) cir.getReturnValue(); bridge.bridge$parseTrackerData(tag); bridge.bridge$parseDataHolderData(tag); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WorldBorderCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/network/PacketProcessor_ListenerAndPacketMixin_Tracker.java similarity index 59% rename from src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WorldBorderCommandMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/tracker/network/PacketProcessor_ListenerAndPacketMixin_Tracker.java index c29688d84ee..b6a90c85cae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WorldBorderCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/network/PacketProcessor_ListenerAndPacketMixin_Tracker.java @@ -22,29 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.server.commands; +package org.spongepowered.common.mixin.tracker.network; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.commands.WorldBorderCommand; -import net.minecraft.server.level.ServerLevel; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.network.PacketListener; +import net.minecraft.network.protocol.Packet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.tracking.phase.packet.PacketPhaseUtil; -@Mixin(WorldBorderCommand.class) -public abstract class WorldBorderCommandMixin { +@Mixin(targets = "net.minecraft.network.PacketProcessor$ListenerAndPacket") +public abstract class PacketProcessor_ListenerAndPacketMixin_Tracker { - @Redirect(method = { - "setDamageBuffer", - "setDamageAmount", - "setWarningTime", - "setWarningDistance", - "getSize", - "setCenter", - "setSize" - }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;")) - private static ServerLevel impl$useCurrentWorld(final MinecraftServer instance, final CommandSourceStack $$0) { - return $$0.getLevel(); + @WrapOperation(method = "handle", + at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/Packet;handle(Lnet/minecraft/network/PacketListener;)V")) + private void tracker$redirectProcessPacket(Packet packet, T listener, Operation original) { + PacketPhaseUtil.onProcessPacket(packet, listener, () -> original.call(packet, listener)); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/network/protocol/PacketUtilsMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/network/protocol/PacketUtilsMixin_Tracker.java deleted file mode 100644 index 5c35446f881..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/network/protocol/PacketUtilsMixin_Tracker.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.tracker.network.protocol; - -import net.minecraft.network.PacketListener; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.PacketUtils; -import net.minecraft.util.thread.BlockableEventLoop; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.event.tracking.phase.packet.PacketPhaseUtil; - -@Mixin(PacketUtils.class) -public abstract class PacketUtilsMixin_Tracker { - - // @formatter:off - @Shadow @Final private static Logger LOGGER; - // @formatter:on - - @Redirect(method = "ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/util/thread/BlockableEventLoop;executeIfPossible(Ljava/lang/Runnable;)V")) - private static void tracker$redirectProcessPacket(BlockableEventLoop threadTaskExecutor, Runnable runnable, - Packet packet, T packetListener, BlockableEventLoop blockableEventLoop) { - threadTaskExecutor.executeIfPossible(() -> { - if (packetListener.isAcceptingMessages()) { - PacketPhaseUtil.onProcessPacket(packet, packetListener); - } else { - LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } - }); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java index afcd93db052..956a50f2f1d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java @@ -62,24 +62,16 @@ public abstract class ServerChunkCacheMixin_Tracker { } } - @WrapOperation( - method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;tickCustomSpawners(ZZ)V" - ) - ) + @WrapOperation(method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tickCustomSpawners(Z)V")) private void tracker$wrapGeneratorEntitySpawner( - final ServerLevel serverWorld, - final boolean spawnHostileMobs, - final boolean spawnPeacefulMobs, - final Operation wrapped + final ServerLevel serverWorld, final boolean spawnEnemies, final Operation wrapped ) { try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING .createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); - wrapped.call(serverWorld, spawnHostileMobs, spawnPeacefulMobs); + wrapped.call(serverWorld, spawnEnemies); } } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index de09fe86223..38f464e7b98 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -69,7 +69,6 @@ "server.commands.SaveAllCommandMixin", "server.commands.TeleportCommandMixin", "server.commands.WeatherCommandMixin", - "server.commands.WorldBorderCommandMixin", "server.dedicated.DedicatedPlayerListMixin", "server.level.ChunkHolderMixin", "server.level.ChunkMap_TrackedEntityMixin", @@ -119,6 +118,7 @@ "world.damagesource.DamageSourcesMixin", "world.entity.ActiveChunkReferentMixin", "world.entity.AgableMobMixin", + "world.entity.AvatarMixin", "world.entity.EntityMaxAirMixin", "world.entity.EntityMixin", "world.entity.EntitySelectorMixin", @@ -129,6 +129,7 @@ "world.entity.LightningBoltMixin", "world.entity.LivingEntityMixin", "world.entity.LivingEntityMixin_Damage", + "world.entity.decoration.MannequinMixin", "world.entity.MobMixin", "world.entity.MobMixin_Attack", "world.entity.PortalProcessorMixin", diff --git a/src/mixins/resources/mixins.sponge.tracker.json b/src/mixins/resources/mixins.sponge.tracker.json index fccb4607b18..59ec46ccd60 100644 --- a/src/mixins/resources/mixins.sponge.tracker.json +++ b/src/mixins/resources/mixins.sponge.tracker.json @@ -8,7 +8,7 @@ "CreatorTrackedPlayerMixin_Tracker", "TrackableTypeMixin", "event.TraitMixin_Tracked_Inventory", - "network.protocol.PacketUtilsMixin_Tracker", + "network.PacketProcessor_ListenerAndPacketMixin_Tracker", "server.MinecraftServerMixin_Tracker", "server.TickTaskMixin_Tracker", "server.dedicated.DedicatedServerMixin_Tracker", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 9bd67bf24d0..3b1f26849cc 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -34,6 +34,7 @@ import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -276,11 +277,11 @@ protected void drawPanel(final GuiGraphics stack, final int entryRight, int rela } @Override - public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeated) { + public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated) { // Find an entry match for where we clicked final Entry entry = this.getAllEntries().stream() - .filter(e -> e.valueBounds != null && e.valueBounds.isInBounds((int) mouseX, (int) mouseY)) + .filter(e -> e.valueBounds != null && e.valueBounds.isInBounds((int) event.x(), (int) event.y())) .findFirst().orElse(null); if (entry == null) { @@ -292,7 +293,7 @@ public boolean mouseClicked(final double mouseX, final double mouseY, final int this.screen.handleComponentClicked(component.getStyle()); return true; } - return super.mouseClicked(mouseX, mouseY, button, repeated); + return super.mouseClicked(event, repeated); } @Override diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 4e32fa9c1bf..4187c5d871f 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -33,6 +33,7 @@ import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.input.MouseButtonEvent; import java.util.Collections; import java.util.List; @@ -122,11 +123,14 @@ public boolean isMouseOver(final double mouseX, final double mouseY) { } @Override - public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeated) { - if (super.mouseClicked(mouseX, mouseY, button, repeated)) { + public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated) { + if (super.mouseClicked(event, repeated)) { return true; } + final var button = event.button(); + final var mouseX = event.x(); + final var mouseY = event.y(); this.scrolling = button == 0 && mouseX >= this.barLeft && mouseX < this.barLeft + this.barWidth; if (this.scrolling) { return true; @@ -139,8 +143,8 @@ public boolean mouseClicked(final double mouseX, final double mouseY, final int } @Override - public boolean mouseReleased(final double p_mouseReleased_1_, final double p_mouseReleased_3_, final int p_mouseReleased_5_) { - if (super.mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_)) { + public boolean mouseReleased(final MouseButtonEvent event) { + if (super.mouseReleased(event)) { return true; } final boolean ret = this.scrolling; @@ -163,7 +167,7 @@ private int getBarHeight() { } @Override - public boolean mouseDragged(final double mouseX, final double mouseY, final int button, final double deltaX, final double deltaY) { + public boolean mouseDragged(final MouseButtonEvent event, final double deltaX, final double deltaY) { if (this.scrolling) { final int maxScroll = this.height - this.getBarHeight(); final double moved = deltaY / maxScroll; diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java index 3cfba5eb7ab..9313a6503bd 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java @@ -33,6 +33,7 @@ import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.narration.NarrationSupplier; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.Component; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.vanilla.util.Bounds; @@ -130,22 +131,29 @@ public void setSelected(@Nullable final E entry) { super.setSelected(entry); } + @Override - public boolean mouseClicked(final double mouseX, final double mouseY, final int button, final boolean repeatedClick) { - this.updateScrolling(mouseX, mouseY, button); + public boolean mouseClicked(final MouseButtonEvent event, final boolean repeatedClick) { + final var mouseX = event.x(); + final var mouseY = event.y(); + final var button = event.button(); + this.updateScrolling(event); if (!this.isMouseOver(mouseX, mouseY)) { return false; } else { final E e = this.getEntryAtPosition(mouseX, mouseY); if (e != null) { - if (e.mouseClicked(mouseX, mouseY, button, repeatedClick)) { + if (e.mouseClicked(event, repeatedClick)) { this.setFocused(e); this.setDragging(true); return true; } } else if (button == 0) { - this.onClick((int) (mouseX - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), - (int) (mouseY - (double) this.getY()) + (int) this.scrollAmount() - 4, repeatedClick); + final var newEvent = new MouseButtonEvent( + (mouseX - (double) (this.getX() + this.width / 2 - this.getRowWidth() / 2)), + (mouseY - (double) this.getY()) + (int) this.scrollAmount() - 4, + event.buttonInfo()); + this.onClick(newEvent, repeatedClick); return true; } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java index 72a84876bd6..b5da68d66fb 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java @@ -28,6 +28,7 @@ import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.MouseButtonEvent; import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.vanilla.util.Bounds; @@ -71,7 +72,7 @@ public void renderContent(GuiGraphics var1, int var2, int var3, boolean var4, fl // } @Override - public boolean mouseClicked(final double p_mouseClicked_1_, final double p_mouseClicked_3_, final int p_mouseClicked_5_, final boolean repeated) { + public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated) { this.getParentList().setSelected(this); return true; } From ce408102075fbdd8aceca7f3a6c413439a772365 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 5 Sep 2025 10:32:44 +0200 Subject: [PATCH 337/586] Update badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 64e71435119..e5f5737eb1a 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) +[![SpongeVanilla 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) +[![SpongeForge 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.5](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.5&queryOpt=%3Aversion%3D1.21.5*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.5*) +[![SpongeNeo 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ## Prerequisites From 3ec7efc95185566ca469bc13fbe9b389aba49900 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 8 Sep 2025 20:19:24 +0300 Subject: [PATCH 338/586] Fix Biome BACKGROUND_MUSIC This should be changed to weighted one in the API --- .../common/data/provider/world/biome/BiomeData.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index dcd9f171d2c..77b45a03ac7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.world.biome; import net.minecraft.core.Holder; +import net.minecraft.util.random.WeightedEntry; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeGenerationSettings; @@ -101,7 +102,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.GRASS_COLOR_MODIFIER) .get(h -> (GrassColorModifier) (Object) h.getSpecialEffects().getGrassColorModifier()) .create(Keys.BACKGROUND_MUSIC) - .get(h -> h.getSpecialEffects().getBackgroundMusic().map(e -> e.unwrap().getFirst().data()).map(SoundConfig.BackgroundMusic.class::cast).orElse(null)) + .get(h -> h.getSpecialEffects().getBackgroundMusic().flatMap(e -> e.unwrap().stream().findFirst().map(WeightedEntry.Wrapper::data)).map(SoundConfig.BackgroundMusic.class::cast).orElse(null)) .create(Keys.AMBIENT_ADDITIONAL_SOUND) .get(h -> h.getSpecialEffects().getAmbientAdditionsSettings().map(SoundConfig.Additional.class::cast).orElse(null)) .create(Keys.AMBIENT_MOOD) From 46fd28e664124b90e628271507bc5b9e4bd5a418 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 8 Sep 2025 20:20:25 +0300 Subject: [PATCH 339/586] Fix AXOLOTL_VARIANT registry missing --- .../common/registry/loader/VanillaRegistryLoader.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index dee8737e7f6..4727ac90857 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -46,6 +46,7 @@ import net.minecraft.world.entity.animal.Rabbit; import net.minecraft.world.entity.animal.Salmon; import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.axolotl.Axolotl; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.animal.horse.Markings; import net.minecraft.world.entity.animal.horse.Variant; @@ -238,6 +239,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.TRIAL_SPAWNER_STATE, TrialSpawnerState.values()); this.automaticName(RegistryTypes.VAULT_STATE, VaultState.values()); this.automaticName(RegistryTypes.EXPLOSION_BLOCK_INTERACTION, Explosion.BlockInteraction.values()); + this.automaticName(RegistryTypes.AXOLOTL_VARIANT, Axolotl.Variant.values()); } private static RegistryLoader criterion() { From 78e804119b3cc26a69ecd080d364b8395a06ab15 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 8 Sep 2025 20:21:24 +0300 Subject: [PATCH 340/586] Fix ItemTier#repairIngredient --- .../api/minecraft/world/item/ToolMaterialMixin_API.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java index b0394d9d962..2a0904d32da 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ToolMaterialMixin_API.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item; -import net.minecraft.core.HolderGetter; -import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import org.spongepowered.api.data.type.ItemTier; @@ -33,6 +33,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; @Mixin(net.minecraft.world.item.ToolMaterial.class) @@ -44,7 +45,7 @@ public abstract class ToolMaterialMixin_API implements ItemTier { @Override public Ingredient repairIngredient() { - HolderGetter holder = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.ITEM); + Registry holder = SpongeCommon.vanillaRegistry(Registries.ITEM); final var items = holder.getOrThrow(this.repairItems); return (Ingredient) (Object) SpongeIngredient.of(items); } From 30a3468b8f1c5e838bde0213e9c0424bf4a7c5cb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 9 Sep 2025 12:46:17 +0200 Subject: [PATCH 341/586] Fix wrong container during open event --- .../common/event/inventory/InventoryEventFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index bca5e6694c3..b4ff0418aa8 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -232,7 +232,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player, final Transaction cursorTransaction = new Transaction<>(ItemStackSnapshot.empty(), newCursor); final InteractContainerEvent.Open event = SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getWorldInstance(player.serverLevel()).currentCause(), - (org.spongepowered.api.item.inventory.Container) player.containerMenu, cursorTransaction); + (org.spongepowered.api.item.inventory.Container) menu, cursorTransaction); SpongeCommon.post(event); if (event.isCancelled()) { return false; From 6820483b98b69b764a1b0b989728fab10417e785 Mon Sep 17 00:00:00 2001 From: Joni Aromaa Date: Wed, 10 Sep 2025 20:33:41 +0300 Subject: [PATCH 342/586] Use LauncherInterceptor for JUnit tests (#4226) * Use LauncherInterceptor for JUnit tests * Reject class loading for BOOTSTRAP-RESOURCES --------- Co-authored-by: Yeregorix --- .../spongepowered/bootstrap/Bootstrap.java | 38 ++++++++--- .../FilteringPassthroughClassLoader.java | 60 ++++++++++++++++++ .../bootstrap/ResourceClassLoader.java | 44 +++++++++++++ .../bootstrap/dev/DevClasspath.java | 4 +- forge/build.gradle.kts | 1 + .../forge/boot/SpongeLauncherInterceptor.java | 57 +++++++++++++++++ .../forge/boot/SpongeSessionListener.java | 20 ++---- ...unit.platform.launcher.LauncherInterceptor | 1 + neoforge/build.gradle.kts | 1 + .../boot/SpongeLauncherInterceptor.java | 63 +++++++++++++++++++ .../neoforge/boot/SpongeSessionListener.java | 20 ++---- ...unit.platform.launcher.LauncherInterceptor | 1 + vanilla/build.gradle.kts | 1 + .../test/SpongeLauncherInterceptor.java | 57 +++++++++++++++++ .../installer/test/SpongeSessionListener.java | 20 ++---- ...unit.platform.launcher.LauncherInterceptor | 1 + .../boot/SpongeLauncherInterceptor.java | 57 +++++++++++++++++ .../vanilla/boot/SpongeSessionListener.java | 20 ++---- ...unit.platform.launcher.LauncherInterceptor | 1 + 19 files changed, 400 insertions(+), 67 deletions(-) create mode 100644 bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java create mode 100644 bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java create mode 100644 forge/src/test/java/org/spongepowered/forge/boot/SpongeLauncherInterceptor.java create mode 100644 forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor create mode 100644 neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java create mode 100644 neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor create mode 100644 vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeLauncherInterceptor.java create mode 100644 vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor create mode 100644 vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeLauncherInterceptor.java create mode 100644 vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 9ef04b2a09f..5f3abbc0c1f 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -26,10 +26,10 @@ import org.spongepowered.bootstrap.dev.DevClasspath; +import java.io.File; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import java.net.URL; -import java.net.URLClassLoader; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -38,6 +38,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; public abstract class Bootstrap { public static final boolean DEBUG = Boolean.getBoolean("sponge.bootstrap.debug"); @@ -73,7 +74,8 @@ public void boot(final List classpath, final boolean isolated) throws Ex // Collect the jars final Set moduleNames = new HashSet<>(); - final List resourceJars = new ArrayList<>(); + final List resourcePaths = new ArrayList<>(); + final List resourceJars = new ArrayList<>(); final List appJars = new ArrayList<>(); for (final Path[] paths : classpath) { @@ -92,7 +94,8 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (Bootstrap.DEBUG) { System.out.println("Filtered: " + name + " " + Bootstrap.formatUnion(paths)); } - resourceJars.addAll(Arrays.asList(paths)); + resourceJars.add(jar); + resourcePaths.addAll(Arrays.asList(paths)); continue; } @@ -100,7 +103,8 @@ public void boot(final List classpath, final boolean isolated) throws Ex if (Bootstrap.DEBUG) { System.out.println("Duplicate: " + name + " " + Bootstrap.formatUnion(paths)); } - resourceJars.addAll(Arrays.asList(paths)); + resourceJars.add(jar); + resourcePaths.addAll(Arrays.asList(paths)); continue; } @@ -117,15 +121,31 @@ public void boot(final List classpath, final boolean isolated) throws Ex // Isolation final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader parentLoader = isolated ? ClassLoader.getPlatformClassLoader() : contextLoader; + ClassLoader parentLoader = ClassLoader.getPlatformClassLoader(); + if (!isolated) { + // Make sure we don't leak classes that are supposed to be + // in the game layer from the boostrap layer. + final String resources = System.getProperty("sponge.resources"); + if (resources != null) { + final List spongeJars = new ArrayList<>(); + for (final String entry : resources.split(File.pathSeparator)) { + final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); + spongeJars.add(this.createJar(paths)); + } + final ModuleFinder spongeFinder = this.createModuleFinder(spongeJars); + final ModuleFinder resourceFinder = this.createModuleFinder(resourceJars); + parentLoader = new FilteringPassthroughClassLoader(contextLoader, + Stream.concat(spongeFinder.findAll().stream(), resourceFinder.findAll().stream())); + } + } // Intermediate classloader to include resources but not modules - if (!resourceJars.isEmpty()) { - final URL[] urls = new URL[resourceJars.size()]; + if (!resourcePaths.isEmpty()) { + final URL[] urls = new URL[resourcePaths.size()]; for (int i = 0; i < urls.length; i++) { - urls[i] = resourceJars.get(i).toUri().toURL(); + urls[i] = resourcePaths.get(i).toUri().toURL(); } - parentLoader = new URLClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); + parentLoader = new ResourceClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); } // Create the application classloader diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java new file mode 100644 index 00000000000..5f17458df0d --- /dev/null +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap; + +import java.lang.module.ModuleReference; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +public final class FilteringPassthroughClassLoader extends ClassLoader { + + private final Set filteredPackages = new HashSet<>(); + + static { + ClassLoader.registerAsParallelCapable(); + } + + FilteringPassthroughClassLoader(final ClassLoader parent, final Stream modules) { + super(parent); + modules.forEach(m -> this.filteredPackages.addAll(m.descriptor().packages())); + } + + @Override + protected Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { + if (!this.filteredPackages.contains(FilteringPassthroughClassLoader.nameToPackage(name))) { + return super.loadClass(name, resolve); + } + throw new ClassNotFoundException(name); + } + + private static String nameToPackage(final String name) { + final int index = name.lastIndexOf('.'); + if (index == -1 || index == name.length() - 1) { + return ""; + } + return name.substring(0, index); + } +} diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java new file mode 100644 index 00000000000..ee11b705544 --- /dev/null +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java @@ -0,0 +1,44 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap; + +import java.net.URL; +import java.net.URLClassLoader; + +public final class ResourceClassLoader extends URLClassLoader { + + static { + ClassLoader.registerAsParallelCapable(); + } + + public ResourceClassLoader(final String name, final URL[] urls, final ClassLoader parent) { + super(name, urls, parent); + } + + @Override + protected Class findClass(final String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } +} diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 8dfc98cb24e..4ca4698babf 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -125,14 +125,14 @@ public static List resolve() { final String fileName = path.getFileName().toString(); - if (fileName.startsWith("junit-") || fileName.startsWith("mockito-")) { + if (fileName.startsWith("junit-") || fileName.startsWith("byte-buddy-")) { if (Bootstrap.DEBUG) { System.out.println("Ignored: " + path); } continue; } - if (bootNames.contains(fileName) || fileName.startsWith("org.jacoco.core-")) { + if (bootNames.contains(fileName) || fileName.startsWith("org.jacoco.core-") || fileName.startsWith("mockito-") || fileName.startsWith("objenesis-")) { if (Bootstrap.DEBUG) { System.out.println("Boot: " + path); } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 5b6369a6709..e93155b1415 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -435,6 +435,7 @@ tasks { jvmArgs(runServer.jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") + jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeLauncherInterceptor.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeLauncherInterceptor.java new file mode 100644 index 00000000000..89e5aa180c3 --- /dev/null +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeLauncherInterceptor.java @@ -0,0 +1,57 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.boot; + +import org.junit.platform.launcher.LauncherInterceptor; +import org.spongepowered.common.applaunch.test.TestGameAccess; + +public final class SpongeLauncherInterceptor implements LauncherInterceptor { + + private final ClassLoader classLoader; + + public SpongeLauncherInterceptor() { + try { + this.classLoader = SpongeTestBoot.getGameClassLoader(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public T intercept(final Invocation invocation) { + final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.classLoader); + try { + return invocation.proceed(); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + + @Override + public void close() { + TestGameAccess.shutdownGame(); + } +} diff --git a/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java index 7e93cdd7301..8ebef7be38c 100644 --- a/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java +++ b/forge/src/test/java/org/spongepowered/forge/boot/SpongeSessionListener.java @@ -26,25 +26,17 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; -import org.spongepowered.common.applaunch.test.TestGameAccess; -public class SpongeSessionListener implements LauncherSessionListener { - private ClassLoader previousLoader; +public final class SpongeSessionListener implements LauncherSessionListener { - @Override - public void launcherSessionOpened(final LauncherSession session) { - this.previousLoader = Thread.currentThread().getContextClassLoader(); + private final ClassLoader classLoader; - try { - Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public SpongeSessionListener() { + this.classLoader = Thread.currentThread().getContextClassLoader(); } @Override - public void launcherSessionClosed(final LauncherSession session) { - TestGameAccess.shutdownGame(); - Thread.currentThread().setContextClassLoader(this.previousLoader); + public void launcherSessionOpened(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.classLoader); } } diff --git a/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 00000000000..a05b9722afb --- /dev/null +++ b/forge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1 @@ +org.spongepowered.forge.boot.SpongeLauncherInterceptor diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 7af530fe46b..3dc2666d864 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -410,6 +410,7 @@ tasks { jvmArgs(runServer.get().jvmArgs) jvmArgs("-Dsponge.test.args=" + runServer.get().args!!.joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") + jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java new file mode 100644 index 00000000000..dcc5924a543 --- /dev/null +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java @@ -0,0 +1,63 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.boot; + +import org.junit.platform.launcher.LauncherInterceptor; +import org.spongepowered.common.applaunch.test.TestGameAccess; + +public final class SpongeLauncherInterceptor implements LauncherInterceptor { + + private final ClassLoader classLoader; + + private long counter; + + public SpongeLauncherInterceptor() { + try { + this.classLoader = SpongeTestBoot.getGameClassLoader(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public T intercept(final Invocation invocation) { + // getResources broken on Neo + if (this.counter++ == 1) { + return invocation.proceed(); + } + final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.classLoader); + try { + return invocation.proceed(); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + + @Override + public void close() { + TestGameAccess.shutdownGame(); + } +} diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java index 53916709244..ee4b16013aa 100644 --- a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeSessionListener.java @@ -26,25 +26,17 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; -import org.spongepowered.common.applaunch.test.TestGameAccess; -public class SpongeSessionListener implements LauncherSessionListener { - private ClassLoader previousLoader; +public final class SpongeSessionListener implements LauncherSessionListener { - @Override - public void launcherSessionOpened(final LauncherSession session) { - this.previousLoader = Thread.currentThread().getContextClassLoader(); + private final ClassLoader classLoader; - try { - Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public SpongeSessionListener() { + this.classLoader = Thread.currentThread().getContextClassLoader(); } @Override - public void launcherSessionClosed(final LauncherSession session) { - TestGameAccess.shutdownGame(); - Thread.currentThread().setContextClassLoader(this.previousLoader); + public void launcherSessionOpened(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.classLoader); } } diff --git a/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 00000000000..0609a02be3d --- /dev/null +++ b/neoforge/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1 @@ +org.spongepowered.neoforge.boot.SpongeLauncherInterceptor diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 86742047026..f655f9f873e 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -516,6 +516,7 @@ tasks { jvmArgs(runServer.allJvmArguments()) jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") + jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeLauncherInterceptor.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeLauncherInterceptor.java new file mode 100644 index 00000000000..17b36640b45 --- /dev/null +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeLauncherInterceptor.java @@ -0,0 +1,57 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.installer.test; + +import org.junit.platform.launcher.LauncherInterceptor; +import org.spongepowered.common.applaunch.test.TestGameAccess; + +public final class SpongeLauncherInterceptor implements LauncherInterceptor { + + private final ClassLoader classLoader; + + public SpongeLauncherInterceptor() { + try { + this.classLoader = SpongeTestBoot.getGameClassLoader(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public T intercept(final Invocation invocation) { + final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.classLoader); + try { + return invocation.proceed(); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + + @Override + public void close() { + TestGameAccess.shutdownGame(); + } +} diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java index 1c7252550ab..2d51c08dacb 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/test/SpongeSessionListener.java @@ -26,25 +26,17 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; -import org.spongepowered.common.applaunch.test.TestGameAccess; -public class SpongeSessionListener implements LauncherSessionListener { - private ClassLoader previousLoader; +public final class SpongeSessionListener implements LauncherSessionListener { - @Override - public void launcherSessionOpened(final LauncherSession session) { - this.previousLoader = Thread.currentThread().getContextClassLoader(); + private final ClassLoader classLoader; - try { - Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public SpongeSessionListener() { + this.classLoader = Thread.currentThread().getContextClassLoader(); } @Override - public void launcherSessionClosed(final LauncherSession session) { - TestGameAccess.shutdownGame(); - Thread.currentThread().setContextClassLoader(this.previousLoader); + public void launcherSessionOpened(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.classLoader); } } diff --git a/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 00000000000..7dae4954143 --- /dev/null +++ b/vanilla/src/installer/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1 @@ +org.spongepowered.vanilla.installer.test.SpongeLauncherInterceptor diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeLauncherInterceptor.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeLauncherInterceptor.java new file mode 100644 index 00000000000..48b33f6bd2a --- /dev/null +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeLauncherInterceptor.java @@ -0,0 +1,57 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.boot; + +import org.junit.platform.launcher.LauncherInterceptor; +import org.spongepowered.common.applaunch.test.TestGameAccess; + +public final class SpongeLauncherInterceptor implements LauncherInterceptor { + + private final ClassLoader classLoader; + + public SpongeLauncherInterceptor() { + try { + this.classLoader = SpongeTestBoot.getGameClassLoader(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public T intercept(final Invocation invocation) { + final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.classLoader); + try { + return invocation.proceed(); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + + @Override + public void close() { + TestGameAccess.shutdownGame(); + } +} diff --git a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java index df8888cb032..1d34fb154ab 100644 --- a/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java +++ b/vanilla/src/test/java/org/spongepowered/vanilla/boot/SpongeSessionListener.java @@ -26,25 +26,17 @@ import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; -import org.spongepowered.common.applaunch.test.TestGameAccess; -public class SpongeSessionListener implements LauncherSessionListener { - private ClassLoader previousLoader; +public final class SpongeSessionListener implements LauncherSessionListener { - @Override - public void launcherSessionOpened(final LauncherSession session) { - this.previousLoader = Thread.currentThread().getContextClassLoader(); + private final ClassLoader classLoader; - try { - Thread.currentThread().setContextClassLoader(SpongeTestBoot.getGameClassLoader()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public SpongeSessionListener() { + this.classLoader = Thread.currentThread().getContextClassLoader(); } @Override - public void launcherSessionClosed(final LauncherSession session) { - TestGameAccess.shutdownGame(); - Thread.currentThread().setContextClassLoader(this.previousLoader); + public void launcherSessionOpened(final LauncherSession session) { + Thread.currentThread().setContextClassLoader(this.classLoader); } } diff --git a/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 00000000000..d40fb2198f3 --- /dev/null +++ b/vanilla/src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1 @@ +org.spongepowered.vanilla.boot.SpongeLauncherInterceptor From 88411b542b8c5bb186e5725f84a16ae1c7607c23 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 10 Sep 2025 20:36:44 +0300 Subject: [PATCH 343/586] Re-enable bunch of disabled tests --- .../tracking/context/StubPhaseState.java | 5 + .../GameTransactionIteratorTest.java | 130 +++++++++--------- .../spongepowered/common/mixin/MixinTest.java | 2 - .../common/registry/RegistryTest.java | 7 +- .../VolumeTransformationTest.java | 16 ++- 5 files changed, 84 insertions(+), 76 deletions(-) diff --git a/src/test/java/org/spongepowered/common/event/tracking/context/StubPhaseState.java b/src/test/java/org/spongepowered/common/event/tracking/context/StubPhaseState.java index d85ce7a0564..f1e013545b3 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/context/StubPhaseState.java +++ b/src/test/java/org/spongepowered/common/event/tracking/context/StubPhaseState.java @@ -56,5 +56,10 @@ static final class StubContext extends PhaseContext { ) { super(state, tracker); } + + @Override + protected boolean isRunaway(final PhaseContext phaseContext) { + return false; + } } } diff --git a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java index 25c47a6ad0e..c71fafba96d 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java +++ b/src/test/java/org/spongepowered/common/event/tracking/context/transaction/GameTransactionIteratorTest.java @@ -26,7 +26,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -39,7 +38,6 @@ import java.util.Iterator; import java.util.stream.Stream; -@Disabled public class GameTransactionIteratorTest { @Test @@ -76,35 +74,35 @@ public static Stream verifyDeeplyNestedIterator() { public void verifyDeeplyNestedIterator(final int effectCount, final int childCount) { final StubTransaction parent = new StubTransaction(); final StubTransaction[][] children = new StubTransaction[effectCount][childCount]; - final PhaseContext<@NonNull ?> phaseContext = StubPhaseState.getInstance().createPhaseContext(PhaseTracker.getInstance()); - phaseContext.buildAndSwitch(); - for (int i = 0; i < effectCount; i++) { - final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( - InventoryEffect.getInstance()); - parent.addLast(effect); - for (int j = 0; j < childCount; j++) { - final StubTransaction child = new StubTransaction(String.format("effect[%d]child[%d]", i, j)); - children[i][j] = child; - effect.addChild(phaseContext, child); + try (final PhaseContext<@NonNull ?> phaseContext = StubPhaseState.getInstance().createPhaseContext(PhaseTracker.getInstance())) { + phaseContext.buildAndSwitch(); + for (int i = 0; i < effectCount; i++) { + final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( + InventoryEffect.getInstance()); + parent.addLast(effect); + for (int j = 0; j < childCount; j++) { + final StubTransaction child = new StubTransaction(String.format("effect[%d]child[%d]", i, j)); + children[i][j] = child; + effect.addChild(phaseContext, child); + } } - } - final Iterator> iterator = parent.childIterator(); - for (int i = 0; i < effectCount; i++) { - Assertions.assertTrue(iterator.hasNext()); - for (int j = 0; j < childCount; j++) { + final Iterator> iterator = parent.childIterator(); + for (int i = 0; i < effectCount; i++) { Assertions.assertTrue(iterator.hasNext()); - final GameTransaction<@NonNull ?> next = iterator.next(); - Assertions.assertEquals(children[i][j], next); + for (int j = 0; j < childCount; j++) { + Assertions.assertTrue(iterator.hasNext()); + final GameTransaction<@NonNull ?> next = iterator.next(); + Assertions.assertEquals(children[i][j], next); + } } - } - final Iterator> reverseIterator = parent.reverseChildIterator(); - for (int i = effectCount - 1; i >= 0; i--) { - for (int j = childCount - 1; j >= 0; j--) { - Assertions.assertTrue(reverseIterator.hasNext()); - final GameTransaction<@NonNull ?> previous = reverseIterator.next(); - Assertions.assertEquals(children[i][j], previous); + final Iterator> reverseIterator = parent.reverseChildIterator(); + for (int i = effectCount - 1; i >= 0; i--) { + for (int j = childCount - 1; j >= 0; j--) { + Assertions.assertTrue(reverseIterator.hasNext()); + final GameTransaction<@NonNull ?> previous = reverseIterator.next(); + Assertions.assertEquals(children[i][j], previous); + } } - } } @@ -112,8 +110,7 @@ private static Stream validateTransactionalIterator() { return Stream.of( Arguments.of(1, 1, 1), Arguments.of(4, 3, 5), - Arguments.of(8, 39, 29), - Arguments.of(293, 87, 112) + Arguments.of(8, 39, 29) ); } @@ -123,57 +120,58 @@ private static Stream validateTransactionalIterator() { public void validateTransactionalIterator(final int transactionCount, final int effectCount, final int childCount) { final StubTransaction[][][] children = new StubTransaction[transactionCount][effectCount][childCount]; final StubTransaction[] transactions = new StubTransaction[transactionCount]; - final PhaseContext<@NonNull ?> phaseContext = StubPhaseState.getInstance().createPhaseContext(PhaseTracker.getInstance()); - phaseContext.buildAndSwitch(); - final TransactionalCaptureSupplier transactor = phaseContext.getTransactor(); + try (final PhaseContext<@NonNull ?> phaseContext = StubPhaseState.getInstance().createPhaseContext(PhaseTracker.getInstance())) { + phaseContext.buildAndSwitch(); + final TransactionalCaptureSupplier transactor = phaseContext.getTransactor(); - for (int t = 0; t < transactionCount; t++) { - final StubTransaction transaction = new StubTransaction("transaction[" + t + "]"); - transactions[t] = transaction; - transactor.logTransaction(transaction); - for (int i = 0; i < effectCount; i++) { - final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( - InventoryEffect.getInstance()); - try (final EffectTransactor ignored = transactor.pushEffect(effect)) { - for (int j = 0; j < childCount; j++) { - final StubTransaction child = new StubTransaction(String.format("effect[%d]child[%d]", i, j)); - children[t][i][j] = child; - transactor.logTransaction(child); + for (int t = 0; t < transactionCount; t++) { + final StubTransaction transaction = new StubTransaction("transaction[" + t + "]"); + transactions[t] = transaction; + transactor.logTransaction(transaction); + for (int i = 0; i < effectCount; i++) { + final ResultingTransactionBySideEffect effect = new ResultingTransactionBySideEffect<>( + InventoryEffect.getInstance()); + try (final EffectTransactor ignored = transactor.pushEffect(effect)) { + for (int j = 0; j < childCount; j++) { + final StubTransaction child = new StubTransaction(String.format("effect[%d]child[%d]", i, j)); + children[t][i][j] = child; + transactor.logTransaction(child); + } } } } - } - final Iterator> iterator = transactor.iterator(); + final Iterator> iterator = transactor.iterator(); - for (int t = 0; t < transactionCount; t++) { - Assertions.assertTrue(iterator.hasNext()); - final StubTransaction parent = transactions[t]; - Assertions.assertEquals(parent, iterator.next()); - for (int i = 0; i < effectCount; i++) { + for (int t = 0; t < transactionCount; t++) { Assertions.assertTrue(iterator.hasNext()); - for (int j = 0; j < childCount; j++) { + final StubTransaction parent = transactions[t]; + Assertions.assertEquals(parent, iterator.next()); + for (int i = 0; i < effectCount; i++) { Assertions.assertTrue(iterator.hasNext()); - final GameTransaction<@NonNull ?> next = iterator.next(); - Assertions.assertEquals(children[t][i][j], next); + for (int j = 0; j < childCount; j++) { + Assertions.assertTrue(iterator.hasNext()); + final GameTransaction<@NonNull ?> next = iterator.next(); + Assertions.assertEquals(children[t][i][j], next); + } } } - } - Assertions.assertFalse(iterator.hasNext()); + Assertions.assertFalse(iterator.hasNext()); - final Iterator> reverseIterator = transactor.descendingIterator(); + final Iterator> reverseIterator = transactor.descendingIterator(); - for (int t = transactionCount - 1; t >= 0; t--) { - for (int i = effectCount - 1; i >= 0; i--) { - for (int j = childCount - 1; j >= 0; j--) { - final GameTransaction<@NonNull ?> next = reverseIterator.next(); - Assertions.assertEquals(children[t][i][j], next); + for (int t = transactionCount - 1; t >= 0; t--) { + for (int i = effectCount - 1; i >= 0; i--) { + for (int j = childCount - 1; j >= 0; j--) { + final GameTransaction<@NonNull ?> next = reverseIterator.next(); + Assertions.assertEquals(children[t][i][j], next); + } } + Assertions.assertTrue(reverseIterator.hasNext()); + final StubTransaction parent = transactions[t]; + Assertions.assertEquals(parent, reverseIterator.next()); } - Assertions.assertTrue(reverseIterator.hasNext()); - final StubTransaction parent = transactions[t]; - Assertions.assertEquals(parent, reverseIterator.next()); + Assertions.assertFalse(reverseIterator.hasNext()); } - Assertions.assertFalse(reverseIterator.hasNext()); } } diff --git a/src/test/java/org/spongepowered/common/mixin/MixinTest.java b/src/test/java/org/spongepowered/common/mixin/MixinTest.java index d7b0811f417..b3564fc8a4f 100644 --- a/src/test/java/org/spongepowered/common/mixin/MixinTest.java +++ b/src/test/java/org/spongepowered/common/mixin/MixinTest.java @@ -24,13 +24,11 @@ */ package org.spongepowered.common.mixin; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.spongepowered.asm.mixin.MixinEnvironment; public class MixinTest { - @Disabled @Test public void auditMixins() { // Ensure all Mixins apply without error diff --git a/src/test/java/org/spongepowered/common/registry/RegistryTest.java b/src/test/java/org/spongepowered/common/registry/RegistryTest.java index 7622087b8ff..dee259942b5 100644 --- a/src/test/java/org/spongepowered/common/registry/RegistryTest.java +++ b/src/test/java/org/spongepowered/common/registry/RegistryTest.java @@ -28,11 +28,13 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; import com.google.common.reflect.TypeToken; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.registrar.tree.CommandCompletionProviders; +import org.spongepowered.api.data.type.BoatTypes; import org.spongepowered.api.registry.*; import org.spongepowered.api.util.annotation.CatalogedBy; @@ -88,10 +90,10 @@ private static Stream streamDefaultedReferenceFields() { .filter(field -> isPublicStatic(field) && DefaultedRegistryReference.class.isAssignableFrom(field.getType())); } - @Disabled @TestFactory public Stream generateDefaultedReferenceTests() { return RegistryTest.streamDefaultedReferenceFields().map(field -> { + Assumptions.assumeFalse(field.getDeclaringClass() == BoatTypes.class || field.getDeclaringClass() == CommandCompletionProviders.class); final String name = "Field " + field.getDeclaringClass().getSimpleName() + "#" + field.getName(); return dynamicTest(name, () -> { final DefaultedRegistryReference ref = (DefaultedRegistryReference) field.get(null); @@ -111,7 +113,6 @@ private static Stream> streamApiInterfaces(final Object instance) { .filter(clazz -> clazz.getName().startsWith("org.spongepowered.api.")); } - @Disabled @TestFactory public Stream generateMethodTests() { return RegistryTest.streamRegistries().flatMap(Registry::streamEntries) diff --git a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java index 8853e8fb264..759ba182b96 100644 --- a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java +++ b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java @@ -25,7 +25,6 @@ package org.spongepowered.common.util.transformation; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -34,9 +33,12 @@ import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.block.entity.BlockEntityArchetype; +import org.spongepowered.api.block.entity.BlockEntityTypes; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataQuery; +import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.util.rotation.Rotation; import org.spongepowered.api.util.rotation.Rotations; @@ -52,7 +54,6 @@ import java.util.Optional; import java.util.stream.Stream; -@Disabled @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) public final class VolumeTransformationTest { @@ -152,14 +153,18 @@ private static SpongeArchetypeVolume fillVolume(final Vector3i min, final Vector final Vector3i rawMax = max.max(min); final Vector3i size = rawMax.sub(rawMin).add(Vector3i.ONE); final Vector3i relativeMin = rawMin.sub(origin); - final RegistryHolder holder = Sponge.game(); + final RegistryHolder holder = Sponge.server(); final SpongeArchetypeVolume volume = new SpongeArchetypeVolume(relativeMin, size, holder); final Vector3i volMax = volume.max().add(Vector3i.ONE); for (int x = relativeMin.x(); x < volMax.x(); x++) { for (int z = relativeMin.z(); z < volMax.z(); z++) { for (int y = relativeMin.y(); y < volMax.y(); y++) { - volume.addBlockEntity(x, y, z, BlockEntityArchetype.builder().blockEntityData(DataContainer.createNew().set(VolumeTransformationTest.POS, new Vector3i(x, y, z))).build()); + volume.addBlockEntity(x, y, z, BlockEntityArchetype.builder() + .state(BlockTypes.CHEST.get().defaultState()) + .blockEntity(BlockEntityTypes.CHEST.get()) + .blockEntityData(DataContainer.createNew().set(VolumeTransformationTest.POS, new Vector3i(x, y, z))) + .build()); } } } @@ -239,7 +244,8 @@ void testTransformationsOfPositions( .sub(VolumePositionTranslators.BLOCK_OFFSET); final Vector3i invertedBlockPos = invertedTransformedPos.toInt(); - final Vector3i expectedPos = (Vector3i) entity.blockEntityData().get(VolumeTransformationTest.POS).get(); + final DataView posView = entity.blockEntityData().getView(VolumeTransformationTest.POS).get(); + final Vector3i expectedPos = new Vector3i(posView.getInt(DataQuery.of("x")).get(), posView.getInt(DataQuery.of("y")).get(), posView.getInt(DataQuery.of("z")).get()); Assertions.assertNotEquals( VolumeTransformationTest.INVALID_STUB_POSITION, From d77fe054578388b8f49fd42c176b7d678276d337 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 11 Sep 2025 22:53:46 +0200 Subject: [PATCH 344/586] Do not drop leash when removed by a plugin --- .../common/data/provider/entity/LeashableData.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java b/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java index c910e629552..ec41edfbcd6 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/LeashableData.java @@ -42,11 +42,10 @@ public static void register(final DataProviderRegistrator registrator) { final var ld = h.getLeashData(); return ld == null ? null : (Entity) ld.leashHolder; }) - .delete(Leashable::dropLeash) + .delete(Leashable::removeLeash) .set((h, v) -> { if (v == null) { - // TODO remove - h.dropLeash(); + h.removeLeash(); } else { h.setLeashedTo((net.minecraft.world.entity.Entity) v, true); } From e1ab86df6ebb78e222bf7965456cf950d98fcb15 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 12 Sep 2025 12:42:58 +0200 Subject: [PATCH 345/586] Fix DamageStep START being ignored --- .../entity/damage/SpongeAttackTracker.java | 6 +---- .../entity/damage/SpongeDamageTracker.java | 13 +++++------ .../entity/LivingEntityMixin_Damage.java | 2 +- .../LivingEntityMixin_Shared_Damage.java | 9 ++++++-- .../core/world/entity/MobMixin_Attack.java | 19 ++++++++-------- .../entity/player/PlayerMixin_Attack.java | 22 ++++++++----------- .../spongepowered/test/damage/DamageTest.java | 13 +++++++++++ .../LivingEntityMixin_Vanilla_Damage.java | 5 +++-- 8 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java index 820fbcd3a13..ba70165a969 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeAttackTracker.java @@ -105,7 +105,6 @@ public boolean callAttackPostEvent(final Entity entity, final DamageSource sourc } public static @Nullable SpongeAttackTracker callAttackPreEvent(final Entity entity, final DamageSource source, final float baseDamage, final ItemStack weapon) { - final SpongeAttackTracker tracker; try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { SpongeDamageTracker.generateCauseFor(source, frame); @@ -114,11 +113,8 @@ public boolean callAttackPostEvent(final Entity entity, final DamageSource sourc return null; } - tracker = new SpongeAttackTracker(event, source, weapon); + return new SpongeAttackTracker(event, source, weapon); } - - tracker.newStep(DamageStepTypes.START).apply(baseDamage); - return tracker; } public static @Nullable SpongeAttackTracker of(final DamageSource source) { diff --git a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java index a4492c6123f..0e5b27dfb5c 100644 --- a/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java +++ b/src/main/java/org/spongepowered/common/event/cause/entity/damage/SpongeDamageTracker.java @@ -148,6 +148,10 @@ public float damageAfter(final DefaultedRegistryReference typeRe return step == null ? 0 : (float) step.damageAfterChildren().orElse(0); } + public float applyStartStep() { + return (float) this.newStep(DamageStepTypes.START).apply(this.preEvent.baseDamage()); + } + public float callDamagePostEvent(final Entity entity, float finalDamage) { if (this.postEvent != null) { throw new IllegalStateException("Post event already fired"); @@ -186,7 +190,6 @@ protected static void generateCauseFor(final DamageSource source, final CauseSta } public static @Nullable SpongeDamageTracker callDamagePreEvent(final Entity entity, final DamageSource source, final float baseDamage) { - final SpongeDamageTracker tracker; try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { SpongeDamageTracker.generateCauseFor(source, frame); @@ -195,11 +198,8 @@ protected static void generateCauseFor(final DamageSource source, final CauseSta return null; } - tracker = new SpongeDamageTracker(event, source); + return new SpongeDamageTracker(event, source); } - - tracker.newStep(DamageStepTypes.START).apply(baseDamage); - return tracker; } public static DamageEntityEvent.@Nullable Post callDamageEvents(final Entity entity, final DamageSource source, final float baseDamage) { @@ -207,8 +207,7 @@ protected static void generateCauseFor(final DamageSource source, final CauseSta if (tracker == null) { return null; } - final DamageStep step = tracker.currentStep(DamageStepTypes.START); - final float finalDamage = step == null ? baseDamage : (float) step.damageAfterChildren().orElse(baseDamage); + final float finalDamage = tracker.applyStartStep(); tracker.callDamagePostEvent(entity, finalDamage); return (DamageEntityEvent.Post) tracker.postEvent; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index e2cbc64f6f8..55358120c57 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -87,7 +87,7 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li cir.setReturnValue(false); } else { this.damage$trackers.addLast(tracker); - this.damage$setContainerDamage((float) tracker.preEvent().baseDamage()); + this.damage$setContainerDamage(tracker.applyStartStep()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java index 206e6a53ee4..a37119cd297 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java @@ -34,6 +34,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.common.bridge.world.entity.TrackedDamageBridge; +import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageTracker; // Forge and Vanilla @@ -41,9 +42,13 @@ public abstract class LivingEntityMixin_Shared_Damage implements TrackedDamageBridge { @ModifyVariable(method = "hurtServer", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I"), argsOnly = true) - private float damage$setBaseDamage(final float damage) { + private float damage$modifyAfterStart(final float damage) { final SpongeDamageTracker tracker = this.damage$tracker(); - return tracker == null ? damage : (float) tracker.preEvent().baseDamage(); + if (tracker == null) { + return damage; + } + final SpongeDamageStep step = tracker.currentStep(DamageStepTypes.START); + return step == null ? damage : (float) step.damageAfterChildren().getAsDouble(); } @ModifyVariable(method = "actuallyHurt", at = @At("STORE"), argsOnly = true, slice = @Slice( diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java index 0c35598a428..c77f998bfb7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/MobMixin_Attack.java @@ -26,6 +26,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Cancellable; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -39,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; @@ -56,20 +56,21 @@ public abstract class MobMixin_Attack extends LivingEntityMixin_Damage implement return this.attack$trackers.peekLast(); } - @Inject( + @WrapOperation( method = "doHurtTarget", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;modifyDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), - cancellable = true, - locals = LocalCapture.CAPTURE_FAILHARD + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;modifyDamage(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;F)F") ) - private void attack$firePreEvent(final ServerLevel level, final Entity target, final CallbackInfoReturnable cir, - final float damage, final ItemStack weapon, final DamageSource source) { + private float attack$firePreEvent(final ServerLevel level, final ItemStack weapon, final Entity target, final DamageSource source, float damage, final Operation original, @Cancellable CallbackInfoReturnable cir) { final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); if (tracker == null) { cir.setReturnValue(false); - } else { - this.attack$trackers.addLast(tracker); + return damage; } + + this.attack$trackers.addLast(tracker); + damage = tracker.applyStartStep(); + + return original.call(level, weapon, target, source, damage); } @WrapOperation(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index c58ded67972..2241ed71bf5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -28,6 +28,8 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Cancellable; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.world.damagesource.DamageSource; @@ -50,7 +52,6 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; import org.spongepowered.common.event.cause.entity.damage.SpongeAttackTracker; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStep; @@ -77,22 +78,17 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return this.attack$trackers.peekLast(); } - @Inject(method = "attack", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0)) - private void attack$firePreEvent(final Entity target, final CallbackInfo ci, final float damage, final ItemStack weapon, final DamageSource source) { + @ModifyVariable(method = "attack", at = @At("LOAD"), + slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0))) + private float attack$firePreEvent(final float damage, @Local(argsOnly = true) final Entity target, @Local final DamageSource source, @Local final ItemStack weapon, final @Cancellable CallbackInfo ci) { final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); if (tracker == null) { ci.cancel(); - } else { - this.attack$trackers.addLast(tracker); + return damage; } - } - @ModifyVariable(method = "attack", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0)) - private float attack$setBaseDamage(final float damage) { - final SpongeAttackTracker tracker = this.attack$tracker(); - return tracker == null ? damage : (float) tracker.preEvent().baseDamage(); + this.attack$trackers.addLast(tracker); + return tracker.applyStartStep(); } @ModifyExpressionValue(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F")) @@ -245,7 +241,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem } this.attack$trackers.addLast(sweepTracker); - damage = (float) sweepTracker.preEvent().baseDamage(); + damage = sweepTracker.applyStartStep(); // In vanilla, this step is outside the loop, but we move it to here so it can be modified per target SpongeDamageStep step = sweepTracker.newStep(DamageStepTypes.SWEEPING, sweepTracker.weaponSnapshot()); diff --git a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java index afdcb5b27e9..e865f0a3037 100644 --- a/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/damage/DamageTest.java @@ -75,6 +75,8 @@ public class DamageTest implements LoadableModule { private static final ResourceKey EXHAUSTING_DAMAGE = ResourceKey.of("damagetest", "test"); + private static final DamageStepType START_BONUS = DamageStepType.create(); + private static final DamageStepType END_BONUS = DamageStepType.create(); private static final DamageStepType DOUBLE_CRITICAL = DamageStepType.create(); private static final DamageStepType DOUBLE_DOUBLE_CRITICAL = DamageStepType.create(); @@ -139,6 +141,8 @@ private void onRegisterTagEvent(final RegisterTagEvent event) { @Listener public void onRegisterDamageStepType(final RegisterRegistryValueEvent.GameScoped event) { event.registry(RegistryTypes.DAMAGE_STEP_TYPE, (r) -> { + r.register(ResourceKey.of(this.plugin, "start_bonus"), START_BONUS); + r.register(ResourceKey.of(this.plugin, "end_bonus"), END_BONUS); r.register(ResourceKey.of(this.plugin, "double_critical"), DOUBLE_CRITICAL); r.register(ResourceKey.of(this.plugin, "double_double_critical"), DOUBLE_DOUBLE_CRITICAL); }); @@ -169,6 +173,15 @@ private void onAttackPre(final AttackEntityEvent.Pre event) { DamageModifier.builder().type(DOUBLE_DOUBLE_CRITICAL).damageFunction((step, damage) -> damage * 2).build()); } + @Listener + private void onDamagePre(final DamageCalculationEvent.Pre event) { + event.addModifierBefore(DamageStepTypes.START, + DamageModifier.builder().type(START_BONUS).damageFunction((step, damage) -> damage + 1).build()); + + event.addModifierAfter(DamageStepTypes.END, + DamageModifier.builder().type(END_BONUS).damageFunction((step, damage) -> damage + 1).build()); + } + @Listener private void onDamagePre(final DamageCalculationEvent.Pre event, @Root final DamageSource damageSource) { final Component eventName = event instanceof AttackEntityEvent ? diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java index e50181c6f12..06552deeb72 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java @@ -25,6 +25,7 @@ package org.spongepowered.vanilla.mixin.core.world.entity; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.animal.Wolf; @@ -46,7 +47,7 @@ public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageBridge { @ModifyExpressionValue(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isDamageSourceBlocked(Lnet/minecraft/world/damagesource/DamageSource;)Z")) - private boolean damage$modifyBeforeAndAfterShield(final boolean original) { + private boolean damage$modifyBeforeAndAfterShield(final boolean original, @Local(argsOnly = true) final float damage) { if (!original) { return false; } @@ -57,7 +58,7 @@ public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageB } final SpongeDamageStep step = tracker.newStep(DamageStepTypes.SHIELD, ItemStackUtil.snapshotOf(((LivingEntity) (Object) this).getUseItem())); - step.applyChildrenBefore((float) tracker.preEvent().baseDamage()); + step.applyChildrenBefore(damage); step.applyChildrenAfter(0); return !step.isSkipped(); } From f1637bc5873d89efe883d0b9df18a200c4ad0a0a Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 13 Sep 2025 20:04:27 +0300 Subject: [PATCH 346/586] Implement BiGenericEvent --- SpongeAPI | 2 +- .../common/event/manager/EventType.java | 9 +- .../event/manager/ListenerClassVisitor.java | 85 +++++++++++-------- .../event/manager/SpongeEventManager.java | 37 +++++--- .../common/util/TypeTokenUtil.java | 8 ++ 5 files changed, 90 insertions(+), 51 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 62832193efb..0884da8dc69 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 62832193efb6b49e4e9a7967ed95d3251ad2409a +Subproject commit 0884da8dc69f6439930d2cf0e28168f275db9413 diff --git a/src/main/java/org/spongepowered/common/event/manager/EventType.java b/src/main/java/org/spongepowered/common/event/manager/EventType.java index bdeb2eee17a..687d7cc01be 100644 --- a/src/main/java/org/spongepowered/common/event/manager/EventType.java +++ b/src/main/java/org/spongepowered/common/event/manager/EventType.java @@ -24,20 +24,21 @@ */ package org.spongepowered.common.event.manager; +import io.leangen.geantyref.TypeToken; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.Event; -import java.lang.reflect.Type; +import java.util.List; import java.util.Objects; public final class EventType { private final Class eventType; - private final @Nullable Type genericType; + private final @Nullable List> genericType; private int hashCode; - EventType(final Class eventType, final @Nullable Type genericType) { + EventType(final Class eventType, final @Nullable List> genericType) { this.genericType = genericType; this.eventType = eventType; } @@ -50,7 +51,7 @@ public Class getType() { return this.eventType; } - public @Nullable Type getGenericType() { + public @Nullable List> getGenericType() { return this.genericType; } diff --git a/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java b/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java index 00cd7e9cfd8..6a0e523db70 100644 --- a/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java +++ b/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java @@ -135,7 +135,7 @@ public void visitLocalVariable( return; } if (signature != null) { // We only care about the first parameter - new SignatureReader(signature).accept(new ListenerSignatureVisitor(parameter)); + new SignatureReader(signature).accept(new ListenerSignatureVisitor(parameter).visitParameterType()); } else if (this.discoveredMethod.signature != null) { // In some compiled languages, the local variable signature is // not available, but we can still grab it from the method's @@ -194,8 +194,7 @@ public AnnotationVisitor visitParameterAnnotation( static final class ListenerSignatureVisitor extends SignatureVisitor { private final ListenerParameter parameter; - private boolean secondType = true; - private boolean isGeneric = false; + private State state; public ListenerSignatureVisitor(final ListenerParameter parameter) { super(ListenerClassVisitor.ASM_VERSION); @@ -203,42 +202,49 @@ public ListenerSignatureVisitor(final ListenerParameter parameter) { } @Override - public void visitClassType(final String name) { - // The order of operations is that visitClassType gets called - // twice, once for the generic class, then a second time for - // the generic type. Ideally we don't have to deal with additional - // nested types, but if we do, well, we'll just ignore them. + public SignatureVisitor visitParameterType() { + this.state = State.PARSING; + return this; + } - // Only accept the first and second type - if (!secondType) { - return; - } - // The first type will be base type - if (this.parameter.baseType == null) { - this.parameter.baseType = Type.getType("L" + name + ";"); - return; - } - // The second type will be generic type or ignore - else if (isGeneric && this.parameter.genericType == null) { - this.parameter.genericType = Type.getType("L" + name + ";"); + @Override + public void visitClassType(final String name) { + if (this.state == State.PARSING) { + if (this.parameter.baseType == null) { + this.parameter.baseType = Type.getType("L" + name + ";"); + } + } else if (this.state == State.GENERIC) { + this.parameter.genericTypes.add(new ListenerParameter.GenericType(Type.getType("L" + name + ";"))); } - // Ignore after second type - secondType = false; } @Override public void visitTypeArgument() { // And sometimes, some plugins just care about the parent type // and wildcard their bounds. - this.parameter.wildcard = true; + if (this.state == State.PARSING) { + this.parameter.genericTypes.add(new ListenerParameter.GenericType(null)); + } } @Override - public SignatureVisitor visitTypeArgument(char wildcard) { - // For treating the second type as generic - this.isGeneric = true; + public SignatureVisitor visitTypeArgument(final char wildcard) { + if (this.state == State.PARSING) { + this.state = State.GENERIC; + } return this; } + + @Override + public void visitEnd() { + this.state = this.state == State.GENERIC ? State.PARSING : State.DONE; + } + + private enum State { + PARSING, + GENERIC, + DONE + } } static final class ListenerAnnotationVisitor extends AnnotationVisitor { @@ -280,7 +286,7 @@ static final class ListenerExtractor extends AnnotationVisitor { private final DiscoveredMethod discoveredMethod; public ListenerExtractor( - final ListenerClassVisitor.DiscoveredMethod discoveredMethod + final DiscoveredMethod discoveredMethod ) { super(ListenerClassVisitor.ASM_VERSION); this.discoveredMethod = discoveredMethod; @@ -439,15 +445,15 @@ public static final class ListenerParameter { private final DiscoveredMethod method; private final Type type; private final List annotations; - public boolean wildcard = false; @MonotonicNonNull Type baseType; - @MonotonicNonNull Type genericType; + List genericTypes; @MonotonicNonNull String name; ListenerParameter(final DiscoveredMethod method, final Type type) { this.method = method; this.type = type; this.annotations = new LinkedList<>(); + this.genericTypes = new LinkedList<>(); } public Class clazz() throws ClassNotFoundException { @@ -490,15 +496,22 @@ public int hashCode() { } public java.lang.reflect.Type genericType() throws ClassNotFoundException { - if (this.genericType == null) { - if (this.wildcard) { - return TypeFactory.parameterizedClass(this.clazz(), TypeFactory.unboundWildcard()); - } + if (this.genericTypes.isEmpty()) { return TypeFactory.parameterizedClass(this.clazz()); } - final Class gClazz = this.method.classByLoader(this.genericType.getClassName()); -// final java.lang.reflect.Type generic = TypeFactory.parameterizedClass(gClazz); - return TypeFactory.parameterizedClass(this.clazz(), gClazz); + final java.lang.reflect.Type[] classes = new java.lang.reflect.Type[this.genericTypes.size()]; + for (int i = 0; i < classes.length; i++) { + final GenericType type = this.genericTypes.get(i); + if (type.type() != null) { + classes[i] = this.method.classByLoader(type.type().getClassName()); + } else { + classes[i] = TypeFactory.unboundWildcard(); + } + } + return TypeFactory.parameterizedClass(this.clazz(), classes); + } + + record GenericType(@Nullable Type type) { } } diff --git a/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java b/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java index 8dbdf82b0c2..0f13cb09912 100644 --- a/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java +++ b/src/main/java/org/spongepowered/common/event/manager/SpongeEventManager.java @@ -29,9 +29,11 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import io.leangen.geantyref.GenericTypeReflector; +import io.leangen.geantyref.TypeToken; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.BiGenericEvent; import org.spongepowered.api.event.Cancellable; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.Event; @@ -61,6 +63,7 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -125,14 +128,20 @@ public SpongeEventManager() { @SuppressWarnings({"unchecked", "rawtypes"}) private static RegisteredListener createRegistration(final PluginContainer plugin, final Type eventType, final Order order, final boolean beforeModifications, final EventListener handler) { - @Nullable Type genericType = null; + @Nullable List> genericType = null; final Class erased = GenericTypeReflector.erase(eventType); - if (GenericEvent.class.isAssignableFrom(erased)) { - genericType = TypeTokenUtil.typeArgumentFromSupertype(eventType, GenericEvent.class, 0); + if (BiGenericEvent.class.isAssignableFrom(erased)) { + genericType = SpongeEventManager.typeArgumentsFromSupertype(eventType, BiGenericEvent.class); + } else if (GenericEvent.class.isAssignableFrom(erased)) { + genericType = SpongeEventManager.typeArgumentsFromSupertype(eventType, GenericEvent.class); } return new RegisteredListener(plugin, new EventType(erased, genericType), order, handler, beforeModifications); } + private static List> typeArgumentsFromSupertype(final Type sub, final Class superType) { + return Arrays.stream(TypeTokenUtil.typeArgumentsFromSupertype(sub, superType)).map(TypeToken::get).toList(); + } + RegisteredListener.Cache bakeHandlers(final EventType eventType) { final List> handlers = new ArrayList<>(); final Stream> types = Types.allSuperTypesAndInterfaces(eventType.getType()) @@ -146,12 +155,20 @@ RegisteredListener.Cache bakeHandlers(final EventType event final Class type = it.next(); final Collection> listeners = this.handlersByEvent.get(type); if (GenericEvent.class.isAssignableFrom(type)) { - final Type genericType = Objects.requireNonNull(eventType.getGenericType()); - for (final RegisteredListener listener : listeners) { - final Type genericType1 = Objects.requireNonNull(listener.getEventType().getGenericType()); - if (TypeTokenUtil.isAssignable(genericType, genericType1)) { - handlers.add(listener); + final List> eventGenericTypes = Objects.requireNonNull(eventType.getGenericType()); + listeners: for (final RegisteredListener listener : listeners) { + final List> listenerGenericTypes = Objects.requireNonNull(listener.getEventType().getGenericType()); + if (eventGenericTypes.size() != listenerGenericTypes.size()) { + continue; + } + for (int i = 0; i < eventGenericTypes.size(); i++) { + final TypeToken eventGenericType = Objects.requireNonNull(eventGenericTypes.get(i)); + final TypeToken listenerGenericType = Objects.requireNonNull(listenerGenericTypes.get(i)); + if (!TypeTokenUtil.isAssignable(eventGenericType.getType(), listenerGenericType.getType())) { + continue listeners; + } } + handlers.add(listener); } } else { handlers.addAll(listeners); @@ -355,8 +372,8 @@ public SpongeEventManager unregisterListeners(final Object obj) { protected RegisteredListener.Cache getHandlerCache(final Event event) { final Class eventClass = Objects.requireNonNull(event, "event").getClass(); final EventType eventType; - if (event instanceof GenericEvent) { - eventType = new EventType(eventClass, Objects.requireNonNull(((GenericEvent) event).paramType().getType())); + if (event instanceof GenericEvent genericEvent) { + eventType = new EventType(eventClass, Objects.requireNonNull(genericEvent.paramTypes())); } else { eventType = new EventType(eventClass, null); } diff --git a/src/main/java/org/spongepowered/common/util/TypeTokenUtil.java b/src/main/java/org/spongepowered/common/util/TypeTokenUtil.java index 1dadf6d8ac1..cc7941a26b1 100644 --- a/src/main/java/org/spongepowered/common/util/TypeTokenUtil.java +++ b/src/main/java/org/spongepowered/common/util/TypeTokenUtil.java @@ -56,6 +56,14 @@ public static Type requireCompleteGenerics(final Type input) { return input; } + public static Type[] typeArgumentsFromSupertype(final Type sub, final Class superType) { + final Type calculatedSuper = GenericTypeReflector.getExactSuperType(sub, superType); + if (!(calculatedSuper instanceof ParameterizedType)) { + throw new IllegalArgumentException("Calculated supertype " + calculatedSuper + " of original type " + sub + " is not parameterized"); + } + return ((ParameterizedType) calculatedSuper).getActualTypeArguments(); + } + /** * Given a known declared subtype, determine the value of a specific type parameter in a supertype. * From 3d13ecbf8620f7212a7a22ea6b05911fc62f66fa Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 13 Sep 2025 20:07:47 +0300 Subject: [PATCH 347/586] Decouple server service scope from MinecraftServer --- SpongeAPI | 2 +- .../spongepowered/forge/SpongeForgeMod.java | 2 - .../ReloadableServerResourcesMixin_Forge.java | 56 +++++++++++++++++ .../resources/mixins.spongeforge.core.json | 1 + .../spongepowered/neoforge/SpongeNeoMod.java | 2 - .../ReloadableServerResourcesMixin_Neo.java | 56 +++++++++++++++++ .../resources/mixins.spongeneo.core.json | 1 + .../server/ServerFunctionManagerAccessor.java | 36 ----------- .../resources/mixins.sponge.accessors.json | 1 - .../common/launch/Lifecycle.java | 2 +- .../spongepowered/common/SpongeLifecycle.java | 8 ++- .../commands/CommandSourceStackBridge.java | 3 + .../bridge/server/MinecraftServerBridge.java | 4 -- .../resources/ResourceManagerBridge.java | 5 ++ .../DelegatingCommandDispatcher.java | 11 ++++ .../dispatcher/SpongeNodePermissionCache.java | 3 +- .../AbstractProvideServiceEventImpl.java | 20 +++---- .../SpongeServerScopedServiceProvider.java | 7 +-- .../server/permission/SpongePermissions.java | 4 +- .../core/commands/CommandFunctionMixin.java | 60 +++++++++++++++++++ .../commands/CommandSourceStackMixin.java | 19 +++++- .../core/server/MinecraftServerMixin.java | 21 +------ .../server/ServerFunctionLibraryMixin.java | 49 --------------- .../mixin/core/server/WorldLoaderMixin.java | 1 + .../MultiPackResourceManagerMixin.java | 12 ++++ src/mixins/resources/mixins.sponge.core.json | 2 +- .../server/IntegratedServerMixin_Vanilla.java | 2 - ...eloadableServerResourcesMixin_Vanilla.java | 56 +++++++++++++++++ .../DedicatedServerMixin_Vanilla.java | 2 - .../resources/mixins.spongevanilla.core.json | 3 +- 30 files changed, 305 insertions(+), 146 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/server/ServerFunctionManagerAccessor.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java diff --git a/SpongeAPI b/SpongeAPI index 0884da8dc69..a22a428744e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 0884da8dc69f6439930d2cf0e28168f275db9413 +Subproject commit a22a428744e471d475d41152613e28fa7922b21a diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index 9731d6c632f..d1265f4510c 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -95,8 +95,6 @@ public void onServerAboutToStart(final ServerAboutToStartEvent event) { ConfigHandle.setSaveSuppressed(false); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(); - lifecycle.establishServerFeatures(); lifecycle.callStartingEngineEvent((Server) event.getServer()); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java new file mode 100644 index 00000000000..2d4516bc38d --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.server; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.commands.Commands; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.flag.FeatureFlagSet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; +import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; + +import java.util.List; + +@Mixin(ReloadableServerResources.class) +public abstract class ReloadableServerResourcesMixin_Forge { + + @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) + private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); + if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); + } + return instance; + } +} diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 1c0b3e43166..b0bfc163d4a 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -26,6 +26,7 @@ "resources.RegistryDataLoaderMixin_Forge", "server.BootstrapMixin_Forge", "server.MinecraftServerMixin_Forge", + "server.ReloadableServerResourcesMixin_Forge", "server.commands.SpreadPlayersCommandMixin_Forge", "server.level.ServerPlayerMixin_Forge", "server.network.ServerGamePacketListenerImplMixin_Forge", diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java index 8620448462d..b79889aee68 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java @@ -90,8 +90,6 @@ public void onServerAboutToStart(final ServerAboutToStartEvent event) { ConfigHandle.setSaveSuppressed(false); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(); - lifecycle.establishServerFeatures(); lifecycle.callStartingEngineEvent((Server) event.getServer()); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java new file mode 100644 index 00000000000..0b0698bfb04 --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.server; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.commands.Commands; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.flag.FeatureFlagSet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; +import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; + +import java.util.List; + +@Mixin(ReloadableServerResources.class) +public abstract class ReloadableServerResourcesMixin_Neo { + + @WrapOperation(method = "lambda$loadResources$3", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) + private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); + if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); + } + return instance; + } +} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index f61741a8226..92619d57dfd 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -22,6 +22,7 @@ "resources.RegistryDataLoaderMixin_Neo", "server.BootstrapMixin_Neo", "server.MinecraftServerMixin_Neo", + "server.ReloadableServerResourcesMixin_Neo", "server.commands.SpreadPlayersCommandMixin_Neo", "server.level.ServerEntityMixin_Neo", "server.level.ServerPlayerMixin_Neo", diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/ServerFunctionManagerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/ServerFunctionManagerAccessor.java deleted file mode 100644 index 17a152c5425..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/server/ServerFunctionManagerAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.server; - -import net.minecraft.server.ServerFunctionLibrary; -import net.minecraft.server.ServerFunctionManager; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerFunctionManager.class) -public interface ServerFunctionManagerAccessor { - - @Accessor("library") ServerFunctionLibrary accessor$library(); -} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 6237bb15ce6..0f7b277d43f 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -36,7 +36,6 @@ "resources.ResourceKeyAccessor", "server.MinecraftServer_ReloadableResourcesAccessor", "server.MinecraftServerAccessor", - "server.ServerFunctionManagerAccessor", "server.level.ChunkMap_TrackedEntityAccessor", "server.level.ChunkMapAccessor", "server.level.ServerChunkCacheAccessor", diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 9f0654f6fcc..5bd760d1644 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -66,7 +66,7 @@ public interface Lifecycle { void establishGameServices(); - void establishServerServices(); + void establishServerServices(ResourceManager resourceManager); void establishServerFeatures(); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 0ddc1a9d09d..d3890b5d3d5 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -47,7 +47,6 @@ import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.applaunch.plugin.DummyPluginContainer; import org.spongepowered.common.bridge.core.WritableRegistryBridge; -import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.event.lifecycle.AbstractRegisterRegistryEvent; @@ -69,6 +68,7 @@ import org.spongepowered.common.registry.SpongeRegistryHolder; import org.spongepowered.common.scheduler.AsyncScheduler; import org.spongepowered.common.service.SpongeServiceProvider; +import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.service.server.permission.SpongeContextCalculator; import org.spongepowered.plugin.PluginContainer; @@ -174,8 +174,10 @@ public void establishGameServices() { } @Override - public void establishServerServices() { - ((MinecraftServerBridge) this.game.server()).bridge$initServices(this.game, this.injector); + public void establishServerServices(final ResourceManager resourceManager) { + final SpongeServerScopedServiceProvider serviceProvider = new SpongeServerScopedServiceProvider(this.game, this.injector); + serviceProvider.init(); + ((ResourceManagerBridge) resourceManager).bridge$services(serviceProvider); } @Override diff --git a/src/main/java/org/spongepowered/common/bridge/commands/CommandSourceStackBridge.java b/src/main/java/org/spongepowered/common/bridge/commands/CommandSourceStackBridge.java index bb0c9c5b666..301d235f029 100644 --- a/src/main/java/org/spongepowered/common/bridge/commands/CommandSourceStackBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/commands/CommandSourceStackBridge.java @@ -29,6 +29,7 @@ import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.service.permission.PermissionService; import java.util.function.Supplier; @@ -47,4 +48,6 @@ public interface CommandSourceStackBridge { void bridge$setCause(Cause build); void bridge$setPotentialPermissionNode(@Nullable Supplier permission); + + void bridge$permissionService(PermissionService permissionService); } diff --git a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java index a3a3a31a5ac..c9312514148 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java @@ -24,11 +24,9 @@ */ package org.spongepowered.common.bridge.server; -import com.google.inject.Injector; import net.kyori.adventure.resource.ResourcePackRequest; import net.minecraft.util.thread.BlockableEventLoop; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.Game; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.common.registry.RegistryHolderLogic; import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; @@ -36,8 +34,6 @@ public interface MinecraftServerBridge { - void bridge$initServices(Game game, Injector injector); - SpongeServerScopedServiceProvider bridge$getServiceProvider(); @Nullable ResourcePackRequest bridge$getResourcePack(); diff --git a/src/main/java/org/spongepowered/common/bridge/server/packs/resources/ResourceManagerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/packs/resources/ResourceManagerBridge.java index 47ba38f97f2..da0676dc11e 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/packs/resources/ResourceManagerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/packs/resources/ResourceManagerBridge.java @@ -24,11 +24,16 @@ */ package org.spongepowered.common.bridge.server.packs.resources; +import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.tag.SpongePluginTags; public interface ResourceManagerBridge { void bridge$pluginProvidedTags(SpongePluginTags pluginTags); + void bridge$services(SpongeServerScopedServiceProvider services); + SpongePluginTags bridge$pluginProvidedTags(); + + SpongeServerScopedServiceProvider bridge$services(); } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/DelegatingCommandDispatcher.java b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/DelegatingCommandDispatcher.java index 533fea294b4..bd90dad1bc1 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/DelegatingCommandDispatcher.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/DelegatingCommandDispatcher.java @@ -36,6 +36,8 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandSourceStack; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.common.command.registrar.BrigadierCommandRegistrar; import java.util.Collection; @@ -44,6 +46,7 @@ public final class DelegatingCommandDispatcher extends CommandDispatcher { private final BrigadierCommandRegistrar brigadier; + @MonotonicNonNull private PermissionService permissionService; public DelegatingCommandDispatcher(final BrigadierCommandRegistrar brigadier) { this.brigadier = brigadier; @@ -124,4 +127,12 @@ public CommandNode findNode(final Collection path) { public void findAmbiguities(final AmbiguityConsumer consumer) { this.brigadier.getDispatcher().findAmbiguities(consumer); } + + public void permissionService(final PermissionService permissionService) { + this.permissionService = permissionService; + } + + public PermissionService permissionService() { + return this.permissionService; + } } diff --git a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java index 018e7377809..e8072a9dcf4 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java @@ -28,6 +28,7 @@ import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandSourceStack; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.common.SpongeCommon; @@ -64,7 +65,7 @@ public static boolean canUse( && ((CommandSourceStackBridge) source).bridge$getCommandSource() instanceof ServerPlayer) { // If the entity is a player, then we should try to add it anyway. final String permission = supplier.get(); - SpongePermissions.registerPermission(permission, 0); + SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), permission, 0); return ((CommandCause) source).hasPermission(permission); } return result; diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractProvideServiceEventImpl.java b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractProvideServiceEventImpl.java index 6e159830d49..65428efd365 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractProvideServiceEventImpl.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractProvideServiceEventImpl.java @@ -73,27 +73,27 @@ public String toString() { } } - public static final class EngineScopedImpl extends AbstractProvideServiceEventImpl implements ProvideServiceEvent.EngineScoped{ + public static final class EngineScopedImpl extends AbstractProvideServiceEventImpl implements ProvideServiceEvent.EngineScoped{ - private final Engine engine; + private final TypeToken engineToken; - public EngineScopedImpl(final Cause cause, final Game game, final TypeToken token, final Engine engine) { + public EngineScopedImpl(final Cause cause, final Game game, final TypeToken token, final TypeToken engineToken) { super(cause, game, token); - this.engine = engine; + this.engineToken = engineToken; } @Override - public Engine engine() { - return this.engine; + public TypeToken secondaryParamType() { + return this.engineToken; } @Override public String toString() { return new StringJoiner(", ", EngineScopedImpl.class.getSimpleName() + "[", "]") - .add("cause=" + this.cause) - .add("token=" + this.token) - .add("engine=" + this.token) - .toString(); + .add("cause=" + this.cause) + .add("token=" + this.token) + .add("engine=" + this.token) + .toString(); } } } diff --git a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java index 845529e28d6..0668b3a6509 100644 --- a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java +++ b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java @@ -52,12 +52,9 @@ public final class SpongeServerScopedServiceProvider extends SpongeServiceProvider implements ServiceProvider.ServerScoped { - private final Server server; - @Inject - public SpongeServerScopedServiceProvider(final Server server, final Game game, final Injector injector) { + public SpongeServerScopedServiceProvider(final Game game, final Injector injector) { super(game, injector); - this.server = server; } @Override @@ -89,7 +86,7 @@ protected List> servicesToSelect() { @Override protected AbstractProvideServiceEventImpl createEvent(final PluginContainer container, final Service service) { return new AbstractProvideServiceEventImpl.EngineScopedImpl<>(Cause.of(EventContext.empty(), this.getGame()), - this.getGame(), TypeToken.get(service.getServiceClass()), this.server); + this.getGame(), TypeToken.get(service.getServiceClass()), TypeToken.get(Server.class)); } @Override diff --git a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java index 2ae631ee52e..814e55910d2 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.service.server.permission; -import org.spongepowered.api.Sponge; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.util.Tristate; @@ -57,9 +56,8 @@ public static void populateNonCommandPermissions(final SubjectData data, final B } } - public static void registerPermission(final String permissionNode, final int opLevel) { + public static void registerPermission(final PermissionService service, final String permissionNode, final int opLevel) { if (SpongePermissions.REGISTERED_PERMISSIONS.add(permissionNode)) { - final PermissionService service = Sponge.server().serviceProvider().permissionService(); if (opLevel == 0) { // register as a default permission service.defaults() diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java new file mode 100644 index 00000000000..3d691f183a8 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.commands; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.ExecutionCommandSource; +import net.minecraft.commands.functions.CommandFunction; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.service.permission.PermissionService; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.bridge.commands.CommandSourceStackBridge; +import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; +import org.spongepowered.common.event.tracking.PhaseTracker; + +import java.util.List; + +@Mixin(CommandFunction.class) +public interface CommandFunctionMixin { + + @WrapMethod(method = "fromLines") + private static > CommandFunction impl$onFromLines( + final ResourceLocation $$0, final CommandDispatcher $$1, final T $$2, final List $$3, final Operation> original) { + if ($$1 instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.pushCause(delegatingCommandDispatcher.permissionService().newSubjectReference(PermissionService.SUBJECTS_SYSTEM, "console").resolve().join()); + final CommandCause cause = ((CommandSourceStackBridge) $$2).bridge$withCurrentCause(); + ((CommandSourceStackBridge) cause).bridge$permissionService(delegatingCommandDispatcher.permissionService()); + return original.call($$0, $$1, cause, $$3); + } + } else { + return original.call($$0, $$1, $$2, $$3); + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java index 9303b25ee66..1a54021147e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java @@ -44,6 +44,7 @@ import org.spongepowered.api.event.EventContext; import org.spongepowered.api.event.EventContextKey; import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -86,6 +87,7 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg @Shadow @Final private TaskChainer chatMessageChainer; private Cause impl$cause; @Nullable private Supplier impl$potentialPermissionNode = null; + private @Nullable PermissionService impl$permissionService; @Inject(method = "(Lnet/minecraft/commands/CommandSource;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec2;Lnet/minecraft/server/level/ServerLevel;ILjava/lang/String;Lnet/minecraft/network/chat/Component;Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/world/entity/Entity;ZLnet/minecraft/commands/CommandResultCallback;Lnet/minecraft/commands/arguments/EntityAnchorArgument$Anchor;Lnet/minecraft/commands/CommandSigningContext;Lnet/minecraft/util/TaskChainer;)V", at = @At("RETURN")) @@ -145,14 +147,17 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg final CommandSourceStackBridge commandSourceStackBridge = ((CommandSourceStackBridge) cir.getReturnValue()); commandSourceStackBridge.bridge$setPotentialPermissionNode(this.impl$potentialPermissionNode); commandSourceStackBridge.bridge$setCause(this.impl$cause); + commandSourceStackBridge.bridge$permissionService(this.impl$permissionService); } } @Override public CommandCause bridge$withCurrentCause() { // Cause is set in ctor. - return (CommandCause) CommandSourceStackAccessor.invoker$new(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, + final CommandCause instance = (CommandCause) CommandSourceStackAccessor.invoker$new(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + ((CommandSourceStackBridge) instance).bridge$permissionService(this.impl$permissionService); + return instance; } /* @@ -197,10 +202,14 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg @Inject(method = "hasPermission", at = @At(value = "HEAD"), cancellable = true) private void impl$checkPermission(final int opLevel, final CallbackInfoReturnable cir) { - if (Sponge.isServerAvailable() && this.impl$potentialPermissionNode != null) { + if (this.impl$potentialPermissionNode != null) { final String perm = this.impl$potentialPermissionNode.get(); // This will register the permission with the first op level we retrieve. - SpongePermissions.registerPermission(perm, opLevel); + if (this.impl$permissionService != null) { + SpongePermissions.registerPermission(this.impl$permissionService, perm, opLevel); + } else if (Sponge.isServerAvailable()) { + SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), perm, opLevel); + } cir.setReturnValue(((CommandCause) this).hasPermission(perm)); } // fall through to the op level check if we haven't set a permission node. @@ -250,4 +259,8 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg return Cause.builder().from(this.impl$cause).build(builder.build()); } + @Override + public void bridge$permissionService(final PermissionService permissionService) { + this.impl$permissionService = permissionService; + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 53a0c966a89..1b152e210e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -24,13 +24,11 @@ */ package org.spongepowered.common.mixin.core.server; -import com.google.inject.Injector; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.datafixers.DataFixer; import net.kyori.adventure.resource.ResourcePackRequest; -import net.minecraft.Util; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; @@ -47,10 +45,8 @@ import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.SimpleReloadInstance; import net.minecraft.server.players.GameProfileCache; import net.minecraft.server.players.PlayerList; -import net.minecraft.util.Unit; import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.Difficulty; import net.minecraft.world.level.Level; @@ -62,7 +58,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; -import org.spongepowered.api.Game; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; @@ -90,13 +85,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; -import org.spongepowered.common.accessor.server.ServerFunctionManagerAccessor; import org.spongepowered.common.adventure.NativeComponentRenderer; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.network.chat.SpongeChatDecorator; import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; +import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.bridge.server.players.GameProfileCacheBridge; import org.spongepowered.common.bridge.server.players.PlayerListBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; @@ -119,7 +114,6 @@ import java.io.IOException; import java.net.Proxy; import java.util.Collection; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -493,18 +487,6 @@ public void setDifficulty(final Difficulty difficulty, final boolean force) { } } - @Override - public void bridge$initServices(final Game game, final Injector injector) { - if (this.impl$serviceProvider == null) { - this.impl$serviceProvider = new SpongeServerScopedServiceProvider(this, game, injector); - this.impl$serviceProvider.init(); - - Util.blockUntilDone(e -> - SimpleReloadInstance.create(this.shadow$getResourceManager(), List.of(((ServerFunctionManagerAccessor) this.functionManager).accessor$library()), - Util.backgroundExecutor(), e, CompletableFuture.completedFuture(Unit.INSTANCE), MinecraftServerMixin.LOGGER.isDebugEnabled()).done()); - } - } - @Override public SpongeServerScopedServiceProvider bridge$getServiceProvider() { return this.impl$serviceProvider; @@ -544,6 +526,7 @@ public String toString() { @Inject(method = "", at = @At("TAIL")) public void impl$onInit(final CallbackInfo ci, final @Local(argsOnly = true) WorldStem levelStem) { this.bridge$reloadedServerRegistries(((SpongeRegistryHolder) levelStem.resourceManager()).registryHolder()); + this.impl$serviceProvider = ((ResourceManagerBridge) levelStem.resourceManager()).bridge$services(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java deleted file mode 100644 index ec623d2a55f..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerFunctionLibraryMixin.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server; - -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import net.minecraft.server.ServerFunctionLibrary; -import net.minecraft.server.packs.resources.PreparableReloadListener; -import net.minecraft.server.packs.resources.ResourceManager; -import org.spongepowered.api.Sponge; -import org.spongepowered.asm.mixin.Mixin; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - -@Mixin(ServerFunctionLibrary.class) -public abstract class ServerFunctionLibraryMixin { - - @WrapMethod(method = "reload") - private CompletableFuture impl$onReload(final PreparableReloadListener.PreparationBarrier barrier, final ResourceManager manager, - final Executor executor1, final Executor executor2, final Operation> original) { - if (Sponge.isServerAvailable()) { - return original.call(barrier, manager, executor1, executor2); - } - return barrier.wait(null); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index 371555bd1ab..40302a0380a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -52,6 +52,7 @@ public abstract class WorldLoaderMixin { final Pair pair = original.call(instance); final CloseableResourceManager resourceManager = pair.getSecond(); final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.establishServerServices(resourceManager); lifecycle.setWorldDataConfiguration(pair.getFirst()); lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); return pair; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/packs/resoruces/MultiPackResourceManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/packs/resoruces/MultiPackResourceManagerMixin.java index 4856a0c13ba..e46e602ba35 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/packs/resoruces/MultiPackResourceManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/packs/resoruces/MultiPackResourceManagerMixin.java @@ -28,20 +28,32 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; +import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.tag.SpongePluginTags; @Mixin(MultiPackResourceManager.class) public abstract class MultiPackResourceManagerMixin implements ResourceManagerBridge { @MonotonicNonNull private SpongePluginTags impl$pluginTags; + @MonotonicNonNull private SpongeServerScopedServiceProvider impl$services; @Override public void bridge$pluginProvidedTags(final SpongePluginTags pluginTags) { this.impl$pluginTags = pluginTags; } + @Override + public void bridge$services(final SpongeServerScopedServiceProvider services) { + this.impl$services = services; + } + @Override public SpongePluginTags bridge$pluginProvidedTags() { return this.impl$pluginTags; } + + @Override + public SpongeServerScopedServiceProvider bridge$services() { + return this.impl$services; + } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index b2b58ebdc48..07ef9e6c57c 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -20,6 +20,7 @@ "block.BedBlockMixin", "block.BlockMixin", "block.DyeColorBlockPropertiesMixin", + "commands.CommandFunctionMixin", "commands.CommandsMixin", "commands.CommandSourceMixin", "commands.CommandSourceStackMixin", @@ -57,7 +58,6 @@ "server.PlayerAdvancementsMixin", "server.ReloadableServerResourcesMixin", "server.ServerAdvancementManagerMixin", - "server.ServerFunctionLibraryMixin", "server.ServerFunctionManagerMixin", "server.ServerScoreboardMixin", "server.WorldLoaderMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java index c987d086652..b34dcebf928 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/server/IntegratedServerMixin_Vanilla.java @@ -47,8 +47,6 @@ public abstract class IntegratedServerMixin_Vanilla extends MinecraftServerMixin ((MinecraftBridge) Minecraft.getInstance()).bridge$setTemporaryIntegratedServer((IntegratedServer) (Object) this); } final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(); - lifecycle.establishServerFeatures(); lifecycle.callStartingEngineEvent(this); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java new file mode 100644 index 00000000000..e1a7b2c7376 --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.server; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.commands.Commands; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.flag.FeatureFlagSet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; +import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; + +import java.util.List; + +@Mixin(ReloadableServerResources.class) +public abstract class ReloadableServerResourcesMixin_Vanilla { + + @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) + private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); + if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); + } + return instance; + } +} diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java index 8b16265344a..adcab4a3f67 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/dedicated/DedicatedServerMixin_Vanilla.java @@ -43,8 +43,6 @@ public abstract class DedicatedServerMixin_Vanilla extends MinecraftServerMixin_ ConfigHandle.setSaveSuppressed(false); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(); - lifecycle.establishServerFeatures(); lifecycle.callStartingEngineEvent(this); diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 5e4128e75da..59cf130b4c2 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -25,6 +25,7 @@ "resources.RegistryDataLoaderMixin_Vanilla", "server.BootstrapMixin_Vanilla", "server.MinecraftServerMixin_Vanilla", + "server.ReloadableServerResourcesMixin_Vanilla", "server.commands.SpreadPlayersCommandMixin_Vanilla", "server.level.ServerPlayerMixin_Vanilla", "server.network.ServerGamePacketListenerImplMixin_Vanilla", @@ -32,8 +33,8 @@ "tags.TagLoaderMixin_Vanilla", "world.entity.EntityMixin_Vanilla", "world.entity.EntityTypeMixin_Vanilla", - "world.entity.LivingEntityMixin_Vanilla_Damage", "world.entity.LivingEntityMixin_Vanilla", + "world.entity.LivingEntityMixin_Vanilla_Damage", "world.entity.ai.attributes.DefaultAttributesMixin", "world.entity.animal.SnowGolemMixin_Vanilla", "world.entity.item.ItemEntityMixin_Vanilla", From 58d7427d890f5703657aa6d7a82ac9b83699e3d0 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 13 Sep 2025 20:16:07 +0300 Subject: [PATCH 348/586] Implement function subject collection in SpongePermissionService --- SpongeAPI | 2 +- .../spongepowered/common/launch/Lifecycle.java | 2 +- .../spongepowered/common/SpongeLifecycle.java | 4 ++-- .../common/service/SpongeServiceProvider.java | 18 +++++++++++++----- .../SpongeServerScopedServiceProvider.java | 11 ++++++----- .../permission/SpongePermissionService.java | 8 +++++--- .../core/commands/CommandFunctionMixin.java | 2 +- .../mixin/core/server/WorldLoaderMixin.java | 4 ++-- 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index a22a428744e..8a5c18b6577 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a22a428744e471d475d41152613e28fa7922b21a +Subproject commit 8a5c18b65772ce56a45a33c603697dc3a3589689 diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 5bd760d1644..01229128bde 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -66,7 +66,7 @@ public interface Lifecycle { void establishGameServices(); - void establishServerServices(ResourceManager resourceManager); + void establishServerServices(ResourceManager resourceManager, int functionsPermissionLevel); void establishServerFeatures(); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index d3890b5d3d5..d88fd56cfe5 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -174,8 +174,8 @@ public void establishGameServices() { } @Override - public void establishServerServices(final ResourceManager resourceManager) { - final SpongeServerScopedServiceProvider serviceProvider = new SpongeServerScopedServiceProvider(this.game, this.injector); + public void establishServerServices(final ResourceManager resourceManager, final int functionsPermissionLevel) { + final SpongeServerScopedServiceProvider serviceProvider = new SpongeServerScopedServiceProvider(this.game, this.injector, functionsPermissionLevel); serviceProvider.init(); ((ResourceManagerBridge) resourceManager).bridge$services(serviceProvider); } diff --git a/src/main/java/org/spongepowered/common/service/SpongeServiceProvider.java b/src/main/java/org/spongepowered/common/service/SpongeServiceProvider.java index a2c3cd6b01f..ea8f268ea55 100644 --- a/src/main/java/org/spongepowered/common/service/SpongeServiceProvider.java +++ b/src/main/java/org/spongepowered/common/service/SpongeServiceProvider.java @@ -269,14 +269,22 @@ private Registration(final Class clazz, final T object, final PluginContainer protected static final class Service { @NonNull private final Class service; - private final @Nullable Class defaultServiceClass; + private final @Nullable Function defaultServiceProvider; @NonNull private final Function configEntryProvider; public Service(final @NonNull Class service, final @NonNull Function configEntryProvider, final @Nullable Class defaultServiceClass) { this.service = service; - this.defaultServiceClass = defaultServiceClass; + this.defaultServiceProvider = defaultServiceClass != null ? i -> i.getInstance(defaultServiceClass) : null; + this.configEntryProvider = configEntryProvider; + } + + public Service(final @NonNull Class service, + final @NonNull Function configEntryProvider, + final @Nullable Function defaultServiceProvider) { + this.service = service; + this.defaultServiceProvider = defaultServiceProvider; this.configEntryProvider = configEntryProvider; } @@ -289,12 +297,12 @@ public String providePluginId(final ServicesCategory.ServicePluginSubCategory se } public boolean suppliesDefault() { - return this.defaultServiceClass != null; + return this.defaultServiceProvider != null; } public @Nullable T provideDefaultService(final Injector injector) { - if (this.defaultServiceClass != null) { - return injector.getInstance(this.defaultServiceClass); + if (this.defaultServiceProvider != null) { + return this.defaultServiceProvider.apply(injector); } else { return null; } diff --git a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java index 0668b3a6509..6babf671566 100644 --- a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java +++ b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java @@ -25,7 +25,6 @@ package org.spongepowered.common.service.server; import com.google.common.collect.ImmutableList; -import com.google.inject.Inject; import com.google.inject.Injector; import io.leangen.geantyref.TypeToken; import org.checkerframework.checker.nullness.qual.NonNull; @@ -52,9 +51,11 @@ public final class SpongeServerScopedServiceProvider extends SpongeServiceProvider implements ServiceProvider.ServerScoped { - @Inject - public SpongeServerScopedServiceProvider(final Game game, final Injector injector) { + private final int functionsPermissionLevel; + + public SpongeServerScopedServiceProvider(final Game game, final Injector injector, final int functionsPermissionLevel) { super(game, injector); + this.functionsPermissionLevel = functionsPermissionLevel; } @Override @@ -71,11 +72,11 @@ protected List> servicesToSelect() { .add(new Service<>( EconomyService.class, servicePluginSubCategory -> servicePluginSubCategory.economyService, - null)) + (Class) null)) .add(new Service<>( PermissionService.class, servicePluginSubCategory -> servicePluginSubCategory.permissionService, - SpongePermissionService.class)) + i -> new SpongePermissionService(this.getGame(), this.functionsPermissionLevel))) .add(new Service<>( WhitelistService.class, servicePluginSubCategory -> servicePluginSubCategory.whitelistService, diff --git a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java index 819721fc656..4960633e903 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java @@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.inject.Inject; import com.google.inject.Singleton; import net.minecraft.server.players.ServerOpList; import org.checkerframework.checker.nullness.qual.Nullable; @@ -68,8 +67,7 @@ public final class SpongePermissionService implements PermissionService { private final SpongeSubjectCollection defaultCollection; private final SpongeSubject defaultData; - @Inject - public SpongePermissionService(final Game game) { + public SpongePermissionService(final Game game, final int functionsPermissionLevel) { this.game = game; this.subjects.put(SpongePermissionService.SUBJECTS_DEFAULT, (this.defaultCollection = this.newCollection(SpongePermissionService.SUBJECTS_DEFAULT))); this.subjects.put(PermissionService.SUBJECTS_USER, new UserCollection(this)); @@ -92,6 +90,10 @@ public SpongePermissionService(final Game game) { // } )); + this.subjects.put(PermissionService.SUBJECTS_FUNCTION, new DataFactoryCollection( + PermissionService.SUBJECTS_FUNCTION, this, + s -> new FixedParentMemorySubjectData(s, this.getGroupForOpLevel(functionsPermissionLevel).asSubjectReference()))); + this.defaultData = this.getDefaultCollection().get(SpongePermissionService.SUBJECTS_DEFAULT); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java index 3d691f183a8..88cd8826d2b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java @@ -48,7 +48,7 @@ public interface CommandFunctionMixin { final ResourceLocation $$0, final CommandDispatcher $$1, final T $$2, final List $$3, final Operation> original) { if ($$1 instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(delegatingCommandDispatcher.permissionService().newSubjectReference(PermissionService.SUBJECTS_SYSTEM, "console").resolve().join()); + frame.pushCause(delegatingCommandDispatcher.permissionService().newSubjectReference(PermissionService.SUBJECTS_FUNCTION, $$0.toString()).resolve().join()); final CommandCause cause = ((CommandSourceStackBridge) $$2).bridge$withCurrentCause(); ((CommandSourceStackBridge) cause).bridge$permissionService(delegatingCommandDispatcher.permissionService()); return original.call($$0, $$1, cause, $$3); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index 40302a0380a..b3b0d496578 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -48,11 +48,11 @@ public abstract class WorldLoaderMixin { @WrapOperation(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$PackConfig;createResourceManager()Lcom/mojang/datafixers/util/Pair;")) private static Pair impl$onCreateResourceManager(final WorldLoader.PackConfig instance, - final Operation> original) { + final Operation> original, final @Local(argsOnly = true) WorldLoader.InitConfig $$0) { final Pair pair = original.call(instance); final CloseableResourceManager resourceManager = pair.getSecond(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(resourceManager); + lifecycle.establishServerServices(resourceManager, $$0.functionCompilationLevel()); lifecycle.setWorldDataConfiguration(pair.getFirst()); lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); return pair; From 201e3db0e95861fa81cda8bac0847e48b84fe677 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 14 Sep 2025 19:57:36 +0200 Subject: [PATCH 349/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index b06229f7846..5222ce3c893 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b06229f78460f09c9f06679d2332bab784d94fa4 +Subproject commit 5222ce3c89367b62bf3ae6ee34bbc4f0bab56e85 From d880795b01f60a87fb3cf6e9e986de219dad2b85 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 14 Sep 2025 21:21:41 +0200 Subject: [PATCH 350/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 5222ce3c893..d15129ee57e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 5222ce3c89367b62bf3ae6ee34bbc4f0bab56e85 +Subproject commit d15129ee57e97491fc3a4e1e1ba6051683d142b2 From 358b223c6433b32367c39af536af2c2e12c3700d Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Fri, 12 Sep 2025 00:42:54 +0300 Subject: [PATCH 351/586] Make Enchantment a ComponentLike (#4229) --- .../item/enchantment/SpongeEnchantment.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/enchantment/SpongeEnchantment.java b/src/main/java/org/spongepowered/common/item/enchantment/SpongeEnchantment.java index c708fff2c70..daa623d4f6c 100644 --- a/src/main/java/org/spongepowered/common/item/enchantment/SpongeEnchantment.java +++ b/src/main/java/org/spongepowered/common/item/enchantment/SpongeEnchantment.java @@ -24,17 +24,22 @@ */ package org.spongepowered.common.item.enchantment; +import net.kyori.adventure.text.Component; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.world.item.enchantment.Enchantment; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.Queries; -import org.spongepowered.api.item.enchantment.Enchantment; import org.spongepowered.api.item.enchantment.EnchantmentType; import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.adventure.SpongeAdventure; import java.util.Objects; -public final class SpongeEnchantment implements Enchantment { +public final class SpongeEnchantment implements org.spongepowered.api.item.enchantment.Enchantment { private final EnchantmentType enchantmentType; private final int level; @@ -54,6 +59,13 @@ public int level() { return this.level; } + @Override + public Component asComponent() { + final Registry registry = (Registry) SpongeCommon.scopedHolder().registry(RegistryTypes.ENCHANTMENT_TYPE); + final Holder holder = registry.wrapAsHolder((Enchantment) (Object) this.enchantmentType); + return SpongeAdventure.asAdventure(Enchantment.getFullname(holder, this.level)); + } + @Override public int contentVersion() { return 1; From 916eead9c825fbbcbc049ad02a874ad7272e4a20 Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Sat, 5 Apr 2025 22:19:43 +0300 Subject: [PATCH 352/586] Add missing tag groups (#4205) --- .../generator/world/TagRegistries.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java index 635f9efdb62..8c3e598c650 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java @@ -79,13 +79,40 @@ public static List tagRegistries(final Context context) { "tag", "EnchantmentTypeTags" ), - new TagGenerator( "DAMAGE_TYPE", Registries.DAMAGE_TYPE, context.relativeClass("event.cause.entity.damage", "DamageType"), "tag", "DamageTypeTags" + ), + new TagGenerator( + "BANNER_PATTERN_SHAPE", + Registries.BANNER_PATTERN, + context.relativeClass("data.type", "BannerPatternShape"), + "tag", + "BannerPatternShapeTags" + ), + new TagGenerator( + "CAT_TYPE", + Registries.CAT_VARIANT, + context.relativeClass("data.type", "CatType"), + "tag", + "CatTypeTags" + ), + new TagGenerator( + "ART_TYPE", + Registries.PAINTING_VARIANT, + context.relativeClass("data.type", "ArtType"), + "tag", + "ArtTypeTags" + ), + new TagGenerator( + "STRUCTURE", + Registries.STRUCTURE, + context.relativeClass("world.generation.structure", "Structure"), + "tag", + "StructureTags" ) ); } From a48bad38ee50f449263c290ff443a9fc585092ce Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 14 Sep 2025 22:04:34 +0200 Subject: [PATCH 353/586] Update lookupGameProfile injection --- .../server/players/GameProfileCacheMixin.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index 443588db5d8..80e3cabc9a5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -146,21 +146,13 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { } } - @Redirect(method = "lookupGameProfile", - at = @At( - value = "INVOKE", - target = "Lcom/mojang/authlib/GameProfileRepository;findProfilesByNames([Ljava/lang/String;Lcom/mojang/authlib/ProfileLookupCallback;)V", - remap = false - ) - ) - private static void impl$lookUpViaSponge(final GameProfileRepository repository, final String[] names, - final ProfileLookupCallback callback) { + @Redirect(method = "lookupGameProfile", at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/GameProfileRepository;findProfileByName(Ljava/lang/String;)Ljava/util/Optional;")) + private static Optional impl$lookUpViaSponge(final GameProfileRepository instance, final String name) { final GameProfileManager profileManager = Sponge.server().gameProfileManager(); try { - callback.onProfileLookupSucceeded(SpongeGameProfile.toMcProfile(profileManager.basicProfile(names[0]).join())); + return Optional.of(SpongeGameProfile.toMcProfile(profileManager.basicProfile(name).join())); } catch (final Throwable e) { - callback.onProfileLookupFailed(names[0], - e instanceof final Exception ex ? ex : new RuntimeException(e)); + return Optional.empty(); } } From 1a0990724c3c3e2311175576c83c054b4f5ab728 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 14 Sep 2025 22:20:45 +0200 Subject: [PATCH 354/586] Update tags --- SpongeAPI | 2 +- .../vanilla/generator/world/TagRegistries.java | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 9ea95cf32e9..92ddc65b835 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9ea95cf32e97067f6eac2f413b804951f3fef486 +Subproject commit 92ddc65b8356ec4e268ba44686b6ca6dd67d1247 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java index 8c3e598c650..a4a2ab41155 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/TagRegistries.java @@ -93,13 +93,6 @@ public static List tagRegistries(final Context context) { "tag", "BannerPatternShapeTags" ), - new TagGenerator( - "CAT_TYPE", - Registries.CAT_VARIANT, - context.relativeClass("data.type", "CatType"), - "tag", - "CatTypeTags" - ), new TagGenerator( "ART_TYPE", Registries.PAINTING_VARIANT, From 21553a62a1ffa7ddd62a2eafe9cd1ede8d7d89bb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 14 Sep 2025 22:33:43 +0200 Subject: [PATCH 355/586] Spotless --- .../common/mixin/core/server/players/GameProfileCacheMixin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index 80e3cabc9a5..33cd58fd114 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -25,7 +25,6 @@ package org.spongepowered.common.mixin.core.server.players; import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.ProfileLookupCallback; import net.minecraft.server.players.GameProfileCache; import org.spongepowered.api.Sponge; import org.spongepowered.api.profile.GameProfile; From b7148ccf434c4e429f94d72f5afa961568619339 Mon Sep 17 00:00:00 2001 From: CanardNocturne Date: Mon, 15 Sep 2025 23:01:58 +0200 Subject: [PATCH 356/586] Fire event for middle click on block or entity (#4219) --- .../transaction/inventory/ClickMenuTransaction.java | 10 ++++++++-- .../event/tracking/phase/packet/PacketPhase.java | 4 ++++ ...ServerGamePacketListenerImplMixin_Inventory.java | 13 +++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java index 1100799f243..7a471c14f31 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java @@ -25,6 +25,8 @@ package org.spongepowered.common.event.tracking.context.transaction.inventory; import net.minecraft.network.protocol.game.ServerboundContainerClickPacket; +import net.minecraft.network.protocol.game.ServerboundPickItemFromBlockPacket; +import net.minecraft.network.protocol.game.ServerboundPickItemFromEntityPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -106,10 +108,14 @@ public void postProcessEvent(final PhaseContext<@NonNull ?> context, final Click boolean isContainerEventAllowed( final PhaseContext<@NonNull ?> context ) { - if (!(context instanceof InventoryPacketContext)) { + if (!(context instanceof InventoryPacketContext inventoryPacketContext)) { return false; } - final int containerId = ((InventoryPacketContext) context).getPacket().getContainerId(); + if(inventoryPacketContext.getPacket() instanceof ServerboundPickItemFromBlockPacket || + inventoryPacketContext.getPacket() instanceof ServerboundPickItemFromEntityPacket) { + return true; //The item is always put in the player container menu + } + final int containerId = inventoryPacketContext.getPacket().getContainerId(); return containerId != this.player.containerMenu.containerId; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java index 37803950dc0..ed22919d93a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java @@ -39,6 +39,8 @@ import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; +import net.minecraft.network.protocol.game.ServerboundPickItemFromBlockPacket; +import net.minecraft.network.protocol.game.ServerboundPickItemFromEntityPacket; import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket; import net.minecraft.network.protocol.game.ServerboundPlayerAbilitiesPacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; @@ -316,6 +318,8 @@ private void setupPacketToStateMapping() { this.packetTranslationMap.put(ServerboundPlayerInputPacket.class, packet -> PacketPhase.General.HANDLED_EXTERNALLY); this.packetTranslationMap.put(ServerboundContainerClosePacket.class, packet -> PacketPhase.General.CLOSE_WINDOW); this.packetTranslationMap.put(ServerboundContainerClickPacket.class, packet -> PacketPhase.fromWindowPacket((ServerboundContainerClickPacket) packet)); + this.packetTranslationMap.put(ServerboundPickItemFromBlockPacket.class, packet -> Inventory.MIDDLE_INVENTORY_CLICK); + this.packetTranslationMap.put(ServerboundPickItemFromEntityPacket.class, packet -> Inventory.MIDDLE_INVENTORY_CLICK); this.packetTranslationMap.put(ServerboundSetCreativeModeSlotPacket.class, packet -> PacketPhase.General.CREATIVE_INVENTORY); this.packetTranslationMap.put(ServerboundContainerButtonClickPacket.class, packet -> PacketPhase.Inventory.ENCHANT_ITEM); this.packetTranslationMap.put(ServerboundSignUpdatePacket.class, packet -> PacketPhase.General.UPDATE_SIGN); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index bddcc9108f6..9c9a8ff8acd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -36,8 +36,10 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.inventory.MerchantMenu; import net.minecraft.world.item.ItemStack; @@ -51,6 +53,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.inventory.AbstractContainerMenu_InventoryBridge; import org.spongepowered.common.bridge.world.inventory.container.MenuBridge; @@ -79,6 +82,16 @@ public class ServerGamePacketListenerImplMixin_Inventory { inventoryMenu.broadcastChanges(); } + @Inject(method = "tryPickItem", + at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/player/Inventory;findSlotMatchingItem(Lnet/minecraft/world/item/ItemStack;)I"), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void impl$onPickItem(final ItemStack stack, final CallbackInfo ci, Inventory inventory, int slotNum) { + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); + final TransactionalCaptureSupplier transactor = context.getTransactor(); + try(final EffectTransactor ignored = transactor.logClickContainer(player.containerMenu, slotNum, 0, ClickType.PICKUP, player)) { + } + } + @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Lnet/minecraft/world/item/ItemStack;Z)Lnet/minecraft/world/entity/item/ItemEntity;")) private ItemEntity impl$onBroadcastCreativeActionResult(final ServerPlayer serverPlayer, final ItemStack stack, final boolean param1) { From 0a745e82e203aee66fc781967aba3632a28ca8fd Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 16 Sep 2025 10:47:43 +0200 Subject: [PATCH 357/586] Properly capture item changes during middle click --- .../ServerGamePacketListenerImplMixin_Inventory.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index 9c9a8ff8acd..54dcb12ae53 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -26,6 +26,7 @@ import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.network.protocol.game.ServerboundContainerClickPacket; import net.minecraft.network.protocol.game.ServerboundSelectTradePacket; import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket; @@ -36,7 +37,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.ClickType; @@ -53,7 +53,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.inventory.AbstractContainerMenu_InventoryBridge; import org.spongepowered.common.bridge.world.inventory.container.MenuBridge; @@ -82,13 +81,12 @@ public class ServerGamePacketListenerImplMixin_Inventory { inventoryMenu.broadcastChanges(); } - @Inject(method = "tryPickItem", - at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/player/Inventory;findSlotMatchingItem(Lnet/minecraft/world/item/ItemStack;)I"), - locals = LocalCapture.CAPTURE_FAILSOFT) - private void impl$onPickItem(final ItemStack stack, final CallbackInfo ci, Inventory inventory, int slotNum) { + @WrapOperation(method = "tryPickItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/InventoryMenu;broadcastChanges()V")) + private void impl$onPickItem(final InventoryMenu menu, final Operation original) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try(final EffectTransactor ignored = transactor.logClickContainer(player.containerMenu, slotNum, 0, ClickType.PICKUP, player)) { + try (final EffectTransactor ignored = transactor.logClickContainer(menu, this.player.getInventory().selected, 0, ClickType.PICKUP, this.player)) { + original.call(menu); } } From d903695e5b59ac02425a0168eb21adf4908ed40f Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 17 Sep 2025 20:31:18 +0300 Subject: [PATCH 358/586] Match OldBlockOnReplaceEffect with vanilla --- .../effect/OldBlockOnReplaceEffect.java | 52 ++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java index 0234c78b667..52ab4d58975 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/OldBlockOnReplaceEffect.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.event.tracking.context.transaction.effect; +import net.minecraft.world.level.block.BaseRailBlock; import net.minecraft.world.level.block.state.BlockState; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.context.transaction.pipeline.BlockPipeline; @@ -47,28 +48,22 @@ public static OldBlockOnReplaceEffect getInstance() { ) { // This replaces LevelChunk#setBlockState block: /* - - if ($$14) { - if (this.level instanceof ServerLevel $$17) { - // -- this block is this side effect - if (hasBlockEntity && $$16) { - BlockEntity $$18 = this.level.getBlockEntity($$0); - if ($$18 != null) { - $$18.preRemoveSideEffects($$0, $$9, $$15); - } + boolean $$13 = !$$9.is($$10); + boolean $$14 = ($$2 & 64) != 0; + boolean $$15 = ($$2 & 256) == 0; + if ($$13 && $$9.hasBlockEntity()) { + if (!this.level.isClientSide && $$15) { + BlockEntity $$16 = this.level.getBlockEntity($$0); + if ($$16 != null) { + $$16.preRemoveSideEffects($$0, $$9); } + } - if (hasBlockEntity) { - this.removeBlockEntity($$0); - } + this.removeBlockEntity($$0); + } - if (($$2 & 1) != 0) { - $$9.affectNeighborsAfterRemoval($$17, $$0, $$15); - } - // -- end of side effect - } else if (hasBlockEntity) { - this.removeBlockEntity($$0); - } + if (($$13 || $$10 instanceof BaseRailBlock) && this.level instanceof ServerLevel $$17 && (($$2 & 1) != 0 || $$14)) { + $$9.affectNeighborsAfterRemoval($$17, $$0, $$14); } Notes: Since we know we're on the server context, we eliminate @@ -81,22 +76,19 @@ public static OldBlockOnReplaceEffect getInstance() { final var flag = args.flag(); final var pos = oldState.pos(); - if (!oldState.state().is(newState.getBlock())) { - return EffectResult.nullPass(); - } - // Spogne adds the block physics flag - if (hasBlockEntity && !flag.performBlockDestruction() && flag.performBlockPhysics()) { - final var blockEntity = oldState.tileEntity(); - if (blockEntity != null) { - blockEntity.preRemoveSideEffects(pos, newState); + final boolean replaced = !oldState.state().is(newState.getBlock()); + if (replaced && hasBlockEntity) { + if (flag.performBlockDestruction()) { + final var blockEntity = oldState.tileEntity(); + if (blockEntity != null) { + blockEntity.preRemoveSideEffects(pos, oldState.state()); + } } - } - if (hasBlockEntity) { pipeline.getAffectedChunk().removeBlockEntity(pos); } - if (flag.updateNeighbors()) { + if ((replaced || newState.getBlock() instanceof BaseRailBlock) && (flag.updateNeighbors() || flag.movingBlocks())) { oldState.state().affectNeighborsAfterRemoval(pipeline.getServerWorld(), pos, flag.movingBlocks()); } From d2b31b690e120060e2b4a8fdc5c919fe740111f2 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 22 Sep 2025 18:31:03 +0300 Subject: [PATCH 359/586] Bump Adventure to 4.24.0 --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 88 +++++++++++++++++++ .../common/adventure/SpongeAdventure.java | 4 +- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 9bd705c3b48..73dc2c7b066 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9bd705c3b482c006acd331184374c3893340720b +Subproject commit 73dc2c7b066e65e394341005cd4b583a949be250 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1dae8da85de..ba9bbd37753 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3161,6 +3161,14 @@ + + + + + + + + @@ -3198,6 +3206,14 @@ + + + + + + + + @@ -3247,6 +3263,14 @@ + + + + + + + + @@ -3293,6 +3317,14 @@ + + + + + + + + @@ -3342,6 +3374,14 @@ + + + + + + + + @@ -3388,6 +3428,14 @@ + + + + + + + + @@ -3404,6 +3452,14 @@ + + + + + + + + @@ -3453,6 +3509,14 @@ + + + + + + + + @@ -3502,6 +3566,14 @@ + + + + + + + + @@ -3551,6 +3623,14 @@ + + + + + + + + @@ -3600,6 +3680,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index b09679ab007..ddf21e6cb2d 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -823,8 +823,7 @@ public static Sound.Source asAdventure(final SoundSource source) { case PLAYERS -> Sound.Source.PLAYER; case AMBIENT -> Sound.Source.AMBIENT; case VOICE -> Sound.Source.VOICE; - // TODO - for now just use master - case UI -> Sound.Source.MASTER; + case UI -> Sound.Source.UI; }; } @@ -840,6 +839,7 @@ public static SoundSource asVanilla(final Sound.Source source) { case PLAYER -> SoundSource.PLAYERS; case AMBIENT -> SoundSource.AMBIENT; case VOICE -> SoundSource.VOICE; + case UI -> SoundSource.UI; }; } From 24999d046be09c2713cdfb5bad032e16e8ae9893 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 21:36:59 -0700 Subject: [PATCH 360/586] feat(minecraft): update to 25w37a Changes: - Changed gamerule tag names - Added NoOpSynchronizer to handle vanished entities See: https://minecraft.wiki/w/Java_Edition_25w37a --- SpongeAPI | 2 +- gradle.properties | 2 +- .../server/level/ChunkMapAccessor.java | 2 +- .../data/datasync/NoOpSynchronizer.java | 52 +++++++++++++ .../VanishedFilteringSynchronizer.java | 73 +++++++++++++++++++ .../entity/living/human/HumanEntity.java | 16 ++-- .../world/SpongePositionSourceFactory.java | 2 +- .../minecraft/world/level/LevelMixin_API.java | 4 +- .../level/ChunkMap_TrackedEntityMixin.java | 7 +- .../core/server/level/ServerEntityMixin.java | 52 ++++++------- .../core/server/level/ServerLevelMixin.java | 13 ++-- .../entity/LivingEntityMixin_Inventory.java | 3 +- 12 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/data/datasync/NoOpSynchronizer.java create mode 100644 src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java diff --git a/SpongeAPI b/SpongeAPI index 9e38f062da8..fefaa09423e 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9e38f062da88ff1e866393c569392fb5d9ed54b1 +Subproject commit fefaa09423ed515119157d8b3ac598ef8b77ae85 diff --git a/gradle.properties b/gradle.properties index fed374b10f7..fcd673c6e34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=25w36b +minecraftVersion=25w37a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/ChunkMapAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/level/ChunkMapAccessor.java index c24a269be3e..5a0dda5ac37 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/ChunkMapAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/level/ChunkMapAccessor.java @@ -43,7 +43,7 @@ public interface ChunkMapAccessor { @Invoker("saveAllChunks") void invoker$saveAllChunks(boolean flush); - @Invoker("getChunks") Iterable invoker$getChunks(); + @Accessor("visibleChunkMap") Long2ObjectLinkedOpenHashMap accessor$visibleChunkMap(); @Accessor("level") ServerLevel accessor$level(); } diff --git a/src/main/java/org/spongepowered/common/data/datasync/NoOpSynchronizer.java b/src/main/java/org/spongepowered/common/data/datasync/NoOpSynchronizer.java new file mode 100644 index 00000000000..a859256152a --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/datasync/NoOpSynchronizer.java @@ -0,0 +1,52 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.datasync; + +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.server.level.ServerEntity; +import net.minecraft.server.level.ServerPlayer; + +import java.util.function.Predicate; + +public record NoOpSynchronizer() implements ServerEntity.Synchronizer { + + public static final NoOpSynchronizer INSTANCE = new NoOpSynchronizer(); + + @Override + public void sendToTrackingPlayers(Packet var1) { + + } + + @Override + public void sendToTrackingPlayersAndSelf(Packet var1) { + + } + + @Override + public void sendToTrackingPlayersFiltered(Packet var1, Predicate var2) { + + } +} diff --git a/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java new file mode 100644 index 00000000000..79365096ecd --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java @@ -0,0 +1,73 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.datasync; + +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.server.level.ServerEntity; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import org.spongepowered.common.bridge.data.VanishableBridge; + +import java.lang.ref.WeakReference; +import java.util.function.Predicate; + +public record VanishedFilteringSynchronizer( + ServerEntity.Synchronizer proxy, + WeakReference ref +) implements ServerEntity.Synchronizer { + @Override + public void sendToTrackingPlayers(Packet var1) { + if (this.ref.get() instanceof VanishableBridge vb) { + if (!vb.bridge$isInvisible()) { + this.proxy.sendToTrackingPlayers(var1); + } + return; + } + this.proxy.sendToTrackingPlayers(var1); + } + + @Override + public void sendToTrackingPlayersAndSelf(Packet var1) { + if (this.ref.get() instanceof VanishableBridge vb) { + if (!vb.bridge$isInvisible()) { + this.proxy.sendToTrackingPlayersAndSelf(var1); + } + return; + } + this.proxy.sendToTrackingPlayersAndSelf(var1); + } + + @Override + public void sendToTrackingPlayersFiltered(Packet var1, Predicate var2) { + if (this.ref.get() instanceof VanishableBridge vb) { + if (!vb.bridge$isInvisible()) { + this.proxy.sendToTrackingPlayersFiltered(var1, var2); + } + return; + } + this.proxy.sendToTrackingPlayersFiltered(var1, var2); + } +} diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 84fcf7fa112..4433905b18d 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -86,6 +86,7 @@ import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor; import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor; import org.spongepowered.common.config.SpongeGameConfigs; +import org.spongepowered.common.data.datasync.NoOpSynchronizer; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.profile.SpongeProfileProperty; import org.spongepowered.common.util.Constants; @@ -117,7 +118,7 @@ public static AttributeSupplier createAttributes() { } // A queue of packets waiting to send to players tracking this human - private final Map>>> playerPacketMap = new HashMap<>(); + private final Map>>> playerPacketMap = new HashMap<>(); private ResolvableProfile fakeProfile; private boolean aiDisabled = false, leftHanded = false; @@ -398,8 +399,7 @@ private void respawnOnClient() { this.pushPackets(new ClientboundRemoveEntitiesPacket(this.getId()), this.createPlayerListPacket(EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class))); this.pushPackets(this.getAddEntityPacket(new ServerEntity( (ServerLevel) this.level(), - this, 1, true, packet -> {}, - (packet, list) -> {} + this, 1, true, NoOpSynchronizer.INSTANCE ))); } @@ -445,7 +445,7 @@ public ClientboundPlayerInfoUpdatePacket createPlayerListPacket(final EnumSet... packets) { + public void pushPackets(final Packet... packets) { this.pushPackets(null, packets); // null = all players } @@ -456,8 +456,8 @@ public void pushPackets(final Packet... packets) { * @param player The player tracking this human * @param packets All packets to send in a single tick */ - public void pushPackets(final @Nullable ServerPlayer player, final Packet... packets) { - final List>> queue; + public void pushPackets(final @Nullable ServerPlayer player, final Packet... packets) { + final List>> queue; if (player == null) { queue = this.playerPacketMap.computeIfAbsent(null, k -> new ArrayList<>()); } else { @@ -472,8 +472,8 @@ public void pushPackets(final @Nullable ServerPlayer player, final Packet... * @param player The player to get packets for (or null for all players) * @return An array of packets to send in a single tick */ - public Stream> popQueuedPackets(final @Nullable ServerPlayer player) { - final List>> queue = this.playerPacketMap.get(player == null ? null : player.getUUID()); + public Stream> popQueuedPackets(final @Nullable ServerPlayer player) { + final List>> queue = this.playerPacketMap.get(player == null ? null : player.getUUID()); return queue == null || queue.isEmpty() ? Stream.empty() : queue.remove(0); } diff --git a/src/main/java/org/spongepowered/common/world/SpongePositionSourceFactory.java b/src/main/java/org/spongepowered/common/world/SpongePositionSourceFactory.java index 338497401d6..c3eb1cc05b0 100644 --- a/src/main/java/org/spongepowered/common/world/SpongePositionSourceFactory.java +++ b/src/main/java/org/spongepowered/common/world/SpongePositionSourceFactory.java @@ -43,7 +43,7 @@ public PositionSource of(final Vector3i position) { @Override public PositionSource of(final int x, final int y, final int z) { - return (PositionSource) new BlockPositionSource(new BlockPos(x, y, z)); + return (PositionSource) (Object) new BlockPositionSource(new BlockPos(x, y, z)); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 09146a1a2ae..4aa6bfaee7d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level; +import com.google.common.collect.Iterables; import net.kyori.adventure.sound.Sound; import net.minecraft.core.BlockPos; import net.minecraft.core.RegistryAccess; @@ -181,7 +182,8 @@ public Iterable loadedChunks() { if (chunkProvider instanceof ServerChunkCache) { final ChunkMapAccessor chunkManager = (ChunkMapAccessor) ((ServerChunkCache) chunkProvider).chunkMap; final List chunks = new ArrayList<>(); - chunkManager.invoker$getChunks().forEach(holder -> { + final var visibleChunks = chunkManager.accessor$visibleChunkMap(); + Iterables.unmodifiableIterable(visibleChunks.values()).forEach(holder -> { final WorldChunk chunk = (WorldChunk) holder.getTickingChunk(); if (chunk != null) { chunks.add(chunk); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMap_TrackedEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMap_TrackedEntityMixin.java index a3a9a2482d4..87c7b16da99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMap_TrackedEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMap_TrackedEntityMixin.java @@ -28,6 +28,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.network.ServerPlayerConnection; @@ -57,12 +58,12 @@ public abstract class ChunkMap_TrackedEntityMixin { * 2) We already have the players being iterated * 3) This achieves the same functionality without adding new accessors etc. */ - @Inject(method = "broadcast(Lnet/minecraft/network/protocol/Packet;)V", at = @At(value = "INVOKE", shift = At.Shift.AFTER, + @Inject(method = "sendToTrackingPlayers(Lnet/minecraft/network/protocol/Packet;)V", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/network/ServerPlayerConnection;send(Lnet/minecraft/network/protocol/Packet;)V")) private void impl$sendQueuedHumanPackets(final CallbackInfo ci, @Local final ServerPlayerConnection connection) { if (this.entity instanceof HumanEntity && connection instanceof ServerGamePacketListenerImpl) { final ServerPlayer player = ((ServerGamePacketListenerImpl) connection).player; - final Stream> packets = ((HumanEntity) this.entity).popQueuedPackets(player); + final Stream> packets = ((HumanEntity) this.entity).popQueuedPackets(player); packets.forEach(player.connection::send); } } @@ -74,7 +75,7 @@ public abstract class ChunkMap_TrackedEntityMixin { * entity is being "removed" from clients by way of literally being mimiced being * "untracked". This safeguards the players being updated erroneously. */ - @Inject(method = "broadcast(Lnet/minecraft/network/protocol/Packet;)V", at = @At("HEAD"), cancellable = true) + @Inject(method = "sendToTrackingPlayers(Lnet/minecraft/network/protocol/Packet;)V", at = @At("HEAD"), cancellable = true) private void impl$ignoreVanished(final Packet packet, final CallbackInfo ci) { if (this.entity instanceof VanishableBridge) { if (((VanishableBridge) this.entity).bridge$vanishState().invisible()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java index f1a98074f9d..2a56f356b46 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java @@ -27,6 +27,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.syncher.SynchedEntityData; @@ -45,15 +46,16 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor; -import org.spongepowered.common.bridge.data.VanishableBridge; import org.spongepowered.common.bridge.server.level.ServerPlayerBridge; +import org.spongepowered.common.data.datasync.VanishedFilteringSynchronizer; import org.spongepowered.common.entity.living.human.HumanEntity; +import java.lang.ref.WeakReference; import java.util.Collection; import java.util.EnumSet; import java.util.List; -import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Stream; @Mixin(ServerEntity.class) @@ -61,10 +63,16 @@ public abstract class ServerEntityMixin { // @formatter:off @Shadow @Final private Entity entity; - @Shadow @Final @Mutable private Consumer> broadcast; + @Shadow @Final @Mutable private ServerEntity.Synchronizer synchronizer; // @formatter:on /** + * @param serverLevel The world + * @param entity The entity being tracked + * @param trackingRange The update frequency + * @param trackMovementDeltas Whether velocity updates are sent + * @param broadcaster The consumer (a method handle for EntityTracker#sendToAllTracking) + * @param ci The callback info * @author gabizou * @reason Because the packets for *most* all entity updates are handled * through this consumer tick, basically all the players tracking the @@ -77,25 +85,13 @@ public abstract class ServerEntityMixin { * any and all players tracking our tracked entity by filtering the consumer first, * then as a fail safe, the EntityTracker mixin. Meanwhile, all other states are updated * just fine. - * - * @param serverLevel The world - * @param entity The entity being tracked - * @param trackingRange The update frequency - * @param trackMovementDeltas Whether velocity updates are sent - * @param broadcaster The consumer (a method handle for EntityTracker#sendToAllTracking) - * @param ci The callback info */ @Inject(method = "", at = @At("TAIL")) - private void impl$wrapConsumer(final ServerLevel serverLevel, final Entity entity, final int trackingRange, - final boolean trackMovementDeltas, final Consumer> broadcaster, - final BiConsumer filter, final CallbackInfo ci) { - this.broadcast = (packet) -> { - if (this.entity instanceof VanishableBridge bridge) { - if (!bridge.bridge$vanishState().invisible()) { - broadcaster.accept(packet); - } - } - }; + private void impl$wrapConsumer( + final ServerLevel serverLevel, final Entity entity, final int trackingRange, + final boolean trackMovementDeltas, final ServerEntity.Synchronizer broadcaster, + final CallbackInfo ci) { + this.synchronizer = new VanishedFilteringSynchronizer(broadcaster, new WeakReference<>(this.entity)); } @Inject(method = "removePairing", at = @At("RETURN")) @@ -139,8 +135,8 @@ public abstract class ServerEntityMixin { if (!(this.entity instanceof final HumanEntity human)) { return; } - final Stream> packets = human.popQueuedPackets(null); - packets.forEach(this.broadcast); + final Stream> packets = human.popQueuedPackets(null); + packets.forEach(this.synchronizer::sendToTrackingPlayers); // Note that this will further call in ChunkManager_EntityTrackerMixin // for any player specific packets to send. } @@ -169,15 +165,19 @@ public abstract class ServerEntityMixin { return packed; } - @WrapOperation(method = "sendChanges", at = @At(value = "INVOKE", target = "Ljava/util/function/BiConsumer;accept(Ljava/lang/Object;Ljava/lang/Object;)V")) - private void impl$sendSetPassengersToSelf(final BiConsumer instance, final Object packet, final Object ignored, final Operation original) { + @WrapOperation(method = "sendChanges", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerEntity$Synchronizer;sendToTrackingPlayersFiltered(Lnet/minecraft/network/protocol/Packet;Ljava/util/function/Predicate;)V")) + private void impl$sendSetPassengersToSelf( + final ServerEntity.Synchronizer instance, final Packet packet, + final Predicate serverPlayerPredicate, final Operation original) { // When passengers are removed from a player entity, the target // is the player itself, and we need to synchronize it to them. // In vanilla, it is not possible to ride player entities // so we never end up hitting this code path. - original.call(instance, packet, ignored); + original.call(instance, packet, serverPlayerPredicate); if (this.entity instanceof final ServerPlayer player) { - player.connection.send((Packet) packet); + player.connection.send(packet); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 9ea5a5c4718..1e8da32f40b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -52,6 +52,7 @@ import net.minecraft.world.RandomSequences; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiManager; +import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.CustomSpawner; @@ -509,18 +510,20 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } } - @Redirect(method = "lambda$updatePOIOnBlockStateChange$14", + @WrapOperation(method = "lambda$updatePOIOnBlockStateChange$15", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;add(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;)V" + target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;add(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;)Lnet/minecraft/world/entity/ai/village/poi/PoiRecord;" ) ) - private void impl$avoidAddingPoiUpdatesOnUnloadedWorld(final PoiManager manager, final BlockPos pos, final Holder type) { + private PoiRecord impl$avoidAddingPoiUpdatesOnUnloadedWorld( + final PoiManager instance, final BlockPos pos, final Holder type, final Operation original + ) { // Unloaded worlds should not notify PoiManager of changes if (!SpongeCommon.server().levelKeys().contains(this.shadow$dimension())) { - return; + return null; } - manager.add(pos, type); + return original.call(instance, pos, type); } @Inject( diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java index b7a44af5cb8..c007045332f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/entity/LivingEntityMixin_Inventory.java @@ -79,8 +79,9 @@ protected LivingEntityMixin_Inventory(final EntityType param0, final Level pa original.call(slot, item); } + @Inject(method = "handleHandSwap", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;broadcast(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/protocol/Packet;)V")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;sendToTrackingPlayers(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/protocol/Packet;)V")) protected void inventory$onHandleHandSwap(final Map map, final CallbackInfo ci) { final Slot mainHand = this.impl$getSpongeSlot(EquipmentSlot.MAINHAND); final var lastMainHand = this.lastEquipmentItems.get(EquipmentSlot.MAINHAND); From 9f1b415f9492da5299f1a327c8ce64293ba7a84f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 22:53:10 -0700 Subject: [PATCH 361/586] feat(minecraft): update to 1.21.9-pre1 Notable changes: - Updated `mixinextras` to 0.5.0. - Refactored respawn logic to use `LevelData.RespawnData`. - Adjusted spawn position handling across level and player data. See: https://minecraft.wiki/w/Java_Edition_1.21.9_Pre-Release_1 --- gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 8 ++++++++ .../advancement/SpongeAdvancementBuilder.java | 2 +- .../data/provider/world/WorldPropertiesData.java | 11 ++++++++--- .../common/world/server/SpongeWorldManager.java | 13 ++++++++----- .../core/server/level/ServerPlayerMixin.java | 16 +--------------- .../core/server/players/PlayerListMixin.java | 4 ++-- .../world/level/block/EndPortalBlockMixin.java | 2 +- .../level/storage/PrimaryLevelDataMixin.java | 12 ++++++------ .../dedicated/DedicatedServerMixin_Tracker.java | 2 +- .../level/ServerExplosionMixin_Vanilla.java | 11 +++++------ 12 files changed, 43 insertions(+), 42 deletions(-) diff --git a/gradle.properties b/gradle.properties index fcd673c6e34..fdf8fb46f56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=25w37a +minecraftVersion=1.21.9-pre1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a4510edfba6..a18b360a996 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ asm = "9.8" log4j = "2.24.1" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" -mixinextras = "0.4.1" +mixinextras = "0.5.0" modlauncher = "10.2.2" securemodules = "2.2.22" fancymodloader = "9.0.16" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a83649978f3..5ff83c7aa5f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2410,6 +2410,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index 217086de3a7..505a182d0d2 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -72,7 +72,7 @@ public Advancement.Builder.RootStep root() { @Override public Advancement.Builder background(final ResourceKey backgroundPath) { - this.backgroundPath = new ClientAsset((ResourceLocation) (Object) backgroundPath); + this.backgroundPath = new ClientAsset.ResourceTexture((ResourceLocation) (Object) backgroundPath); return this; } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index fde1474eb0a..2969efd9ec0 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.data.provider.world; +import net.minecraft.core.GlobalPos; import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.storage.LevelData; @@ -56,15 +57,19 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(LevelData.class) .create(Keys.SPAWN_POSITION) - .get(h -> VecHelper.toVector3i(h.getSpawnPos())) + .get(h -> VecHelper.toVector3i(h.getRespawnData().pos())) .create(Keys.HARDCORE) .get(LevelData::isHardcore) .create(Keys.WORLD_DIFFICULTY) .get(h -> (Difficulty) (Object) h.getDifficulty()) .asMutable(WritableLevelData.class) .create(Keys.SPAWN_POSITION) - .get(h -> VecHelper.toVector3i(h.getSpawnPos())) - .set((h, v) -> h.setSpawn(VecHelper.toBlockPos(v), h.getSpawnAngle())) + .get(h -> VecHelper.toVector3i(h.getRespawnData().pos())) + .set((h, v) -> h.setSpawn( + new LevelData.RespawnData(new GlobalPos( + h.getRespawnData().dimension(), + VecHelper.toBlockPos(v) + ), h.getRespawnData().pitch(), h.getRespawnData().yaw()))) .asMutable(ServerLevelData.class) .create(Keys.GAME_MODE) .get(h -> (GameMode) (Object) h.getGameType()) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 3e431f0ef9c..c3a9249a9f1 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -32,6 +32,7 @@ import net.minecraft.ReportedException; import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.MiscOverworldFeatures; @@ -61,6 +62,7 @@ import net.minecraft.world.level.levelgen.PhantomSpawner; import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelDataAndDimensions; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; @@ -933,10 +935,10 @@ private ServerLevel prepareLevel(final ServerLevel level) { if (levelDataBridge.bridge$performsSpawnLogic()) { MinecraftServerAccessor.invoker$setInitialSpawn(level, levelData, worldData.worldGenOptions().generateBonusChest(), isDebugGeneration, server.getLevelLoadListener()); } else if (Level.END.equals(level.dimension())) { - levelData.setSpawn(ServerLevel.END_SPAWN_POINT, 0); + levelData.setSpawn(new LevelData.RespawnData(new GlobalPos(level.dimension(), ServerLevel.END_SPAWN_POINT), 0, 0)); } } else if (worldData.worldGenOptions().generateBonusChest()) { - final BlockPos pos = levelData.getSpawnPos(); + final BlockPos pos = levelData.getRespawnData().pos(); final ConfiguredFeature bonusChestFeature = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE).getValue(MiscOverworldFeatures.BONUS_CHEST); bonusChestFeature.place(level, level.getChunkSource().getGenerator(), level.random, pos); } @@ -975,7 +977,8 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel le MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().location()); final ServerChunkCache chunkSource = level.getChunkSource(); - level.setDefaultSpawnPos(level.getSharedSpawnPos(), level.getSharedSpawnAngle()); + final var respawnData = level.getRespawnData(); + level.setRespawnData(new LevelData.RespawnData(respawnData.globalPos(), respawnData.pitch(), respawnData.yaw())); final CompletableFuture generationFuture = new CompletableFuture<>(); Sponge.asyncScheduler().submit( @@ -999,10 +1002,10 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel le private void loadSpawnChunks(final ServerLevel level) { MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().location()); - final BlockPos spawnPoint = level.getSharedSpawnPos(); + final var respawnData = level.getRespawnData(); final ServerChunkCache chunkSource = level.getChunkSource(); ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos()); - level.setDefaultSpawnPos(spawnPoint, level.getSharedSpawnAngle()); + level.setRespawnData(respawnData); ((MinecraftServerAccessor) this.server).accessor$nextTickTimeNanos(Util.getNanos() + 10L * TimeUtil.NANOSECONDS_PER_MILLISECOND); ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 45ed29153b4..ec91e056274 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -1009,7 +1009,7 @@ private boolean isPvpAllowed() { @Share("sponge:overridden-respawn") final LocalRef> dimension ) { final var config = original.call(player); - final var defaulted = config == null ? Level.OVERWORLD : config.dimension(); + final var defaulted = config == null ? Level.OVERWORLD : config.respawnData().dimension(); var playerRespawnDestination = this.server.getLevel(defaulted); if (playerRespawnDestination == null) { @@ -1042,20 +1042,6 @@ private boolean isPvpAllowed() { return original.call(instance, key); } - @WrapOperation( - method = "findRespawnPositionAndUseSpawnBlock", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;") - ) - private ServerLevel impl$callRespawnPlayerSelectWorld( - final MinecraftServer instance, final Operation original, - @Share("sponge:overridden-respawn") final LocalRef> dimension - ) { - if (dimension.get() != null) { - return instance.getLevel(dimension.get()); - } - return original.call(instance); - } - @Inject(method = "findRespawnPositionAndUseSpawnBlock", at = @At("RETURN")) private void impl$onFindRespawnPositionAndUseSpawnBlock(final CallbackInfoReturnable cir) { ((TeleportTransitionAccessor) (Object) cir.getReturnValue()).accessor$newLevel(this.impl$respawnLevel); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 98ccf4867d6..24fa09a364c 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -278,7 +278,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { SpongeCommon.logger().warn("The player '{}' was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().name()); mcWorld = this.server.overworld(); - final BlockPos spawnPoint = mcWorld.getSharedSpawnPos(); + final BlockPos spawnPoint = mcWorld.getRespawnData().pos(); mcPlayer.setPos(spawnPoint.getX() + 0.5, spawnPoint.getY() + 0.5, spawnPoint.getZ() + 0.5); } @@ -488,7 +488,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getX()D"), slice = @Slice( from = @At(value = "NEW", target = "(Lnet/minecraft/network/protocol/game/CommonPlayerSpawnInfo;B)Lnet/minecraft/network/protocol/game/ClientboundRespawnPacket;"), - to = @At(value = "NEW", target = "(Lnet/minecraft/core/BlockPos;F)Lnet/minecraft/network/protocol/game/ClientboundSetDefaultSpawnPositionPacket;") + to = @At(value = "NEW", target = "(Lnet/minecraft/world/level/storage/LevelData$RespawnData;)Lnet/minecraft/network/protocol/game/ClientboundSetDefaultSpawnPositionPacket;") ) ) private double impl$callRespawnPlayerRecreateEvent(final net.minecraft.server.level.ServerPlayer newPlayer, diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java index c331e66722d..0f985a63a76 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java @@ -70,7 +70,7 @@ public abstract class EndPortalBlockMixin implements PortalBlockBridge { return ServerLocation.of((ServerWorld) transition.newLevel(), VecHelper.toVector3d(transition.position())); } - final var sharedSpawnPos = toLevel.getSharedSpawnPos(); + final var sharedSpawnPos = toLevel.getRespawnData().pos(); final var spawnPos = ((net.minecraft.world.entity.Entity) entity).adjustSpawnLocation(toLevel, sharedSpawnPos).getBottomCenter(); return ServerLocation.of((ServerWorld) toLevel, VecHelper.toVector3d(spawnPos)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 1f9f0090dc9..bee0076bc00 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -32,7 +32,7 @@ import com.mojang.serialization.Dynamic; import com.mojang.serialization.DynamicOps; import net.kyori.adventure.text.Component; -import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; import net.minecraft.core.UUIDUtil; @@ -55,6 +55,7 @@ import net.minecraft.world.level.levelgen.WorldDimensions; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WorldData; @@ -91,11 +92,10 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat // @formatter:off @Shadow private LevelSettings settings; - @Shadow private BlockPos spawnPos; - @Shadow private float spawnAngle; + @Shadow private LevelData.RespawnData respawnData; @Shadow public abstract boolean shadow$isDifficultyLocked(); - @Shadow public abstract void shadow$setSpawn(BlockPos p_176143_1_, float p_176143_2_); + @Shadow public abstract void shadow$setSpawn(LevelData.RespawnData $$0); // @formatter:on @Shadow @@ -249,7 +249,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat final Vector3i spawnPos = bridge.bridge$spawnPosition(); if (spawnPos != null) { - this.shadow$setSpawn(VecHelper.toBlockPos(spawnPos), this.spawnAngle); + this.shadow$setSpawn(new RespawnData(new GlobalPos(this.respawnData.dimension(), VecHelper.toBlockPos(spawnPos)),this.respawnData.pitch(), this.respawnData.yaw())); this.impl$customSpawnPosition = true; } @@ -362,7 +362,7 @@ public String toString() { .add("key=" + this.impl$spongeData.key()) .add("worldType=" + this.impl$dimensionType) .add("uniqueId=" + this.impl$spongeData.uniqueId()) - .add("spawn=" + VecHelper.toVector3i(this.spawnPos)) + .add("spawn=" + this.respawnData.toString()) .add("gameType=" + this.getGameType()) .add("hardcore=" + this.isHardcore()) .add("difficulty=" + this.getDifficulty()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java index 0ae3cea6ea8..e47a30607f6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/dedicated/DedicatedServerMixin_Tracker.java @@ -70,7 +70,7 @@ public boolean isUnderSpawnProtection(final ServerLevel worldIn, final BlockPos } } - final BlockPos spawnPoint = worldIn.getSharedSpawnPos(); + final BlockPos spawnPoint = worldIn.getRespawnData().pos(); final int protectionRadius = this.shadow$spawnProtectionRadius(); return protectionRadius > 0 diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java index e8ed777f954..28606236790 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/ServerExplosionMixin_Vanilla.java @@ -24,6 +24,8 @@ */ package org.spongepowered.vanilla.mixin.core.world.level; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -105,12 +107,9 @@ public abstract class ServerExplosionMixin_Vanilla { return entities; } - @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 vanilla$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { - // Honor our knockback value from event - return new Vec3($$0 * this.impl$knockbackMultiplier, - $$1 * this.impl$knockbackMultiplier, - $$2 * this.impl$knockbackMultiplier); + @WrapOperation(method = "hurtEntities",at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;scale(D)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 vanilla$setKnockbackMultiplier(Vec3 instance, double xVel, Operation original) { + return original.call(instance, xVel * this.impl$knockbackMultiplier); } } From 08771a9da2085c3e47397e4be12f6169c2c8a0c0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 23:06:19 -0700 Subject: [PATCH 362/586] fix(gameprofile): update `impl$lookUpViaSponge` to use appropriate NameAndId --- .../mixin/core/server/players/GameProfileCacheMixin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java index 062f6bc1ba1..f1dcdc8088e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/GameProfileCacheMixin.java @@ -148,10 +148,11 @@ public abstract class GameProfileCacheMixin implements GameProfileCacheBridge { } @Redirect(method = "lookupGameProfile", at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/GameProfileRepository;findProfileByName(Ljava/lang/String;)Ljava/util/Optional;")) - private static Optional impl$lookUpViaSponge(final GameProfileRepository instance, final String name) { + private static Optional impl$lookUpViaSponge(final GameProfileRepository instance, final String name) { final GameProfileManager profileManager = Sponge.server().gameProfileManager(); try { - return Optional.of(SpongeGameProfile.toMcProfile(profileManager.basicProfile(name).join())); + final var join = profileManager.basicProfile(name).join(); + return Optional.of(new com.mojang.authlib.yggdrasil.response.NameAndId(join.uuid(), join.name().orElse(""))); } catch (final Throwable e) { return Optional.empty(); } From ee89a9331eab9beeb404fd7f8e24e88bee65c597 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 23:06:38 -0700 Subject: [PATCH 363/586] feat(minecraft): update to 1.21.9-pre2 See: https://minecraft.wiki/w/Java_Edition_1.21.9_Pre-Release_2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fdf8fb46f56..d67f6b9e064 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=1.21.9-pre1 +minecraftVersion=1.21.9-pre2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From c8c8a5b62286767ef59ff3d146c2c4201209cc93 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 23:22:10 -0700 Subject: [PATCH 364/586] feat(minecraft): update to 1.21.9-pre3 See: https://minecraft.wiki/w/Java_Edition_1.21.9_Pre-Release_3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d67f6b9e064..8ff61ee3b4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=1.21.9-pre2 +minecraftVersion=1.21.9-pre3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 8596256cab7807c18dcebc568fdae542a36bd563 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 23 Sep 2025 23:33:49 -0700 Subject: [PATCH 365/586] feat(minecraft): update to 1.21.9-pre4 See: https://minecraft.wiki/w/Java_Edition_1.21.9_Pre-Release_4 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8ff61ee3b4e..41511f810c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=1.21.9-pre3 +minecraftVersion=1.21.9-pre4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From f8b5721ed291ad49251e8c872e74c473aee2227e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 24 Sep 2025 14:41:55 +0200 Subject: [PATCH 366/586] Implement Viewer#playTotemOfUndyingEffect (#4196) --- SpongeAPI | 2 +- .../common/effect/SpongeForwardingViewer.java | 6 ++++ .../common/effect/util/ViewerPacketUtil.java | 36 +++++++++++++++++++ .../common/item/util/ItemStackUtil.java | 4 +++ .../world/entity/player/PlayerMixin_API.java | 6 ++++ 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index d15129ee57e..5dd330e27cd 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d15129ee57e97491fc3a4e1e1ba6051683d142b2 +Subproject commit 5dd330e27cd42eee90c289bdbb51f760b4f4e038 diff --git a/src/main/java/org/spongepowered/common/effect/SpongeForwardingViewer.java b/src/main/java/org/spongepowered/common/effect/SpongeForwardingViewer.java index 74b7197b3c6..d964a819cfb 100644 --- a/src/main/java/org/spongepowered/common/effect/SpongeForwardingViewer.java +++ b/src/main/java/org/spongepowered/common/effect/SpongeForwardingViewer.java @@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener; import org.spongepowered.api.effect.ForwardingViewer; import org.spongepowered.api.effect.sound.music.MusicDisc; +import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.common.bridge.effect.ViewerBridge; public interface SpongeForwardingViewer extends SpongeViewer, ForwardingViewer, ViewerBridge { @@ -50,6 +51,11 @@ public interface SpongeForwardingViewer extends SpongeViewer, ForwardingViewer, // Viewer + @Override + default void playTotemOfUndyingEffect(final ItemStackLike stack) { + this.audiences().forEach(viewer -> viewer.playTotemOfUndyingEffect(stack)); + } + @Override default void playMusicDisc(final int x, final int y, final int z, final MusicDisc musicDisc) { this.audiences().forEach(viewer -> viewer.playMusicDisc(x, y, z, musicDisc)); diff --git a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java index a8cfbed2216..d2d53c0086e 100644 --- a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java +++ b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java @@ -31,6 +31,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; @@ -38,8 +39,10 @@ import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.network.protocol.game.ClientboundBundlePacket; import net.minecraft.network.protocol.game.ClientboundClearTitlesPacket; +import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetPlayerInventoryPacket; import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket; import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket; import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket; @@ -50,7 +53,10 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.JukeboxSong; +import net.minecraft.world.item.component.DeathProtection; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.NonNull; @@ -60,12 +66,15 @@ import org.spongepowered.api.effect.particle.ParticleEffect; import org.spongepowered.api.effect.sound.music.MusicDisc; import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.api.world.World; import org.spongepowered.api.world.WorldType; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeEngine; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.effect.particle.SpongeParticleHelper; +import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.network.packet.ChangeViewerEnvironmentPacket; import java.time.Duration; @@ -80,6 +89,33 @@ public static ChangeViewerEnvironmentPacket changeEnvironment(final WorldType wo return new ChangeViewerEnvironmentPacket((DimensionType) (Object) Objects.requireNonNull(worldType, "worldType")); } + public static ClientboundBundlePacket deathProtection(final Player player, final ItemStackLike stack) { + final ItemStack item = ItemStackUtil.fromLikeToNativeCopy(stack); + // Client will play item animation only if it has DEATH_PROTECTION component, + // otherwise it will use totem of undying + if (!item.has(DataComponents.DEATH_PROTECTION)) { + item.set(DataComponents.DEATH_PROTECTION, new DeathProtection(List.of())); + } + + final net.minecraft.world.entity.player.Player mcPlayer = (net.minecraft.world.entity.player.Player) player; + final Inventory inventory = mcPlayer.getInventory(); + final int totemSlot = inventory.selected; + final net.minecraft.world.item.ItemStack oldItem = inventory.getSelected(); + + final List> packets = new ArrayList<>(); + + // First we need to send a fake totem ItemStack to the player's hand + packets.add(new ClientboundSetPlayerInventoryPacket(totemSlot, item)); + + // Next we tell the client to play death protection animation + packets.add(new ClientboundEntityEventPacket(mcPlayer, (byte) 35)); + + // Now we can remove the fake totem + packets.add(new ClientboundSetPlayerInventoryPacket(totemSlot, oldItem)); + + return new ClientboundBundlePacket(packets); + } + public static ClientboundBundlePacket spawnParticles(final ParticleEffect particleEffect, final double x, final double y, final double z) { return SpongeParticleHelper.createPacket(particleEffect, x, y, z); } diff --git a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java index b9b30d606d2..e9d91aa1786 100644 --- a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java +++ b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java @@ -167,6 +167,10 @@ public static net.minecraft.world.item.ItemStack fromLikeToNative(@Nullable Item return itemStack == null ? ItemStackUtil.emptyNative() : itemStack.isEmpty() ? ItemStackUtil.emptyNative() : ItemStackUtil.toNative(itemStack.asMutable()); } + public static net.minecraft.world.item.ItemStack fromLikeToNativeCopy(@Nullable ItemStackLike itemStack) { + return itemStack == null ? ItemStackUtil.emptyNative() : itemStack.isEmpty() ? ItemStackUtil.emptyNative() : ItemStackUtil.toNative(itemStack.asMutableCopy()); + } + public static ItemStack empty() { return ItemStackUtil.fromNative(net.minecraft.world.item.ItemStack.EMPTY); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java index 28b4c304ef8..a611c75afe2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java @@ -38,6 +38,7 @@ import org.spongepowered.api.effect.sound.music.MusicDisc; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface.Remap; @@ -111,6 +112,11 @@ public String name() { // Viewer + @Override + public void playTotemOfUndyingEffect(final ItemStackLike stack) { + ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.deathProtection(this, stack)); + } + @Override public void playMusicDisc(final int x, final int y, final int z, final MusicDisc musicDisc) { ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.playMusicDisc(x, y, z, musicDisc, this.shadow$level().registryAccess())); From 6926cd7e5243f7053af1ef4d290f8a39258a7abe Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 24 Sep 2025 14:39:18 +0200 Subject: [PATCH 367/586] Add Viewer test plugin --- .../common/effect/util/ViewerPacketUtil.java | 11 +++- .../world/entity/player/PlayerMixin_API.java | 2 +- .../spongepowered/test/viewer/ViewerTest.java | 55 +++++++++++++++++++ .../META-INF/sponge_plugins.json | 6 ++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 testplugins/src/main/java/org/spongepowered/test/viewer/ViewerTest.java diff --git a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java index d2d53c0086e..9700f91dfab 100644 --- a/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java +++ b/src/main/java/org/spongepowered/common/effect/util/ViewerPacketUtil.java @@ -89,7 +89,7 @@ public static ChangeViewerEnvironmentPacket changeEnvironment(final WorldType wo return new ChangeViewerEnvironmentPacket((DimensionType) (Object) Objects.requireNonNull(worldType, "worldType")); } - public static ClientboundBundlePacket deathProtection(final Player player, final ItemStackLike stack) { + public static Packet totemOfUndying(final Player player, final ItemStackLike stack) { final ItemStack item = ItemStackUtil.fromLikeToNativeCopy(stack); // Client will play item animation only if it has DEATH_PROTECTION component, // otherwise it will use totem of undying @@ -102,13 +102,18 @@ public static ClientboundBundlePacket deathProtection(final Player player, final final int totemSlot = inventory.selected; final net.minecraft.world.item.ItemStack oldItem = inventory.getSelected(); + final ClientboundEntityEventPacket effectPacket = new ClientboundEntityEventPacket(mcPlayer, (byte) 35); + if (ItemStack.matches(oldItem, item)) { + return effectPacket; + } + final List> packets = new ArrayList<>(); // First we need to send a fake totem ItemStack to the player's hand packets.add(new ClientboundSetPlayerInventoryPacket(totemSlot, item)); - // Next we tell the client to play death protection animation - packets.add(new ClientboundEntityEventPacket(mcPlayer, (byte) 35)); + // Next we tell the client to play the totem of undying effect + packets.add(effectPacket); // Now we can remove the fake totem packets.add(new ClientboundSetPlayerInventoryPacket(totemSlot, oldItem)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java index a611c75afe2..9d0a167240e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java @@ -114,7 +114,7 @@ public String name() { @Override public void playTotemOfUndyingEffect(final ItemStackLike stack) { - ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.deathProtection(this, stack)); + ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.totemOfUndying(this, stack)); } @Override diff --git a/testplugins/src/main/java/org/spongepowered/test/viewer/ViewerTest.java b/testplugins/src/main/java/org/spongepowered/test/viewer/ViewerTest.java new file mode 100644 index 00000000000..99943c3dd25 --- /dev/null +++ b/testplugins/src/main/java/org/spongepowered/test/viewer/ViewerTest.java @@ -0,0 +1,55 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.test.viewer; + +import com.google.inject.Inject; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.effect.Viewer; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; + +@Plugin("viewertest") +public final class ViewerTest { + + private final PluginContainer plugin; + + @Inject + public ViewerTest(final PluginContainer plugin) { + this.plugin = plugin; + } + + @Listener + public void onRegisterCommand(final RegisterCommandEvent event) { + event.register(this.plugin, Command.builder().executor(context -> { + context.cause().first(Viewer.class).get().playTotemOfUndyingEffect(ItemStack.of(ItemTypes.REDSTONE)); + return CommandResult.success(); + }).build(), "totem"); + } +} diff --git a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json index 8af3eb43009..54935839503 100644 --- a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json +++ b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json @@ -377,6 +377,12 @@ "name": "Decorated Pot Data", "entrypoint": "org.spongepowered.test.data.PotDataTest", "description": "Decorated Pot Data" + }, + { + "id": "viewertest", + "name": "Viewer Test", + "entrypoint": "org.spongepowered.test.viewer.ViewerTest", + "description": "Viewer tests" } ] } From 687e0d178e16fe478179b9538826268dd6407899 Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Fri, 28 Mar 2025 04:25:19 +0300 Subject: [PATCH 368/586] Implement ItemActions (#4195) --- SpongeAPI | 2 +- .../generator/item/ItemRegistries.java | 7 + .../provider/item/stack/ItemStackData.java | 34 ++--- .../common/item/SpongeItemActionFactory.java | 93 +++++++++++++ .../registry/SpongeFactoryProvider.java | 3 + ...lyStatusEffectsConsumeEffectMixin_API.java | 56 ++++++++ ...llStatusEffectsConsumeEffectMixin_API.java | 33 +++++ .../ConsumeEffectMixin_API.java | 60 +++++++++ .../ConsumeEffect_TypeMixin_API.java | 33 +++++ .../PlaySoundConsumeEffectMixin_API.java | 45 +++++++ ...veStatusEffectsConsumeEffectMixin_API.java | 49 +++++++ ...eleportRandomlyConsumeEffectMixin_API.java | 42 ++++++ src/mixins/resources/mixins.sponge.api.json | 7 + .../test/data/ConsumableDataTest.java | 125 ++++++++++++++++++ .../org/spongepowered/test/data/DataTest.java | 1 - .../META-INF/sponge_plugins.json | 6 + 16 files changed, 578 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java create mode 100644 testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java diff --git a/SpongeAPI b/SpongeAPI index 5dd330e27cd..34622032e7b 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 5dd330e27cd42eee90c289bdbb51f760b4f4e038 +Subproject commit 34622032e7bda623d9eff36cd00e7d1503cb2af6 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java index 63366a3e4c3..205a2cc1934 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java @@ -111,6 +111,13 @@ public static List itemRegistries(final Context context) { $ -> true, RegistryScope.SERVER ), + new RegistryEntriesGenerator<>( + "data.type", + "ItemActionTypes", + "ITEM_ACTION_TYPE", + context.relativeClass("data.type", "ItemActionType"), + Registries.CONSUME_EFFECT_TYPE + ), new EnumEntriesValidator<>( "entity.display", "ItemDisplayTypes", diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index d0996aa7c40..eb411c5c0b7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -25,12 +25,11 @@ package org.spongepowered.common.data.provider.item.stack; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; @@ -43,22 +42,19 @@ import net.minecraft.world.item.component.Consumable; import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.DamageResistant; +import net.minecraft.world.item.component.DeathProtection; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; import net.minecraft.world.item.component.UseCooldown; import net.minecraft.world.item.component.UseRemainder; -import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; -import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; import net.minecraft.world.item.consume_effects.ConsumeEffect; -import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; -import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; -import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Platform; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.DataTransactionResult; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ItemAction; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; @@ -78,7 +74,7 @@ public final class ItemStackData { public static final FoodProperties DEFAULT_FOOD_PROPERTIES = new FoodProperties(0, 0, false); - public static final Consumable DEFAULT_CONSUMABLE_PROPERTIES = new Consumable(1.6F, ItemUseAnimation.EAT, null, true, List.of()); + public static final Consumable DEFAULT_CONSUMABLE_PROPERTIES = new Consumable(1.6F, ItemUseAnimation.EAT, SoundEvents.GENERIC_EAT, true, List.of()); private ItemStackData() { } @@ -100,14 +96,6 @@ public static void register(final DataProviderRegistrator registrator) { // TODO DataComponents.RECIPES - for Items.KNOWLEDGE_BOOK // TODO DataComponents.OMINOUS_BOTTLE_AMPLIFIER 1.21 - // TODO rework applicable potion effects to consume effects - final var applicablePotionEffects = Keys.APPLICABLE_POTION_EFFECTS; - ConsumeEffect newPotionEffects = new ApplyStatusEffectsConsumeEffect(List.of()); - ConsumeEffect teleportRand = new TeleportRandomlyConsumeEffect(5); - ConsumeEffect removeStatusEffects = new RemoveStatusEffectsConsumeEffect(HolderSet.empty()); - ConsumeEffect clearStatusEffects = new ClearAllStatusEffectsConsumeEffect(); - ConsumeEffect playSoundEffect = new PlaySoundConsumeEffect(Holder.direct(null)); - registrator .asMutable(ItemStack.class) .create(Keys.BURN_TIME) @@ -252,6 +240,20 @@ public static void register(final DataProviderRegistrator registrator) { }) .set((h, v) -> h.update(DataComponents.CONSUMABLE, DEFAULT_CONSUMABLE_PROPERTIES, c -> new Consumable(v.ticks() / 20f, c.animation(), c.sound(), c.hasConsumeParticles(), c.onConsumeEffects()))) + .create(Keys.CONSUME_ACTIONS) + .get(h -> { + final var consumable = h.get(DataComponents.CONSUMABLE); + return consumable == null ? null : (List) (Object) consumable.onConsumeEffects(); + }) + .set((h, v) -> h.update(DataComponents.CONSUMABLE, DEFAULT_CONSUMABLE_PROPERTIES, + c -> new Consumable(c.consumeSeconds(), c.animation(), c.sound(), c.hasConsumeParticles(), (List) (Object) v))) + .create(Keys.DEATH_PROTECTION_ACTIONS) + .get(h -> { + final var deathProtection = h.get(DataComponents.DEATH_PROTECTION); + return deathProtection == null ? null : (List) (Object) deathProtection.deathEffects(); + }) + .set((h, v) -> h.set(DataComponents.DEATH_PROTECTION, new DeathProtection((List) (Object) v))) + .delete(h -> h.remove(DataComponents.DEATH_PROTECTION)) .create(Keys.FOOD_CONVERTS_TO) .get(h -> { final var remainder = h.get(DataComponents.USE_REMAINDER); diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java b/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java new file mode 100644 index 00000000000..ce8a0bcc56f --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java @@ -0,0 +1,93 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item; + +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; +import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.api.effect.potion.PotionEffectType; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.api.tag.Tag; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class SpongeItemActionFactory implements ItemAction.Factory { + + @Override + public ItemAction.ApplyEffects applyEffects(final double chance, final List effects) { + Objects.requireNonNull(effects, "effects"); + if (chance < 0 || chance > 1) { + throw new IllegalArgumentException("chance must be in range [0; 1]: " + chance); + } + return (ItemAction.ApplyEffects) (Object) new ApplyStatusEffectsConsumeEffect((List) List.copyOf(effects), (float) chance); + } + + @Override + public ItemAction.RemoveEffects removeEffects(final Set effectTypes) { + Objects.requireNonNull(effectTypes, "effectTypes"); + final var holderSet = HolderSet.direct( + effectType -> BuiltInRegistries.MOB_EFFECT.wrapAsHolder((MobEffect) effectType), + effectTypes); + return (ItemAction.RemoveEffects) (Object) new RemoveStatusEffectsConsumeEffect(holderSet); + } + + @Override + public ItemAction.RemoveEffects removeEffects(final Tag effectTypeTag) { + Objects.requireNonNull(effectTypeTag, "effectTypeTag"); + final var tag = (TagKey) (Object) effectTypeTag; + final var holderSet = BuiltInRegistries.MOB_EFFECT.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return (ItemAction.RemoveEffects) (Object) new RemoveStatusEffectsConsumeEffect(holderSet); + } + + @Override + public ItemAction.ClearEffects clearEffects() { + return (ItemAction.ClearEffects) (Object) ClearAllStatusEffectsConsumeEffect.INSTANCE; + } + + @Override + public ItemAction.PlaySound playSound(final SoundType soundType) { + Objects.requireNonNull(soundType, "soundType"); + return (ItemAction.PlaySound) (Object) new PlaySoundConsumeEffect(BuiltInRegistries.SOUND_EVENT.wrapAsHolder((SoundEvent) (Object) soundType)); + } + + @Override + public ItemAction.TeleportRandomly teleportRandomly(final double distance) { + if (distance <= 0) { + throw new IllegalArgumentException("distance must be positive: " + distance); + } + return (ItemAction.TeleportRandomly) (Object) new TeleportRandomlyConsumeEffect((float) distance * 2); + } +} diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index 201ebe38af7..b39affb0bce 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -41,6 +41,7 @@ import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.command.selector.Selector; import org.spongepowered.api.data.DataManipulator; +import org.spongepowered.api.data.type.ItemAction; import org.spongepowered.api.data.type.ToolRule; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.effect.ForwardingViewer; @@ -126,6 +127,7 @@ import org.spongepowered.common.event.SpongeEventListenerRegistration; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType; import org.spongepowered.common.event.tracking.BlockChangeFlagManager; +import org.spongepowered.common.item.SpongeItemActionFactory; import org.spongepowered.common.item.SpongeItemStack; import org.spongepowered.common.item.SpongeItemStackSnapshot; import org.spongepowered.common.item.SpongeToolRuleFactory; @@ -285,6 +287,7 @@ public void registerDefaultFactories() { .registerFactory(NaturalSpawner.Factory.class, new SpongeNaturalSpawnerFactory()) .registerFactory(ScoreFormat.Factory.class, new SpongeScoreFormatFactory()) .registerFactory(ToolRule.Factory.class, new SpongeToolRuleFactory()) + .registerFactory(ItemAction.Factory.class, new SpongeItemActionFactory()) .registerFactory(PortalLogic.Factory.class, new SpongePortalLogicFactory()) .registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory()) .registerFactory(ArmorTrim.Factory.class, new SpongeArmorTrimFactory()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..1a2c5a5b2c4 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(ApplyStatusEffectsConsumeEffect.class) +@Implements(@Interface(iface = ItemAction.ApplyEffects.class, prefix = "consumeEffect$")) +public abstract class ApplyStatusEffectsConsumeEffectMixin_API implements ItemAction.ApplyEffects { + + @Shadow @Final private float probability; + @Shadow @Final private List effects; + + @Override + public double chance() { + return this.probability; + } + + @Intrinsic + public List consumeEffect$effects() { + return (List) this.effects; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..ffb15a2514d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ClearAllStatusEffectsConsumeEffect.class) +public abstract class ClearAllStatusEffectsConsumeEffectMixin_API implements ItemAction.ClearEffects { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java new file mode 100644 index 00000000000..b6157338515 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.consume_effects.ConsumeEffect; +import net.minecraft.world.level.Level; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.data.type.ItemActionType; +import org.spongepowered.api.entity.living.Living; +import org.spongepowered.api.item.inventory.ItemStackLike; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.util.ItemStackUtil; + +import java.util.Objects; + +@Mixin(ConsumeEffect.class) +public interface ConsumeEffectMixin_API extends ItemAction { + + @Shadow ConsumeEffect.Type shadow$getType(); + @Shadow boolean shadow$apply(Level level, ItemStack itemStack, LivingEntity livingEntity); + + @Override + default ItemActionType type() { + return (ItemActionType) (Object) this.shadow$getType(); + } + + @Override + default boolean apply(final Living entity, final ItemStackLike stack) { + Objects.requireNonNull(entity, "entity"); + return this.shadow$apply( + (Level) entity.world(), + ItemStackUtil.fromLikeToNativeCopy(stack), + (LivingEntity) entity); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java new file mode 100644 index 00000000000..31e206c0c91 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.ConsumeEffect; +import org.spongepowered.api.data.type.ItemActionType; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ConsumeEffect.Type.class) +public abstract class ConsumeEffect_TypeMixin_API implements ItemActionType { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java new file mode 100644 index 00000000000..4e3f681d634 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java @@ -0,0 +1,45 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.core.Holder; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(PlaySoundConsumeEffect.class) +public abstract class PlaySoundConsumeEffectMixin_API implements ItemAction.PlaySound { + + @Shadow @Final private Holder sound; + + @Override + public SoundType soundType() { + return (SoundType) (Object) this.sound.value(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..1aad96d28f3 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffectType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Set; +import java.util.stream.Collectors; + +@Mixin(RemoveStatusEffectsConsumeEffect.class) +public abstract class RemoveStatusEffectsConsumeEffectMixin_API implements ItemAction.RemoveEffects { + + @Shadow @Final private HolderSet effects; + + @Override + public Set effectTypes() { + return this.effects.stream().map(Holder::value).map(PotionEffectType.class::cast).collect(Collectors.toSet()); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java new file mode 100644 index 00000000000..b1a9f2bd27d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(TeleportRandomlyConsumeEffect.class) +public abstract class TeleportRandomlyConsumeEffectMixin_API implements ItemAction.TeleportRandomly { + + @Shadow @Final private float diameter; + + @Override + public double distance() { + return this.diameter / 2; + } +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index bcfb7af29ce..835e8e57719 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -333,6 +333,13 @@ "minecraft.world.item.alchemy.PotionMixin_API", "minecraft.world.item.component.FireworkExplosionMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", + "minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.ConsumeEffect_TypeMixin_API", + "minecraft.world.item.consume_effects.ConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.PlaySoundConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffectMixin_API", "minecraft.world.item.crafting.AbstractCookingRecipeMixin_API", "minecraft.world.item.crafting.CraftingRecipeMixin_API", "minecraft.world.item.crafting.CustomRecipeMixin_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java new file mode 100644 index 00000000000..2f228a8f3a5 --- /dev/null +++ b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java @@ -0,0 +1,125 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.test.data; + +import com.google.inject.Inject; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.parameter.CommandContext; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.api.effect.potion.PotionEffectTypes; +import org.spongepowered.api.effect.sound.SoundTypes; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; +import org.spongepowered.test.LoadableModule; + +@Plugin("consumabledata") +public class ConsumableDataTest implements LoadableModule { + + private final PluginContainer plugin; + + @Inject + public ConsumableDataTest(final PluginContainer plugin) { + this.plugin = plugin; + } + + @Override + public void enable(final CommandContext ctx) { + } + + @Listener + public void onRegisterCommand(final RegisterCommandEvent event) { + final Command.Builder builder = Command.builder(); + builder.addChild(Command.builder().executor(this::items).build(), "items"); + builder.addChild(Command.builder().executor(this::applyTeleport).build(), "applyteleport"); + builder.addChild(Command.builder().executor(this::applySound).build(), "applysound"); + event.register(this.plugin, builder.build(), "consumabledata"); + } + + private CommandResult items(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + final ItemStack stack1 = ItemStack.of(ItemTypes.BRICKS); + stack1.offer(Keys.CUSTOM_NAME, Component.text("Remove slowness, get speed & regeneration")); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.playSound(SoundTypes.BLOCK_ANVIL_BREAK)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.teleportRandomly(5)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.removeEffects(PotionEffectTypes.SLOWNESS)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.applyEffects( + PotionEffect.of(PotionEffectTypes.SPEED, 1, Ticks.of(20 * 30)), + PotionEffect.of(PotionEffectTypes.REGENERATION, 0, Ticks.of(20 * 30)) + )); + + final ItemStack stack2 = ItemStack.of(ItemTypes.CHORUS_FRUIT); + stack2.offer(Keys.CUSTOM_NAME, Component.text("Remove all effects, get slowness & haste with 50% chance")); + stack2.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.clearEffects()); + stack2.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.applyEffects(0.5, + PotionEffect.of(PotionEffectTypes.SLOWNESS, 1, Ticks.of(20 * 10)), + PotionEffect.of(PotionEffectTypes.HASTE, 0, Ticks.of(20 * 10)) + )); + + final ItemStack stack3 = ItemStack.of(ItemTypes.TOTEM_OF_UNDYING); + stack3.offer(Keys.CUSTOM_NAME, Component.text("No death protection")); + stack3.remove(Keys.DEATH_PROTECTION_ACTIONS); + + final ItemStack stack4 = ItemStack.of(ItemTypes.ANVIL); + stack4.offer(Keys.CUSTOM_NAME, Component.text("Teleport on death")); + stack4.offerSingle(Keys.DEATH_PROTECTION_ACTIONS, ItemAction.teleportRandomly(20)); + + player.inventory().offer(stack1, stack2, stack3, stack4); + return CommandResult.success(); + } + + private CommandResult applyTeleport(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + ItemAction.teleportRandomly(20).apply(player); + return CommandResult.success(); + } + + private CommandResult applySound(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + ItemAction.playSound(SoundTypes.BLOCK_BELL_USE).apply(player); + return CommandResult.success(); + } +} diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 8a2fa01995b..be7a3bb5f18 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -239,7 +239,6 @@ public void testData(final ServerPlayer player) { PotionEffect.builder().potionType(PotionEffectTypes.RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), PotionEffect.builder().potionType(PotionEffectTypes.FIRE_RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), PotionEffect.builder().potionType(PotionEffectTypes.ABSORPTION).amplifier(3).ambient(false).duration(Ticks.of(2400)).build()); - this.checkGetWeightedData(goldenApple, Keys.APPLICABLE_POTION_EFFECTS, notchAppleEffects); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.SHARPNESS, 5))); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.PROTECTION, 4))); diff --git a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json index 54935839503..b0d8f7fcf9d 100644 --- a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json +++ b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json @@ -383,6 +383,12 @@ "name": "Viewer Test", "entrypoint": "org.spongepowered.test.viewer.ViewerTest", "description": "Viewer tests" + }, + { + "id": "consumabledata", + "name": "Consumable ItemStack Data", + "entrypoint": "org.spongepowered.test.data.ConsumableDataTest", + "description": "Consumable ItemStack Data" } ] } From 667ff751116f5937f1995b476157bccc2a5380d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:31:57 +0300 Subject: [PATCH 369/586] Add Keys.TOOLTIP_STYLE (#4232) --- SpongeAPI | 2 +- .../common/data/provider/item/stack/ItemStackData.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 92ddc65b835..79e07291bdc 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 92ddc65b8356ec4e268ba44686b6ca6dd67d1247 +Subproject commit 79e07291bdc22e15939edac8213a3295b38b87bd diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 773187ec2c4..1f635d22968 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -364,6 +364,10 @@ public static void register(final DataProviderRegistrator registrator) { return builder.build(); }) .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) + .create(Keys.TOOLTIP_STYLE) + .get(h -> (ResourceKey) (Object) h.get(DataComponents.TOOLTIP_STYLE)) + .set((h, v) -> h.set(DataComponents.TOOLTIP_STYLE, (ResourceLocation) (Object) v)) + .delete(h -> h.remove(DataComponents.TOOLTIP_STYLE)) ; } // @formatter:on From 4c7bd6d55330e1c3e5920afd8953cc669036b4c4 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 27 Sep 2025 19:07:47 -0700 Subject: [PATCH 370/586] feat(minecraft): update to 1.21.9-rc1 See: https://minecraft.wiki/w/Java_Edition_1.21.9_Release_Candidate_1 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 41511f810c2..0203cf330be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=1.21.9-pre4 +minecraftVersion=1.21.9-rc1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5ff83c7aa5f..df1a7205e1f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1533,6 +1533,14 @@ + + + + + + + + From d4ef097ecfd26ae5fe61e094d8143ad251510332 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 28 Sep 2025 00:10:25 -0700 Subject: [PATCH 371/586] chore(git): point towards api-17 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 0a42e85e8c0..fd8795b3c77 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 0a42e85e8c05399bdc72dcae97678e78ad46caff +Subproject commit fd8795b3c7738672711a49f6a9cd79ff3461de6b From af1f0b0bb7c9a8ca58df67f1718449f76e245103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Mon, 29 Sep 2025 02:33:46 +0300 Subject: [PATCH 372/586] Expose minecraft:blocks_attacks and minecraft:weapon (#4233) --- SpongeAPI | 2 +- .../provider/item/stack/ItemStackData.java | 53 +++++ .../item/stack/ShieldItemStackData.java | 206 +++++++++++++++++- .../SpongeShieldDamageReductionFactory.java | 36 +++ ...ieldDamageReductionMultiplyAddBuilder.java | 109 +++++++++ ...SpongeShieldItemDamageFunctionFactory.java | 36 +++ ...dItemDamageFunctionMultiplyAddBuilder.java | 76 +++++++ .../registry/SpongeBuilderProvider.java | 6 + .../registry/SpongeFactoryProvider.java | 6 + .../spongepowered/common/util/Constants.java | 1 + ...locksAttacks_DamageReductionMixin_API.java | 84 +++++++ .../BlocksAttacks_ItemDamageFunction_API.java | 67 ++++++ src/mixins/resources/mixins.sponge.api.json | 2 + .../common/data/key/KeysTest.java | 125 +++++++++++ 14 files changed, 804 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionFactory.java create mode 100644 src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionMultiplyAddBuilder.java create mode 100644 src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionFactory.java create mode 100644 src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionMultiplyAddBuilder.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_DamageReductionMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_ItemDamageFunction_API.java create mode 100644 src/test/java/org/spongepowered/common/data/key/KeysTest.java diff --git a/SpongeAPI b/SpongeAPI index 9b0d6786155..214a97c9174 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9b0d678615595bec00cf099af576c931cc044d48 +Subproject commit 214a97c9174a315b226bc716c77d7a4d7c7091d2 diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index a9d1d4212fd..e4d0d005a1c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -47,6 +47,7 @@ import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.UseCooldown; import net.minecraft.world.item.component.UseRemainder; +import net.minecraft.world.item.component.Weapon; import net.minecraft.world.item.consume_effects.ConsumeEffect; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Platform; @@ -65,6 +66,7 @@ import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.util.Constants; import java.util.List; import java.util.Optional; @@ -370,6 +372,57 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (ResourceKey) (Object) h.get(DataComponents.TOOLTIP_STYLE)) .set((h, v) -> h.set(DataComponents.TOOLTIP_STYLE, (ResourceLocation) (Object) v)) .delete(h -> h.remove(DataComponents.TOOLTIP_STYLE)) + .create(Keys.WEAPON_DAMAGE_PER_ATTACK) + .get(h -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + if (weapon == null) { + return null; + } + return weapon.itemDamagePerAttack(); + }) + .set((h, v) -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + h.set(DataComponents.WEAPON, new Weapon(v, weapon == null ? 0 : weapon.disableBlockingForSeconds())); + }) + .delete(h -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + if (weapon == null) { + return; + } + if (weapon.disableBlockingForSeconds() == 0) { + h.remove(DataComponents.WEAPON); + } else { + h.set(DataComponents.WEAPON, new Weapon(0, weapon.disableBlockingForSeconds())); + } + }) + .create(Keys.DISABLE_SHIELD_TICKS) + .get(h -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + if (weapon == null) { + return null; + } + return Ticks.of(Math.round( + Constants.TickConversions.TICKS_PER_SECOND * weapon.disableBlockingForSeconds() + )); + }) + .set((h, v) -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + h.set(DataComponents.WEAPON, new Weapon( + weapon == null ? 0 : weapon.itemDamagePerAttack(), + v.ticks() / (float) Constants.TickConversions.TICKS_PER_SECOND + )); + }) + .delete(h -> { + final @Nullable Weapon weapon = h.get(DataComponents.WEAPON); + if (weapon == null) { + return; + } + if (weapon.itemDamagePerAttack() == 0) { + h.remove(DataComponents.WEAPON); + } else { + h.set(DataComponents.WEAPON, new Weapon(weapon.itemDamagePerAttack())); + } + }) ; } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java index 9b499f8084f..d0438441f6e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java @@ -24,15 +24,28 @@ */ package org.spongepowered.common.data.provider.item.stack; +import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; -import net.minecraft.world.item.BannerItem; +import net.minecraft.sounds.SoundEvent; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ShieldItem; +import net.minecraft.world.item.component.BlocksAttacks; import net.minecraft.world.level.block.entity.BannerPatternLayers; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.meta.BannerPatternLayer; import org.spongepowered.api.data.type.DyeColor; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.api.event.cause.entity.damage.DamageType; +import org.spongepowered.api.tag.Tag; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.common.bridge.tags.TagBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; +import org.spongepowered.common.util.Constants; + +import java.util.List; +import java.util.Optional; public final class ShieldItemStackData { @@ -46,7 +59,6 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) h.getOrDefault(DataComponents.BASE_COLOR, net.minecraft.world.item.DyeColor.WHITE)) .set((h, v) -> h.set(DataComponents.BASE_COLOR, (net.minecraft.world.item.DyeColor) (Object) v)) - .supports(h -> h.getItem() instanceof ShieldItem) .create(Keys.BANNER_PATTERN_LAYERS) .get(h -> h.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY).layers() .stream().map(BannerPatternLayer.class::cast).toList()) @@ -54,8 +66,194 @@ public static void register(final DataProviderRegistrator registrator) { h.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers(v.stream().map(BannerPatternLayers.Layer.class::cast).toList())); // TODO check setting banner base? Constants.TileEntity.Banner.BANNER_BASE / BannerPatternShapes.BASE }) - .supports(h -> h.getItem() instanceof ShieldItem || h.getItem() instanceof BannerItem); + .create(Keys.SHIELD_DEPLOY_TICKS) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null) { + return null; + } + return Ticks.of((long) (Constants.TickConversions.TICKS_PER_SECOND * blocksAttacks.blockDelaySeconds())); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + v.ticks() / (float) Constants.TickConversions.TICKS_PER_SECOND, + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.DISABLE_SHIELD_TICKS_SCALE) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null) { + return null; + } + return (double) blocksAttacks.disableCooldownScale(); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + v.floatValue(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.SHIELD_DAMAGE_REDUCTIONS) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null) { + return null; + } + return (List>) (Object) List.copyOf(blocksAttacks.damageReductions()); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + (List) (Object) List.copyOf(v), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.SHIELD_ITEM_DAMAGE_FUNCTION) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null) { + return null; + } + return (ShieldItemDamageFunction) (Object) blocksAttacks.itemDamage(); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + (BlocksAttacks.ItemDamageFunction) (Object) v, + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.BYPASS_DAMAGE_TAG) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null || blocksAttacks.bypassedBy().isEmpty()) { + return null; + } + return (Tag) (Object) blocksAttacks.bypassedBy().get(); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + Optional.of(((TagBridge) v).bridge$asVanillaTag()), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .delete(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + Optional.empty(), + blocksAttacks.blockSound(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.SHIELD_BLOCK_SOUND) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null || blocksAttacks.blockSound().isEmpty()) { + return null; + } + return (SoundType) (Object) blocksAttacks.blockSound().get().value(); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + Optional.of(Holder.direct((SoundEvent) (Object) v)), + blocksAttacks.disableSound() + )); + }) + .delete(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + Optional.empty(), + blocksAttacks.disableSound() + )); + }) + .create(Keys.SHIELD_DISABLE_SOUND) + .get(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.get(DataComponents.BLOCKS_ATTACKS); + if (blocksAttacks == null || blocksAttacks.disableSound().isEmpty()) { + return null; + } + return (SoundType) (Object) blocksAttacks.disableSound().get().value(); + }) + .set((h, v) -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + Optional.of(Holder.direct((SoundEvent) (Object) v)) + )); + }) + .delete(h -> { + final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( + blocksAttacks.blockDelaySeconds(), + blocksAttacks.disableCooldownScale(), + blocksAttacks.damageReductions(), + blocksAttacks.itemDamage(), + blocksAttacks.bypassedBy(), + blocksAttacks.blockSound(), + Optional.empty() + )); + }) + ; } // @formatter:on + private static final BlocksAttacks BLOCKS_ATTACKS_DEFAULTS = new BlocksAttacks( + 0, + 1, + List.of(), + BlocksAttacks.ItemDamageFunction.DEFAULT, + Optional.empty(), + Optional.empty(), + Optional.empty() + ); + } diff --git a/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionFactory.java b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionFactory.java new file mode 100644 index 00000000000..719ab097f17 --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionFactory.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item.shield; + +import org.spongepowered.api.data.type.ShieldDamageReduction; + +public final class SpongeShieldDamageReductionFactory implements ShieldDamageReduction.Factory { + + @Override + public ShieldDamageReduction create(final ShieldDamageReduction.MultiplyAdd config) { + return (ShieldDamageReduction) config; + } + +} diff --git a/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionMultiplyAddBuilder.java b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionMultiplyAddBuilder.java new file mode 100644 index 00000000000..194978f163d --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldDamageReductionMultiplyAddBuilder.java @@ -0,0 +1,109 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item.shield; + +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.world.item.component.BlocksAttacks; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.event.cause.entity.damage.DamageType; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.tag.Tag; +import org.spongepowered.common.bridge.tags.TagBridge; +import org.spongepowered.common.util.Preconditions; + +import java.util.Optional; +import java.util.Set; + +public final class SpongeShieldDamageReductionMultiplyAddBuilder implements ShieldDamageReduction.MultiplyAdd.Builder { + private HolderSet damageTypes; + private Double horizontalBlockingAngle; + private double base = 0; + private double factor = 0; + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder damageTypes(final Set damageTypes) { + final Registry registry = (Registry) Sponge.server().registry(RegistryTypes.DAMAGE_TYPE); + + this.damageTypes = HolderSet.direct(damageTypes.stream() + .map(dt -> registry.wrapAsHolder((net.minecraft.world.damagesource.DamageType) (Object) dt)) + .toList()); + + return this; + } + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder damageTypes(final Tag tag) { + final Registry registry = (Registry) Sponge.server().registry(RegistryTypes.DAMAGE_TYPE); + final var vanillaTag = ((TagBridge) tag).bridge$asVanillaTag(); + this.damageTypes = registry.getOrThrow(vanillaTag); + + return this; + } + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder horizontalBlockingAngle(final double angle) { + Preconditions.checkArgument(angle > 0, "angle must be positive"); + this.horizontalBlockingAngle = angle; + + return this; + } + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder constantReduction(final double constant) { + this.base = constant; + + return this; + } + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder fractionalReduction(final double fraction) { + this.factor = fraction; + + return this; + } + + @Override + public ShieldDamageReduction.MultiplyAdd build() { + return (ShieldDamageReduction.MultiplyAdd) (Object) new BlocksAttacks.DamageReduction( + this.horizontalBlockingAngle != null ? this.horizontalBlockingAngle.floatValue() : 90, + Optional.ofNullable(this.damageTypes), + (float) this.base, + (float) this.factor + ); + } + + @Override + public ShieldDamageReduction.MultiplyAdd.Builder reset() { + this.damageTypes = null; + this.horizontalBlockingAngle = null; + this.base = 0; + this.factor = 0; + + return this; + } + +} diff --git a/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionFactory.java b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionFactory.java new file mode 100644 index 00000000000..6174a5cb8c1 --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionFactory.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item.shield; + +import org.spongepowered.api.data.type.ShieldItemDamageFunction; + +public final class SpongeShieldItemDamageFunctionFactory implements ShieldItemDamageFunction.Factory { + + @Override + public ShieldItemDamageFunction create(final ShieldItemDamageFunction.MultiplyAdd config) { + return (ShieldItemDamageFunction) config; + } + +} diff --git a/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionMultiplyAddBuilder.java b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionMultiplyAddBuilder.java new file mode 100644 index 00000000000..cb241ad33f6 --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/shield/SpongeShieldItemDamageFunctionMultiplyAddBuilder.java @@ -0,0 +1,76 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item.shield; + +import net.minecraft.world.item.component.BlocksAttacks; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; +import org.spongepowered.common.util.Preconditions; + +public final class SpongeShieldItemDamageFunctionMultiplyAddBuilder implements ShieldItemDamageFunction.MultiplyAdd.Builder { + private double minAttackDamage = 0; + private double constantDamage = 0; + private double fractionalDamage = 0; + + @Override + public ShieldItemDamageFunction.MultiplyAdd.Builder minAttackDamage(final double minDamage) { + Preconditions.checkArgument(minDamage >= 0, "minAttackDamage must not be negative"); + this.minAttackDamage = minDamage; + + return this; + } + + @Override + public ShieldItemDamageFunction.MultiplyAdd.Builder constantDamage(final double constantDamage) { + this.constantDamage = constantDamage; + + return this; + } + + @Override + public ShieldItemDamageFunction.MultiplyAdd.Builder fractionalDamage(final double fractionalDamage) { + this.fractionalDamage = fractionalDamage; + + return this; + } + + @Override + public ShieldItemDamageFunction.MultiplyAdd build() { + return (ShieldItemDamageFunction.MultiplyAdd) (Object) new BlocksAttacks.ItemDamageFunction( + (float) this.minAttackDamage, + (float) this.constantDamage, + (float) this.fractionalDamage + ); + } + + @Override + public ShieldItemDamageFunction.MultiplyAdd.Builder reset() { + this.minAttackDamage = 0; + this.constantDamage = 0; + this.fractionalDamage = 0; + + return this; + } + +} diff --git a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java index 821ca0dcb09..3ddcd3873f3 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeBuilderProvider.java @@ -51,6 +51,8 @@ import org.spongepowered.api.data.meta.BannerPatternLayer; import org.spongepowered.api.data.persistence.DataStore; import org.spongepowered.api.data.type.ArtType; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; import org.spongepowered.api.effect.particle.ParticleEffect; import org.spongepowered.api.effect.potion.PotionEffect; import org.spongepowered.api.effect.sound.SoundType; @@ -204,6 +206,8 @@ import org.spongepowered.common.item.recipe.ingredient.SpongeIngredientBuilder; import org.spongepowered.common.item.recipe.smithing.SpongeSmithingRecipeBuilder; import org.spongepowered.common.item.recipe.stonecutting.SpongeStoneCutterRecipeBuilder; +import org.spongepowered.common.item.shield.SpongeShieldDamageReductionMultiplyAddBuilder; +import org.spongepowered.common.item.shield.SpongeShieldItemDamageFunctionMultiplyAddBuilder; import org.spongepowered.common.map.canvas.SpongeMapCanvasBuilder; import org.spongepowered.common.map.color.SpongeMapColorBuilder; import org.spongepowered.common.map.decoration.SpongeMapDecorationBuilder; @@ -395,6 +399,8 @@ public void registerDefaultBuilders() { .register(PortalLogic.Builder.class, SpongePortalLogicBuilder::new) .register(ServerWorldProperties.LoadOptions.Builder.class, SpongeServerWorldPropertiesLoadOptions.BuilderImpl::new) .register(WorldArchetype.Builder.class, SpongeWorldArchetype.BuilderImpl::new) + .register(ShieldDamageReduction.MultiplyAdd.Builder.class, SpongeShieldDamageReductionMultiplyAddBuilder::new) + .register(ShieldItemDamageFunction.MultiplyAdd.Builder.class, SpongeShieldItemDamageFunctionMultiplyAddBuilder::new) ; } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index b39affb0bce..bdebce0d637 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -42,6 +42,8 @@ import org.spongepowered.api.command.selector.Selector; import org.spongepowered.api.data.DataManipulator; import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; import org.spongepowered.api.data.type.ToolRule; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.effect.ForwardingViewer; @@ -133,6 +135,8 @@ import org.spongepowered.common.item.SpongeToolRuleFactory; import org.spongepowered.common.item.recipe.SpongeRecipeInputFactory; import org.spongepowered.common.item.recipe.smithing.SpongeArmorTrimFactory; +import org.spongepowered.common.item.shield.SpongeShieldDamageReductionFactory; +import org.spongepowered.common.item.shield.SpongeShieldItemDamageFunctionFactory; import org.spongepowered.common.item.util.SpongeItemStackComparatorFactory; import org.spongepowered.common.network.channel.SpongeChannelExceptionHandlerFactory; import org.spongepowered.common.network.status.SpongeFavicon; @@ -292,6 +296,8 @@ public void registerDefaultFactories() { .registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory()) .registerFactory(ArmorTrim.Factory.class, new SpongeArmorTrimFactory()) .registerFactory(RegistryRegistrationSet.Factory.class, new SpongeRegistryRegistrationSet.FactoryImpl()) + .registerFactory(ShieldDamageReduction.Factory.class, new SpongeShieldDamageReductionFactory()) + .registerFactory(ShieldItemDamageFunction.Factory.class, new SpongeShieldItemDamageFunctionFactory()) ; } } diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index db3dbb7b1f8..eb2601246ba 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -1539,6 +1539,7 @@ public static final class KeyValueMatcher { public static final class TickConversions { public static final int TICK_DURATION_MS = 50; + public static final int TICKS_PER_SECOND = 1000 / TICK_DURATION_MS; public static final Duration EFFECTIVE_MINIMUM_DURATION = Duration.ofMillis(TickConversions.TICK_DURATION_MS); public static final int MINECRAFT_DAY_TICKS = 24000; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_DamageReductionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_DamageReductionMixin_API.java new file mode 100644 index 00000000000..248bc1f1910 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_DamageReductionMixin_API.java @@ -0,0 +1,84 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.component; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.world.item.component.BlocksAttacks; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.event.cause.entity.damage.DamageType; +import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; +import org.spongepowered.asm.mixin.*; + +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@Mixin(BlocksAttacks.DamageReduction.class) +@Implements({ + @Interface(iface = ShieldDamageReduction.class, prefix = "shielddamagereduction$"), + @Interface(iface = ShieldDamageReduction.MultiplyAdd.class, prefix = "shielddamagereductionmultiplyadd$") +}) +public abstract class BlocksAttacks_DamageReductionMixin_API implements ShieldDamageReduction, ShieldDamageReduction.MultiplyAdd { + + @Shadow @Final private Optional> type; + @Shadow @Final private float base; + @Shadow @Final private float factor; + @Shadow @Final private float horizontalBlockingAngle; + + @Shadow public abstract float shadow$resolve(net.minecraft.world.damagesource.DamageSource $$0, float $$1, double $$2); + + @Override + public MultiplyAdd configuration() { + return this; + } + + public double shielddamagereduction$resolve(final DamageSource source, final double damage, final double angle) { + return this.shadow$resolve((net.minecraft.world.damagesource.DamageSource) source, (float) damage, angle); + } + + @Override + public Optional> damageTypes() { + return this.type.map(set -> set.stream() + .map(Holder::value) + .map(DamageType.class::cast) + .collect(Collectors.toSet())); + } + + public double shielddamagereductionmultiplyadd$horizontalBlockingAngle() { + return this.horizontalBlockingAngle; + } + + @Override + public double constantReduction() { + return this.base; + } + + @Override + public double fractionalReduction() { + return this.factor; + } + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_ItemDamageFunction_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_ItemDamageFunction_API.java new file mode 100644 index 00000000000..558458c2460 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/BlocksAttacks_ItemDamageFunction_API.java @@ -0,0 +1,67 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.component; + +import net.minecraft.world.item.component.BlocksAttacks; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(BlocksAttacks.ItemDamageFunction.class) +public abstract class BlocksAttacks_ItemDamageFunction_API implements ShieldItemDamageFunction.MultiplyAdd, ShieldItemDamageFunction { + + @Shadow @Final private float threshold; + @Shadow @Final private float base; + @Shadow @Final private float factor; + + @Shadow public abstract int shadow$apply(float $$0); + + @Override + public MultiplyAdd configuration() { + return this; + } + + @Override + public double resolve(final double damage) { + return this.shadow$apply((float) damage); + } + + @Override + public double minAttackDamage() { + return this.threshold; + } + + @Override + public double constantDamage() { + return this.base; + } + + @Override + public double fractionalDamage() { + return this.factor; + } + +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index c0189a5990e..840a6f902da 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -333,6 +333,8 @@ "minecraft.world.item.RarityMixin_API", "minecraft.world.item.ToolMaterialMixin_API", "minecraft.world.item.alchemy.PotionMixin_API", + "minecraft.world.item.component.BlocksAttacks_DamageReductionMixin_API", + "minecraft.world.item.component.BlocksAttacks_ItemDamageFunction_API", "minecraft.world.item.component.FireworkExplosionMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", "minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffectMixin_API", diff --git a/src/test/java/org/spongepowered/common/data/key/KeysTest.java b/src/test/java/org/spongepowered/common/data/key/KeysTest.java new file mode 100644 index 00000000000..5a7f8a4ac9f --- /dev/null +++ b/src/test/java/org/spongepowered/common/data/key/KeysTest.java @@ -0,0 +1,125 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.key; + +import io.leangen.geantyref.GenericTypeReflector; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.spongepowered.api.ResourceKeyed; +import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.effect.sound.SoundTypes; +import org.spongepowered.api.event.cause.entity.damage.DamageTypes; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.tag.DamageTypeTags; +import org.spongepowered.api.util.Ticks; + +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + +public class KeysTest { + + private static Stream testSingleKeys() { + return Stream.of( + Arguments.of(Keys.WEAPON_DAMAGE_PER_ATTACK, 5), + Arguments.of(Keys.DISABLE_SHIELD_TICKS, Ticks.of(10)), + Arguments.of(Keys.SHIELD_DEPLOY_TICKS, Ticks.of(15)), + Arguments.of(Keys.DISABLE_SHIELD_TICKS_SCALE, 2.5), + Arguments.of(Keys.SHIELD_DAMAGE_REDUCTIONS, List.of(ShieldDamageReduction.of(ShieldDamageReduction.MultiplyAdd.builder() + .horizontalBlockingAngle(45) + .constantReduction(2) + .fractionalReduction(0.5) + .damageTypes(Set.of(DamageTypes.ARROW.get(), DamageTypes.PLAYER_ATTACK.get())) + .build()))), + Arguments.of(Keys.SHIELD_ITEM_DAMAGE_FUNCTION, ShieldItemDamageFunction.of(ShieldItemDamageFunction.MultiplyAdd.builder() + .constantDamage(5) + .fractionalDamage(2) + .minAttackDamage(2.5) + .build())), + Arguments.of(Keys.SHIELD_BLOCK_SOUND, SoundTypes.ENTITY_SHULKER_HURT.get()), + Arguments.of(Keys.SHIELD_DISABLE_SOUND, SoundTypes.ENTITY_ENDER_DRAGON_DEATH.get()) + ); + } + + @MethodSource + @ParameterizedTest + void testSingleKeys(Key k, Object value) { + testSingleKeyUnchecked(k, value); + } + + @Test + void testBypassDamageTag() { + testSingleKey(Keys.BYPASS_DAMAGE_TAG, DamageTypeTags.BYPASSES_ARMOR, ResourceKeyed::key); + } + + @Test + void testAllWeaponKeys() { + final var stack = ItemStack.builder() + .itemType(ItemTypes.DIAMOND_SWORD) + .add(Keys.WEAPON_DAMAGE_PER_ATTACK, 5) + .add(Keys.DISABLE_SHIELD_TICKS, Ticks.of(5)) + .build(); + + Assertions.assertEquals(5, stack.require(Keys.WEAPON_DAMAGE_PER_ATTACK)); + Assertions.assertEquals(Ticks.of(5), stack.require(Keys.DISABLE_SHIELD_TICKS)); + + stack.remove(Keys.DISABLE_SHIELD_TICKS); + Assertions.assertEquals(5, stack.require(Keys.WEAPON_DAMAGE_PER_ATTACK)); + + stack.remove(Keys.WEAPON_DAMAGE_PER_ATTACK); + + Assertions.assertNull(stack.getOrNull(Keys.WEAPON_DAMAGE_PER_ATTACK)); + Assertions.assertNull(stack.getOrNull(Keys.DISABLE_SHIELD_TICKS)); + } + + @SuppressWarnings("unchecked") + private static > void testSingleKeyUnchecked(Key k, Object value) { + if (!GenericTypeReflector.isSuperType(k.elementType(), value.getClass())) { + throw new IllegalArgumentException("Invalid value type for key " + k.key() + ": " + value.getClass().getName()); + } + + testSingleKey((Key) k, (T) value, a -> a); + } + + private static > void testSingleKey(Key k, T value, Function equalityExtractor) { + final var stack = ItemStack.builder() + .itemType(ItemTypes.DIAMOND_SWORD) + .add(k, value) + .build(); + + Assertions.assertEquals(equalityExtractor.apply(value), equalityExtractor.apply(stack.require(k)), () -> "retrieved value is not equal " + + "to the original for " + k.key().asString()); + } + +} From 13d5b1580a405923d64fa20b3ec4169480ad9034 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 29 Sep 2025 22:10:01 +0300 Subject: [PATCH 373/586] Add unit test for custom Data API --- .../common/data/DataHolderTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/test/java/org/spongepowered/common/data/DataHolderTest.java diff --git a/src/test/java/org/spongepowered/common/data/DataHolderTest.java b/src/test/java/org/spongepowered/common/data/DataHolderTest.java new file mode 100644 index 00000000000..0e568400210 --- /dev/null +++ b/src/test/java/org/spongepowered/common/data/DataHolderTest.java @@ -0,0 +1,85 @@ +package data; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.level.Level; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.block.entity.BlockEntity; +import org.spongepowered.api.block.entity.BlockEntityArchetype; +import org.spongepowered.api.block.entity.BlockEntityType; +import org.spongepowered.api.block.entity.BlockEntityTypes; +import org.spongepowered.api.data.*; +import org.spongepowered.api.data.persistence.DataContainer; +import org.spongepowered.api.data.persistence.DataQuery; +import org.spongepowered.api.data.persistence.DataSerializable; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.EntityTypes; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.world.DefaultWorldKeys; +import org.spongepowered.api.world.chunk.WorldChunk; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.api.world.server.storage.ServerWorldProperties; +import org.spongepowered.common.data.SpongeDataManager; +import org.spongepowered.common.data.SpongeDataRegistration; +import org.spongepowered.common.util.Constants; +import org.spongepowered.math.vector.Vector3d; + +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public class DataHolderTest { + + private static final Key> STRING_KEY = Key.from(ResourceKey.of("test", "string"), String.class); + + static { + SpongeDataManager.INSTANCE.registerCustomDataRegistration((SpongeDataRegistration) DataRegistration.of(DataHolderTest.STRING_KEY, ItemStack.class, BlockEntity.class, Entity.class, WorldChunk.class, ServerWorldProperties.class)); + } + + public static Stream testEntity() { + final ServerWorld world = Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); + + return Stream.of( + DataHolderTest.testEntityArguments(() -> ItemStack.of(ItemTypes.DIAMOND), c -> ItemStack.builder().fromContainer(c).build()), + DataHolderTest.testEntityArguments(() -> BlockEntityArchetype.builder().blockEntity(BlockEntityTypes.CHEST).state(BlockTypes.CHEST.get().defaultState()).build(), c -> BlockEntityArchetype.builder().build(c).orElseThrow()), + DataHolderTest.testEntityArguments(() -> world.createEntity(EntityTypes.CAT, Vector3d.ZERO), c -> world.createEntity(c).orElseThrow()) + ); + } + + private static Arguments testEntityArguments(final Supplier supplier, final Function function) { + return Arguments.of(supplier, function); + } + + @ParameterizedTest + @MethodSource + public void testEntity(final Supplier supplier, final Function function) { + final var input = "test" + System.currentTimeMillis(); + + final T holder = supplier.get(); + final var offerResult = holder.offer(DataHolderTest.STRING_KEY, input); + + Assertions.assertEquals(DataTransactionResult.successResult(Value.immutableOf(DataHolderTest.STRING_KEY, input)), offerResult); + Assertions.assertEquals(Optional.of(input), holder.get(DataHolderTest.STRING_KEY)); + + final DataContainer originalContainer = holder.toContainer(); + + final T copy = function.apply(originalContainer); + + final DataContainer copyContainer = copy.toContainer(); + + originalContainer.remove(Constants.Sponge.UNSAFE_NBT.then(Constants.Entity.ENTITY_UUID)); + copyContainer.remove(Constants.Sponge.UNSAFE_NBT.then(Constants.Entity.ENTITY_UUID)); + + Assertions.assertEquals(originalContainer, copyContainer); + } +} From c4b7a1a1964c32a2568e3e4745e2690907a46cf4 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 29 Sep 2025 22:34:26 +0300 Subject: [PATCH 374/586] spotlessApply --- .../common/data/DataHolderTest.java | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/test/java/org/spongepowered/common/data/DataHolderTest.java b/src/test/java/org/spongepowered/common/data/DataHolderTest.java index 0e568400210..83b74779d12 100644 --- a/src/test/java/org/spongepowered/common/data/DataHolderTest.java +++ b/src/test/java/org/spongepowered/common/data/DataHolderTest.java @@ -1,9 +1,29 @@ -package data; +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.animal.Cat; -import net.minecraft.world.level.Level; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -13,12 +33,12 @@ import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.block.entity.BlockEntity; import org.spongepowered.api.block.entity.BlockEntityArchetype; -import org.spongepowered.api.block.entity.BlockEntityType; import org.spongepowered.api.block.entity.BlockEntityTypes; -import org.spongepowered.api.data.*; +import org.spongepowered.api.data.DataRegistration; +import org.spongepowered.api.data.DataTransactionResult; +import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.SerializableDataHolder; import org.spongepowered.api.data.persistence.DataContainer; -import org.spongepowered.api.data.persistence.DataQuery; -import org.spongepowered.api.data.persistence.DataSerializable; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.EntityTypes; @@ -28,8 +48,6 @@ import org.spongepowered.api.world.chunk.WorldChunk; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.api.world.server.storage.ServerWorldProperties; -import org.spongepowered.common.data.SpongeDataManager; -import org.spongepowered.common.data.SpongeDataRegistration; import org.spongepowered.common.util.Constants; import org.spongepowered.math.vector.Vector3d; From dffb33cbe0a4f467a185caa6233647d00052e2ab Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 29 Sep 2025 22:57:18 +0300 Subject: [PATCH 375/586] Fix entity custom Data API --- .../level/storage/TagValueInputAccessor.java | 37 +++++++++++++++++++ .../resources/mixins.sponge.accessors.json | 1 + .../mixin/core/world/entity/EntityMixin.java | 9 +---- 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/level/storage/TagValueInputAccessor.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/TagValueInputAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/TagValueInputAccessor.java new file mode 100644 index 00000000000..012212391fe --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/TagValueInputAccessor.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.level.storage; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.storage.TagValueInput; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(TagValueInput.class) +public interface TagValueInputAccessor { + + @Accessor("input") @Final CompoundTag accessor$input(); +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index d8234c3f63d..bf57fddb562 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -219,6 +219,7 @@ "world.level.saveddata.maps.MapItemSavedDataAccessor", "world.level.storage.PlayerDataStorageAccessor", "world.level.storage.PrimaryLevelDataAccessor", + "world.level.storage.TagValueInputAccessor", "world.phys.AABBAccessor", "world.scores.PlayerTeamAccessor", "world.scores.ScoreboardAccessor", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 34d28462f2f..fe7a1bb8f1a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -54,7 +54,6 @@ import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -108,6 +107,7 @@ import org.spongepowered.common.accessor.server.level.ChunkMap_TrackedEntityAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; import org.spongepowered.common.accessor.world.entity.PortalProcessorAccessor; +import org.spongepowered.common.accessor.world.level.storage.TagValueInputAccessor; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.bridge.data.SpongeDataHolderBridge; @@ -955,12 +955,7 @@ public void stopRiding() { @Inject(method = "load", at = @At("RETURN")) private void impl$ReadSpongeDataFromCompound(final ValueInput input, final CallbackInfo ci) { - // TODO If we are in Forge data is already present - final var spongeData = input.read(Constants.Sponge.Data.V3.SPONGE_TAG_KEY, CustomData.CODEC); - if (spongeData.isEmpty()) { - return; - } - this.data$setCompound(spongeData.get().copyTag()); // For vanilla we set the incoming nbt + this.data$setCompound(((TagValueInputAccessor) input).accessor$input()); // For vanilla we set the incoming nbt // Deserialize custom data... DataUtil.syncTagToData(this); this.data$setCompound(null); // done reading From dbc12077b46f6f408c084834adb64f7165c02409 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 29 Sep 2025 23:31:31 +0300 Subject: [PATCH 376/586] Bump test heap size to 4G --- forge/build.gradle.kts | 2 +- neoforge/build.gradle.kts | 2 +- vanilla/build.gradle.kts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index e93155b1415..18ec3c137b3 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,6 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.common.util.RunConfig -import org.gradle.api.tasks.JavaExec import org.gradle.internal.DefaultTaskExecutionRequest import org.spongepowered.gradle.impl.AWToAT import org.spongepowered.gradle.impl.IdeHelper @@ -429,6 +428,7 @@ tasks { test { useJUnitPlatform() + maxHeapSize = "4G" testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs val runServer = minecraft.runs.getByName("server") diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 3dc2666d864..551f1993492 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,6 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.neoforged.moddevgradle.internal.RunGameTask -import org.gradle.api.tasks.JavaExec import org.spongepowered.gradle.impl.AWToAT buildscript { @@ -405,6 +404,7 @@ tasks { test { useJUnitPlatform() + maxHeapSize = "4G" testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs jvmArgs(runServer.get().jvmArgs) diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index f655f9f873e..271a41a0c0e 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -510,6 +510,7 @@ tasks { test { useJUnitPlatform() + maxHeapSize = "4G" testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs val runServer = minecraft.runs.server().get() From 898bd33ca3274fb015627d811806b73c91da5e5e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 30 Sep 2025 19:51:40 -0700 Subject: [PATCH 377/586] feat(minecraft): update to 1.21.9 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0203cf330be..d8b9710cb8e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json superClassChanges=common.superclasschange -minecraftVersion=1.21.9-rc1 +minecraftVersion=1.21.9 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From a18ae551d48a9c3912f590254924ff00793a61f0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 30 Sep 2025 20:31:09 -0700 Subject: [PATCH 378/586] chore(ci): disable forge & neoforge for 1.21.9 for now Forge at the time of writing does not have a public release, and NeoForge has breaking changes to their fancymodloader, which requires more work to get updated. So, I'm disabling Forge and NeoForge from building on api-17 for now. This will allow SpongeVanilla to build for 1.21.9 --- .github/workflows/common-run-build.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 82dc1d45351..c990a549625 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -16,15 +16,15 @@ jobs: matrix: project: - vanilla - - forge - - neoforge +# - forge +# - neoforge include: - project: vanilla gradleProject: SpongeVanilla - - project: forge - gradleProject: SpongeForge - - project: neoforge - gradleProject: SpongeNeo +# - project: forge +# gradleProject: SpongeForge +# - project: neoforge +# gradleProject: SpongeNeo steps: - name: setup id: setup From ed272c8dcd50115faf22018cbdd5e0d7021be623 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 1 Oct 2025 23:12:06 +0300 Subject: [PATCH 379/586] Ensure tests run inside phase tracker phase --- forge/build.gradle.kts | 1 + neoforge/build.gradle.kts | 1 + .../bridge/server/MinecraftServerBridge.java | 4 + .../common/event/tracking/PhaseTracker.java | 20 ++-- .../server/MinecraftServerMixin_Test.java | 5 + .../server/MinecraftServerMixin_Tracker.java | 5 +- .../event/tracking/PhaseTrackerTest.java | 4 +- .../test/TestInvocationInterceptor.java | 100 ++++++++++++++++++ .../org.junit.jupiter.api.extension.Extension | 1 + vanilla/build.gradle.kts | 1 + 10 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 src/test/java/org/spongepowered/common/test/TestInvocationInterceptor.java create mode 100644 src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 18ec3c137b3..3effe845092 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -436,6 +436,7 @@ tasks { jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") + jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 551f1993492..414858b77a7 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -411,6 +411,7 @@ tasks { jvmArgs("-Dsponge.test.args=" + runServer.get().args!!.joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") + jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { diff --git a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java index a3a3a31a5ac..9277ecded0f 100644 --- a/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/server/MinecraftServerBridge.java @@ -57,4 +57,8 @@ public interface MinecraftServerBridge { default void bridge$tickServer(int ticks) { throw new UnsupportedOperationException("Cannot trigger manual server tick outside test environment"); } + + default boolean bridge$insideTestEnvironment() { + return false; + } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 60f637b8a9e..062626d1204 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -111,15 +111,17 @@ public static PhaseTracker getInstance() { return PhaseTracker.CLIENT; } - return PhaseTracker.SPINOFF_TRACKERS.computeIfAbsent(current, (thread) -> { - try { - final PhaseTracker phaseTracker = new PhaseTracker(); - phaseTracker.setThread(thread); - return phaseTracker; - } catch (final IllegalAccessException e) { - throw new RuntimeException("Unable to create a new PhaseTracker for Thread: " + thread, e); - } - }); + return PhaseTracker.SPINOFF_TRACKERS.computeIfAbsent(current, PhaseTracker::createNew); + } + + public static PhaseTracker createNew(final Thread thread) { + try { + final PhaseTracker phaseTracker = new PhaseTracker(); + phaseTracker.setThread(thread); + return phaseTracker; + } catch (final IllegalAccessException e) { + throw new RuntimeException("Unable to create a new PhaseTracker for Thread: " + thread, e); + } } /** diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java index 8d92a0c9168..79c6b77ab55 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java @@ -119,4 +119,9 @@ private boolean haveTime() { this.waitUntilNextTick(); } } + + @Override + public boolean bridge$insideTestEnvironment() { + return true; + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java index 8828ef785d1..78a5851d1d9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java @@ -37,6 +37,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.bridge.server.MinecraftServerBridge; import org.spongepowered.common.bridge.server.TickTaskBridge; import org.spongepowered.common.event.tracking.CauseTrackerCrashHandler; import org.spongepowered.common.event.tracking.PhaseContext; @@ -70,7 +71,9 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix context.buildAndSwitch(); original.call(hasTimeLeft); } - PhaseTracker.getServerInstanceExplicitly().ensureEmpty(); + if (!((MinecraftServerBridge) this).bridge$insideTestEnvironment()) { + PhaseTracker.getServerInstanceExplicitly().ensureEmpty(); + } } @WrapOperation( diff --git a/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java b/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java index 1555dfc1cdb..cf2159fe51b 100644 --- a/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java +++ b/src/test/java/org/spongepowered/common/event/tracking/PhaseTrackerTest.java @@ -35,7 +35,7 @@ public class PhaseTrackerTest { @Test public void testPoppingFramePopsCauses() { - final PhaseTracker phaseTracker = PhaseTracker.getInstance(); + final PhaseTracker phaseTracker = PhaseTracker.createNew(Thread.currentThread()); // We start by pushing a frame... CauseStackManager.StackFrame frame1 = phaseTracker.pushCauseFrame(); @@ -60,7 +60,7 @@ public void testPoppingFramePopsCauses() { @Test public void testPoppingFrameRemovesFrameContexts() { - final PhaseTracker phaseTracker = PhaseTracker.getInstance(); + final PhaseTracker phaseTracker = PhaseTracker.createNew(Thread.currentThread()); String cmd1 = "one"; String cmd2 = "two"; diff --git a/src/test/java/org/spongepowered/common/test/TestInvocationInterceptor.java b/src/test/java/org/spongepowered/common/test/TestInvocationInterceptor.java new file mode 100644 index 00000000000..2a1b9fdd69a --- /dev/null +++ b/src/test/java/org/spongepowered/common/test/TestInvocationInterceptor.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.test; + +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.junit.jupiter.api.extension.DynamicTestInvocationContext; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.InvocationInterceptor; +import org.junit.jupiter.api.extension.ReflectiveInvocationContext; +import org.spongepowered.api.Sponge; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.phase.tick.TickPhase; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +public final class TestInvocationInterceptor implements InvocationInterceptor { + + @Override + public T interceptTestClassConstructor(final Invocation invocation, final ReflectiveInvocationContext> invocationContext, final ExtensionContext extensionContext) throws Throwable { + return this.intercept(invocation); + } + + @Override + public void interceptBeforeAllMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public void interceptBeforeEachMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public void interceptTestMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public T interceptTestFactoryMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + return this.intercept(invocation); + } + + @Override + public void interceptTestTemplateMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public void interceptDynamicTest(final Invocation invocation, final DynamicTestInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public void interceptAfterAllMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + @Override + public void interceptAfterEachMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + this.intercept(invocation); + } + + private T intercept(final Invocation invocation) throws Throwable { + try ( + final PhaseContext<@NonNull ?> context = TickPhase.Tick.SERVER_TICK + .createPhaseContext(PhaseTracker.getServerInstanceExplicitly()) + .server((MinecraftServer) Sponge.server()) + ) { + context.buildAndSwitch(); + return invocation.proceed(); + } finally { + PhaseTracker.getServerInstanceExplicitly().ensureEmpty(); + } + } +} diff --git a/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension new file mode 100644 index 00000000000..d427d69cee9 --- /dev/null +++ b/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension @@ -0,0 +1 @@ +org.spongepowered.common.test.TestInvocationInterceptor \ No newline at end of file diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 271a41a0c0e..4ac4e3e52de 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -518,6 +518,7 @@ tasks { jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") + jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile doFirst { From 359ef2562be6d5455402e6ee472aac331c682ec0 Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:15:41 -0500 Subject: [PATCH 380/586] Fixed modern forwarding support (#4234) * fix: Fixed modern forwarding support * fix: Fixed another immutability issue --- .../ipforward/velocity/VelocityForwardingInfo.java | 14 +++++++++----- .../common/profile/SpongeGameProfile.java | 10 +++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java b/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java index c79a5096e42..99486ad4e48 100644 --- a/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java +++ b/src/main/java/org/spongepowered/common/ipforward/velocity/VelocityForwardingInfo.java @@ -24,9 +24,11 @@ */ package org.spongepowered.common.ipforward.velocity; +import com.google.common.collect.ImmutableMultimap; import com.google.common.net.InetAddresses; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import io.netty.buffer.ByteBuf; import net.kyori.adventure.text.Component; import net.minecraft.network.Connection; @@ -135,18 +137,20 @@ public static InetAddress readAddress(final ChannelBuf buf) { } public static GameProfile createProfile(final ChannelBuf buf) { - final GameProfile profile = new GameProfile(buf.readUniqueId(), ((FriendlyByteBuf) buf).readUtf(16)); // TODO: ChannelBuf length-limited strings - VelocityForwardingInfo.readProperties(buf, profile); - return profile; + // TODO: ChannelBuf length-limited strings + return new GameProfile(buf.readUniqueId(), ((FriendlyByteBuf) buf).readUtf(16), VelocityForwardingInfo.readProperties(buf)); } - private static void readProperties(final ChannelBuf buf, final GameProfile profile) { + private static PropertyMap readProperties(final ChannelBuf buf) { + final ImmutableMultimap.Builder propertiesBuilder = ImmutableMultimap.builder(); final int properties = buf.readVarInt(); for (int i1 = 0; i1 < properties; i1++) { final String name = buf.readString(); final String value = buf.readString(); final String signature = buf.readBoolean() ? buf.readString() : null; - profile.properties().put(name, new Property(name, value, signature)); + propertiesBuilder.put(name, new Property(name, value, signature)); } + final ImmutableMultimap propertiesMap = propertiesBuilder.build(); + return new PropertyMap(propertiesMap); } } diff --git a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java index 49264d46148..0c093c82fbf 100644 --- a/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java +++ b/src/main/java/org/spongepowered/common/profile/SpongeGameProfile.java @@ -25,8 +25,11 @@ package org.spongepowered.common.profile; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -148,11 +151,12 @@ public SpongeGameProfile(final UUID uniqueId, final @Nullable String name, final public com.mojang.authlib.GameProfile toMcProfile() { final UUID uniqueId = this.uniqueId; final String name = (this.name == null) ? "" : this.name; - final com.mojang.authlib.GameProfile mcProfile = new com.mojang.authlib.GameProfile(uniqueId, name); + final ImmutableMultimap.Builder propertyBuilder = ImmutableMultimap.builder(); for (final SpongeProfileProperty property : this.properties) { - mcProfile.properties().put(property.name(), property.asProperty()); + propertyBuilder.put(property.name(), property.asProperty()); } - return mcProfile; + final PropertyMap propertyMap = new PropertyMap(propertyBuilder.build()); + return new com.mojang.authlib.GameProfile(uniqueId, name, propertyMap); } @Override From 3e6f55cbad5bda2f8afd9ba8ccd5737775ed8b86 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 1 Oct 2025 23:35:32 +0300 Subject: [PATCH 381/586] Fix whitelist and ban commands --- .../common/service/server/whitelist/SpongeUserWhiteList.java | 2 +- .../service/server/whitelist/SpongeWhitelistService.java | 2 +- .../minecraft/server/players/UserBanListEntryMixin_API.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java index 760b7d297dc..7e858440e48 100644 --- a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java +++ b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeUserWhiteList.java @@ -64,7 +64,7 @@ public String[] getUserList() { @SuppressWarnings("unchecked") @Override public boolean add(final UserWhiteListEntry entry) { - return Sponge.server().serviceProvider().whitelistService().addProfile(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())).join(); + return Sponge.server().serviceProvider().whitelistService().addProfile(SpongeGameProfile.of(((StoredUserEntryAccessor) entry).accessor$user())).join(); } @Override diff --git a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java index dd9d59dfc12..3a1779c5eb2 100644 --- a/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java +++ b/src/main/java/org/spongepowered/common/service/server/whitelist/SpongeWhitelistService.java @@ -75,7 +75,7 @@ public CompletableFuture addProfile(final GameProfile profile) { @Override public CompletableFuture removeProfile(final GameProfile profile) { - final boolean wasWhitelisted = UserListUtil.removeEntry(SpongeWhitelistService.getWhitelist(), SpongeGameProfile.toMcProfile(profile)) != null; + final boolean wasWhitelisted = UserListUtil.removeEntry(SpongeWhitelistService.getWhitelist(), SpongeGameProfile.toNameAndId(profile)) != null; return CompletableFuture.completedFuture(wasWhitelisted); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/UserBanListEntryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/UserBanListEntryMixin_API.java index 1316d762aac..5c5aa2ae390 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/UserBanListEntryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/UserBanListEntryMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.server.players; +import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.UserBanListEntry; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.api.service.ban.Ban; @@ -33,7 +34,7 @@ import org.spongepowered.common.profile.SpongeGameProfile; @Mixin(UserBanListEntry.class) -public abstract class UserBanListEntryMixin_API extends BanListEntryMixin_API implements Ban.Profile { +public abstract class UserBanListEntryMixin_API extends BanListEntryMixin_API implements Ban.Profile { @Override public BanType type() { From 6e3641d1f138f4d56192be6f13ada2a439dcd8e2 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 1 Oct 2025 21:08:14 -0700 Subject: [PATCH 382/586] feat(forge): update Forge for 1.21.9 Upgraded Forge dependencies and introduced MixinExtras for better injector handling. Adjusted lambda mixin methods, improved client-side checks, and refined explosion knockback logic with `WrapOperation`. Updated verification metadata for new component versions. --- .github/workflows/common-run-build.yaml | 6 +- .github/workflows/deploy.yaml | 6 +- forge/gradle.properties | 2 +- .../server/MinecraftServerMixin_Forge.java | 4 +- .../entity/item/ItemEntityMixin_Forge.java | 2 +- .../level/ServerExplosionMixin_Forge.java | 10 +- .../level/block/FireBlockMixin_Forge.java | 4 +- gradle/verification-metadata.xml | 163 ++++++++++++++++++ 8 files changed, 180 insertions(+), 17 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index c990a549625..53ce2ca1cd7 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -16,13 +16,13 @@ jobs: matrix: project: - vanilla -# - forge + - forge # - neoforge include: - project: vanilla gradleProject: SpongeVanilla -# - project: forge -# gradleProject: SpongeForge + - project: forge + gradleProject: SpongeForge # - project: neoforge # gradleProject: SpongeNeo steps: diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 99c138c7923..0012154aba1 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -42,9 +42,9 @@ jobs: - project: forge gradleProject: ':SpongeForge' skipUpdateBranch: true - - project: neoforge - gradleProject: ':SpongeNeo' - skipUpdateBranch: true +# - project: neoforge +# gradleProject: ':SpongeNeo' +# skipUpdateBranch: true steps: - name: setup if: "!(matrix.skipUpdateBranch && startsWith(github.ref, 'refs/heads/update/'))" diff --git a/forge/gradle.properties b/forge/gradle.properties index 5919c25080f..1dcd7d36c1e 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=58.0.5 +forgeVersion=59.0.0 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java index e4ae8e4a76a..32f53051f12 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java @@ -63,13 +63,13 @@ public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } - @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$30", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager forge$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$31", at = @At("TAIL")) public void forge$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java index 1ad9b4ed978..516ee798c28 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java @@ -46,7 +46,7 @@ public abstract class ItemEntityMixin_Forge { final CallbackInfo ci ) { // Check the level is not null to avoid an NPE - if (level != null && !level.isClientSide) { + if (level != null && !level.isClientSide()) { this.lifespan = SpongeGameConfigs.getForWorld(level).get().entity.item.despawnRate; } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java index 1b2f324c8f6..9ac4759c2cf 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java @@ -24,6 +24,8 @@ */ package org.spongepowered.forge.mixin.core.world.level; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -104,12 +106,10 @@ public abstract class ServerExplosionMixin_Forge { } - @Redirect(method = "hurtEntities", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 forge$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { + @WrapOperation(method = "hurtEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;scale(D)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 forge$useKnockbackMultiplier(Vec3 instance, double $$0, Operation original) { // Honor our knockback value from event - return new Vec3($$0 * this.impl$knockbackMultiplier, - $$1 * this.impl$knockbackMultiplier, - $$2 * this.impl$knockbackMultiplier); + return original.call(instance, $$0 * this.impl$knockbackMultiplier); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java index da13efce569..8b0d491eebc 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java @@ -49,7 +49,7 @@ public class FireBlockMixin_Forge { cancellable = true) private void impl$onCatchFirePreCheck( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final Direction dir, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } @@ -65,7 +65,7 @@ public class FireBlockMixin_Forge { cancellable = true) private void impl$onCatchFirePreCheckOther( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final Direction dir, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index df1a7205e1f..40ed35dec15 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2434,6 +2434,14 @@ + + + + + + + + @@ -3044,6 +3052,14 @@ + + + + + + + + @@ -4347,6 +4363,14 @@ + + + + + + + + @@ -4505,6 +4529,14 @@ + + + + + + + + @@ -4655,6 +4687,14 @@ + + + + + + + + @@ -4805,6 +4845,14 @@ + + + + + + + + @@ -4939,6 +4987,14 @@ + + + + + + + + @@ -5124,6 +5180,14 @@ + + + + + + + + @@ -5282,6 +5346,14 @@ + + + + + + + + @@ -5440,6 +5512,14 @@ + + + + + + + + @@ -5745,6 +5825,14 @@ + + + + + + + + @@ -5812,6 +5900,14 @@ + + + + + + + + @@ -5820,6 +5916,14 @@ + + + + + + + + @@ -5947,6 +6051,11 @@ + + + + + @@ -6168,6 +6277,20 @@ + + + + + + + + + + + + + + @@ -6232,6 +6355,14 @@ + + + + + + + + @@ -6320,6 +6451,14 @@ + + + + + + + + @@ -6400,6 +6539,14 @@ + + + + + + + + @@ -6480,6 +6627,14 @@ + + + + + + + + @@ -8344,6 +8499,14 @@ + + + + + + + + From 882845e43636f9a2088015b92cb6912e6620c59b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 5 Oct 2025 15:45:48 +0200 Subject: [PATCH 383/586] Update NeoForge transformers --- bootstrap/build.gradle.kts | 2 +- .../spongepowered/bootstrap/Bootstrap.java | 3 +- .../bootstrap/dev/DevClasspath.java | 2 +- .../bootstrap/neoforge/NeoForgeBootstrap.java | 10 +- build.gradle.kts | 7 +- forge/build.gradle.kts | 6 +- .../ForgeAccessWidenerTransformer.java | 70 +++--- ...mer.java => ForgeListenerTransformer.java} | 18 +- .../ForgeSuperclassChangeTransformer.java | 93 ++++++++ .../ForgeTransformationService.java | 28 ++- .../transformation/JacocoPluginService.java | 62 +++++ .../SpongeForgeTransformationService.java | 119 ---------- ...ods.modlauncher.api.ITransformationService | 2 +- ...odlauncher.serviceapi.ILaunchPluginService | 1 + gradle.properties | 1 - gradle/libs.versions.toml | 9 +- gradle/verification-metadata.xml | 33 +++ modlauncher-transformers/build.gradle.kts | 26 -- .../AccessWidenerTransformationService.java | 168 ------------- .../modlauncher/SuperclassChanger.java | 224 ------------------ .../src/main/resources/META-INF/MANIFEST.MF | 1 - ...ods.modlauncher.api.ITransformationService | 2 - ...odlauncher.serviceapi.ILaunchPluginService | 1 - neoforge/build.gradle.kts | 5 - neoforge/gradle.properties | 2 +- .../SpongeNeoDependencyLocator.java | 14 +- .../moddiscovery/SpongeNeoModLocator.java | 21 +- .../moddiscovery/reader/PluginFileParser.java | 14 +- .../moddiscovery/reader/PluginFileReader.java | 2 +- .../plugin/NeoForgePluginPlatform.java | 13 +- .../NeoAccessWidenerTransformer.java | 87 +++++++ .../NeoListenerTransformer.java | 75 ++++++ .../NeoSuperclassChangeTransformer.java | 78 ++++++ .../SpongeNeoTransformationService.java | 117 --------- ...ods.modlauncher.api.ITransformationService | 1 - ....neoforgespi.transformation.ClassProcessor | 3 + .../neoforge/launch/NeoLaunch.java | 6 +- .../launch/plugin/NeoPluginContainer.java | 5 +- .../launch/plugin/PluginModContainer.java | 2 +- .../entity/item/ItemEntityMixin_Neo.java | 2 +- .../world/level/block/FireBlockMixin_Neo.java | 4 +- settings.gradle.kts | 1 - .../AccessWidenerTransformer.java | 91 +++++++ .../transformation/ListenerTransformer.java | 26 +- .../SuperclassChangeTransformer.java | 136 +++++++++++ .../jacoco/AgentAccessGenerator.java | 2 +- .../transformation}/jacoco/Instrumenter.java | 2 +- .../jacoco/JacocoTransformer.java | 54 ++--- .../PrefixedCondyProbeArrayStrategy.java | 2 +- vanilla/build.gradle.kts | 15 +- .../plugin/VanillaTransformationService.java | 56 +---- .../transformation/JacocoPluginService.java | 62 +++++ .../ListenerPluginService.java | 12 +- .../VanillaAccessWidenerTransformer.java | 88 +++++++ .../VanillaSuperclassChangeTransformer.java | 93 ++++++++ ...ods.modlauncher.api.ITransformationService | 2 +- ...odlauncher.serviceapi.ILaunchPluginService | 3 +- 57 files changed, 1091 insertions(+), 893 deletions(-) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/ListenerTransformer.java => forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java (54%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/{ListenerTransformer.java => ForgeListenerTransformer.java} (88%) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/Constants.java => forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeTransformationService.java (60%) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/JacocoPluginService.java delete mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/SpongeForgeTransformationService.java create mode 100644 forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService delete mode 100644 modlauncher-transformers/build.gradle.kts delete mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/AccessWidenerTransformationService.java delete mode 100644 modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/SuperclassChanger.java delete mode 100644 modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF delete mode 100644 modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService delete mode 100644 modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoListenerTransformer.java create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java delete mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/SpongeNeoTransformationService.java delete mode 100644 neoforge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService create mode 100644 neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.transformation.ClassProcessor create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/transformation/AccessWidenerTransformer.java rename modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/ListenerTransformerHelper.java => src/applaunch/java/org/spongepowered/common/applaunch/transformation/ListenerTransformer.java (71%) create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/transformation/SuperclassChangeTransformer.java rename {modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher => src/applaunch/java/org/spongepowered/common/applaunch/transformation}/jacoco/AgentAccessGenerator.java (96%) rename {modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher => src/applaunch/java/org/spongepowered/common/applaunch/transformation}/jacoco/Instrumenter.java (98%) rename modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java => src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/JacocoTransformer.java (78%) rename {modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher => src/applaunch/java/org/spongepowered/common/applaunch/transformation}/jacoco/PrefixedCondyProbeArrayStrategy.java (97%) create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/JacocoPluginService.java rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/{plugin => transformation}/ListenerPluginService.java (84%) create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts index 0372e14307b..b5ea55595d5 100644 --- a/bootstrap/build.gradle.kts +++ b/bootstrap/build.gradle.kts @@ -17,5 +17,5 @@ dependencies { forgeLib(libs.securemodules) val neoforgeLib = neoforge.implementationConfigurationName - neoforgeLib(libs.fancymodloader.securejarhandler) + neoforgeLib(libs.fancymodloader) } diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 5f3abbc0c1f..9245922bc7c 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -27,6 +27,7 @@ import org.spongepowered.bootstrap.dev.DevClasspath; import java.io.File; +import java.io.IOException; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import java.net.URL; @@ -45,7 +46,7 @@ public abstract class Bootstrap { public abstract String name(); - protected abstract Jar createJar(Path[] paths); + protected abstract Jar createJar(Path[] paths) throws IOException; protected abstract String getModuleName(Jar jar); diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 4ca4698babf..7a65655e3d7 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -79,7 +79,7 @@ public static List resolve() { case "bootstrap": // ignore break; - case "modlauncher-transformers", "library-manager": + case "library-manager": bootUnions.add(projectName, path); break; case "SpongeAPI": diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java index 852e88e448e..f4805062ec2 100644 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java @@ -24,11 +24,12 @@ */ package org.spongepowered.bootstrap.neoforge; -import cpw.mods.cl.JarModuleFinder; -import cpw.mods.cl.ModuleClassLoader; -import cpw.mods.jarhandling.SecureJar; +import net.neoforged.fml.classloading.JarModuleFinder; +import net.neoforged.fml.classloading.ModuleClassLoader; +import net.neoforged.fml.classloading.SecureJar; import org.spongepowered.bootstrap.Bootstrap; +import java.io.IOException; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import java.nio.file.Path; @@ -48,7 +49,7 @@ public String name() { } @Override - protected SecureJar createJar(final Path[] paths) { + protected SecureJar createJar(final Path[] paths) throws IOException { return SecureJar.from(paths); } @@ -69,6 +70,7 @@ protected ClassLoader createApplicationClassLoader(final Configuration config, f @Override protected void runApplication(final ModuleLayer layer) throws Exception { + // TODO net.neoforged.fml.startup.* final Class appClass = layer.findModule("fml_loader").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); } diff --git a/build.gradle.kts b/build.gradle.kts index 905da3c316d..246515cac53 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -142,7 +142,6 @@ dependencies { exclude(group = "com.google.errorprone", module = "error_prone_annotations") } launchConfig(apiLibs.gson) - launchConfig(libs.asm.tree) launchConfig(libs.asm.util) // Applaunch -- initialization that needs to occur without game access @@ -159,6 +158,12 @@ dependencies { exclude(group = "com.google.code.gson", module = "gson") exclude(group = "org.apache.logging.log4j", module = "log4j-api") } + applaunchConfig(libs.asm.commons) + applaunchConfig(libs.accessWidener) + + // Optional + val applaunchCompileOnly = applaunch.get().compileOnlyConfigurationName + applaunchCompileOnly(libs.jacoco.core) add(mixins.get().implementationConfigurationName, "org.spongepowered:spongeapi:$apiVersion") diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 25e1e11f3fd..74ad0fc8ccc 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -25,7 +25,6 @@ plugins { val commonProject = parent!! val bootstrapProject = commonProject.project(":bootstrap") -val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -193,9 +192,7 @@ dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) - service(project(transformersProject.path)) { - exclude(group = "net.neoforged.fancymodloader", module = "loader") - } + service(libs.accessWidener) service(project(libraryManagerProject.path)) val game = gameLibrariesConfig.name @@ -206,7 +203,6 @@ dependencies { game(libs.mixinextras.common) val serviceShadedLibraries = serviceShadedLibrariesConfig.name - serviceShadedLibraries(project(transformersProject.path)) { isTransitive = false } serviceShadedLibraries(project(libraryManagerProject.path)) { isTransitive = false } val gameShadedLibraries = gameShadedLibrariesConfig.name diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/ListenerTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java similarity index 54% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/ListenerTransformer.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java index d2e116316c6..9a54cfdc85f 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/ListenerTransformer.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java @@ -22,63 +22,67 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.transformation; +package org.spongepowered.forge.applaunch.transformation; +import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.ITransformer; import cpw.mods.modlauncher.api.ITransformerActivity; import cpw.mods.modlauncher.api.ITransformerVotingContext; -import cpw.mods.modlauncher.api.TargetType; import cpw.mods.modlauncher.api.TransformerVoteResult; -import net.neoforged.fml.loading.LoadingModList; -import net.neoforged.fml.loading.moddiscovery.ModFileInfo; -import net.neoforged.neoforgespi.language.ModFileScanData; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.objectweb.asm.Type; +import net.minecraftforge.fml.loading.LoadingModList; +import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.transformers.modlauncher.ListenerTransformerHelper; +import org.spongepowered.common.applaunch.transformation.AccessWidenerTransformer; -import java.util.HashSet; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; import java.util.Set; +import java.util.jar.Attributes; +import java.util.stream.Collectors; -public class ListenerTransformer implements ITransformer { +public class ForgeAccessWidenerTransformer extends AccessWidenerTransformer implements ITransformer { + private static final String[] LABELS = { AccessWidenerTransformer.NAME }; + + @Override + public String[] labels() { + return LABELS; + } - @NonNull @Override public ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { - ListenerTransformerHelper.transform(input); - return input; + return this.transform(input); } - @NonNull @Override public TransformerVoteResult castVote(final ITransformerVotingContext context) { return context.getReason().equals(ITransformerActivity.CLASSLOADING_REASON) ? TransformerVoteResult.YES : TransformerVoteResult.NO; } - @NonNull @Override - public Set> targets() { - final Type listenerType = Type.getType(ListenerTransformerHelper.LISTENER_DESC); + public Set targets() { + return this.targetClasses().stream().map(Target::targetClass).collect(Collectors.toSet()); + } - final Set listenerClasses = new HashSet<>(); + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { - for (ModFileScanData.AnnotationData annotation : fileInfo.getFile().getScanResult().getAnnotations()) { - if (listenerType.equals(annotation.annotationType())) { - listenerClasses.add(annotation.clazz()); + final SecureJar jar = fileInfo.getFile().getSecureJar(); + final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + + final String attribute = attributes.getValue(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); + if (attribute != null) { + for (final String path : attribute.split(",")) { + try { + resources.add(jar.getPath(path).toUri().toURL()); + } catch (final MalformedURLException e) { + LOGGER.warn("Failed to locate access widener {} from {}", path, fileInfo.getFile().getFileName(), e); + } } } } - - final Set> targets = new HashSet<>(); - for (Type listener : listenerClasses) { - targets.add(Target.targetClass(listener.getInternalName())); - } - return targets; - } - - @NonNull - @Override - public TargetType getTargetType() { - return TargetType.CLASS; + return resources; } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ListenerTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java similarity index 88% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ListenerTransformer.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java index 4bbaab1e6f4..83a6eeed82c 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ListenerTransformer.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java @@ -31,33 +31,35 @@ import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.forgespi.language.ModFileScanData; -import org.checkerframework.checker.nullness.qual.NonNull; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.transformers.modlauncher.ListenerTransformerHelper; +import org.spongepowered.common.applaunch.transformation.ListenerTransformer; import java.util.HashSet; import java.util.Set; -public class ListenerTransformer implements ITransformer { +public class ForgeListenerTransformer extends ListenerTransformer implements ITransformer { + private static final String[] LABELS = { ListenerTransformer.NAME }; + + @Override + public String[] labels() { + return LABELS; + } - @NonNull @Override public ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { - ListenerTransformerHelper.transform(input); + this.transform(input); return input; } - @NonNull @Override public TransformerVoteResult castVote(final ITransformerVotingContext context) { return context.getReason().equals(ITransformerActivity.CLASSLOADING_REASON) ? TransformerVoteResult.YES : TransformerVoteResult.NO; } - @NonNull @Override public Set targets() { - final Type listenerType = Type.getType(ListenerTransformerHelper.LISTENER_DESC); + final Type listenerType = Type.getType(ListenerTransformer.ANNOTATION_DESC); final Set listenerClasses = new HashSet<>(); for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java new file mode 100644 index 00000000000..f7d351d2845 --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java @@ -0,0 +1,93 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.transformation; + +import cpw.mods.jarhandling.SecureJar; +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.api.ITransformerVotingContext; +import cpw.mods.modlauncher.api.TransformerVoteResult; +import net.minecraftforge.fml.loading.LoadingModList; +import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.SuperclassChangeTransformer; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.stream.Collectors; + +public class ForgeSuperclassChangeTransformer extends SuperclassChangeTransformer implements ITransformer { + private static final String MIXIN_PLUGIN_REASON = "mixin"; + private static final String[] LABELS = { SuperclassChangeTransformer.NAME }; + + @Override + public String[] labels() { + return LABELS; + } + + @Override + public ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { + this.transform(input); + return input; + } + + @Override + public TransformerVoteResult castVote(final ITransformerVotingContext context) { + return switch (context.getReason()) { + case ITransformerActivity.CLASSLOADING_REASON, ForgeSuperclassChangeTransformer.MIXIN_PLUGIN_REASON -> TransformerVoteResult.YES; + default -> TransformerVoteResult.NO; + }; + } + + @Override + public Set targets() { + return this.targetClasses().stream().map(Target::targetClass).collect(Collectors.toSet()); + } + + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); + for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { + final SecureJar jar = fileInfo.getFile().getSecureJar(); + final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + + final String attribute = attributes.getValue(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); + if (attribute != null) { + for (final String path : attribute.split(",")) { + try { + resources.add(jar.getPath(path).toUri().toURL()); + } catch (final MalformedURLException e) { + LOGGER.warn("Failed to locate superclass changer {} from {}", path, fileInfo.getFile().getFileName(), e); + } + } + } + } + return resources; + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/Constants.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeTransformationService.java similarity index 60% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/Constants.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeTransformationService.java index 969dea1eb7c..3fbfb913fb3 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/Constants.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeTransformationService.java @@ -22,12 +22,30 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch; +package org.spongepowered.forge.applaunch.transformation; -public final class Constants { +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; +import cpw.mods.modlauncher.api.ITransformer; - public static final class ManifestAttributes { - public static final String ACCESS_WIDENER = "Access-Widener"; - public static final String SUPERCLASS_CHANGE = "Superclass-Transformer"; +import java.util.List; +import java.util.Set; + +public class ForgeTransformationService implements ITransformationService { + @Override + public String name() { + return "spongeforge"; + } + + @Override + public void initialize(final IEnvironment environment) {} + + @Override + public void onLoad(final IEnvironment env, final Set otherServices) {} + + @SuppressWarnings("rawtypes") + @Override + public List transformers() { + return List.of(new ForgeAccessWidenerTransformer(), new ForgeListenerTransformer(), new ForgeSuperclassChangeTransformer()); } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/JacocoPluginService.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/JacocoPluginService.java new file mode 100644 index 00000000000..40b919f9cba --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/JacocoPluginService.java @@ -0,0 +1,62 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.transformation; + +import cpw.mods.modlauncher.TransformingClassLoader; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.jacoco.JacocoTransformer; + +import java.util.EnumSet; + +public class JacocoPluginService extends JacocoTransformer implements ILaunchPluginService { + private static final EnumSet YAY = EnumSet.of(Phase.BEFORE); + private static final EnumSet NAY = EnumSet.noneOf(Phase.class); + + @Override + public String name() { + return JacocoTransformer.NAME; + } + + @Override + protected boolean isTransformingClassloader(ClassLoader loader) { + return loader instanceof TransformingClassLoader; + } + + @Override + public EnumSet handlesClass(Type classType, boolean isEmpty) { + return this.disabled || isEmpty ? NAY : YAY; + } + + @Override + public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { + if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) { + return ComputeFlags.NO_REWRITE; + } + return this.transform(classNode) ? ComputeFlags.SIMPLE_REWRITE : ComputeFlags.NO_REWRITE; + } +} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/SpongeForgeTransformationService.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/SpongeForgeTransformationService.java deleted file mode 100644 index d8e27aad5b3..00000000000 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/SpongeForgeTransformationService.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.applaunch.transformation; - -import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.Environment; -import cpw.mods.modlauncher.Launcher; -import cpw.mods.modlauncher.api.IEnvironment; -import cpw.mods.modlauncher.api.IModuleLayerManager; -import cpw.mods.modlauncher.api.ITransformationService; -import cpw.mods.modlauncher.api.ITransformer; -import net.minecraftforge.fml.loading.LoadingModList; -import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.transformers.modlauncher.AccessWidenerTransformationService; -import org.spongepowered.transformers.modlauncher.SuperclassChanger; - -import java.net.MalformedURLException; -import java.util.List; -import java.util.Set; -import java.util.jar.Attributes; - -public class SpongeForgeTransformationService implements ITransformationService { - private static final Logger LOGGER = LogManager.getLogger(); - - @NonNull - @Override - public String name() { - return "spongeforge"; - } - - @Override - public void initialize(final IEnvironment environment) { - } - - @Override - public void onLoad(final IEnvironment env, final Set otherServices) { - } - - @Override - public List completeScan(IModuleLayerManager layerManager) { - final Environment env = Launcher.INSTANCE.environment(); - final AccessWidenerTransformationService accessWidener = env.getProperty(AccessWidenerTransformationService.INSTANCE.get()).orElse(null); - final SuperclassChanger superclassChanger = env.getProperty(SuperclassChanger.INSTANCE.get()).orElse(null); - - if (accessWidener != null || superclassChanger != null) { - // TODO move this inside modlauncher-transformers when updating SpongeVanilla to latest ModLauncher - for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { - final SecureJar jar = fileInfo.getFile().getSecureJar(); - final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); - - if (accessWidener != null) { - final String awPaths = attributes.getValue("Access-Widener"); - if (awPaths != null) { - final String jarFileName = fileInfo.getFile().getFileName(); - LOGGER.debug("Registering access wideners from {} ...", jarFileName); - - for (final String awPath : awPaths.split(",")) { - try { - accessWidener.offerResource(jar.getPath(awPath).toUri().toURL(), awPath); - } catch (final MalformedURLException e) { - LOGGER.warn("Failed to register access widener {} from {}", awPath, jarFileName, e); - } - } - } - } - - if (superclassChanger != null) { - final String scPaths = attributes.getValue("Superclass-Transformer"); - if (scPaths != null) { - final String jarFileName = fileInfo.getFile().getFileName(); - LOGGER.debug("Registering superclass changers from {} ...", jarFileName); - - for (final String scPath : scPaths.split(",")) { - try { - superclassChanger.offerResource(jar.getPath(scPath).toUri().toURL(), scPath); - } catch (final MalformedURLException e) { - LOGGER.warn("Failed to register superclass changer {} from {}", scPath, jarFileName, e); - } - } - } - } - } - } - - return List.of(); - } - - @NonNull - @Override - @SuppressWarnings("rawtypes") // :) - public List transformers() { - return List.of(new ListenerTransformer()); - } -} diff --git a/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService index ced7680d190..a346646d5ea 100644 --- a/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService +++ b/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -1 +1 @@ -org.spongepowered.forge.applaunch.transformation.SpongeForgeTransformationService +org.spongepowered.forge.applaunch.transformation.ForgeTransformationService diff --git a/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService new file mode 100644 index 00000000000..26f9b4d60bf --- /dev/null +++ b/forge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService @@ -0,0 +1 @@ +org.spongepowered.forge.applaunch.transformation.JacocoPluginService diff --git a/gradle.properties b/gradle.properties index d8b9710cb8e..7855e5bc16d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,6 @@ projectDescription=The SpongeAPI implementation targeting vanilla Minecraft and mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.concurrent.json,mixins.sponge.core.json,\ mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -superClassChanges=common.superclasschange minecraftVersion=1.21.9 recommendedVersion=0-SNAPSHOT diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a18b360a996..2c2be61ec21 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ mixin = "0.8.7" mixinextras = "0.5.0" modlauncher = "10.2.2" securemodules = "2.2.22" -fancymodloader = "9.0.16" +fancymodloader = "10.0.14" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" @@ -34,19 +34,16 @@ log4j-jpl = { module = "org.apache.logging.log4j:log4j-jpl", version.ref = "log4 log4j-slf4j2 = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" } modlauncher = { module = "net.minecraftforge:modlauncher", version.ref = "modlauncher" } securemodules = { module = "net.minecraftforge:securemodules", version.ref = "securemodules" } -fancymodloader-loader = { module = "net.neoforged.fancymodloader:loader", version.ref = "fancymodloader" } -fancymodloader-securejarhandler = { module = "net.neoforged.fancymodloader:securejarhandler", version.ref = "fancymodloader" } +fancymodloader = { module = "net.neoforged.fancymodloader:loader", version.ref = "fancymodloader" } tinylog-api = { module = "org.tinylog:tinylog-api", version.ref = "tinylog" } tinylog-impl = { module = "org.tinylog:tinylog-impl", version.ref = "tinylog" } tinylog-slf4j = { module = "org.tinylog:slf4j-tinylog", version.ref = "tinylog" } +accessWidener = { module = "net.fabricmc:access-widener", version = "2.1.0" } # generator javaparser = { module = "com.github.javaparser:javaparser-core", version = "3.25.9" } javapoet = { module = "com.squareup:javapoet", version = "1.13.0" } -# modlauncher-transformers -accessWidener = { module = "net.fabricmc:access-widener", version = "2.1.0" } - # Sponge adventure-serializerAnsi = { module = "net.kyori:adventure-text-serializer-ansi" } # version inherited from bom in API catalog adventure-serializerConfigurate4 = { module = "net.kyori:adventure-serializer-configurate4" } # version inherited from bom in API catalog diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 40ed35dec15..5f30a98c124 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1628,6 +1628,9 @@ + + + @@ -6277,6 +6280,20 @@ + + + + + + + + + + + + + + @@ -6459,6 +6476,14 @@ + + + + + + + + @@ -6547,6 +6572,14 @@ + + + + + + + + diff --git a/modlauncher-transformers/build.gradle.kts b/modlauncher-transformers/build.gradle.kts deleted file mode 100644 index bc80591a4c3..00000000000 --- a/modlauncher-transformers/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -dependencies { - implementation(libs.accessWidener) { - exclude(group="org.apache.logging.log4j") - } - - compileOnly(libs.log4j.api) - compileOnly(libs.fancymodloader.loader) { - exclude(group = "org.ow2.asm") - exclude(group = "org.apache.logging.log4j") - } - - compileOnly(libs.joptSimple) - compileOnly(libs.asm.commons) - compileOnly(apiLibs.checkerQual) - - // Optional - compileOnly(libs.jacoco.core) -} - -tasks { - jar { - manifest { - attributes("Automatic-Module-Name" to "sponge.modlauncher_transformers") - } - } -} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/AccessWidenerTransformationService.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/AccessWidenerTransformationService.java deleted file mode 100644 index 2d82371fc13..00000000000 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/AccessWidenerTransformationService.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.transformers.modlauncher; - -import cpw.mods.modlauncher.api.IEnvironment; -import cpw.mods.modlauncher.api.ITransformationService; -import cpw.mods.modlauncher.api.ITransformer; -import cpw.mods.modlauncher.api.ITransformerActivity; -import cpw.mods.modlauncher.api.ITransformerVotingContext; -import cpw.mods.modlauncher.api.TargetType; -import cpw.mods.modlauncher.api.TransformerVoteResult; -import cpw.mods.modlauncher.api.TypesafeMap; -import joptsimple.OptionSpec; -import joptsimple.OptionSpecBuilder; -import net.fabricmc.accesswidener.AccessWidener; -import net.fabricmc.accesswidener.AccessWidenerClassVisitor; -import net.fabricmc.accesswidener.AccessWidenerReader; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -@DefaultQualifier(NonNull.class) -public class AccessWidenerTransformationService implements ITransformationService { - - public static final String NAME = "access_widener"; - public static final String ACCESS_WIDENER_EXTENSION = "accesswidener"; - public static final Supplier> - INSTANCE = IEnvironment.buildKey("sponge:aw", AccessWidenerTransformationService.class); - static final Logger LOGGER = LogManager.getLogger(); - - private final AccessWidener widener = new AccessWidener(); - private final AccessWidenerReader reader = new AccessWidenerReader(this.widener); - private @MonotonicNonNull OptionSpec configSpec; - - @NonNull - @Override - public String name() { - return AccessWidenerTransformationService.NAME; - } - - @Override - public void onLoad(final IEnvironment env, final Set otherServices) { - env.computePropertyIfAbsent(AccessWidenerTransformationService.INSTANCE.get(), k -> this); - } - - @Override - public void arguments(final BiFunction argumentBuilder) { - this.configSpec = argumentBuilder.apply("config", "An AW file to apply at runtime") - .withOptionalArg() - .withValuesSeparatedBy(","); - } - - @Override - public void argumentValues(final OptionResult option) { - if (this.configSpec != null) { - for (final String value : option.values(this.configSpec)) { - final URL resource = AccessWidenerTransformationService.class.getClassLoader().getResource(value); - if (resource == null) { - throw new IllegalStateException("Could not locate AW resource specified on command line " + value); - } - this.offerResource(resource, "command-line"); - } - } - ITransformationService.super.argumentValues(option); - } - - @Override - public void initialize(final IEnvironment environment) { - } - - @Override - public @NonNull List> transformers() { - return Collections.singletonList(new AWTransformer(this.widener)); - } - - // register additional AWs with the transformation service - public void offerResource(final URL resource, final String name) { - if (resource.getFile().endsWith(AccessWidenerTransformationService.ACCESS_WIDENER_EXTENSION)) { - try (final BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { - AccessWidenerTransformationService.LOGGER.debug("Reading access widener {} from {}", name, resource); - this.reader.read(reader); - } catch (final IOException ex) { - AccessWidenerTransformationService.LOGGER.error("Failed to load access widener {} from {}", name, resource, ex); - } - } else { - AccessWidenerTransformationService.LOGGER.warn("Offered access widener {} from {} that does not end with expected extension '{}'", - name, resource, AccessWidenerTransformationService.ACCESS_WIDENER_EXTENSION); - } - } - - static class AWTransformer implements ITransformer { - private final AccessWidener widener; - - AWTransformer(final AccessWidener widener) { - this.widener = widener; - } - - @Override - public @NonNull ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { - AccessWidenerTransformationService.LOGGER.debug("Transforming {}", context.getClassName()); - final ClassNode output = new ClassNode(Opcodes.ASM9); - final ClassVisitor visitor = AccessWidenerClassVisitor.createClassVisitor(Opcodes.ASM9, output, this.widener); - input.accept(visitor); - return output; - } - - @Override - public @NonNull TransformerVoteResult castVote(final ITransformerVotingContext context) { - final TransformerVoteResult result = context.getReason().equals(ITransformerActivity.CLASSLOADING_REASON) ? TransformerVoteResult.YES : TransformerVoteResult.NO; - AccessWidenerTransformationService.LOGGER.debug("Voting on {} with reason {}, result: {}", context.getClassName(), context.getReason(), result); - return result; - } - - @Override - public @NonNull Set> targets() { - final Set classNames = this.widener.getTargets(); - final Set> targets = new HashSet<>(classNames.size()); - for (final String clazz : classNames) { - targets.add(Target.targetClass(clazz.replace('.', '/'))); - } - return targets; - } - - @Override - public @NonNull TargetType getTargetType() { - return TargetType.CLASS; - } - } -} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/SuperclassChanger.java b/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/SuperclassChanger.java deleted file mode 100644 index c56190963e7..00000000000 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/SuperclassChanger.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.transformers.modlauncher; - -import cpw.mods.modlauncher.api.IEnvironment; -import cpw.mods.modlauncher.api.ITransformationService; -import cpw.mods.modlauncher.api.ITransformer; -import cpw.mods.modlauncher.api.ITransformerActivity; -import cpw.mods.modlauncher.api.ITransformerVotingContext; -import cpw.mods.modlauncher.api.TargetType; -import cpw.mods.modlauncher.api.TransformerVoteResult; -import cpw.mods.modlauncher.api.TypesafeMap; -import joptsimple.OptionSpec; -import joptsimple.OptionSpecBuilder; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.framework.qual.DefaultQualifier; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -@DefaultQualifier(NonNull.class) -public class SuperclassChanger implements ITransformationService { - - public static final String NAME = "superclass_change"; - public static final String SUPER_CLASS_EXTENSION = "superclasschange"; - // Pulled from org.spongepowered.asm.launch.MixinLaunchPluginLegacy as - // when Mixin prepares target class nodes, it requests other ITransformers - // to load changes as necessary. - public static final String MIXIN_PLUGIN_REASON = "mixin"; - public static final Supplier> - INSTANCE = IEnvironment.buildKey("sponge:scc", SuperclassChanger.class); - static final Logger LOGGER = LogManager.getLogger(); - - private @MonotonicNonNull OptionSpec configSpec; - private final Map superclassTargets = new ConcurrentHashMap<>(); - - @NonNull - @Override - public String name() { - return SuperclassChanger.NAME; - } - - @Override - public void onLoad(final IEnvironment env, final Set otherServices) { - env.computePropertyIfAbsent(SuperclassChanger.INSTANCE.get(), k -> this); - } - - @Override - public void arguments(final BiFunction argumentBuilder) { - this.configSpec = argumentBuilder.apply("config", "An SCC file to apply at runtime") - .withRequiredArg() - .ofType(String.class); - } - - @Override - public void argumentValues(final OptionResult option) { - option.values(this.configSpec).forEach(file -> { - SuperclassChanger.LOGGER.debug("Loading SCC file: " + file); - final @Nullable URL resource = SuperclassChanger.class.getClassLoader().getResource(file); - if (resource == null) { - SuperclassChanger.LOGGER.warn("Could not find SCC file: " + file); - return; - } - this.offerResource(resource, "command-line"); - }); - } - - @Override - public void initialize(final IEnvironment environment) { - } - - @Override - public @NonNull List> transformers() { - return Collections.singletonList( - new SuperclassTransformer(new ConcurrentHashMap<>(this.superclassTargets))); - } - - // register additional AWs with the transformation service - public void offerResource(final URL resource, final String name) { - if (resource.getFile().endsWith(SuperclassChanger.SUPER_CLASS_EXTENSION)) { - try { - SuperclassChanger.LOGGER.debug("Reading superclass change {} from {}", name, resource); - this.superclassTargets.putAll(SuperclassChanger.readMap(resource)); - } catch (final Exception ex) { - SuperclassChanger.LOGGER.error("Failed to load superclass change {} from {}", name, resource, ex); - } - } else { - SuperclassChanger.LOGGER.warn( - "Offered superclass change {} from {} that does not end with expected extension '{}'", - name, resource, SuperclassChanger.SUPER_CLASS_EXTENSION - ); - } - } - - private static Map readMap(final URL resource) throws IOException { - final Map targets = new HashMap<>(); - try (final BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (!line.isEmpty()) { - String[] parts = line.split(":", 2); - if (parts.length != 2) { - throw new IllegalArgumentException("Invalid map entry: " + line); - } - targets.put(parts[0], parts[1]); - } - } - } - return targets; - } - - static class SuperclassTransformer implements ITransformer { - private final ConcurrentHashMap superclassTargets; - - public SuperclassTransformer(final ConcurrentHashMap superclassTargets) { - this.superclassTargets = superclassTargets; - } - - @Override - public @NonNull ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { - final String inputKey = input.name.replace("/", "."); - final String newSuperclass = this.superclassTargets.get(inputKey); - if (newSuperclass == null) { - SuperclassChanger.LOGGER.warn("No superclass change for {}", inputKey); - return input; - } - final String sanitizedSuperClass = newSuperclass.replace('.', '/'); - - input.methods.forEach(m -> SuperclassTransformer.transformMethod(m, input.superName, sanitizedSuperClass)); - input.superName = sanitizedSuperClass; - return input; - } - - private static void transformMethod( - final MethodNode node, final String originalSuperclass, final String superClass - ) { - for (final MethodInsnNode insn : SuperclassTransformer.findSuper(node, originalSuperclass)) { - insn.owner = superClass; - } - } - - private static List findSuper( - final MethodNode method, final String originalSuperClass - ) { - final List nodes = new ArrayList<>(); - for (final AbstractInsnNode node : method.instructions.toArray()) { - if (node.getOpcode() == Opcodes.INVOKESPECIAL && originalSuperClass.equals( - ((MethodInsnNode) node).owner)) { - nodes.add((MethodInsnNode) node); - } - } - return nodes; - } - - @Override - public @NonNull TransformerVoteResult castVote(final ITransformerVotingContext context) { - return switch (context.getReason()) { - case ITransformerActivity.CLASSLOADING_REASON, SuperclassChanger.MIXIN_PLUGIN_REASON -> TransformerVoteResult.YES; - default -> TransformerVoteResult.NO; - }; - } - - @Override - public @NonNull Set> targets() { - return this.superclassTargets - .keySet() - .stream() - .map(s -> s.replace('.', '/')) - .map(Target::targetClass) - .collect(Collectors.toSet()); - } - - @Override - public @NonNull TargetType getTargetType() { - return TargetType.CLASS; - } - } - -} diff --git a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF b/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 8e5fb5b07e5..00000000000 --- a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Automatic-Module-Name: sponge.modlauncher_transformers diff --git a/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService deleted file mode 100644 index 7b38f18930e..00000000000 --- a/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService +++ /dev/null @@ -1,2 +0,0 @@ -org.spongepowered.transformers.modlauncher.SuperclassChanger -org.spongepowered.transformers.modlauncher.AccessWidenerTransformationService \ No newline at end of file diff --git a/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService deleted file mode 100644 index f95865eabf0..00000000000 --- a/modlauncher-transformers/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.transformers.modlauncher.jacoco.JacocoPluginService diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 5373799f983..4552f651f1a 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -23,7 +23,6 @@ plugins { val commonProject = parent!! val bootstrapProject = commonProject.project(":bootstrap") -val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -205,9 +204,6 @@ configurations.testRuntimeOnly.get().extendsFrom(configurations.getByName("modDe dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) - service(project(transformersProject.path)) { - exclude(group = "net.neoforged.fancymodloader", module = "loader") - } service(project(libraryManagerProject.path)) val game = gameLibrariesConfig.name @@ -217,7 +213,6 @@ dependencies { game(libs.adventure.serializerConfigurate4) val serviceShadedLibraries = serviceShadedLibrariesConfig.name - serviceShadedLibraries(project(transformersProject.path)) { isTransitive = false } serviceShadedLibraries(project(libraryManagerProject.path)) { isTransitive = false } val gameShadedLibraries = gameShadedLibrariesConfig.name diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 6edfca92836..6567ff76563 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.8.31 +neoForgeVersion=21.9.14-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java index e4e0293c216..b5817886024 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; -import cpw.mods.jarhandling.SecureJar; +import net.neoforged.fml.classloading.SecureJar; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.locating.IDependencyLocator; @@ -38,6 +38,7 @@ import org.spongepowered.libs.LibraryManager; import org.spongepowered.neoforge.applaunch.loading.moddiscovery.library.Log4JLogger; +import java.io.IOException; import java.nio.file.Path; import java.util.List; @@ -46,7 +47,7 @@ public class SpongeNeoDependencyLocator implements IDependencyLocator { @Override public void scanMods(final List loadedMods, final IDiscoveryPipeline pipeline) { - if (!FMLEnvironment.production) { + if (!FMLEnvironment.isProduction()) { return; } @@ -70,7 +71,14 @@ public void scanMods(final List loadedMods, final IDiscoveryPipeline p final Path path = library.file(); SpongeNeoDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - pipeline.addModFile(IModFile.create(SecureJar.from(path), JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes)); + final SecureJar jar; + try { + jar = SecureJar.from(path); + } catch (IOException e) { + throw new RuntimeException("Failed to create jar from " + path, e); + } + + pipeline.addModFile(IModFile.create(jar, JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes)); } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java index 6b9920bb342..f68e8687f3d 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java @@ -25,10 +25,8 @@ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; import com.google.common.collect.ImmutableMap; -import cpw.mods.jarhandling.JarContents; -import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.Environment; -import cpw.mods.modlauncher.Launcher; +import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.ILaunchContext; @@ -42,6 +40,7 @@ import org.spongepowered.neoforge.applaunch.plugin.NeoForgePluginPlatform; import java.io.File; +import java.io.IOException; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; @@ -56,15 +55,14 @@ public final class SpongeNeoModLocator implements IModFileCandidateLocator { private static final Logger LOGGER = LogManager.getLogger(); public SpongeNeoModLocator() { - final Environment env = Launcher.INSTANCE.environment(); - NeoForgePluginPlatform.bootstrap(env); + NeoForgePluginPlatform.bootstrap(); } @Override public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) { final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); - if (!FMLEnvironment.production) { + if (!FMLEnvironment.isProduction()) { final String resourcesProp = System.getProperty("sponge.resources"); if (resourcesProp != null) { for (final String entry : resourcesProp.split(File.pathSeparator)) { @@ -72,7 +70,14 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) continue; } - final JarContents jarContents = JarContents.of(Stream.of(entry.split("&")).map(Path::of).toList()); + final JarContents jarContents; + try { + jarContents = JarContents.ofPaths(Stream.of(entry.split("&")).map(Path::of).toList()); + } catch (IOException e) { + LOGGER.error("Failed to create jar contents from {}", entry, e); + continue; + } + IModFile modFile = null; try { // attempt to load as mod or plugin diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java index 5c17d96749d..0cf129c9ad7 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java @@ -24,8 +24,9 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader; -import cpw.mods.jarhandling.JarContents; -import cpw.mods.jarhandling.SecureJar; +import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.jarcontents.JarContents; +import net.neoforged.fml.jarcontents.JarResource; import net.neoforged.fml.loading.moddiscovery.ModFile; import net.neoforged.fml.loading.moddiscovery.ModFileInfo; import net.neoforged.fml.loading.moddiscovery.ModJarMetadata; @@ -43,8 +44,6 @@ import java.io.Reader; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -52,11 +51,14 @@ public final class PluginFileParser { @SuppressWarnings("UnstableApiUsage") private static IModFileInfo parsePluginMetadata(final IModFile modFile) throws InvalidModFileException { - final Path metadataFile = modFile.findResource(PluginPlatformConstants.METADATA_FILE_LOCATION); + final JarResource metadataFile = modFile.getContents().get(PluginPlatformConstants.METADATA_FILE_LOCATION); + if (metadataFile == null) { + throw new InvalidModFileException("Plugin metadata not found", modFile.getModFileInfo()); + } try { final MetadataContainer container; - try (final Reader reader = Files.newBufferedReader(metadataFile, StandardCharsets.UTF_8)) { + try (final Reader reader = metadataFile.bufferedReader(StandardCharsets.UTF_8)) { container = MetadataParser.read(reader); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java index 899952076da..3fdc3a181e8 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader; -import cpw.mods.jarhandling.JarContents; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.neoforgespi.locating.IModFile; import net.neoforged.neoforgespi.locating.IModFileReader; import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java index 5e780d757f8..b5b7e1092c9 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java @@ -24,9 +24,8 @@ */ package org.spongepowered.neoforge.applaunch.plugin; -import cpw.mods.modlauncher.Environment; -import cpw.mods.modlauncher.api.IEnvironment; import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; @@ -43,28 +42,26 @@ public final class NeoForgePluginPlatform implements PluginPlatform { private static volatile boolean bootstrapped; - private final Environment environment; private final Logger logger; private final LaunchConfig config; private final TokenReplacement tokens; private final List pluginDirectories; - public static synchronized void bootstrap(final Environment environment) { + public static synchronized void bootstrap() { if (NeoForgePluginPlatform.bootstrapped) { return; } NeoForgePluginPlatform.bootstrapped = true; final NeoForgePluginPlatform platform; try { - platform = new NeoForgePluginPlatform(environment); + platform = new NeoForgePluginPlatform(); } catch (final IOException e) { throw new RuntimeException(e); } AppLaunch.setPluginPlatform(platform); } - private NeoForgePluginPlatform(final Environment environment) throws IOException { - this.environment = environment; + private NeoForgePluginPlatform() throws IOException { this.logger = LogManager.getLogger("plugin"); this.config = LaunchConfig.load(this.baseDirectory(), true); @@ -80,7 +77,7 @@ private NeoForgePluginPlatform(final Environment environment) throws IOException @Override public String version() { - return this.environment.getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev"); + return NeoForgeVersion.getVersion(); } @Override diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java new file mode 100644 index 00000000000..dbfbb01d1a8 --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java @@ -0,0 +1,87 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.transformation; + +import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.moddiscovery.ModFileInfo; +import net.neoforged.neoforgespi.transformation.ClassProcessor; +import net.neoforged.neoforgespi.transformation.ProcessorName; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.AccessWidenerTransformer; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.jar.Attributes; + +public class NeoAccessWidenerTransformer extends AccessWidenerTransformer implements ClassProcessor { + private static final ProcessorName NAME = new ProcessorName("neoforge", AccessWidenerTransformer.NAME); + + @Override + public ProcessorName name() { + return NeoAccessWidenerTransformer.NAME; + } + + @Override + public boolean handlesClass(final SelectionContext context) { + return this.targetClasses().contains(context.type().getClassName()); + } + + @Override + public ComputeFlags processClass(final TransformationContext context) { + final ClassNode input = context.node(); + final ClassNode output = this.transform(input); + + input.access = output.access; + input.permittedSubclasses = output.permittedSubclasses; + input.innerClasses = output.innerClasses; + input.fields = output.fields; + input.methods = output.methods; + + return ComputeFlags.SIMPLE_REWRITE; + } + + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); + for (ModFileInfo fileInfo : FMLLoader.getCurrent().getLoadingModList().getModFiles()) { + final SecureJar jar = fileInfo.getFile().getSecureJar(); + final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + + final String attribute = attributes.getValue(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); + if (attribute != null) { + for (final String path : attribute.split(",")) { + try { + resources.add(jar.contents().findFile(path).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate access widener {} from {}", path, fileInfo.getFile().getFileName(), e); + } + } + } + } + return resources; + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoListenerTransformer.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoListenerTransformer.java new file mode 100644 index 00000000000..b2943095b43 --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoListenerTransformer.java @@ -0,0 +1,75 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.transformation; + +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.moddiscovery.ModFileInfo; +import net.neoforged.neoforgespi.language.ModFileScanData; +import net.neoforged.neoforgespi.transformation.ClassProcessor; +import net.neoforged.neoforgespi.transformation.ProcessorName; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.objectweb.asm.Type; +import org.spongepowered.common.applaunch.transformation.ListenerTransformer; + +import java.util.HashSet; +import java.util.Set; + +public class NeoListenerTransformer extends ListenerTransformer implements ClassProcessor { + private static final ProcessorName NAME = new ProcessorName("neoforge", ListenerTransformer.NAME); + + private @MonotonicNonNull Set targets; + + private synchronized void loadTargets() { + if (this.targets == null) { + this.targets = new HashSet<>(); + + final Type listenerType = Type.getType(ListenerTransformer.ANNOTATION_DESC); + for (ModFileInfo fileInfo : FMLLoader.getCurrent().getLoadingModList().getModFiles()) { + for (ModFileScanData.AnnotationData annotation : fileInfo.getFile().getScanResult().getAnnotations()) { + if (listenerType.equals(annotation.annotationType())) { + this.targets.add(annotation.clazz()); + } + } + } + } + } + + @Override + public ProcessorName name() { + return NeoListenerTransformer.NAME; + } + + @Override + public boolean handlesClass(final SelectionContext context) { + this.loadTargets(); + return this.targets.contains(context.type()); + } + + @Override + public ComputeFlags processClass(final TransformationContext context) { + this.transform(context.node()); + return ComputeFlags.COMPUTE_FRAMES; + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java new file mode 100644 index 00000000000..240c1000fad --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java @@ -0,0 +1,78 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.transformation; + +import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.moddiscovery.ModFileInfo; +import net.neoforged.neoforgespi.transformation.ClassProcessor; +import net.neoforged.neoforgespi.transformation.ProcessorName; +import org.spongepowered.common.applaunch.transformation.SuperclassChangeTransformer; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.jar.Attributes; + +public class NeoSuperclassChangeTransformer extends SuperclassChangeTransformer implements ClassProcessor { + private static final ProcessorName NAME = new ProcessorName("neoforge", SuperclassChangeTransformer.NAME); + + @Override + public ProcessorName name() { + return NeoSuperclassChangeTransformer.NAME; + } + + @Override + public boolean handlesClass(final SelectionContext context) { + return this.targetClasses().contains(context.type().getClassName()); + } + + @Override + public ComputeFlags processClass(final TransformationContext context) { + this.transform(context.node()); + return ComputeFlags.SIMPLE_REWRITE; + } + + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); + for (ModFileInfo fileInfo : FMLLoader.getCurrent().getLoadingModList().getModFiles()) { + final SecureJar jar = fileInfo.getFile().getSecureJar(); + final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + + final String attribute = attributes.getValue(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); + if (attribute != null) { + for (final String path : attribute.split(",")) { + try { + resources.add(jar.contents().findFile(path).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate superclass changer {} from {}", path, fileInfo.getFile().getFileName(), e); + } + } + } + } + return resources; + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/SpongeNeoTransformationService.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/SpongeNeoTransformationService.java deleted file mode 100644 index d63a361cbe3..00000000000 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/SpongeNeoTransformationService.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.applaunch.transformation; - -import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.Environment; -import cpw.mods.modlauncher.Launcher; -import cpw.mods.modlauncher.api.IEnvironment; -import cpw.mods.modlauncher.api.IModuleLayerManager; -import cpw.mods.modlauncher.api.ITransformationService; -import cpw.mods.modlauncher.api.ITransformer; -import net.neoforged.fml.loading.LoadingModList; -import net.neoforged.fml.loading.moddiscovery.ModFileInfo; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.transformers.modlauncher.AccessWidenerTransformationService; -import org.spongepowered.transformers.modlauncher.SuperclassChanger; - -import java.net.MalformedURLException; -import java.util.List; -import java.util.Set; -import java.util.jar.Attributes; - -public class SpongeNeoTransformationService implements ITransformationService { - private static final Logger LOGGER = LogManager.getLogger(); - - @NonNull - @Override - public String name() { - return "spongeneo"; - } - - @Override - public void initialize(final IEnvironment environment) { - } - - @Override - public void onLoad(final IEnvironment env, final Set otherServices) { - } - - @Override - public List completeScan(IModuleLayerManager layerManager) { - final Environment env = Launcher.INSTANCE.environment(); - final AccessWidenerTransformationService accessWidener = env.getProperty(AccessWidenerTransformationService.INSTANCE.get()).orElse(null); - final SuperclassChanger superclassChanger = env.getProperty(SuperclassChanger.INSTANCE.get()).orElse(null); - - if (accessWidener != null || superclassChanger != null) { - for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { - final SecureJar jar = fileInfo.getFile().getSecureJar(); - final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); - - if (accessWidener != null) { - final String awPaths = attributes.getValue("Access-Widener"); - if (awPaths != null) { - final String jarFileName = fileInfo.getFile().getFileName(); - LOGGER.debug("Registering access wideners from {} ...", jarFileName); - - for (final String awPath : awPaths.split(",")) { - try { - accessWidener.offerResource(jar.getPath(awPath).toUri().toURL(), awPath); - } catch (final MalformedURLException e) { - LOGGER.warn("Failed to register access widener {} from {}", awPath, jarFileName, e); - } - } - } - } - - if (superclassChanger != null) { - final String scPaths = attributes.getValue("Superclass-Transformer"); - if (scPaths != null) { - final String jarFileName = fileInfo.getFile().getFileName(); - LOGGER.debug("Registering superclass changers from {} ...", jarFileName); - - for (final String scPath : scPaths.split(",")) { - try { - superclassChanger.offerResource(jar.getPath(scPath).toUri().toURL(), scPath); - } catch (final MalformedURLException e) { - LOGGER.warn("Failed to register superclass changer {} from {}", scPath, jarFileName, e); - } - } - } - } - } - } - - return List.of(); - } - - @NonNull - @Override - public List> transformers() { - return List.of(new ListenerTransformer()); - } -} diff --git a/neoforge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/neoforge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService deleted file mode 100644 index 6561a0860dd..00000000000 --- a/neoforge/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.neoforge.applaunch.transformation.SpongeNeoTransformationService diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.transformation.ClassProcessor b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.transformation.ClassProcessor new file mode 100644 index 00000000000..de4422cd642 --- /dev/null +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.transformation.ClassProcessor @@ -0,0 +1,3 @@ +org.spongepowered.neoforge.applaunch.transformation.NeoAccessWidenerTransformer +org.spongepowered.neoforge.applaunch.transformation.NeoListenerTransformer +org.spongepowered.neoforge.applaunch.transformation.NeoSuperclassChangeTransformer diff --git a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/NeoLaunch.java b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/NeoLaunch.java index ae9e0b98419..57ce3dcb301 100644 --- a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/NeoLaunch.java +++ b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/NeoLaunch.java @@ -30,7 +30,7 @@ import com.google.inject.Module; import com.google.inject.Stage; import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.FMLEnvironment; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.inject.SpongeCommonModule; import org.spongepowered.common.inject.SpongeModule; @@ -53,7 +53,7 @@ public NeoLaunch(final PluginPlatform platform) { @Override public boolean dedicatedServer() { - return FMLLoader.getDist() == Dist.DEDICATED_SERVER; + return FMLEnvironment.getDist() == Dist.DEDICATED_SERVER; } @Override @@ -63,7 +63,7 @@ public NeoPluginManager pluginManager() { @Override public Stage injectionStage() { - return FMLLoader.isProduction() ? Stage.PRODUCTION : Stage.DEVELOPMENT; + return FMLEnvironment.isProduction() ? Stage.PRODUCTION : Stage.DEVELOPMENT; } @Override diff --git a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java index e3dd33d8703..6448d458d87 100644 --- a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java +++ b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java @@ -34,8 +34,6 @@ import org.spongepowered.plugin.metadata.PluginMetadata; import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -70,8 +68,7 @@ public Logger logger() { @Override public Optional locateResource(String relative) { - final Path p = this.modContainer.getModInfo().getOwningFile().getFile().findResource(Objects.requireNonNull(relative, "relative")); - return Files.exists(p) ? Optional.of(p.toUri()) : Optional.empty(); + return this.modContainer.getModInfo().getOwningFile().getFile().getContents().findFile(Objects.requireNonNull(relative, "relative")); } @Override diff --git a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java index 4529e2c37b0..585e0129a5e 100644 --- a/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java +++ b/neoforge/src/launch/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java @@ -66,7 +66,7 @@ public PluginModContainer(IModInfo info, String className, ModFileScanData modFi .markerType(IModBusEvent.class) .allowPerPhasePost() .build(); - this.module = gameLayer.findModule(info.getOwningFile().moduleName()).orElseThrow(); + this.module = gameLayer.findModule(info.getOwningFile().getFile().getId()).orElseThrow(); ModLoadingContext context = ModLoadingContext.get(); try { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/item/ItemEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/item/ItemEntityMixin_Neo.java index 850ddc5dc63..5e30f96ee9c 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/item/ItemEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/item/ItemEntityMixin_Neo.java @@ -46,7 +46,7 @@ public abstract class ItemEntityMixin_Neo { final CallbackInfo ci ) { // Check the level is not null to avoid an NPE - if (level != null && !level.isClientSide) { + if (level != null && !level.isClientSide()) { this.lifespan = SpongeGameConfigs.getForWorld(level).get().entity.item.despawnRate; } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/FireBlockMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/FireBlockMixin_Neo.java index f81da0b2646..513efba73b7 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/FireBlockMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/FireBlockMixin_Neo.java @@ -49,7 +49,7 @@ public class FireBlockMixin_Neo { cancellable = true) private void impl$onCatchFirePreCheck( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final Direction dir, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } @@ -65,7 +65,7 @@ public class FireBlockMixin_Neo { cancellable = true) private void impl$onCatchFirePreCheckOther( final Level world, final BlockPos pos, final int chance, final RandomSource random, final int age, final Direction dir, final CallbackInfo callbackInfo) { - if (!world.isClientSide) { + if (!world.isClientSide()) { if (ShouldFire.CHANGE_BLOCK_EVENT_PRE && SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, pos).isCancelled()) { callbackInfo.cancel(); } diff --git a/settings.gradle.kts b/settings.gradle.kts index 0f758666587..8a8dc35a7cc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -83,7 +83,6 @@ includeBuild("SpongeAPI") { substitute(module("org.spongepowered:spongeapi")).using(project(":")) } } -include("modlauncher-transformers") include("library-manager") include("bootstrap") include("generator") diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/transformation/AccessWidenerTransformer.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/AccessWidenerTransformer.java new file mode 100644 index 00000000000..b47590b480a --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/AccessWidenerTransformer.java @@ -0,0 +1,91 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.transformation; + +import net.fabricmc.accesswidener.AccessWidener; +import net.fabricmc.accesswidener.AccessWidenerClassVisitor; +import net.fabricmc.accesswidener.AccessWidenerReader; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Set; + +public abstract class AccessWidenerTransformer { + public static final String NAME = "access_widener"; + public static final String EXTENSION = "accesswidener"; + public static final String MANIFEST_ATTRIBUTE = "Access-Widener"; + + protected static final Logger LOGGER = LogManager.getLogger(); + + private @MonotonicNonNull AccessWidener widener; + + protected final ClassNode transform(final ClassNode input) { + if (this.widener == null) { + throw new IllegalStateException("Resources not loaded"); + } + AccessWidenerTransformer.LOGGER.debug("Transforming {}", input.name); + final ClassNode output = new ClassNode(Opcodes.ASM9); + final ClassVisitor visitor = AccessWidenerClassVisitor.createClassVisitor(Opcodes.ASM9, output, this.widener); + input.accept(visitor); + return output; + } + + protected abstract Collection collectResources(); + + public final synchronized void loadResources() { + if (this.widener == null) { + this.widener = new AccessWidener(); + final AccessWidenerReader awReader = new AccessWidenerReader(this.widener); + + for (final URL resource : this.collectResources()) { + if (resource.getFile().endsWith(AccessWidenerTransformer.EXTENSION)) { + try (final BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { + AccessWidenerTransformer.LOGGER.debug("Reading access widener {}", resource); + awReader.read(reader); + } catch (final IOException ex) { + AccessWidenerTransformer.LOGGER.error("Failed to load access widener {}", resource, ex); + } + } else { + AccessWidenerTransformer.LOGGER.warn("Offered access widener {} that does not end with expected extension '{}'", resource, AccessWidenerTransformer.EXTENSION); + } + } + } + } + + protected final Set targetClasses() { + this.loadResources(); + return this.widener.getTargets(); + } +} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/ListenerTransformerHelper.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/ListenerTransformer.java similarity index 71% rename from modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/ListenerTransformerHelper.java rename to src/applaunch/java/org/spongepowered/common/applaunch/transformation/ListenerTransformer.java index 7b65503bfa1..1b5ff36aae9 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/ListenerTransformerHelper.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/ListenerTransformer.java @@ -22,12 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.transformers.modlauncher; - -import static org.objectweb.asm.Opcodes.ACC_STATIC; -import static org.objectweb.asm.Opcodes.INVOKESTATIC; -import static org.objectweb.asm.Opcodes.RETURN; +package org.spongepowered.common.applaunch.transformation; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AnnotationNode; import org.objectweb.asm.tree.ClassNode; @@ -37,14 +34,15 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; -public class ListenerTransformerHelper { - public static final String LISTENER_DESC = "Lorg/spongepowered/api/event/Listener;"; +public class ListenerTransformer { + public static final String NAME = "listener"; + public static final String ANNOTATION_DESC = "Lorg/spongepowered/api/event/Listener;"; - public static boolean shouldTransform(ClassNode classNode) { + public final boolean shouldTransform(final ClassNode classNode) { for (final MethodNode method : classNode.methods) { if (method.visibleAnnotations != null) { for (final AnnotationNode annotation : method.visibleAnnotations) { - if (annotation.desc.equals(LISTENER_DESC)) { + if (annotation.desc.equals(ANNOTATION_DESC)) { return true; } } @@ -53,7 +51,7 @@ public static boolean shouldTransform(ClassNode classNode) { return false; } - public static void transform(ClassNode classNode) { + public final void transform(final ClassNode classNode) { MethodNode clinit = null; for (final MethodNode method : classNode.methods) { if (method.name.equals("") && method.desc.equals("()V")) { @@ -63,16 +61,16 @@ public static void transform(ClassNode classNode) { } if (clinit == null) { - clinit = new MethodNode(ACC_STATIC, "", "()V", null, null); - clinit.instructions.add(new InsnNode(RETURN)); + clinit = new MethodNode(Opcodes.ACC_STATIC, "", "()V", null, null); + clinit.instructions.add(new InsnNode(Opcodes.RETURN)); classNode.methods.add(clinit); } final InsnList list = new InsnList(); list.add(new LdcInsnNode(Type.getObjectType(classNode.name))); - list.add(new MethodInsnNode(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false)); - list.add(new MethodInsnNode(INVOKESTATIC, "org/spongepowered/common/event/ListenerLookups", "set", "(Ljava/lang/Class;Ljava/lang/invoke/MethodHandles$Lookup;)V")); + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false)); + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "org/spongepowered/common/event/ListenerLookups", "set", "(Ljava/lang/Class;Ljava/lang/invoke/MethodHandles$Lookup;)V")); clinit.instructions.insert(list); } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/transformation/SuperclassChangeTransformer.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/SuperclassChangeTransformer.java new file mode 100644 index 00000000000..bc18b0d6ab8 --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/SuperclassChangeTransformer.java @@ -0,0 +1,136 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.transformation; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class SuperclassChangeTransformer { + public static final String NAME = "superclass_change"; + public static final String EXTENSION = "superclasschange"; + public static final String MANIFEST_ATTRIBUTE = "Superclass-Transformer"; + + protected static final Logger LOGGER = LogManager.getLogger(); + + private @MonotonicNonNull Map superclassMap; + + private static Map readMap(final URL resource) throws IOException { + final Map targets = new HashMap<>(); + try (final BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty()) { + String[] parts = line.split(":", 2); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid map entry: " + line); + } + targets.put(parts[0], parts[1]); + } + } + } + return targets; + } + + protected abstract Collection collectResources(); + + public final synchronized void loadResources() { + if (this.superclassMap == null) { + this.superclassMap = new ConcurrentHashMap<>(); + + for (final URL resource : this.collectResources()) { + if (resource.getFile().endsWith(SuperclassChangeTransformer.EXTENSION)) { + try { + SuperclassChangeTransformer.LOGGER.debug("Reading superclass change {}", resource); + this.superclassMap.putAll(SuperclassChangeTransformer.readMap(resource)); + } catch (final Exception ex) { + SuperclassChangeTransformer.LOGGER.error("Failed to load superclass change {}", resource, ex); + } + } else { + SuperclassChangeTransformer.LOGGER.warn("Offered superclass change {} that does not end with expected extension '{}'", resource, SuperclassChangeTransformer.EXTENSION); + } + } + } + } + + protected final boolean transform(final ClassNode classNode) { + if (this.superclassMap == null) { + throw new IllegalStateException("Resources not loaded"); + } + + final String inputKey = classNode.name.replace("/", "."); + final String newSuperclass = this.superclassMap.get(inputKey); + if (newSuperclass == null) { + SuperclassChangeTransformer.LOGGER.warn("No superclass change for {}", inputKey); + return false; + } + + final String sanitizedSuperClass = newSuperclass.replace('.', '/'); + classNode.methods.forEach(m -> SuperclassChangeTransformer.transformMethod(m, classNode.superName, sanitizedSuperClass)); + classNode.superName = sanitizedSuperClass; + return true; + } + + private static void transformMethod(final MethodNode node, final String originalSuperclass, final String superClass) { + for (final MethodInsnNode insn : SuperclassChangeTransformer.findSuper(node, originalSuperclass)) { + insn.owner = superClass; + } + } + + private static List findSuper(final MethodNode method, final String originalSuperClass) { + final List nodes = new ArrayList<>(); + for (final AbstractInsnNode node : method.instructions.toArray()) { + if (node.getOpcode() == Opcodes.INVOKESPECIAL && originalSuperClass.equals( + ((MethodInsnNode) node).owner)) { + nodes.add((MethodInsnNode) node); + } + } + return nodes; + } + + protected final Set targetClasses() { + this.loadResources(); + return this.superclassMap.keySet(); + } +} diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/AgentAccessGenerator.java similarity index 96% rename from modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java rename to src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/AgentAccessGenerator.java index d4b2c8a9698..9f0232396a7 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/AgentAccessGenerator.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/AgentAccessGenerator.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.transformers.modlauncher.jacoco; +package org.spongepowered.common.applaunch.transformation.jacoco; import org.jacoco.core.runtime.IExecutionDataAccessorGenerator; import org.jacoco.core.runtime.RuntimeData; diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/Instrumenter.java similarity index 98% rename from modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java rename to src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/Instrumenter.java index 3c9457f54bc..58540247c3f 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/Instrumenter.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/Instrumenter.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.transformers.modlauncher.jacoco; +package org.spongepowered.common.applaunch.transformation.jacoco; import org.jacoco.core.internal.data.CRC64; import org.jacoco.core.internal.flow.ClassProbesAdapter; diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/JacocoTransformer.java similarity index 78% rename from modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java rename to src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/JacocoTransformer.java index e8c176b047b..b9de381068e 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/JacocoPluginService.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/JacocoTransformer.java @@ -22,15 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.transformers.modlauncher.jacoco; +package org.spongepowered.common.applaunch.transformation.jacoco; -import cpw.mods.modlauncher.TransformingClassLoader; -import cpw.mods.modlauncher.api.ITransformerActivity; -import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; -import org.objectweb.asm.Type; import org.objectweb.asm.tree.AnnotationNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; @@ -39,22 +35,19 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; -public class JacocoPluginService implements ILaunchPluginService { - private static final Logger logger = LogManager.getLogger(); - +public abstract class JacocoTransformer { + public static final String NAME = "jacoco"; private static final String MIXIN_DESC = "Lorg/spongepowered/asm/mixin/Mixin;"; - private static final EnumSet YAY = EnumSet.of(Phase.BEFORE); - private static final EnumSet NAY = EnumSet.noneOf(Phase.class); + private static final Logger LOGGER = LogManager.getLogger(); - private boolean disabled; + protected boolean disabled; private String[] packages; private ClassLoader loader; - public JacocoPluginService() { + public JacocoTransformer() { try { getClass().getClassLoader().loadClass("org.jacoco.core.JaCoCo"); } catch (final ClassNotFoundException e) { @@ -71,16 +64,6 @@ public JacocoPluginService() { } } - @Override - public String name() { - return "jacoco"; - } - - @Override - public EnumSet handlesClass(Type classType, boolean isEmpty) { - return this.disabled || isEmpty ? NAY : YAY; - } - private boolean testClassName(final String name) { for (final String pkg : this.packages) { if (name.startsWith(pkg)) { @@ -90,17 +73,18 @@ private boolean testClassName(final String name) { return false; } - @Override - public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { - if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) { - return ComputeFlags.NO_REWRITE; + protected abstract boolean isTransformingClassloader(final ClassLoader loader); + + protected boolean transform(final ClassNode classNode) { + if (this.disabled) { + return false; } // Capture a reference to the transforming class loader if (this.loader == null) { // First transformed class context, aka game entrypoint is supposed to be the transforming class loader final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - if (!((Object) contextLoader instanceof TransformingClassLoader)) { // Ignore IDE warning + if (!isTransformingClassloader(contextLoader)) { throw new IllegalStateException("Context class loader of the first transformed class is not a transforming class loader"); } // Context class loader may change for next classes, so capture it @@ -111,7 +95,7 @@ public int processClassWithFlags(final Phase phase, final ClassNode classNode, f // - Performance // - JaCoCo changes the LVT which can cause mixins targeting the current class to fail if (!this.testClassName(classNode.name)) { - return ComputeFlags.NO_REWRITE; + return false; } // We need the original bytes for two reasons: @@ -120,16 +104,16 @@ public int processClassWithFlags(final Phase phase, final ClassNode classNode, f byte[] originalBytes; try (final InputStream in = this.loader.getResourceAsStream(classNode.name + ".class")) { if (in == null) { - logger.warn("Failed to find original class bytes for class {}", classNode.name); - return ComputeFlags.NO_REWRITE; + LOGGER.warn("Failed to find original class bytes for class {}", classNode.name); + return false; } final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); in.transferTo(buffer); originalBytes = buffer.toByteArray(); } catch (IOException e) { - logger.warn("Failed to read original class bytes for class {}", classNode.name, e); - return ComputeFlags.NO_REWRITE; + LOGGER.warn("Failed to read original class bytes for class {}", classNode.name, e); + return false; } // Detect the mixin annotation @@ -168,9 +152,7 @@ public int processClassWithFlags(final Phase phase, final ClassNode classNode, f classNode.methods = instrumentedClassNode.methods; } - // JaCoCo has already updated the frames - return ComputeFlags.SIMPLE_REWRITE; + return true; } - } diff --git a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/PrefixedCondyProbeArrayStrategy.java similarity index 97% rename from modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java rename to src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/PrefixedCondyProbeArrayStrategy.java index 3d38c30951a..f1f1fa5599f 100644 --- a/modlauncher-transformers/src/main/java/org/spongepowered/transformers/modlauncher/jacoco/PrefixedCondyProbeArrayStrategy.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/transformation/jacoco/PrefixedCondyProbeArrayStrategy.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.transformers.modlauncher.jacoco; +package org.spongepowered.common.applaunch.transformation.jacoco; import org.jacoco.core.internal.instr.CondyProbeArrayStrategy; import org.jacoco.core.internal.instr.IProbeArrayStrategy; diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 0de671757e9..ec8eca4b45a 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -11,7 +11,6 @@ plugins { val commonProject = parent!! val bootstrapProject = commonProject.project(":bootstrap") -val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -146,7 +145,6 @@ val testSources = sourceSets.named("test") { spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) } -val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations minecraft { @@ -217,6 +215,7 @@ dependencies { boot(libs.log4j.core) boot(libs.log4j.slf4j2) + boot(libs.accessWidener) boot(libs.mixin) boot(libs.mixinextras.common) boot(libs.asm.tree) @@ -228,10 +227,6 @@ dependencies { // All minecraft dependencies except itself spongeImpl.copyModulesExcludingPrefix(configurations.minecraft.get(), "net.minecraft", "joined", bootLibrariesConfig.get()) - boot(project(transformersProject.path)) { - exclude(group = "net.neoforged.fancymodloader", module = "loader") - } - val game = gameLibrariesConfig.name game("org.spongepowered:spongeapi:$apiVersion") game(platform(apiLibs.adventure.bom)) { @@ -246,9 +241,6 @@ dependencies { exclude(group = "org.checkerframework", module = "checker-qual") } - val bootShadedLibraries = bootShadedLibrariesConfig.name - bootShadedLibraries(project(transformersProject.path)) { isTransitive = false } - val gameShadedLibraries = gameShadedLibrariesConfig.name gameShadedLibraries("org.spongepowered:spongeapi:$apiVersion") { isTransitive = false } @@ -318,11 +310,6 @@ minecraft { .flatMap { sequenceOf("--mixin.config", it) } .toList() } - allArgumentProviders += CommandLineArgumentProvider { - superclassConfigs.asSequence() - .flatMap { sequenceOf("--superclass_change.config", it) } - .toList() - } // ModLauncher // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java index 69097b21a06..c2631356d4c 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java @@ -24,7 +24,6 @@ */ package org.spongepowered.vanilla.applaunch.plugin; -import com.google.common.collect.ImmutableList; import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IEnvironment; @@ -33,29 +32,26 @@ import cpw.mods.modlauncher.api.ITransformer; import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.checkerframework.checker.nullness.qual.NonNull; import org.fusesource.jansi.AnsiConsole; import org.spongepowered.asm.launch.MixinLaunchPlugin; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.plugin.PluginResource; -import org.spongepowered.transformers.modlauncher.AccessWidenerTransformationService; -import org.spongepowered.transformers.modlauncher.SuperclassChanger; -import org.spongepowered.vanilla.applaunch.Constants; import org.spongepowered.vanilla.applaunch.plugin.resource.SecureJarPluginResource; +import org.spongepowered.vanilla.applaunch.transformation.VanillaAccessWidenerTransformer; +import org.spongepowered.vanilla.applaunch.transformation.VanillaSuperclassChangeTransformer; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.Set; public final class VanillaTransformationService implements ITransformationService { private @MonotonicNonNull VanillaPluginPlatform pluginPlatform; @Override - public @NonNull String name() { + public String name() { return "spongevanilla"; } @@ -102,15 +98,13 @@ public List beginScanning(final IEnvironment environment) { } @Override - public List completeScan(IModuleLayerManager layerManager) { + public List completeScan(final IModuleLayerManager layerManager) { this.pluginPlatform.discoverLanguageServices(); this.pluginPlatform.getLanguageServices().forEach((k, v) -> this.pluginPlatform.logger().info("Plugin language loader '{}' found.", k)); this.pluginPlatform.createPluginCandidates(); - IEnvironment env = Launcher.INSTANCE.environment(); - final AccessWidenerTransformationService accessWidener = env.getProperty(AccessWidenerTransformationService.INSTANCE.get()).orElse(null); - final SuperclassChanger superclassChanger = env.getProperty(SuperclassChanger.INSTANCE.get()).orElse(null); + final IEnvironment env = Launcher.INSTANCE.environment(); final ILaunchPluginService mixin = env.findLaunchPlugin(MixinLaunchPlugin.NAME).orElse(null); final List gameResources = new ArrayList<>(); @@ -131,40 +125,6 @@ public List completeScan(IModuleLayerManager layerManager) { mixin.offerResource(resource.path(), resource.path().getFileName().toString()); } - // Offer jar to the AW service - if (accessWidener != null) { - final Optional awFiles = resource.property(Constants.ManifestAttributes.ACCESS_WIDENER); - if (awFiles.isPresent()) { - for (final String awFile : awFiles.get().split(",")) { - if (!awFile.endsWith(AccessWidenerTransformationService.ACCESS_WIDENER_EXTENSION)) { - continue; - } - try { - accessWidener.offerResource(resource.locateResource(awFile).get().toURL(), awFile); - } catch (final Exception ex) { - this.pluginPlatform.logger().warn("Failed to read declared access widener {}, from {}:", awFile, resource.locator()); - } - } - } - } - - // Offer jar to the SuperclassChanger service - if (superclassChanger != null) { - final Optional superclassChangeFiles = resource.property(Constants.ManifestAttributes.SUPERCLASS_CHANGE); - if (superclassChangeFiles.isPresent()) { - for (final String superclassChangeFile : superclassChangeFiles.get().split(",")) { - if (!superclassChangeFile.endsWith(SuperclassChanger.SUPER_CLASS_EXTENSION)) { - continue; - } - try { - superclassChanger.offerResource(resource.locateResource(superclassChangeFile).get().toURL(), superclassChangeFile); - } catch (final Exception ex) { - this.pluginPlatform.logger().warn("Failed to read declared superclass changer {}, from {}:", superclassChangeFile, resource.locator()); - } - } - } - } - // Log warning about plugin using Mixin if (mixin != null && resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { if (!VanillaTransformationService.isSponge(resource)) { @@ -181,10 +141,10 @@ private static boolean isSponge(final PluginResource resource) { return resource instanceof SecureJarPluginResource secureJarResource && secureJarResource.jar().name().equals("spongevanilla"); } - @Override @SuppressWarnings("rawtypes") - public @NonNull List transformers() { - return ImmutableList.of(); + @Override + public List transformers() { + return List.of(new VanillaAccessWidenerTransformer(this.pluginPlatform), new VanillaSuperclassChangeTransformer(this.pluginPlatform)); } private String getCodeSource() { diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/JacocoPluginService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/JacocoPluginService.java new file mode 100644 index 00000000000..99bc2142157 --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/JacocoPluginService.java @@ -0,0 +1,62 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.transformation; + +import cpw.mods.modlauncher.TransformingClassLoader; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.jacoco.JacocoTransformer; + +import java.util.EnumSet; + +public class JacocoPluginService extends JacocoTransformer implements ILaunchPluginService { + private static final EnumSet YAY = EnumSet.of(Phase.BEFORE); + private static final EnumSet NAY = EnumSet.noneOf(Phase.class); + + @Override + public String name() { + return JacocoTransformer.NAME; + } + + @Override + protected boolean isTransformingClassloader(ClassLoader loader) { + return loader instanceof TransformingClassLoader; + } + + @Override + public EnumSet handlesClass(Type classType, boolean isEmpty) { + return this.disabled || isEmpty ? NAY : YAY; + } + + @Override + public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { + if (ITransformerActivity.COMPUTING_FRAMES_REASON.equals(reason)) { + return ComputeFlags.NO_REWRITE; + } + return this.transform(classNode) ? ComputeFlags.SIMPLE_REWRITE : ComputeFlags.NO_REWRITE; + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ListenerPluginService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/ListenerPluginService.java similarity index 84% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ListenerPluginService.java rename to vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/ListenerPluginService.java index 6953b18551c..9c718f44359 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ListenerPluginService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/ListenerPluginService.java @@ -22,22 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch.plugin; +package org.spongepowered.vanilla.applaunch.transformation; import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.transformers.modlauncher.ListenerTransformerHelper; +import org.spongepowered.common.applaunch.transformation.ListenerTransformer; import java.util.EnumSet; -public class ListenerPluginService implements ILaunchPluginService { +public class ListenerPluginService extends ListenerTransformer implements ILaunchPluginService { private static final EnumSet YAY = EnumSet.of(Phase.AFTER); private static final EnumSet NAY = EnumSet.noneOf(Phase.class); @Override public String name() { - return "listener"; + return ListenerTransformer.NAME; } @Override @@ -47,8 +47,8 @@ public EnumSet handlesClass(Type classType, boolean isEmpty) { @Override public int processClassWithFlags(final Phase phase, final ClassNode classNode, final Type classType, final String reason) { - if (ListenerTransformerHelper.shouldTransform(classNode)) { - ListenerTransformerHelper.transform(classNode); + if (this.shouldTransform(classNode)) { + this.transform(classNode); return ComputeFlags.COMPUTE_FRAMES; } return ComputeFlags.NO_REWRITE; diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java new file mode 100644 index 00000000000..58ca2f4e226 --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java @@ -0,0 +1,88 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.transformation; + +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.api.ITransformerVotingContext; +import cpw.mods.modlauncher.api.TransformerVoteResult; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.AccessWidenerTransformer; +import org.spongepowered.plugin.PluginResource; +import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; + +import java.net.URL; +import java.util.*; +import java.util.stream.Collectors; + +public class VanillaAccessWidenerTransformer extends AccessWidenerTransformer implements ITransformer { + private static final String[] LABELS = { AccessWidenerTransformer.NAME }; + + private final VanillaPluginPlatform pluginPlatform; + + public VanillaAccessWidenerTransformer(final VanillaPluginPlatform pluginPlatform) { + this.pluginPlatform = pluginPlatform; + } + + @Override + public String[] labels() { + return LABELS; + } + + @Override + public ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { + return this.transform(input); + } + + @Override + public TransformerVoteResult castVote(final ITransformerVotingContext context) { + return context.getReason().equals(ITransformerActivity.CLASSLOADING_REASON) ? TransformerVoteResult.YES : TransformerVoteResult.NO; + } + + @Override + public Set targets() { + return this.targetClasses().stream().map(Target::targetClass).collect(Collectors.toSet()); + } + + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); + for (final Set plugins : this.pluginPlatform.getResources().values()) { + for (final PluginResource plugin : plugins) { + final Optional attribute = plugin.property(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); + if (attribute.isPresent()) { + for (final String path : attribute.get().split(",")) { + try { + resources.add(plugin.locateResource(path).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate access widener {} from {}", path, plugin.path().getFileName(), e); + } + } + } + } + } + return resources; + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java new file mode 100644 index 00000000000..d2d8dd5aede --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java @@ -0,0 +1,93 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.transformation; + +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.ITransformerActivity; +import cpw.mods.modlauncher.api.ITransformerVotingContext; +import cpw.mods.modlauncher.api.TransformerVoteResult; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.transformation.SuperclassChangeTransformer; +import org.spongepowered.plugin.PluginResource; +import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; + +import java.net.URL; +import java.util.*; +import java.util.stream.Collectors; + +public class VanillaSuperclassChangeTransformer extends SuperclassChangeTransformer implements ITransformer { + private static final String MIXIN_PLUGIN_REASON = "mixin"; + private static final String[] LABELS = { SuperclassChangeTransformer.NAME }; + + private final VanillaPluginPlatform pluginPlatform; + + public VanillaSuperclassChangeTransformer(final VanillaPluginPlatform pluginPlatform) { + this.pluginPlatform = pluginPlatform; + } + + @Override + public String[] labels() { + return LABELS; + } + + @Override + public ClassNode transform(final ClassNode input, final ITransformerVotingContext context) { + this.transform(input); + return input; + } + + @Override + public TransformerVoteResult castVote(final ITransformerVotingContext context) { + return switch (context.getReason()) { + case ITransformerActivity.CLASSLOADING_REASON, VanillaSuperclassChangeTransformer.MIXIN_PLUGIN_REASON -> TransformerVoteResult.YES; + default -> TransformerVoteResult.NO; + }; + } + + @Override + public Set targets() { + return this.targetClasses().stream().map(Target::targetClass).collect(Collectors.toSet()); + } + + @Override + protected Collection collectResources() { + final Collection resources = new ArrayList<>(); + for (final Set plugins : this.pluginPlatform.getResources().values()) { + for (final PluginResource plugin : plugins) { + final Optional attribute = plugin.property(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); + if (attribute.isPresent()) { + for (final String scPath : attribute.get().split(",")) { + try { + resources.add(plugin.locateResource(scPath).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin.path().getFileName()); + } + } + } + } + } + return resources; + } +} diff --git a/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService index fcea6e880a6..b17475d9e1c 100644 --- a/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService +++ b/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -1 +1 @@ -org.spongepowered.vanilla.applaunch.plugin.VanillaTransformationService \ No newline at end of file +org.spongepowered.vanilla.applaunch.plugin.VanillaTransformationService diff --git a/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService index 819258d57e1..9abe0b2f9b2 100644 --- a/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService +++ b/vanilla/src/applaunch/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService @@ -1 +1,2 @@ -org.spongepowered.vanilla.applaunch.plugin.ListenerPluginService \ No newline at end of file +org.spongepowered.vanilla.applaunch.transformation.JacocoPluginService +org.spongepowered.vanilla.applaunch.transformation.ListenerPluginService From 67ec76490b68e238ad62430b53795d818ed1c76b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 7 Oct 2025 13:50:29 +0200 Subject: [PATCH 384/586] Update NeoForge bootstrap --- .../bootstrap/neoforge/DevClient.java | 36 ++++++++ .../bootstrap/neoforge/DevServer.java | 36 ++++++++ .../bootstrap/neoforge/NeoForgeBootstrap.java | 81 ----------------- .../bootstrap/neoforge/TestServer.java | 50 +++++++++++ .../spongepowered/gradle/impl/DigestUtil.java | 87 +++++++++++++++++++ .../gradle/impl/OutputDependenciesToJson.java | 38 +------- .../applaunch/plugin/ForgePluginPlatform.java | 28 ++++-- neoforge/build.gradle.kts | 15 ++-- .../moddiscovery/SpongeNeoModLocator.java | 42 +++++---- .../plugin/NeoForgePluginPlatform.java | 14 ++- .../META-INF/neoforge.mods.toml | 2 + .../core/server/MinecraftServerMixin_Neo.java | 4 +- .../level/ServerExplosionMixin_NeoForge.java | 11 ++- .../boot/SpongeLauncherInterceptor.java | 8 +- .../neoforge/boot/SpongeTestBoot.java | 4 +- .../applaunch/plugin/PluginPlatform.java | 12 ++- .../spongepowered/common/SpongeCommon.java | 14 --- .../common/config/PluginConfigManager.java | 7 +- .../core/server/level/ServerLevelMixin.java | 16 ++-- .../AbstractFurnaceBlockEntityMixin.java | 4 +- .../plugin/VanillaPluginPlatform.java | 25 ++++-- 21 files changed, 328 insertions(+), 206 deletions(-) create mode 100644 bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevClient.java create mode 100644 bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevServer.java delete mode 100644 bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java create mode 100644 bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java create mode 100644 build-logic/src/main/java/org/spongepowered/gradle/impl/DigestUtil.java diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevClient.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevClient.java new file mode 100644 index 00000000000..1895f85d2fb --- /dev/null +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevClient.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.neoforge; + +import net.neoforged.fml.startup.Client; +import org.spongepowered.bootstrap.dev.DevClasspath; + +public class DevClient { + + public static void main(final String[] args) { + DevClasspath.resolve(); + Client.main(args); + } +} diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevServer.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevServer.java new file mode 100644 index 00000000000..0eff65b1fb3 --- /dev/null +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/DevServer.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.neoforge; + +import net.neoforged.fml.startup.Server; +import org.spongepowered.bootstrap.dev.DevClasspath; + +public class DevServer { + + public static void main(final String[] args) { + DevClasspath.resolve(); + Server.main(args); + } +} diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java deleted file mode 100644 index f4805062ec2..00000000000 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/NeoForgeBootstrap.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.bootstrap.neoforge; - -import net.neoforged.fml.classloading.JarModuleFinder; -import net.neoforged.fml.classloading.ModuleClassLoader; -import net.neoforged.fml.classloading.SecureJar; -import org.spongepowered.bootstrap.Bootstrap; - -import java.io.IOException; -import java.lang.module.Configuration; -import java.lang.module.ModuleFinder; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; - -public class NeoForgeBootstrap extends Bootstrap { - private final String[] args; - - public NeoForgeBootstrap(final String[] args) { - this.args = args; - } - - @Override - public String name() { - return "NeoForge"; - } - - @Override - protected SecureJar createJar(final Path[] paths) throws IOException { - return SecureJar.from(paths); - } - - @Override - protected String getModuleName(final SecureJar jar) { - return jar.name(); - } - - @Override - protected ModuleFinder createModuleFinder(final Collection jars) { - return JarModuleFinder.of(jars.toArray(SecureJar[]::new)); - } - - @Override - protected ClassLoader createApplicationClassLoader(final Configuration config, final List parentLayers, final ClassLoader parentLoader) { - return new ModuleClassLoader("APP-BOOTSTRAP", config, parentLayers, parentLoader); - } - - @Override - protected void runApplication(final ModuleLayer layer) throws Exception { - // TODO net.neoforged.fml.startup.* - final Class appClass = layer.findModule("fml_loader").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); - appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); - } - - public static void main(final String[] args) throws Exception { - new NeoForgeBootstrap(args).devBoot(true); - } -} diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java new file mode 100644 index 00000000000..01b11972f89 --- /dev/null +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.neoforge; + +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.startup.Entrypoint; +import net.neoforged.fml.startup.FatalStartupException; +import org.spongepowered.bootstrap.dev.DevClasspath; + +import java.lang.invoke.MethodHandle; + +public class TestServer extends Entrypoint { + + public static void main(final String[] args) { + DevClasspath.resolve(); + + // Do not close the loader until tests are done + final FMLLoader loader = Entrypoint.startup(args, true, Dist.DEDICATED_SERVER, true); + + final MethodHandle main = Entrypoint.createMainMethodCallable(loader, "net.minecraft.server.Main"); + try { + main.invokeExact(loader.getProgramArgs().getArguments()); + } catch (Throwable e) { + throw new FatalStartupException("Failed to invoke main", e); + } + } +} diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/DigestUtil.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/DigestUtil.java new file mode 100644 index 00000000000..08fe4320f97 --- /dev/null +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/DigestUtil.java @@ -0,0 +1,87 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.gradle.impl; + +import org.gradle.api.GradleException; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +public class DigestUtil { + private static final char[] hexChars = "0123456789abcdef".toCharArray(); + + public static String toHexString(final byte[] bytes) { + final char[] chars = new char[bytes.length << 1]; + int i = 0; + for (final byte b : bytes) { + chars[i++] = DigestUtil.hexChars[(b >> 4) & 15]; + chars[i++] = DigestUtil.hexChars[b & 15]; + } + return new String(chars); + } + + public static String digest(final Path file, final String algorithm) { + final MessageDigest digest; + try { + digest = MessageDigest.getInstance(algorithm); + } catch (final NoSuchAlgorithmException e) { + throw new GradleException("Failed to find digest algorithm", e); + } + + try (final InputStream in = Files.newInputStream(file)) { + final byte[] buf = new byte[4096]; + int read; + while ((read = in.read(buf)) != -1) { + digest.update(buf, 0, read); + } + } catch (final IOException e) { + throw new GradleException("Failed to digest file " + file, e); + } + + return DigestUtil.toHexString(digest.digest()); + } + + public static void generateChecksums(final File jarFile, final String dirPath, final String algorithm) throws Exception { + try (final FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + jarFile.toURI()), Map.of())) { + final Path dir = fs.getPath(dirPath); + final List lines; + try (final Stream st = Files.list(dir)) { + lines = st.map(p -> DigestUtil.digest(p, algorithm) + " " + p.getFileName()).toList(); + } + Files.write(dir.resolve("checksums.txt"), lines); + } + } +} diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/OutputDependenciesToJson.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/OutputDependenciesToJson.java index d6ff84c50f5..89824a41893 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/OutputDependenciesToJson.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/OutputDependenciesToJson.java @@ -46,10 +46,7 @@ import java.io.BufferedWriter; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -61,8 +58,6 @@ public abstract class OutputDependenciesToJson extends DefaultTask { - private static final char[] hexChars = "0123456789abcdef".toCharArray(); - private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); /** @@ -171,44 +166,19 @@ private List configToDescriptor(final Set { final ModuleComponentIdentifier id = (ModuleComponentIdentifier) dependency.getId().getComponentIdentifier(); - final MessageDigest digest; + final String digest; try { - digest = MessageDigest.getInstance("SHA-512"); - } catch (final NoSuchAlgorithmException e) { - throw new GradleException("Failed to find digest algorithm", e); - } - - try (final InputStream in = Files.newInputStream(dependency.getFile().toPath())) { - final byte[] buf = new byte[4096]; - int read; - while ((read = in.read(buf)) != -1) { - digest.update(buf, 0, read); - } - } catch (final IOException e) { + digest = DigestUtil.digest(dependency.getFile().toPath(), "SHA-512"); + } catch (final Exception e) { throw new GradleException("Failed to digest file for " + dependency, e); } - return new DependencyDescriptor( - id.getGroup(), - id.getModule(), - id.getVersion(), - OutputDependenciesToJson.toHexString(digest.digest()) - ); + return new DependencyDescriptor(id.getGroup(), id.getModule(), id.getVersion(), digest); }) .sorted(Comparator.naturalOrder()) // sort dependencies for stable output .collect(Collectors.toList()); } - public static String toHexString(final byte[] bytes) { - final char[] chars = new char[bytes.length << 1]; - int i = 0; - for (final byte b : bytes) { - chars[i++] = OutputDependenciesToJson.hexChars[(b >> 4) & 15]; - chars[i++] = OutputDependenciesToJson.hexChars[b & 15]; - } - return new String(chars); - } - public static class ConfigurationHolder { private final Provider> artifacts; diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java index fb545091686..a622afd05a7 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java @@ -27,8 +27,6 @@ import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.api.IEnvironment; import net.minecraftforge.fml.loading.FMLPaths; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; @@ -37,14 +35,15 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; public final class ForgePluginPlatform implements PluginPlatform { + private static final List closeCallbacks = new ArrayList<>(); private static volatile boolean bootstrapped; private final Environment environment; - private final Logger logger; private final LaunchConfig config; private final TokenReplacement tokens; private final List pluginDirectories; @@ -65,7 +64,6 @@ public static synchronized void bootstrap(final Environment environment) { private ForgePluginPlatform(final Environment environment) throws IOException { this.environment = environment; - this.logger = LogManager.getLogger("plugin"); this.config = LaunchConfig.load(this.baseDirectory(), true); this.tokens = new TokenReplacement(); @@ -83,11 +81,6 @@ public String version() { return this.environment.getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev"); } - @Override - public Logger logger() { - return this.logger; - } - @Override public boolean vanilla() { return false; @@ -117,4 +110,21 @@ public TokenReplacement tokens() { public List pluginDirectories() { return this.pluginDirectories; } + + @Override + public void addLoaderCloseCallback(final AutoCloseable closeable) { + ForgePluginPlatform.closeCallbacks.add(closeable); + } + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final AutoCloseable closeCallback : ForgePluginPlatform.closeCallbacks) { + try { + closeCallback.close(); + } catch (Exception e) { + PluginPlatform.LOGGER.error("Failed to run close callback {}", closeCallback, e); + } + } + }, "Sponge shutdown thread")); + } } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 4552f651f1a..23ee9f49e07 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,6 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.neoforged.moddevgradle.internal.RunGameTask import org.spongepowered.gradle.impl.AWToAT +import org.spongepowered.gradle.impl.DigestUtil buildscript { repositories { @@ -182,18 +183,17 @@ neoForge { runs { configureEach { // jvmArgument("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath - mainClass = "org.spongepowered.bootstrap.neoforge.NeoForgeBootstrap" - - programArguments.addAll(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) } create("client") { client() + mainClass = "org.spongepowered.bootstrap.neoforge.DevClient" } create("server") { server() programArgument("--nogui") + mainClass = "org.spongepowered.bootstrap.neoforge.DevServer" } } } @@ -204,6 +204,7 @@ configurations.testRuntimeOnly.get().extendsFrom(configurations.getByName("modDe dependencies { val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) + service(libs.accessWidener) service(project(libraryManagerProject.path)) val game = gameLibrariesConfig.name @@ -275,6 +276,7 @@ sourceSets { property("version", version.toString()) property("description", description.toString()) property("neoForgeVersion", neoForgeVersion) + property("mixins", mixinConfigs.joinToString(",") { "{config=\"$it\"}" }) } } @@ -357,8 +359,7 @@ tasks { from(neoManifest) attributes( "Access-Widener" to "common.accesswidener", - "Superclass-Transformer" to "common.superclasschange,neoforge.superclasschange", - "MixinConfigs" to mixinConfigs.joinToString(",") + "Superclass-Transformer" to "common.superclasschange,neoforge.superclasschange" ) } @@ -387,6 +388,10 @@ tasks { from(langJar) rename("spongeneo-(.*)-lang.jar", "spongeneo-lang.jar") } + + doLast { + DigestUtil.generateChecksums(archiveFile.get().asFile, "jars", "SHA-256") + } } assemble { diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java index f68e8687f3d..b7cdce0589f 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java @@ -24,10 +24,10 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; -import com.google.common.collect.ImmutableMap; import net.neoforged.fml.classloading.SecureJar; import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.ILaunchContext; import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; @@ -47,7 +47,6 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Locale; import java.util.Map; import java.util.stream.Stream; @@ -93,24 +92,33 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) return; } + // Official JiJ cannot be used in a service jar. We have to reimplement it. + // FML 10 only supports files directly on disk, so we must extract them. try { - URL rootJar = SpongeNeoModLocator.class.getProtectionDomain().getCodeSource().getLocation(); - FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar - try (Stream st = Files.list(fs.getPath("jars"))) { - st.filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar")) - .map(path -> { - try { - URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); - final Map env = ImmutableMap.of("packagePath", path); - FileSystem jijFS = FileSystems.newFileSystem(jij, env); - return jijFS.getPath("/"); // root of the archive to load - } catch (Exception e) { - throw new RuntimeException(e); - } - }).forEach(path -> pipeline.addPath(path, attributes, IncompatibleFileReporting.WARN_ALWAYS)); + final URL rootJar = SpongeNeoModLocator.class.getProtectionDomain().getCodeSource().getLocation(); + final Path cacheDir = FMLPaths.JIJ_CACHEDIR.get(); + + try (final FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + rootJar), Map.of())) { + final Path jarsDir = fs.getPath("jars"); + + // Difference with the official JiJ: our checksums are precalculated, to avoid unnecessary IO. + for (final String line : Files.readAllLines(jarsDir.resolve("checksums.txt"))) { + final int i = line.indexOf(' '); + final String digest = line.substring(0, i), name = line.substring(i + 1); + final Path target = cacheDir.resolve(digest).resolve(name); + + // FML does not verify the cached file checksum, so neither do we. + // The checksum is only there to distinguish different files. + if (!Files.exists(target)) { + Files.createDirectories(target.getParent()); + Files.copy(jarsDir.resolve(name), target); + } + + pipeline.addPath(target, attributes, IncompatibleFileReporting.WARN_ALWAYS); + } } } catch (Exception e) { - LOGGER.error("Failed to scan mod candidates", e); + LOGGER.error("Failed to register embedded mod candidates", e); } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java index b5b7e1092c9..77e6a125c31 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java @@ -26,8 +26,6 @@ import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; @@ -42,7 +40,6 @@ public final class NeoForgePluginPlatform implements PluginPlatform { private static volatile boolean bootstrapped; - private final Logger logger; private final LaunchConfig config; private final TokenReplacement tokens; private final List pluginDirectories; @@ -62,7 +59,6 @@ public static synchronized void bootstrap() { } private NeoForgePluginPlatform() throws IOException { - this.logger = LogManager.getLogger("plugin"); this.config = LaunchConfig.load(this.baseDirectory(), true); this.tokens = new TokenReplacement(); @@ -80,11 +76,6 @@ public String version() { return NeoForgeVersion.getVersion(); } - @Override - public Logger logger() { - return this.logger; - } - @Override public boolean vanilla() { return false; @@ -114,4 +105,9 @@ public TokenReplacement tokens() { public List pluginDirectories() { return this.pluginDirectories; } + + @Override + public void addLoaderCloseCallback(AutoCloseable closeable) { + // TODO FML + } } diff --git a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml b/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml index 7f3e1176ba4..0a6428683c8 100644 --- a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml +++ b/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml @@ -4,6 +4,8 @@ license="MIT License" issueTrackerURL="https://github.com/SpongePowered/Sponge/issues" +mixins = [{{ mixins }}] + [[mods]] modId="spongeneo" diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java index 1d8b60b7cf3..373d42b3fd6 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java @@ -63,13 +63,13 @@ public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } - @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$30", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager neo$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$31", at = @At("TAIL")) public void neo$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java index c1baa5318b7..73ca288cc9b 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java @@ -24,6 +24,8 @@ */ package org.spongepowered.neoforge.mixin.core.world.level; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -104,13 +106,10 @@ public abstract class ServerExplosionMixin_NeoForge { return entities; } - - @Redirect(method = "hurtEntities(Ljava/util/List;)V", at = @At(value = "NEW", target = "(DDD)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 neo$useKnockbackMultiplier(final double $$0, final double $$1, final double $$2) { + @WrapOperation(method = "hurtEntities(Ljava/util/List;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;scale(D)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 neo$useKnockbackMultiplier(Vec3 instance, double $$0, Operation original) { // Honor our knockback value from event - return new Vec3($$0 * this.impl$knockbackMultiplier, - $$1 * this.impl$knockbackMultiplier, - $$2 * this.impl$knockbackMultiplier); + return original.call(instance, $$0 * this.impl$knockbackMultiplier); } } diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java index dcc5924a543..7d9338f4ae9 100644 --- a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeLauncherInterceptor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.neoforge.boot; +import net.neoforged.fml.loading.FMLLoader; import org.junit.platform.launcher.LauncherInterceptor; import org.spongepowered.common.applaunch.test.TestGameAccess; @@ -31,8 +32,6 @@ public final class SpongeLauncherInterceptor implements LauncherInterceptor { private final ClassLoader classLoader; - private long counter; - public SpongeLauncherInterceptor() { try { this.classLoader = SpongeTestBoot.getGameClassLoader(); @@ -43,10 +42,6 @@ public SpongeLauncherInterceptor() { @Override public T intercept(final Invocation invocation) { - // getResources broken on Neo - if (this.counter++ == 1) { - return invocation.proceed(); - } final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { @@ -59,5 +54,6 @@ public T intercept(final Invocation invocation) { @Override public void close() { TestGameAccess.shutdownGame(); + FMLLoader.getCurrent().close(); } } diff --git a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java index 416b5317e49..70a051fd0ea 100644 --- a/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java +++ b/neoforge/src/test/java/org/spongepowered/neoforge/boot/SpongeTestBoot.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.boot; -import org.spongepowered.bootstrap.neoforge.NeoForgeBootstrap; +import org.spongepowered.bootstrap.neoforge.TestServer; import org.spongepowered.common.applaunch.test.TestGameAccess; import java.nio.file.Files; @@ -39,7 +39,7 @@ public static ClassLoader getGameClassLoader() throws Exception { .skip(1) // main class .toArray(String[]::new); System.setProperty("sponge.test.active", "true"); - new NeoForgeBootstrap(args).devBoot(false); + TestServer.main(args); } return TestGameAccess.getGameClassLoader(); } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java index 75a82e00b96..84310a04721 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.applaunch.plugin; +import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; @@ -32,10 +33,13 @@ import java.util.List; public interface PluginPlatform { + Logger LOGGER = LogManager.getLogger("plugin"); String version(); - Logger logger(); + default Logger logger() { + return LOGGER; + } boolean vanilla(); @@ -49,4 +53,10 @@ public interface PluginPlatform { List pluginDirectories(); + /** + * Adds a callback that will be called once, when the platform loader is about to close. + * When the platform loader is closed, no new class can be loaded, so this is the last thing we can do. + */ + void addLoaderCloseCallback(AutoCloseable closeable); + } diff --git a/src/main/java/org/spongepowered/common/SpongeCommon.java b/src/main/java/org/spongepowered/common/SpongeCommon.java index efee66998c2..d93067dda13 100644 --- a/src/main/java/org/spongepowered/common/SpongeCommon.java +++ b/src/main/java/org/spongepowered/common/SpongeCommon.java @@ -45,7 +45,6 @@ import org.spongepowered.common.scheduler.AsyncScheduler; import org.spongepowered.common.scheduler.ServerScheduler; -import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @@ -62,19 +61,6 @@ public final class SpongeCommon { private static @MonotonicNonNull Path pluginConfigDir; - static { - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - final @Nullable SpongeGame game = SpongeCommon.game; - if (game != null) { - try { - game.configManager().close(); - } catch (final IOException e) { - SpongeCommon.logger().error("Failed to shut down configuration watch service", e); - } - } - }, "Sponge shutdown thread")); - } - private SpongeCommon() { } diff --git a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java index 3fb5af7a96c..68249067f77 100644 --- a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java +++ b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java @@ -30,6 +30,7 @@ import org.spongepowered.api.config.ConfigRoot; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.adventure.SpongeAdventure; +import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.reference.WatchServiceListener; import org.spongepowered.configurate.serialize.TypeSerializerCollection; @@ -55,6 +56,8 @@ public final class PluginConfigManager implements ConfigManager { .threadFactory(new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Sponge-WatchService-%d").build()) .build(); + AppLaunch.pluginPlatform().addLoaderCloseCallback(this.listener); + this.serializers = TypeSerializerCollection.defaults().childBuilder() // We have a separate type serializer for CatalogTypes, so we explicitly discount them here. // See https://github.com/SpongePowered/SpongeCommon/issues/1348 @@ -90,8 +93,4 @@ public static ConfigurationOptions getOptions(final TypeSerializerCollection ser return ConfigurationOptions.defaults() .serializers(serializers); } - - public void close() throws IOException { - this.listener.close(); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 1e8da32f40b..5a9c64cfd6c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -558,13 +558,13 @@ public String toString() { .toString(); } - @Redirect(method = { - "advanceWeatherCycle", - "globalLevelEvent", - "setDefaultSpawnPos" - }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V")) - private void impl$broadcastAllCurrentDimensionOnly(final PlayerList instance, final Packet $$0) { - //Weather, game rules and spawns are per world in Sponge. - instance.broadcastAll($$0, this.shadow$dimension()); + @Redirect( + method = "advanceWeatherCycle", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V"), + require = 0 // already done in Neo + ) + private void impl$broadcastAllCurrentDimensionOnly(final PlayerList instance, final Packet packet) { + // Weather is per world in Sponge. + instance.broadcastAll(packet, this.shadow$dimension()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index e83e18cf797..3917fd62776 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -113,13 +113,13 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock } // Interrupt-Active - e.g. a player removing the currently smelting item - @Inject( + /*@Inject( method = "setItem", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" ) - ) + )*/ // TODO Neo private void impl$interruptSmelt(final CallbackInfo ci) { this.impl$callInteruptSmeltEvent(); } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java index a67bd50caaa..d6c47ff9206 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java @@ -26,7 +26,6 @@ import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IModuleLayerManager; -import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; import org.spongepowered.common.applaunch.plugin.PluginPlatform; @@ -45,6 +44,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; @@ -56,6 +56,7 @@ import java.util.Set; public final class VanillaPluginPlatform implements PluginPlatform { + private static final List closeCallbacks = new ArrayList<>(); private final Environment environment; private final LaunchConfig config; @@ -103,11 +104,6 @@ private void setVersion(final String version) { this.environment.blackboard().set(Keys.VERSION, version); } - @Override - public Logger logger() { - return this.environment.logger(); - } - @Override public boolean vanilla() { return true; @@ -146,6 +142,11 @@ private void setPluginDirectories(final List pluginDirectories) { this.environment.blackboard().set(Keys.PLUGIN_DIRECTORIES, pluginDirectories); } + @Override + public void addLoaderCloseCallback(final AutoCloseable closeable) { + VanillaPluginPlatform.closeCallbacks.add(closeable); + } + public String metadataFilePath() { return this.environment.blackboard().get(Keys.METADATA_FILE_PATH); } @@ -255,4 +256,16 @@ public void createPluginCandidates() { } } } + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final AutoCloseable closeCallback : VanillaPluginPlatform.closeCallbacks) { + try { + closeCallback.close(); + } catch (Exception e) { + PluginPlatform.LOGGER.error("Failed to run close callback {}", closeCallback, e); + } + } + }, "Sponge shutdown thread")); + } } From 7e1bc4369fd6151217a8e0bfa941ebac21006b8c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 9 Oct 2025 10:28:14 +0200 Subject: [PATCH 385/586] Fix CookingEventInterrupt injection on Neo --- ...AbstractFurnaceBlockEntityMixin_Forge.java | 13 ++++++++++++ .../AbstractFurnaceBlockEntityMixin_Neo.java | 13 ++++++++++++ .../AbstractFurnaceBlockEntityBridge.java | 1 + .../AbstractFurnaceBlockEntityMixin.java | 21 +++++-------------- ...stractFurnaceBlockEntityMixin_Vanilla.java | 13 ++++++++++++ 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 708712c77fc..aa0bd75b07c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -49,6 +49,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; @@ -180,4 +181,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } + + // Interrupt-Active - e.g. a player removing the currently smelting item + @Inject( + method = "setItem", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" + ) + ) + private void forge$interruptSmelt(final CallbackInfo ci) { + this.impl$callInterruptSmeltEvent(); + } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index 58326bfcd2d..fbfa6af4670 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -51,6 +51,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; @@ -188,4 +189,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } + + // Interrupt-Active - e.g. a player removing the currently smelting item + @Inject( + method = "setItem(ILnet/minecraft/world/item/ItemStack;Z)V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" + ) + ) + private void neo$interruptSmelt(final CallbackInfo ci) { + this.impl$callInterruptSmeltEvent(); + } } diff --git a/src/main/java/org/spongepowered/common/bridge/block/entity/AbstractFurnaceBlockEntityBridge.java b/src/main/java/org/spongepowered/common/bridge/block/entity/AbstractFurnaceBlockEntityBridge.java index e16bf8271d1..01f2295d218 100644 --- a/src/main/java/org/spongepowered/common/bridge/block/entity/AbstractFurnaceBlockEntityBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/block/entity/AbstractFurnaceBlockEntityBridge.java @@ -33,4 +33,5 @@ public interface AbstractFurnaceBlockEntityBridge { Optional> bridge$getCurrentRecipe(); + void impl$callInterruptSmeltEvent(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 3917fd62776..c3763b9df18 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -108,20 +108,8 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock if (!(this.level instanceof ServerLevel se)) { return Optional.empty(); } - var recipeInpuit = new SingleRecipeInput(this.items.get(0)); - return this.quickCheck.getRecipeFor(recipeInpuit, se); - } - - // Interrupt-Active - e.g. a player removing the currently smelting item - /*@Inject( - method = "setItem", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" - ) - )*/ // TODO Neo - private void impl$interruptSmelt(final CallbackInfo ci) { - this.impl$callInteruptSmeltEvent(); + var recipeInput = new SingleRecipeInput(this.items.get(0)); + return this.quickCheck.getRecipeFor(recipeInput, se); } // Interrupt-Passive - if the currently smelting item was removed in some other way @@ -145,10 +133,11 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock ) private static void impl$onResetCookTimePassive(final ServerLevel level, final BlockPos pos, final BlockState state, @Coerce final AbstractFurnaceBlockEntityMixin entity, final CallbackInfo ci) { - entity.impl$callInteruptSmeltEvent(); + entity.impl$callInterruptSmeltEvent(); } - private void impl$callInteruptSmeltEvent() { + @Override + public void impl$callInterruptSmeltEvent() { if (this.cookingTimer > 0) { final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(this.items.get(1)); final Cause cause = PhaseTracker.getInstance().currentCause(); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 533d290b943..704ddefeb7b 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -51,6 +51,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; @@ -186,4 +187,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } + + // Interrupt-Active - e.g. a player removing the currently smelting item + @Inject( + method = "setItem", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getTotalCookTime(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)I" + ) + ) + private void vanilla$interruptSmelt(final CallbackInfo ci) { + this.impl$callInterruptSmeltEvent(); + } } From e8a5a4aeae95a66024c6bc6b629313ca40f03344 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 9 Oct 2025 10:48:09 +0200 Subject: [PATCH 386/586] Move custom bootstrap to Forge only --- .../bootstrap/forge/ForgeLikeBootstrap.java | 140 ++++++++++++++--- .../FilteringPassthroughClassLoader.java | 4 +- .../classloader}/ResourceClassLoader.java | 2 +- .../spongepowered/bootstrap/Bootstrap.java | 144 +----------------- 4 files changed, 126 insertions(+), 164 deletions(-) rename bootstrap/src/{main/java/org/spongepowered/bootstrap => forge/java/org/spongepowered/bootstrap/forge/classloader}/FilteringPassthroughClassLoader.java (93%) rename bootstrap/src/{main/java/org/spongepowered/bootstrap => forge/java/org/spongepowered/bootstrap/forge/classloader}/ResourceClassLoader.java (96%) diff --git a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java index f7fbd101d01..5fc15b9c5d5 100644 --- a/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/ForgeLikeBootstrap.java @@ -28,43 +28,147 @@ import net.minecraftforge.securemodules.SecureModuleClassLoader; import net.minecraftforge.securemodules.SecureModuleFinder; import org.spongepowered.bootstrap.Bootstrap; +import org.spongepowered.bootstrap.dev.DevClasspath; +import org.spongepowered.bootstrap.forge.classloader.FilteringPassthroughClassLoader; +import org.spongepowered.bootstrap.forge.classloader.ResourceClassLoader; +import java.io.File; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; +import java.net.URL; import java.nio.file.Path; -import java.util.Collection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; -public abstract class ForgeLikeBootstrap extends Bootstrap { +public abstract class ForgeLikeBootstrap { private final String[] args; public ForgeLikeBootstrap(final String[] args) { this.args = args; } - @Override - protected SecureJar createJar(final Path[] paths) { - return SecureJar.from(paths); + public abstract String name(); + + /** + * When filtered, the jar content is still accessible via the application classloader but is not loaded as a module. + */ + protected boolean filterApplicationModule(final SecureJar jar) { + return false; } - @Override - protected String getModuleName(final SecureJar jar) { - return jar.name(); + protected void runApplication(final ModuleLayer layer) throws Exception { + final Class appClass = layer.findLoader("cpw.mods.modlauncher").loadClass("cpw.mods.modlauncher.Launcher"); + appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); } - @Override - protected ModuleFinder createModuleFinder(final Collection jars) { - return SecureModuleFinder.of(jars); + public void devBoot(final boolean isolated) throws Exception { + this.boot(DevClasspath.resolve(), isolated); } - @Override - protected ClassLoader createApplicationClassLoader(final Configuration config, final List parentLayers, final ClassLoader parentLoader) { - return new SecureModuleClassLoader("APP-BOOTSTRAP", null, config, parentLayers, List.of(parentLoader)); + public void boot(final List classpath, final boolean isolated) throws Exception { + if (Bootstrap.DEBUG) { + System.out.println("Bootstrapping " + this.name() + " from classloader: " + getClass().getClassLoader()); + System.out.println("Isolated: " + isolated); + } + + // Collect the jars + final Set moduleNames = new HashSet<>(); + final List resourcePaths = new ArrayList<>(); + final List resourceJars = new ArrayList<>(); + final List appJars = new ArrayList<>(); + + for (final Path[] paths : classpath) { + final SecureJar jar = SecureJar.from(paths); + final String name = jar.name(); + + // Ignore modules already present + if (ModuleLayer.boot().findModule(name).isPresent()) { + if (Bootstrap.DEBUG) { + System.out.println("Boot: " + name + " " + ForgeLikeBootstrap.formatUnion(paths)); + } + continue; + } + + if (this.filterApplicationModule(jar)) { + if (Bootstrap.DEBUG) { + System.out.println("Filtered: " + name + " " + ForgeLikeBootstrap.formatUnion(paths)); + } + resourceJars.add(jar); + resourcePaths.addAll(Arrays.asList(paths)); + continue; + } + + if (!moduleNames.add(name)) { + if (Bootstrap.DEBUG) { + System.out.println("Duplicate: " + name + " " + ForgeLikeBootstrap.formatUnion(paths)); + } + resourceJars.add(jar); + resourcePaths.addAll(Arrays.asList(paths)); + continue; + } + + if (Bootstrap.DEBUG) { + System.out.println("App: " + name + " " + ForgeLikeBootstrap.formatUnion(paths)); + } + appJars.add(jar); + } + + // Create the layer configuration + final ModuleFinder finder = SecureModuleFinder.of(appJars); + final Configuration config = ModuleLayer.boot().configuration().resolveAndBind(finder, ModuleFinder.ofSystem(), moduleNames); + final List parentLayers = List.of(ModuleLayer.boot()); + + // Isolation + final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader parentLoader = ClassLoader.getPlatformClassLoader(); + if (!isolated) { + // Make sure we don't leak classes that are supposed to be + // in the game layer from the boostrap layer. + final String resources = System.getProperty("sponge.resources"); + if (resources != null) { + final List spongeJars = new ArrayList<>(); + for (final String entry : resources.split(File.pathSeparator)) { + final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); + spongeJars.add(SecureJar.from(paths)); + } + final ModuleFinder spongeFinder = SecureModuleFinder.of(spongeJars); + final ModuleFinder resourceFinder = SecureModuleFinder.of(resourceJars); + parentLoader = new FilteringPassthroughClassLoader(contextLoader, + Stream.concat(spongeFinder.findAll().stream(), resourceFinder.findAll().stream())); + } + } + + // Intermediate classloader to include resources but not modules + if (!resourcePaths.isEmpty()) { + final URL[] urls = new URL[resourcePaths.size()]; + for (int i = 0; i < urls.length; i++) { + urls[i] = resourcePaths.get(i).toUri().toURL(); + } + parentLoader = new ResourceClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); + } + + // Create the application classloader + final ClassLoader loader = new SecureModuleClassLoader("APP-BOOTSTRAP", null, config, parentLayers, List.of(parentLoader)); + final ModuleLayer layer = ModuleLayer.boot().defineModules(config, moduleName -> loader); + + // Run the application + try { + Thread.currentThread().setContextClassLoader(loader); + if (Bootstrap.DEBUG) { + System.out.println("Starting application ..."); + } + this.runApplication(layer); + } finally { + Thread.currentThread().setContextClassLoader(contextLoader); + } } - @Override - protected void runApplication(final ModuleLayer layer) throws Exception { - final Class appClass = layer.findModule("cpw.mods.modlauncher").get().getClassLoader().loadClass("cpw.mods.modlauncher.Launcher"); - appClass.getDeclaredMethod("main", String[].class).invoke(null, (Object) this.args); + public static String formatUnion(final Path[] paths) { + return Arrays.stream(paths).map(Path::toString).collect(Collectors.joining("&")); } } diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/FilteringPassthroughClassLoader.java similarity index 93% rename from bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java rename to bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/FilteringPassthroughClassLoader.java index 5f17458df0d..21f5a718ecf 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/FilteringPassthroughClassLoader.java +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/FilteringPassthroughClassLoader.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.bootstrap; +package org.spongepowered.bootstrap.forge.classloader; import java.lang.module.ModuleReference; import java.util.HashSet; @@ -37,7 +37,7 @@ public final class FilteringPassthroughClassLoader extends ClassLoader { ClassLoader.registerAsParallelCapable(); } - FilteringPassthroughClassLoader(final ClassLoader parent, final Stream modules) { + public FilteringPassthroughClassLoader(final ClassLoader parent, final Stream modules) { super(parent); modules.forEach(m -> this.filteredPackages.addAll(m.descriptor().packages())); } diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/ResourceClassLoader.java similarity index 96% rename from bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java rename to bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/ResourceClassLoader.java index ee11b705544..0aa8ade915d 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/ResourceClassLoader.java +++ b/bootstrap/src/forge/java/org/spongepowered/bootstrap/forge/classloader/ResourceClassLoader.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.bootstrap; +package org.spongepowered.bootstrap.forge.classloader; import java.net.URL; import java.net.URLClassLoader; diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java index 9245922bc7c..55c77fbaf01 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/Bootstrap.java @@ -24,148 +24,6 @@ */ package org.spongepowered.bootstrap; -import org.spongepowered.bootstrap.dev.DevClasspath; - -import java.io.File; -import java.io.IOException; -import java.lang.module.Configuration; -import java.lang.module.ModuleFinder; -import java.net.URL; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public abstract class Bootstrap { +public class Bootstrap { public static final boolean DEBUG = Boolean.getBoolean("sponge.bootstrap.debug"); - - public abstract String name(); - - protected abstract Jar createJar(Path[] paths) throws IOException; - - protected abstract String getModuleName(Jar jar); - - protected abstract ModuleFinder createModuleFinder(Collection jars); - - /** - * When filtered, the jar content is still accessible via the application classloader but is not loaded as a module. - */ - protected boolean filterApplicationModule(final Jar jar) { - return false; - } - - protected abstract ClassLoader createApplicationClassLoader(Configuration config, List parentLayers, ClassLoader parentLoader); - - protected abstract void runApplication(ModuleLayer layer) throws Exception; - - public void devBoot(final boolean isolated) throws Exception { - this.boot(DevClasspath.resolve(), isolated); - } - - public void boot(final List classpath, final boolean isolated) throws Exception { - if (Bootstrap.DEBUG) { - System.out.println("Bootstrapping " + this.name() + " from classloader: " + getClass().getClassLoader()); - System.out.println("Isolated: " + isolated); - } - - // Collect the jars - final Set moduleNames = new HashSet<>(); - final List resourcePaths = new ArrayList<>(); - final List resourceJars = new ArrayList<>(); - final List appJars = new ArrayList<>(); - - for (final Path[] paths : classpath) { - final Jar jar = this.createJar(paths); - final String name = this.getModuleName(jar); - - // Ignore modules already present - if (ModuleLayer.boot().findModule(name).isPresent()) { - if (Bootstrap.DEBUG) { - System.out.println("Boot: " + name + " " + Bootstrap.formatUnion(paths)); - } - continue; - } - - if (this.filterApplicationModule(jar)) { - if (Bootstrap.DEBUG) { - System.out.println("Filtered: " + name + " " + Bootstrap.formatUnion(paths)); - } - resourceJars.add(jar); - resourcePaths.addAll(Arrays.asList(paths)); - continue; - } - - if (!moduleNames.add(name)) { - if (Bootstrap.DEBUG) { - System.out.println("Duplicate: " + name + " " + Bootstrap.formatUnion(paths)); - } - resourceJars.add(jar); - resourcePaths.addAll(Arrays.asList(paths)); - continue; - } - - if (Bootstrap.DEBUG) { - System.out.println("App: " + name + " " + Bootstrap.formatUnion(paths)); - } - appJars.add(jar); - } - - // Create the layer configuration - final ModuleFinder finder = this.createModuleFinder(appJars); - final Configuration config = ModuleLayer.boot().configuration().resolveAndBind(finder, ModuleFinder.ofSystem(), moduleNames); - final List parentLayers = List.of(ModuleLayer.boot()); - - // Isolation - final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); - ClassLoader parentLoader = ClassLoader.getPlatformClassLoader(); - if (!isolated) { - // Make sure we don't leak classes that are supposed to be - // in the game layer from the boostrap layer. - final String resources = System.getProperty("sponge.resources"); - if (resources != null) { - final List spongeJars = new ArrayList<>(); - for (final String entry : resources.split(File.pathSeparator)) { - final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); - spongeJars.add(this.createJar(paths)); - } - final ModuleFinder spongeFinder = this.createModuleFinder(spongeJars); - final ModuleFinder resourceFinder = this.createModuleFinder(resourceJars); - parentLoader = new FilteringPassthroughClassLoader(contextLoader, - Stream.concat(spongeFinder.findAll().stream(), resourceFinder.findAll().stream())); - } - } - - // Intermediate classloader to include resources but not modules - if (!resourcePaths.isEmpty()) { - final URL[] urls = new URL[resourcePaths.size()]; - for (int i = 0; i < urls.length; i++) { - urls[i] = resourcePaths.get(i).toUri().toURL(); - } - parentLoader = new ResourceClassLoader("BOOTSTRAP-RESOURCES", urls, parentLoader); - } - - // Create the application classloader - final ClassLoader loader = this.createApplicationClassLoader(config, parentLayers, parentLoader); - final ModuleLayer layer = ModuleLayer.boot().defineModules(config, moduleName -> loader); - - // Run the application - try { - Thread.currentThread().setContextClassLoader(loader); - if (Bootstrap.DEBUG) { - System.out.println("Starting application ..."); - } - this.runApplication(layer); - } finally { - Thread.currentThread().setContextClassLoader(contextLoader); - } - } - - public static String formatUnion(final Path[] paths) { - return Arrays.stream(paths).map(Path::toString).collect(Collectors.joining("&")); - } } From c0dc2799a1fe530cd77da045d2128cdbfecca326 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 9 Oct 2025 13:28:07 +0200 Subject: [PATCH 387/586] Merge SpongeNeo lang sourceset into applaunch --- neoforge/build.gradle.kts | 27 +------------------ .../plugin}/JavaPluginLanguageProvider.java | 2 +- ...ed.neoforgespi.language.IModLanguageLoader | 1 + .../src/lang/resources/META-INF/MANIFEST.MF | 2 -- ...ed.neoforgespi.language.IModLanguageLoader | 1 - 5 files changed, 3 insertions(+), 30 deletions(-) rename neoforge/src/{lang/java/org/spongepowered/neoforge/lang/provider => applaunch/java/org/spongepowered/neoforge/applaunch/plugin}/JavaPluginLanguageProvider.java (98%) create mode 100644 neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader delete mode 100644 neoforge/src/lang/resources/META-INF/MANIFEST.MF delete mode 100644 neoforge/src/lang/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 23ee9f49e07..f5100100ec0 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -60,12 +60,8 @@ val serviceLayerConfig = configurations.register("serviceLayer") { extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) } -val langLayerConfig = configurations.register("langLayer") { - extendsFrom(bootLayerConfig.get()) -} val gameLayerConfig = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) - extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) } @@ -93,13 +89,6 @@ val appLaunch by sourceSets.register("applaunch") { } } -// Lang layer -val lang by sourceSets.register("lang") { - configurations.named(implementationConfigurationName) { - extendsFrom(langLayerConfig.get()) - } -} - // Game layer val launch by sourceSets.register("launch") { spongeImpl.addDependencyToImplementation(commonAppLaunchConf.get(), this) @@ -153,7 +142,6 @@ val main by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(commonMixins.get(), this) spongeImpl.addDependencyToRuntimeOnly(mixins, this) - spongeImpl.addDependencyToRuntimeOnly(lang, this) // The bootstrap spongeImpl.addDependencyToRuntimeOnly(bootstrapMain.get(), this) @@ -302,13 +290,6 @@ tasks { manifest.from(neoManifest) } - val langJar by existing(Jar::class) { - manifest.attributes( - "Automatic-Module-Name" to "spongeneo.lang", - "FMLModType" to "LIBRARY" - ) - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") appLaunch.resources.srcDir(installerResources) @@ -384,9 +365,6 @@ tasks { into("jars") { from(shadowJar) rename("spongeneo-(.*)-mod.jar", "spongeneo-mod.jar") - - from(langJar) - rename("spongeneo-(.*)-lang.jar", "spongeneo-lang.jar") } doLast { @@ -431,7 +409,7 @@ tasks { jacocoTestReport { sourceSets(commonAppLaunchConf.get(), commonAppLaunch.get(), commonLaunch.get(), commonAccessors.get(), commonMixins.get(), commonMain.get()) - sourceSets(appLaunch, launch, lang, accessors, mixins, main) + sourceSets(appLaunch, launch, accessors, mixins, main) dependsOn(test) } } @@ -444,9 +422,6 @@ publishing { artifact(tasks["jar"]) artifact(tasks["sourcesJar"]) - artifact(tasks["langJar"]) - artifact(tasks["langSourcesJar"]) - artifact(tasks["mixinsJar"]) artifact(tasks["mixinsSourcesJar"]) diff --git a/neoforge/src/lang/java/org/spongepowered/neoforge/lang/provider/JavaPluginLanguageProvider.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java similarity index 98% rename from neoforge/src/lang/java/org/spongepowered/neoforge/lang/provider/JavaPluginLanguageProvider.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java index be4d14fcfe3..1de9c31e1ce 100644 --- a/neoforge/src/lang/java/org/spongepowered/neoforge/lang/provider/JavaPluginLanguageProvider.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.lang.provider; +package org.spongepowered.neoforge.applaunch.plugin; import net.neoforged.fml.Logging; import net.neoforged.fml.ModContainer; diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader new file mode 100644 index 00000000000..135fde603ee --- /dev/null +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader @@ -0,0 +1 @@ +org.spongepowered.neoforge.applaunch.plugin.JavaPluginLanguageProvider diff --git a/neoforge/src/lang/resources/META-INF/MANIFEST.MF b/neoforge/src/lang/resources/META-INF/MANIFEST.MF deleted file mode 100644 index c93f76cce69..00000000000 --- a/neoforge/src/lang/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Automatic-Module-Name: spongeneo.lang -FMLModType: LIBRARY diff --git a/neoforge/src/lang/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader b/neoforge/src/lang/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader deleted file mode 100644 index 656f03f2f30..00000000000 --- a/neoforge/src/lang/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.neoforge.lang.provider.JavaPluginLanguageProvider \ No newline at end of file From 69b1268e622a875e67f9c9290430259e1a039562 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 9 Oct 2025 13:31:27 +0200 Subject: [PATCH 388/586] Re-enable SpongeNeo CI --- .github/workflows/common-run-build.yaml | 6 +++--- .github/workflows/deploy.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 53ce2ca1cd7..82dc1d45351 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -17,14 +17,14 @@ jobs: project: - vanilla - forge -# - neoforge + - neoforge include: - project: vanilla gradleProject: SpongeVanilla - project: forge gradleProject: SpongeForge -# - project: neoforge -# gradleProject: SpongeNeo + - project: neoforge + gradleProject: SpongeNeo steps: - name: setup id: setup diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 0012154aba1..99c138c7923 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -42,9 +42,9 @@ jobs: - project: forge gradleProject: ':SpongeForge' skipUpdateBranch: true -# - project: neoforge -# gradleProject: ':SpongeNeo' -# skipUpdateBranch: true + - project: neoforge + gradleProject: ':SpongeNeo' + skipUpdateBranch: true steps: - name: setup if: "!(matrix.skipUpdateBranch && startsWith(github.ref, 'refs/heads/update/'))" From 4dc3a2eb35fd0e13b3c61ab4b777e4ff0598e844 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 10 Oct 2025 11:39:44 -0400 Subject: [PATCH 389/586] feat(minecraft): update Minecraft to 1.21.10 Upgraded game to 1.21.10. A small change to a single mixin target was involved for all three platforms. See: https://minecraft.wiki/w/Java_Edition_1.21.10 See: https://maven.minecraftforge.net/net/minecraftforge/forge/1.21.10-60.0.1/forge-1.21.10-60.0.1-changelog.txt See: https://maven.neoforged.net/releases/net/neoforged/neoforge/21.10.6-beta/neoforge-21.10.6-beta-changelog.txt --- forge/gradle.properties | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 380 ++++-------------- neoforge/gradle.properties | 2 +- .../mixin/core/world/entity/EntityMixin.java | 8 +- 5 files changed, 90 insertions(+), 304 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 1dcd7d36c1e..6759ac977d5 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=59.0.0 +forgeVersion=60.0.1 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index 7855e5bc16d..009b19b0151 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=1.21.9 +minecraftVersion=1.21.10 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5f30a98c124..7ffdb41ee0c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4374,6 +4374,14 @@ + + + + + + + + @@ -4430,6 +4438,14 @@ + + + + + + + + @@ -4588,6 +4604,14 @@ + + + + + + + + @@ -4746,6 +4770,14 @@ + + + + + + + + @@ -4990,6 +5022,14 @@ + + + + + + + + @@ -5081,6 +5121,14 @@ + + + + + + + + @@ -5239,6 +5287,14 @@ + + + + + + + + @@ -5405,6 +5461,14 @@ + + + + + + + + @@ -6024,6 +6088,11 @@ + + + + + @@ -6075,309 +6144,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - + + + - - + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 6567ff76563..d0545202229 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.9.14-beta +neoForgeVersion=21.10.6-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index abe8beee105..6628e4b0be4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -742,20 +742,20 @@ public void stopRiding() { @WrapOperation(method = "lambda$checkInsideBlocks$0", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/InsideBlockEffectApplier;)V" + target = "Lnet/minecraft/world/level/block/state/BlockState;entityInside(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/InsideBlockEffectApplier;Z)V" ) ) // doBlockCollisions private void impl$onCheckInsideBlocksCollide( final BlockState blockState, final Level worldIn, final BlockPos pos, final Entity entityIn, - final InsideBlockEffectApplier insideBlockEffectApplier, final Operation original) { + final InsideBlockEffectApplier insideBlockEffectApplier, final boolean applies, final Operation original) { if (!ShouldFire.COLLIDE_BLOCK_EVENT_INSIDE || worldIn.isClientSide() || blockState.isAir()) { - original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier); + original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier, applies); return; } final org.spongepowered.api.util.Direction dir = org.spongepowered.api.util.Direction.NONE; if (!SpongeCommonEventFactory.handleCollideBlockEvent(blockState.getBlock(), worldIn, pos, blockState, entityIn, dir, SpongeCommonEventFactory.CollisionType.INSIDE)) { - original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier); + original.call(blockState, worldIn, pos, entityIn, insideBlockEffectApplier, applies); this.impl$lastCollidedBlockPos = pos; } From 090e9f43956ae5d13a3fed340603c28a77a7b151 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 10 Oct 2025 19:21:37 +0200 Subject: [PATCH 390/586] Fix superclass changes in dev environment --- .../bootstrap/dev/DevClasspath.java | 34 +++++++-------- .../bootstrap/dev/WeightedPath.java | 38 +++++++++++++++++ forge/src/main/resources/META-INF/MANIFEST.MF | 1 + gradle.properties | 1 - .../src/main/resources/META-INF/MANIFEST.MF | 1 + src/main/resources/common.superclasschange | 3 -- .../{mixin => transformation}/MixinTest.java | 2 +- .../transformation/SuperclassChangeTest.java | 42 +++++++++++++++++++ vanilla/build.gradle.kts | 6 --- .../src/main/resources/META-INF/MANIFEST.MF | 1 + 10 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 bootstrap/src/main/java/org/spongepowered/bootstrap/dev/WeightedPath.java create mode 100644 forge/src/main/resources/META-INF/MANIFEST.MF create mode 100644 neoforge/src/main/resources/META-INF/MANIFEST.MF rename src/test/java/org/spongepowered/common/{mixin => transformation}/MixinTest.java (96%) create mode 100644 src/test/java/org/spongepowered/common/transformation/SuperclassChangeTest.java create mode 100644 vanilla/src/main/resources/META-INF/MANIFEST.MF diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index 4ca4698babf..fc623dffc0e 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -49,11 +49,11 @@ public static List resolve() { final Set gameShadedNames = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); // boot layer - final Multimap bootUnions = new Multimap<>(); + final Multimap bootUnions = new Multimap<>(); final List bootLibs = new ArrayList<>(); // game or plugin layer - final Multimap unions = new Multimap<>(); + final Multimap unions = new Multimap<>(); final List libs = new ArrayList<>(); final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false); @@ -80,7 +80,7 @@ public static List resolve() { // ignore break; case "modlauncher-transformers", "library-manager": - bootUnions.add(projectName, path); + bootUnions.add(projectName, new WeightedPath(0, path)); break; case "SpongeAPI": switch (sourceSet.name()) { @@ -91,26 +91,27 @@ public static List resolve() { hasAPISourceSet.set(true); // no break default: - unions.add("sponge", path); + unions.add("sponge", new WeightedPath(0, path)); break; } break; case "", "vanilla", "forge", "neoforge": + final WeightedPath weightedPath = new WeightedPath(projectName.isEmpty() ? 1 : 2, path); switch (sourceSet.name()) { case "applaunchConfig": case "applaunch": - bootUnions.add("applaunch", path); + bootUnions.add("applaunch", weightedPath); break; case "lang": - unions.add("lang", path); + unions.add("lang", weightedPath); break; default: - unions.add("sponge", path); + unions.add("sponge", weightedPath); break; } break; default: - unions.add(projectName, path); + unions.add(projectName, new WeightedPath(0, path)); break; } } else { @@ -118,7 +119,7 @@ public static List resolve() { System.out.println("External SourceSet (" + sourceSet + "): " + path); } - unions.add(sourceSet.project().toString(), path); + unions.add(sourceSet.project().toString(), new WeightedPath(0, path)); } continue; } @@ -144,7 +145,7 @@ public static List resolve() { if (Bootstrap.DEBUG) { System.out.println("Sponge: " + path); } - unions.add("sponge", path); + unions.add("sponge", new WeightedPath(0, path)); continue; } @@ -160,12 +161,13 @@ public static List resolve() { classpath.add(new Path[] { lib }); } - for (final List sourceSets : bootUnions.values()) { - classpath.add(sourceSets.toArray(Path[]::new)); + for (final List sourceSets : bootUnions.values()) { + classpath.add(sourceSets.stream().sorted().map(WeightedPath::path).toArray(Path[]::new)); } if (hasAPISourceSet.get()) { - unions.get("sponge").removeIf((path) -> { + unions.get("sponge").removeIf((w) -> { + final Path path = w.path(); if (Files.isRegularFile(path)) { final String fileName = path.getFileName().toString(); if (fileName.startsWith("spongeapi") && fileName.endsWith(".jar")) { @@ -183,10 +185,8 @@ public static List resolve() { for (final Path resource : libs) { resourcesEnvBuilder.append(resource).append(File.pathSeparator); } - for (final List project : unions.values()) { - for (final Path resource : project) { - resourcesEnvBuilder.append(resource).append('&'); - } + for (final List project : unions.values()) { + project.stream().sorted().forEachOrdered(w -> resourcesEnvBuilder.append(w.path()).append('&')); resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar); } resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/WeightedPath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/WeightedPath.java new file mode 100644 index 00000000000..bc7c4dc8dc0 --- /dev/null +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/WeightedPath.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.dev; + +import java.nio.file.Path; + +public record WeightedPath(int weight, Path path) implements Comparable { + @Override + public int compareTo(WeightedPath o) { + final int result = Integer.compare(this.weight, o.weight); + if (result != 0) { + return result; + } + return this.path.compareTo(o.path); + } +} diff --git a/forge/src/main/resources/META-INF/MANIFEST.MF b/forge/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..85d411bad57 --- /dev/null +++ b/forge/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Superclass-Transformer: common.superclasschange,forge.superclasschange diff --git a/gradle.properties b/gradle.properties index 948f91c0633..9db1417b282 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,6 @@ projectDescription=The SpongeAPI implementation targeting vanilla Minecraft and mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.concurrent.json,mixins.sponge.core.json,\ mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -superClassChanges=common.superclasschange minecraftVersion=1.21.4 recommendedVersion=0-SNAPSHOT diff --git a/neoforge/src/main/resources/META-INF/MANIFEST.MF b/neoforge/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..6818dcc8cd0 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Superclass-Transformer: common.superclasschange,neoforge.superclasschange diff --git a/src/main/resources/common.superclasschange b/src/main/resources/common.superclasschange index b0d1f80c3b3..09e20d1d75d 100644 --- a/src/main/resources/common.superclasschange +++ b/src/main/resources/common.superclasschange @@ -1,4 +1 @@ -org.spongepowered.api.event.cause.entity.damage.source.common.AbstractDamageSource:org.spongepowered.common.event.cause.entity.damage.SpongeCommonDamageSource -org.spongepowered.api.event.cause.entity.damage.source.common.AbstractEntityDamageSource:org.spongepowered.common.event.cause.entity.damage.SpongeCommonEntityDamageSource -org.spongepowered.api.event.cause.entity.damage.source.common.AbstractIndirectEntityDamageSource:org.spongepowered.common.event.cause.entity.damage.SpongeCommonIndirectEntityDamageSource org.spongepowered.api.entity.ai.goal.AbstractGoal:net.minecraft.world.entity.ai.goal.Goal diff --git a/src/test/java/org/spongepowered/common/mixin/MixinTest.java b/src/test/java/org/spongepowered/common/transformation/MixinTest.java similarity index 96% rename from src/test/java/org/spongepowered/common/mixin/MixinTest.java rename to src/test/java/org/spongepowered/common/transformation/MixinTest.java index b3564fc8a4f..34037ed2c8e 100644 --- a/src/test/java/org/spongepowered/common/mixin/MixinTest.java +++ b/src/test/java/org/spongepowered/common/transformation/MixinTest.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin; +package org.spongepowered.common.transformation; import org.junit.jupiter.api.Test; import org.spongepowered.asm.mixin.MixinEnvironment; diff --git a/src/test/java/org/spongepowered/common/transformation/SuperclassChangeTest.java b/src/test/java/org/spongepowered/common/transformation/SuperclassChangeTest.java new file mode 100644 index 00000000000..11b66a44327 --- /dev/null +++ b/src/test/java/org/spongepowered/common/transformation/SuperclassChangeTest.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.transformation; + +import net.minecraft.world.entity.ai.goal.Goal; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.spongepowered.api.entity.ai.goal.AbstractGoal; + +public class SuperclassChangeTest { + + @Test + public void testSuperclassChange() { + assertSuperclassEquals(AbstractGoal.class, Goal.class); + } + + private static void assertSuperclassEquals(final Class base, final Class expectedSuper) { + Assertions.assertEquals(expectedSuper, base.getSuperclass()); + } +} diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 4ac4e3e52de..c0ac5f1081c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -146,7 +146,6 @@ val testSources = sourceSets.named("test") { spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) } -val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations minecraft { @@ -318,11 +317,6 @@ minecraft { .flatMap { sequenceOf("--mixin.config", it) } .toList() } - allArgumentProviders += CommandLineArgumentProvider { - superclassConfigs.asSequence() - .flatMap { sequenceOf("--superclass_change.config", it) } - .toList() - } // ModLauncher // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath diff --git a/vanilla/src/main/resources/META-INF/MANIFEST.MF b/vanilla/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..84b6d5f1fc0 --- /dev/null +++ b/vanilla/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Superclass-Transformer: common.superclasschange,vanilla.superclasschange From 368d0ab917696f75a016505fdcaa2ce9e7232532 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 10 Oct 2025 19:02:45 -0400 Subject: [PATCH 391/586] feat(minecraft): update towards 25w41a Introduced updates to reflect changes in Minecraft's codebase, particularly around permissions, world rules, and API adaptations. Adjusted permission levels to integrate with new PermissionLevel and PermissionSet systems while incorporating various minor fixes and deprecations. See: https://minecraft.wiki/w/Java_Edition_25w41a --- SpongeAPI | 2 +- .../vanilla/generator/GeneratorMain.java | 3 +- gradle.properties | 2 +- .../commands/CommandSourceStackAccessor.java | 3 +- .../server/MinecraftServerAccessor.java | 2 - .../monster/ZombifiedPiglinAccessor.java | 4 +- .../world/entity/player/PlayerAccessor.java | 3 +- .../world/level/BaseCommandBlockAccessor.java | 3 +- .../common/launch/Lifecycle.java | 3 +- .../spongepowered/common/SpongeLifecycle.java | 3 +- .../dispatcher/SpongeNodePermissionCache.java | 3 +- .../manager/SpongeCommandCauseFactory.java | 8 +- .../provider/entity/ZombifiedPiglinData.java | 2 +- .../provider/world/WorldPropertiesData.java | 3 +- .../entity/player/LoginPermissions.java | 4 +- .../merchant/TradeOfferGeneratorWrapper.java | 4 +- .../server/ServerConsoleSystemSubject.java | 17 +-- .../SpongeServerScopedServiceProvider.java | 5 +- .../server/permission/OpLevelCollection.java | 21 ++-- .../permission/SpongePermissionService.java | 15 +-- .../server/permission/SpongePermissions.java | 7 +- .../server/permission/UserSubject.java | 18 +-- .../spongepowered/common/util/Constants.java | 7 +- .../world/biome/SpongeBiomeBuilder.java | 6 +- .../ambient/SpongeParticleConfigFactory.java | 2 +- .../ambient/SpongeSoundConfigFactory.java | 4 +- .../server/MinecraftServerMixin_API.java | 11 +- .../server/level/ServerLevelMixin_API.java | 1 + .../nautilus/AbstractNautilusMixin_API.java} | 36 +++--- .../animal/nautilus/NautilusMixin_API.java | 32 ++++++ .../nautilus/ZombieNautilusMixin_API.java | 32 ++++++ .../VillagerTrades_ItemListingMixin_API.java | 8 +- .../AmbientAdditionsSettingsMixin_API.java | 8 +- .../biome/AmbientMoodSettingsMixin_API.java | 16 ++- .../AmbientParticleSettingsMixin_API.java | 8 +- .../entity/CommandBlockEntityMixin_API.java | 12 +- .../commands/CommandSourceStackMixin.java | 108 +++++++++--------- .../core/server/MinecraftServerMixin.java | 2 +- .../ReloadableServerResourcesMixin.java | 19 ++- .../mixin/core/server/WorldLoaderMixin.java | 9 +- .../commands/DifficultyCommandMixin.java | 4 +- .../core/server/level/ServerLevelMixin.java | 87 ++++++++++++++ .../core/world/BaseCommandBlockMixin.java | 27 +---- .../core/world/entity/LivingEntityMixin.java | 9 +- .../entity/monster/ZombifiedPiglinMixin.java | 6 +- .../core/world/entity/player/PlayerMixin.java | 13 ++- .../entity/player/PlayerMixin_Attack.java | 36 +++--- .../vehicle/MinecartCommandBlockMixin.java | 5 +- ...CommandBlock_MinecartCommandBaseMixin.java | 31 ++++- .../entity/vehicle/MinecartTNTMixin.java | 4 +- .../mixin/core/world/level/LevelMixin.java | 89 --------------- .../block/entity/CommandBlockEntityMixin.java | 14 ++- .../entity/CommandBlockEntity_Mixin.java | 28 +++++ .../level/storage/PrimaryLevelDataMixin.java | 4 +- .../BlockableEventLoopMixin_Tracker.java | 13 ++- src/mixins/resources/mixins.sponge.api.json | 5 +- src/mixins/resources/mixins.sponge.core.json | 1 - ...eloadableServerResourcesMixin_Vanilla.java | 13 ++- 58 files changed, 516 insertions(+), 329 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/{core/server/commands/GameRuleCommandMixin.java => api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java} (52%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/NautilusMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/ZombieNautilusMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index a0493bdb270..c315763d065 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a0493bdb27098185d001b1c43bbd7a3f0e3cdd02 +Subproject commit c315763d06548b6a3f13b837ce9a28e7b581f871 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 2978e69c86e..3da6cc3f97d 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -42,6 +42,7 @@ import net.minecraft.server.packs.repository.ServerPacksSource; import net.minecraft.server.packs.resources.CloseableResourceManager; import net.minecraft.server.packs.resources.MultiPackResourceManager; +import net.minecraft.server.permissions.LevelBasedPermissionSet; import net.minecraft.tags.TagLoader; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.vanilla.generator.item.ItemRegistries; @@ -151,7 +152,7 @@ private static Pair loadVanill pendingTags, packRepository.getRequestedFeatureFlags(), CommandSelection.ALL, - 2, // functionPermissionLevel + LevelBasedPermissionSet.ALL_PERMISSIONS, // functionPermissionLevel Util.backgroundExecutor(), // prepareExecutor Runnable::run // applyExecutor ).whenComplete((result, ex) -> { diff --git a/gradle.properties b/gradle.properties index 009b19b0151..0730178be65 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=1.21.10 +minecraftVersion=25w41a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/commands/CommandSourceStackAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/commands/CommandSourceStackAccessor.java index f138e5b446f..c4ad6b45358 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/commands/CommandSourceStackAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/commands/CommandSourceStackAccessor.java @@ -32,6 +32,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.util.TaskChainer; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec2; @@ -50,7 +51,7 @@ public interface CommandSourceStackAccessor { final Vec3 $$1, final Vec2 $$2, final ServerLevel $$3, - final int $$4, + final PermissionSet $$4, final String $$5, final Component $$6, final MinecraftServer $$7, @Nullable final Entity $$8, diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java index a6d7e9e6127..cb25acec6a2 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/MinecraftServerAccessor.java @@ -61,8 +61,6 @@ public interface MinecraftServerAccessor { @Accessor("nextTickTimeNanos") void accessor$nextTickTimeNanos(final long nextTickTime); - @Invoker("isSpawningMonsters") boolean invoker$isSpawningMonsters(); - @Invoker("setupDebugLevel") void invoker$setupDebugLevel(final WorldData serverConfiguration); @Invoker("forceDifficulty") void invoker$forceDifficulty(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java index 4ab6bb3e630..644030a22c0 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java @@ -31,7 +31,7 @@ @Mixin(ZombifiedPiglin.class) public interface ZombifiedPiglinAccessor { - @Accessor("remainingPersistentAngerTime") int accessor$remainingPersistentAngerTime(); + @Accessor("persistentAngerEndTime") long accessor$remainingPersistentAngerTime(); - @Accessor("remainingPersistentAngerTime") void accessor$remainingPersistentAngerTime(final int remainingPersistentAngerTime); + @Accessor("persistentAngerEndTime") void accessor$remainingPersistentAngerTime(final long remainingPersistentAngerTime); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java index b865b4bcd36..b419f06bf7b 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/player/PlayerAccessor.java @@ -25,6 +25,7 @@ package org.spongepowered.common.accessor.world.entity.player; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -51,7 +52,7 @@ public interface PlayerAccessor { @Accessor("DATA_SHOULDER_PARROT_RIGHT") static EntityDataAccessor accessor$DATA_SHOULDER_RIGHT() { throw new UntransformedAccessorError(); } - @Invoker("getPermissionLevel") int invoker$getPermissionLevel(); + @Invoker("permissions") PermissionSet invoker$permissions(); @Accessor("sleepCounter") void accessor$sleepCounter(final int sleepCounter); diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java index 0ac83b2a8c0..9b527e7d30c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/BaseCommandBlockAccessor.java @@ -25,6 +25,7 @@ package org.spongepowered.common.accessor.world.level; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BaseCommandBlock; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -41,6 +42,6 @@ public interface BaseCommandBlockAccessor { @Accessor("command") void accessor$command(final String command); - @Invoker("createSource") BaseCommandBlock.CloseableCommandBlockSource invoker$createSource(); + @Invoker("createSource") BaseCommandBlock.CloseableCommandBlockSource invoker$createSource(ServerLevel level); } diff --git a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java index 01229128bde..20d0d6de404 100644 --- a/src/launch/java/org/spongepowered/common/launch/Lifecycle.java +++ b/src/launch/java/org/spongepowered/common/launch/Lifecycle.java @@ -26,6 +26,7 @@ import com.google.inject.Injector; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.api.Client; import org.spongepowered.api.Engine; @@ -66,7 +67,7 @@ public interface Lifecycle { void establishGameServices(); - void establishServerServices(ResourceManager resourceManager, int functionsPermissionLevel); + void establishServerServices(ResourceManager resourceManager, PermissionLevel functionsPermissionLevel); void establishServerFeatures(); diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index d88fd56cfe5..fbe98f3abe1 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -31,6 +31,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.level.WorldDataConfiguration; import org.checkerframework.checker.nullness.qual.Nullable; @@ -174,7 +175,7 @@ public void establishGameServices() { } @Override - public void establishServerServices(final ResourceManager resourceManager, final int functionsPermissionLevel) { + public void establishServerServices(final ResourceManager resourceManager, final PermissionLevel functionsPermissionLevel) { final SpongeServerScopedServiceProvider serviceProvider = new SpongeServerScopedServiceProvider(this.game, this.injector, functionsPermissionLevel); serviceProvider.init(); ((ResourceManagerBridge) resourceManager).bridge$services(serviceProvider); diff --git a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java index e8072a9dcf4..f85eae9e1b0 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/dispatcher/SpongeNodePermissionCache.java @@ -27,6 +27,7 @@ import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.RootCommandNode; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.permissions.PermissionLevel; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandCause; @@ -65,7 +66,7 @@ public static boolean canUse( && ((CommandSourceStackBridge) source).bridge$getCommandSource() instanceof ServerPlayer) { // If the entity is a player, then we should try to add it anyway. final String permission = supplier.get(); - SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), permission, 0); + SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), permission, PermissionLevel.ALL); return ((CommandCause) source).hasPermission(permission); } return result; diff --git a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandCauseFactory.java b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandCauseFactory.java index a22773569cf..7e1ea641a09 100644 --- a/src/main/java/org/spongepowered/common/command/manager/SpongeCommandCauseFactory.java +++ b/src/main/java/org/spongepowered/common/command/manager/SpongeCommandCauseFactory.java @@ -28,6 +28,8 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.permissions.LevelBasedPermissionSet; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; @@ -58,9 +60,9 @@ public final class SpongeCommandCauseFactory implements CommandCause.Factory { final CommandSource iCommandSource = cause.first(CommandSource.class).orElseGet(() -> SpongeCommon.game().systemSubject()); final CommandSourceStack commandSource; - if (iCommandSource instanceof CommandSourceProviderBridge) { + if (iCommandSource instanceof CommandSourceProviderBridge cspb) { // We know about this one so we can create it using the factory method on the source. - commandSource = ((CommandSourceProviderBridge) iCommandSource).bridge$getCommandSource(cause); + commandSource = cspb.bridge$getCommandSource(cause); } else { // try to create a command cause from the given ICommandSource, but as Mojang did not see fit to // put any identifying characteristics on the object, we have to go it alone... @@ -88,7 +90,7 @@ public final class SpongeCommandCauseFactory implements CommandCause.Factory { context.get(EventContextKeys.LOCATION).map(x -> (ServerLevel) x.world()) .orElseGet(() -> locatable == null ? SpongeCommon.server().getLevel(Level.OVERWORLD) : (ServerLevel) locatable.serverLocation().world()), - 4, + LevelBasedPermissionSet.forLevel(PermissionLevel.OWNERS), name, displayName, SpongeCommon.server(), diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java index d0867fcdd3c..5f188d08b21 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java @@ -42,7 +42,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.ANGER_LEVEL) .get(ZombifiedPiglinAccessor::accessor$remainingPersistentAngerTime) .set(ZombifiedPiglinAccessor::accessor$remainingPersistentAngerTime) - .resetOnDelete(400 + new SplittableRandom().nextInt(400)); + .resetOnDelete(() -> (long)(400 + new SplittableRandom().nextInt(400))); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index 2969efd9ec0..a7cc3be36db 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.world; import net.minecraft.core.GlobalPos; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.storage.LevelData; @@ -87,7 +88,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.WORLD_TYPE) .get(h -> (WorldType) (Object) h.bridge$dimensionType()) .create(Keys.PVP) - .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().isPvpAllowed())) + .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().getWorldData().getGameRules().getBoolean(GameRules.RULE_PVP))) .create(Keys.SERIALIZATION_BEHAVIOR) .get(h -> h.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC)) .create(Keys.VIEW_DISTANCE) diff --git a/src/main/java/org/spongepowered/common/entity/player/LoginPermissions.java b/src/main/java/org/spongepowered/common/entity/player/LoginPermissions.java index ba9b7cfbcb6..89687b2a5a9 100644 --- a/src/main/java/org/spongepowered/common/entity/player/LoginPermissions.java +++ b/src/main/java/org/spongepowered/common/entity/player/LoginPermissions.java @@ -24,9 +24,11 @@ */ package org.spongepowered.common.entity.player; +import net.minecraft.server.permissions.PermissionLevel; + public final class LoginPermissions { - public static final int BYPASS_WHITELIST_LEVEL = 1; + public static final PermissionLevel BYPASS_WHITELIST_LEVEL = PermissionLevel.MODERATORS; public static final String BYPASS_WHITELIST_PERMISSION = "minecraft.login.bypass-whitelist"; diff --git a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java index c5368a64499..916b7f1dfee 100644 --- a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java +++ b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.item.merchant; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; @@ -44,7 +45,7 @@ public TradeOfferGeneratorWrapper(final TradeOfferGenerator generator) { } @Override - public MerchantOffer getOffer(final Entity trader, final RandomSource rand) { + public MerchantOffer getOffer(final ServerLevel level, final Entity trader, final RandomSource rand) { return (MerchantOffer) this.generator.apply((org.spongepowered.api.entity.Entity) trader, (RandomProvider.Source) rand); } @@ -80,4 +81,5 @@ public String toString() { .add("generator=" + this.generator) .toString(); } + } diff --git a/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java b/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java index 2b3e2cf0fc9..397af351916 100644 --- a/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java +++ b/src/main/java/org/spongepowered/common/server/ServerConsoleSystemSubject.java @@ -29,6 +29,7 @@ import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSource; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.permissions.LevelBasedPermissionSet; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; @@ -59,14 +60,14 @@ public void sendMessage(final @NonNull Identity identity, final @NonNull Compone @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { return new CommandSourceStack(this, - Vec3.ZERO, - Vec2.ZERO, - SpongeCommon.server().getLevel(Level.OVERWORLD), - 4, - "System Subject", - net.minecraft.network.chat.Component.literal("System Subject"), - SpongeCommon.server(), - null); + Vec3.ZERO, + Vec2.ZERO, + SpongeCommon.server().getLevel(Level.OVERWORLD), + LevelBasedPermissionSet.OWNER, + "System Subject", + net.minecraft.network.chat.Component.literal("System Subject"), + SpongeCommon.server(), + null); } @Override diff --git a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java index 6babf671566..ad153385623 100644 --- a/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java +++ b/src/main/java/org/spongepowered/common/service/server/SpongeServerScopedServiceProvider.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableList; import com.google.inject.Injector; import io.leangen.geantyref.TypeToken; +import net.minecraft.server.permissions.PermissionLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.Game; import org.spongepowered.api.Server; @@ -51,9 +52,9 @@ public final class SpongeServerScopedServiceProvider extends SpongeServiceProvider implements ServiceProvider.ServerScoped { - private final int functionsPermissionLevel; + private final PermissionLevel functionsPermissionLevel; - public SpongeServerScopedServiceProvider(final Game game, final Injector injector, final int functionsPermissionLevel) { + public SpongeServerScopedServiceProvider(final Game game, final Injector injector, final PermissionLevel functionsPermissionLevel) { super(game, injector); this.functionsPermissionLevel = functionsPermissionLevel; } diff --git a/src/main/java/org/spongepowered/common/service/server/permission/OpLevelCollection.java b/src/main/java/org/spongepowered/common/service/server/permission/OpLevelCollection.java index 0994d18d9ba..15b2c5bd086 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/OpLevelCollection.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/OpLevelCollection.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import net.minecraft.server.permissions.PermissionLevel; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.Subject; @@ -45,8 +46,8 @@ public class OpLevelCollection extends SpongeSubjectCollection { public OpLevelCollection(final SpongePermissionService service) { super(PermissionService.SUBJECTS_GROUP, service); final ImmutableMap.Builder build = ImmutableMap.builder(); - for (int i = 0; i <= 4; ++i) { - build.put("op_" + i, new OpLevelSubject(service, i)); // TODO: Add subject data + for (var level : PermissionLevel.values()) { + build.put("op_" + level.ordinal(), new OpLevelSubject(service, level)); // TODO: Add subject data } this.levels = build.build(); } @@ -74,10 +75,10 @@ public Collection loadedSubjects() { public static class OpLevelSubject extends SpongeSubject { private final SpongePermissionService service; - private final int level; + private final PermissionLevel level; private final MemorySubjectData data; - public OpLevelSubject(final SpongePermissionService service, final int level) { + public OpLevelSubject(final SpongePermissionService service, final PermissionLevel level) { this.service = service; this.level = level; this.data = new GlobalMemorySubjectData(this) { @@ -87,23 +88,27 @@ public List parents(final Set contexts) { if (!contexts.isEmpty()) { return Collections.emptyList(); } - if (level == 0) { + if (level == PermissionLevel.ALL) { return super.parents(contexts); } else { - return ImmutableList.builder().add(service.getGroupForOpLevel(level - 1).asSubjectReference()).addAll(super.parents(contexts)).build(); + if (level == PermissionLevel.ALL) { + return ImmutableList.builder().add(service.getGroupForOpLevel(level).asSubjectReference()).addAll(super.parents(contexts)).build(); + } + var lesser = PermissionLevel.values()[level.ordinal() - 1]; + return ImmutableList.builder().add(service.getGroupForOpLevel(lesser).asSubjectReference()).addAll(super.parents(contexts)).build(); } } }; SpongePermissions.populateNonCommandPermissions(this.data, (permLevel, name) -> level == permLevel); } - public int opLevel() { + public PermissionLevel opLevel() { return this.level; } @Override public String identifier() { - return "op_" + this.level; + return "op_" + this.level.ordinal(); } @Override diff --git a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java index b31e2b0a85e..de2b0702280 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissionService.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.inject.Singleton; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.server.players.ServerOpList; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Game; @@ -67,7 +68,7 @@ public final class SpongePermissionService implements PermissionService { private final SpongeSubjectCollection defaultCollection; private final SpongeSubject defaultData; - public SpongePermissionService(final Game game, final int functionsPermissionLevel) { + public SpongePermissionService(final Game game, final PermissionLevel functionsPermissionLevel) { this.game = game; this.subjects.put(SpongePermissionService.SUBJECTS_DEFAULT, (this.defaultCollection = this.newCollection(SpongePermissionService.SUBJECTS_DEFAULT))); this.subjects.put(PermissionService.SUBJECTS_USER, new UserCollection(this)); @@ -75,11 +76,11 @@ public SpongePermissionService(final Game game, final int functionsPermissionLev this.subjects.put(PermissionService.SUBJECTS_COMMAND_BLOCK, new DataFactoryCollection( PermissionService.SUBJECTS_COMMAND_BLOCK, this, - s -> new FixedParentMemorySubjectData(s, this.getGroupForOpLevel(2).asSubjectReference()))); + s -> new FixedParentMemorySubjectData(s, this.getGroupForOpLevel(PermissionLevel.GAMEMASTERS).asSubjectReference()))); this.subjects.put(PermissionService.SUBJECTS_SYSTEM, new DataFactoryCollection( PermissionService.SUBJECTS_SYSTEM, this, - s -> new FixedParentMemorySubjectData(s, this.getGroupForOpLevel(4).asSubjectReference()) + s -> new FixedParentMemorySubjectData(s, this.getGroupForOpLevel(PermissionLevel.ALL).asSubjectReference()) // , s -> { // if (s.equals("Server")) { // return SpongeImpl.game().getServer().getConsole(); @@ -101,12 +102,12 @@ static ServerOpList getOps() { return SpongeCommon.server().getPlayerList().getOps(); } - static int getServerOpLevel() { - return SpongeCommon.server().operatorUserPermissionLevel(); + static PermissionLevel getServerOpLevel() { + return SpongeCommon.server().operatorUserPermissions().level(); } - public Subject getGroupForOpLevel(final int level) { - return this.groupSubjects().get("op_" + level); + public Subject getGroupForOpLevel(final PermissionLevel level) { + return this.groupSubjects().get("op_" + level.ordinal()); } @Override diff --git a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java index 814e55910d2..5c092b38864 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/SpongePermissions.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.service.server.permission; +import net.minecraft.server.permissions.PermissionLevel; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.util.Tristate; @@ -41,7 +42,7 @@ public final class SpongePermissions { private SpongePermissions() { } - public static void populateNonCommandPermissions(final SubjectData data, final BiFunction testPermission) { + public static void populateNonCommandPermissions(final SubjectData data, final BiFunction testPermission) { if (testPermission.apply(Constants.Permissions.COMMAND_BLOCK_LEVEL, Constants.Command.COMMAND_BLOCK_COMMAND)) { data.setPermission(SubjectData.GLOBAL_CONTEXT, Constants.Permissions.COMMAND_BLOCK_PERMISSION, Tristate.TRUE); } @@ -56,9 +57,9 @@ public static void populateNonCommandPermissions(final SubjectData data, final B } } - public static void registerPermission(final PermissionService service, final String permissionNode, final int opLevel) { + public static void registerPermission(final PermissionService service, final String permissionNode, final PermissionLevel opLevel) { if (SpongePermissions.REGISTERED_PERMISSIONS.add(permissionNode)) { - if (opLevel == 0) { + if (opLevel == PermissionLevel.ALL) { // register as a default permission service.defaults() .transientSubjectData() diff --git a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java index 6dc24539697..de5b085e69c 100644 --- a/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java +++ b/src/main/java/org/spongepowered/common/service/server/permission/UserSubject.java @@ -25,6 +25,8 @@ package org.spongepowered.common.service.server.permission; import com.mojang.authlib.GameProfile; +import net.minecraft.server.permissions.LevelBasedPermissionSet; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.server.players.NameAndId; import net.minecraft.server.players.ServerOpListEntry; import org.spongepowered.api.Sponge; @@ -59,18 +61,18 @@ public SubjectReference parent() { @Override public void setParent(final SubjectReference parent) { - final int opLevel; + final PermissionLevel opLevel; if (parent == null) { - opLevel = 0; + opLevel = PermissionLevel.ALL; } else { if (!(parent.resolve().join() instanceof OpLevelCollection.OpLevelSubject)) { return; } opLevel = ((OpLevelCollection.OpLevelSubject) parent).opLevel(); } - if (opLevel > 0) { + if (opLevel.isEqualOrHigherThan(PermissionLevel.ALL)) { // TODO: Should bypassesPlayerLimit be true or false? - SpongePermissionService.getOps().add(new ServerOpListEntry(UserSubject.this.nameAndId, opLevel, false)); + SpongePermissionService.getOps().add(new ServerOpListEntry(UserSubject.this.nameAndId, LevelBasedPermissionSet.forLevel(opLevel), false)); } else { SpongePermissionService.getOps().remove(UserSubject.this.nameAndId); } @@ -99,16 +101,16 @@ public Optional associatedObject() { return Sponge.server().player(this.player.id()); } - int getOpLevel() { + PermissionLevel getOpLevel() { Preconditions.checkState(Sponge.isServerAvailable(), "Server is not available!"); // Query op level from server ops list based on player's game profile final ServerOpListEntry entry = SpongePermissionService.getOps().get(this.nameAndId); if (entry == null) { // Take care of singleplayer commands -- unless an op level is specified, this player follows global rules - return SpongeCommon.server().getPlayerList().isOp(this.nameAndId) ? SpongeCommon.server().operatorUserPermissionLevel() : 0; + return SpongeCommon.server().getPlayerList().isOp(this.nameAndId) ? SpongeCommon.server().operatorUserPermissions().level() : PermissionLevel.ALL; } else { - return entry.getLevel(); + return entry.permissions().level(); } } @@ -136,7 +138,7 @@ public Tristate permissionValue(final String permission, final Cause cause) { if (ret == Tristate.UNDEFINED) { ret = this.dataPermissionValue(this.collection.getService().defaults().subjectData(), permission); } - if (ret == Tristate.UNDEFINED && this.getOpLevel() >= SpongePermissionService.getServerOpLevel()) { + if (ret == Tristate.UNDEFINED && this.getOpLevel().compareTo(SpongePermissionService.getServerOpLevel()) >= 0) { ret = Tristate.TRUE; } return ret; diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index fc0c2e5c025..b6504b202a4 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -42,6 +42,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -397,11 +398,11 @@ public static final class Permissions { public static final String SELECTOR_PERMISSION = "minecraft.selector"; public static final String COMMAND_BLOCK_PERMISSION = "minecraft.commandblock"; - public static final int COMMAND_BLOCK_LEVEL = 2; - public static final int SELECTOR_LEVEL = 2; + public static final PermissionLevel COMMAND_BLOCK_LEVEL = PermissionLevel.GAMEMASTERS; + public static final PermissionLevel SELECTOR_LEVEL = PermissionLevel.GAMEMASTERS; public static final String SPONGE_HELP_PERMISSION = "sponge.command.help"; public static final String DEBUG_HOVER_STACKTRACE = "sponge.debug.hover-stacktrace"; - public static final int SPONGE_HELP_LEVEL = 0; + public static final PermissionLevel SPONGE_HELP_LEVEL = PermissionLevel.ALL; } /** diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java index d7729837bc5..179d1ced86d 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java @@ -125,10 +125,10 @@ public Biome build() { .grassColorModifier((BiomeSpecialEffects.GrassColorModifier) (Object) grassColorModifier); foliageColor.ifPresent(c -> effectsBuilder.foliageColorOverride(c.rgb())); grassColor.ifPresent(c -> effectsBuilder.grassColorOverride(c.rgb())); - particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) ps)); + particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) (Object) ps)); ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); - ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) m)); - additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) s)); + ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) (Object) m)); + additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) (Object) s)); backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) (Object) m)); final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java index 104cd5051ec..fb9455c541e 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java @@ -33,6 +33,6 @@ public class SpongeParticleConfigFactory implements ParticleConfig.Factory { @Override public ParticleConfig of(final ParticleType type, final float probability) { - return (ParticleConfig) new AmbientParticleSettings(((ParticleOptions) type), probability); + return (ParticleConfig) (Object) new AmbientParticleSettings(((ParticleOptions) type), probability); } } diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java index 99964b0f271..6d69000d327 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java @@ -36,12 +36,12 @@ public class SpongeSoundConfigFactory implements SoundConfig.Factory { @Override public SoundConfig.Mood ofAmbientMood(final SoundType sound, final int tickDelay, final int searchRadius, final double distanceModifier) { - return (SoundConfig.Mood) new AmbientMoodSettings(Holder.direct((SoundEvent) (Object) sound), tickDelay, searchRadius, distanceModifier); + return (SoundConfig.Mood) (Object) new AmbientMoodSettings(Holder.direct((SoundEvent) (Object) sound), tickDelay, searchRadius, distanceModifier); } @Override public SoundConfig.Additional ofAdditional(final SoundType sound, final double tickChance) { - return (SoundConfig.Additional) new AmbientAdditionsSettings(Holder.direct((SoundEvent) (Object) sound), tickChance); + return (SoundConfig.Additional) (Object) new AmbientAdditionsSettings(Holder.direct((SoundEvent) (Object) sound), tickChance); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index b56db122407..c03cfdee411 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -125,9 +125,6 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe @Shadow public abstract void shadow$halt(boolean p_71263_1_); @Shadow public abstract void shadow$setPlayerIdleTimeout(int p_143006_1_); @Shadow public abstract boolean shadow$isHardcore(); - @Shadow public abstract boolean shadow$isPvpAllowed(); - @Shadow public abstract boolean shadow$isCommandBlockEnabled(); - @Shadow protected abstract boolean shadow$isSpawningMonsters(); @Shadow public abstract Commands shadow$getCommands(); @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract net.minecraft.server.packs.resources.ResourceManager shadow$getResourceManager(); @@ -251,17 +248,17 @@ public boolean isGameModeEnforced() { @Override public boolean isPVPEnabled() { - return this.shadow$isPvpAllowed(); + return this.worldData.getGameRules().getBoolean(GameRules.RULE_PVP); } @Override public boolean areCommandBlocksEnabled() { - return this.shadow$isCommandBlockEnabled(); + return this.worldData.getGameRules().getBoolean(GameRules.RULE_COMMAND_BLOCKS_ENABLED); } @Override public boolean isMonsterSpawnsEnabled() { - return this.shadow$isSpawningMonsters(); + return this.worldData.getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS); } @Override @@ -274,7 +271,7 @@ public boolean isAnimalSpawnsEnabled() { */ @Override public boolean isMultiWorldEnabled() { - return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER); + return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getWorldData().getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 9adc9c0b625..1972c935181 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -336,6 +336,7 @@ public ChunkLayout chunkLayout() { return this.api$chunkLayout; } + @SuppressWarnings("deprecation") @Override public WorldBorder setBorder(final WorldBorder border) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java similarity index 52% rename from src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java index 06440f66c08..017fc3a1fac 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/GameRuleCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java @@ -22,27 +22,29 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.server.commands; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.nautilus; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.commands.GameRuleCommand; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.entity.animal.nautilus.AbstractNautilus; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.entity.living.animal.NautilusLike; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.mixin.api.minecraft.world.entity.TamableAnimalMixin_API; -@Mixin(GameRuleCommand.class) -public abstract class GameRuleCommandMixin { +import java.util.Set; - @Redirect(method = "setRule", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getGameRules()Lnet/minecraft/world/level/GameRules;")) - private static GameRules impl$usePerWorldGameRules(final MinecraftServer server, final CommandContext context) { - return context.getSource().getLevel().getGameRules(); - } +@Mixin(AbstractNautilus.class) +public abstract class AbstractNautilusMixin_API extends TamableAnimalMixin_API implements NautilusLike { + + @Override + protected Set> api$getVanillaValues() { + final Set> values = super.api$getVanillaValues(); + + values.add(this.requireValue(Keys.MAX_HEALTH).asImmutable()); + values.add(this.requireValue(Keys.IS_TAMED).asImmutable()); + + this.getValue(Keys.OWNER).map(Value::asImmutable).ifPresent(values::add); - @Redirect(method = "queryRule", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getGameRules()Lnet/minecraft/world/level/GameRules;")) - private static GameRules impl$usePerWorldGameRules(final MinecraftServer server, final CommandSourceStack source) { - return source.getLevel().getGameRules(); + return values; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/NautilusMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/NautilusMixin_API.java new file mode 100644 index 00000000000..6d7055a6163 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/NautilusMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.nautilus; + +import org.spongepowered.api.entity.living.animal.Nautilus; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(net.minecraft.world.entity.animal.nautilus.Nautilus.class) +public abstract class NautilusMixin_API extends AbstractNautilusMixin_API implements Nautilus { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/ZombieNautilusMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/ZombieNautilusMixin_API.java new file mode 100644 index 00000000000..d01987a1957 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/ZombieNautilusMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.nautilus; + +import org.spongepowered.api.entity.living.animal.ZombieNautilus; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(net.minecraft.world.entity.animal.nautilus.ZombieNautilus.class) +public abstract class ZombieNautilusMixin_API extends AbstractNautilusMixin_API implements ZombieNautilus { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java index 9bbed6e93d7..aa40f796fab 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; @@ -39,12 +40,15 @@ public interface VillagerTrades_ItemListingMixin_API extends TradeOfferGenerator { // @formatter:off - @Shadow @Nullable MerchantOffer shadow$getOffer(Entity entity, RandomSource random); + @Shadow @Nullable MerchantOffer shadow$getOffer(ServerLevel level, Entity entity, RandomSource random); // @formatter:on @Override default TradeOffer apply(final org.spongepowered.api.entity.Entity merchant, final RandomProvider.Source random) { - return (TradeOffer) this.shadow$getOffer((Entity) merchant, (RandomSource) random); + if (merchant.world() instanceof ServerLevel sl) { + return (TradeOffer) this.shadow$getOffer(sl, (Entity) merchant, (RandomSource) random); + } + throw new IllegalStateException("The merchant is not in a server world!"); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java index 5aecb500911..6aa511b938c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java @@ -30,10 +30,14 @@ import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(AmbientAdditionsSettings.class) +@Implements(@Interface(iface = SoundConfig.Additional.class, prefix = "api$")) public abstract class AmbientAdditionsSettingsMixin_API implements SoundConfig.Additional { // @formatter:off @@ -46,8 +50,8 @@ public SoundType sound() { return (SoundType) (Object) this.soundEvent.value(); } - @Override - public double tickChance() { + @Intrinsic + public double api$tickChance() { return this.tickChance; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java index 4b93d6398b0..fb02cb60796 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java @@ -30,10 +30,14 @@ import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(AmbientMoodSettings.class) +@Implements(@Interface(iface = SoundConfig.Mood.class, prefix = "api$")) public abstract class AmbientMoodSettingsMixin_API implements SoundConfig.Mood { // @formatter:off @@ -48,18 +52,18 @@ public SoundType sound() { return (SoundType) (Object) this.soundEvent.value(); } - @Override - public int tickDelay() { + @Intrinsic + public int api$tickDelay() { return this.tickDelay; } - @Override - public int searchRadius() { + @Intrinsic + public int api$searchRadius() { return this.blockSearchExtent; } - @Override - public double distanceModifier() { + @Intrinsic + public double api$distanceModifier() { return this.soundPositionOffset; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java index f5cf1b58c32..3190132e2e9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java @@ -28,10 +28,14 @@ import org.spongepowered.api.effect.particle.ParticleType; import org.spongepowered.api.world.biome.ambient.ParticleConfig; import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(AmbientParticleSettings.class) +@Implements(@Interface(iface = ParticleConfig.class, prefix = "api$")) public abstract class AmbientParticleSettingsMixin_API implements ParticleConfig { // @formatter:off @@ -39,8 +43,8 @@ public abstract class AmbientParticleSettingsMixin_API implements ParticleConfig @Shadow @Final private net.minecraft.core.particles.ParticleOptions options; // @formatter:on - @Override - public float probability() { + @Intrinsic + public float api$probability() { return this.probability; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java index 367285e8f68..848ed9d0a87 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/CommandBlockEntityMixin_API.java @@ -28,6 +28,7 @@ import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BaseCommandBlock; import net.minecraft.world.level.block.entity.CommandBlockEntity; import org.checkerframework.checker.nullness.qual.NonNull; @@ -51,7 +52,10 @@ public abstract class CommandBlockEntityMixin_API extends BlockEntityMixin_API i @Override public void execute() { - this.shadow$getCommandBlock().performCommand(this.level); + if (!(this.level instanceof ServerLevel sl)) { + return; + } + this.shadow$getCommandBlock().performCommand(sl); } @Override @@ -93,7 +97,11 @@ public String identifier() { @SuppressWarnings({"UnstableApiUsage", "deprecation"}) @Override public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { - final var source = ((BaseCommandBlockAccessor) this.shadow$getCommandBlock()).invoker$createSource(); + final var block = this.shadow$getCommandBlock(); + if (!(this.level instanceof ServerLevel sl)) { + return; + } + final var source = ((BaseCommandBlockAccessor) block).invoker$createSource(sl); if (source == null) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java index 1a54021147e..a27740e9733 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandSourceStackMixin.java @@ -32,6 +32,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.util.TaskChainer; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec2; @@ -54,6 +55,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.commands.CommandSourceStackAccessor; import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor; import org.spongepowered.common.bridge.commands.CommandSourceBridge; @@ -68,11 +70,12 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridge { + //@formatter:off @Shadow @Final private CommandSource source; @Shadow @Final @Mutable private Vec3 worldPosition; @Shadow @Final @Mutable private Vec2 rotation; @Shadow @Final @Mutable private ServerLevel level; - @Shadow @Final @Mutable private int permissionLevel; + @Shadow @Final @Mutable private PermissionSet permissions; @Shadow @Final private Component displayName; @Shadow @Final private String textName; @@ -85,33 +88,35 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg @Shadow @Final private CommandSigningContext signingContext; @Shadow @Final private TaskChainer chatMessageChainer; + //@formatter:on + private Cause impl$cause; @Nullable private Supplier impl$potentialPermissionNode = null; private @Nullable PermissionService impl$permissionService; - @Inject(method = "(Lnet/minecraft/commands/CommandSource;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec2;Lnet/minecraft/server/level/ServerLevel;ILjava/lang/String;Lnet/minecraft/network/chat/Component;Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/world/entity/Entity;ZLnet/minecraft/commands/CommandResultCallback;Lnet/minecraft/commands/arguments/EntityAnchorArgument$Anchor;Lnet/minecraft/commands/CommandSigningContext;Lnet/minecraft/util/TaskChainer;)V", - at = @At("RETURN")) + @Inject(method = "(Lnet/minecraft/commands/CommandSource;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec2;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/server/permissions/PermissionSet;Ljava/lang/String;Lnet/minecraft/network/chat/Component;Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/world/entity/Entity;ZLnet/minecraft/commands/CommandResultCallback;Lnet/minecraft/commands/arguments/EntityAnchorArgument$Anchor;Lnet/minecraft/commands/CommandSigningContext;Lnet/minecraft/util/TaskChainer;)V", + at = @At("RETURN")) private void impl$setCauseOnConstruction( - final CommandSource $$0, - final Vec3 $$1, - final Vec2 $$2, - final ServerLevel $$3, - final int $$4, - final String $$5, - final Component $$6, - final MinecraftServer $$7, - final Entity $$8, - final boolean $$9, - final CommandResultCallback $$10, - final EntityAnchorArgument.Anchor $$11, - final CommandSigningContext $$12, - final TaskChainer $$13, - final CallbackInfo ci + final CommandSource $$0, + final Vec3 $$1, + final Vec2 $$2, + final ServerLevel $$3, + final PermissionSet permissionLevel, + final String $$5, + final Component $$6, + final MinecraftServer $$7, + final Entity $$8, + final boolean $$9, + final CommandResultCallback $$10, + final EntityAnchorArgument.Anchor $$11, + final CommandSigningContext $$12, + final TaskChainer $$13, + final CallbackInfo ci ) { this.impl$cause = PhaseTracker.getInstance().currentCause(); final EventContext context = this.impl$cause.context(); - context.get(EventContextKeys.LOCATION).ifPresent(x ->{ + context.get(EventContextKeys.LOCATION).ifPresent(x -> { this.worldPosition = VecHelper.toVanillaVector3d(x.position()); this.level = (ServerLevel) x.world(); }); @@ -119,11 +124,25 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg context.get(EventContextKeys.ROTATION).ifPresent(x -> this.rotation = new Vec2((float) x.x(), (float) x.y())); context.get(EventContextKeys.SUBJECT).ifPresent(x -> { if (x instanceof PlayerAccessor pa) { - this.permissionLevel = pa.invoker$getPermissionLevel(); + this.permissions = pa.invoker$permissions(); } else if (x instanceof MinecraftServer ms && !ms.isSingleplayer()) { - this.permissionLevel = 4; + this.permissions = PermissionSet.ALL_PERMISSIONS; } }); + this.permissions = (incoming) -> { + if (this.impl$potentialPermissionNode != null) { + final var opLevel = SpongeCommon.server().operatorUserPermissions().level(); + final String perm = this.impl$potentialPermissionNode.get(); + // This will register the permission with the first op level we retrieve. + if (this.impl$permissionService != null) { + SpongePermissions.registerPermission(this.impl$permissionService, perm, opLevel); + } else if (Sponge.isServerAvailable()) { + SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), perm, opLevel); + } + return ((CommandCause) this).hasPermission(perm); + } + return permissionLevel.hasPermission(incoming); + }; } /* @@ -132,15 +151,15 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg * FIRST. That way, we don't overwrite any changes we then need to make. */ @Inject(method = { - "withEntity", - "withPosition", - "withRotation(Lnet/minecraft/world/phys/Vec2;)Lnet/minecraft/commands/CommandSourceStack;", - "withCallback(Lnet/minecraft/commands/CommandResultCallback;)Lnet/minecraft/commands/CommandSourceStack;", - "withSuppressedOutput", - "withPermission", - "withMaximumPermission", - "withAnchor", - "withLevel" + "withEntity", + "withPosition", + "withRotation(Lnet/minecraft/world/phys/Vec2;)Lnet/minecraft/commands/CommandSourceStack;", + "withCallback(Lnet/minecraft/commands/CommandResultCallback;)Lnet/minecraft/commands/CommandSourceStack;", + "withSuppressedOutput", + "withPermission", + "withMaximumPermission", + "withAnchor", + "withLevel" }, at = @At("RETURN")) private void impl$copyPermissionOnCopy(final CallbackInfoReturnable cir) { if (cir.getReturnValue() != (Object) this) { @@ -154,8 +173,8 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg @Override public CommandCause bridge$withCurrentCause() { // Cause is set in ctor. - final CommandCause instance = (CommandCause) CommandSourceStackAccessor.invoker$new(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, - this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + final CommandCause instance = (CommandCause) CommandSourceStackAccessor.invoker$new(this.source, this.worldPosition, this.rotation, this.level, this.permissions, + this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ((CommandSourceStackBridge) instance).bridge$permissionService(this.impl$permissionService); return instance; } @@ -174,9 +193,9 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg private void impl$updateCauseOnWithWorld(final ServerLevel serverWorld, final CallbackInfoReturnable cir) { if (cir.getReturnValue() != (Object) this) { final ServerLocation location = this.impl$cause.context().get(EventContextKeys.LOCATION) - .map(x -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, x.position())) - .orElseGet(() -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, - VecHelper.toVector3d(cir.getReturnValue().getPosition()))); + .map(x -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, x.position())) + .orElseGet(() -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, + VecHelper.toVector3d(cir.getReturnValue().getPosition()))); ((CommandSourceStackBridge) cir.getReturnValue()).bridge$setCause(this.impl$applyToCause(EventContextKeys.LOCATION, location)); } } @@ -186,8 +205,8 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg if (cir.getReturnValue() != (Object) this) { final org.spongepowered.math.vector.Vector3d position = VecHelper.toVector3d(pos); final ServerLocation location = this.impl$cause.context().get(EventContextKeys.LOCATION) - .map(x -> ServerLocation.of(x.world(), position)) - .orElseGet(() -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) cir.getReturnValue().getLevel(), position)); + .map(x -> ServerLocation.of(x.world(), position)) + .orElseGet(() -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) cir.getReturnValue().getLevel(), position)); ((CommandSourceStackBridge) cir.getReturnValue()).bridge$setCause(this.impl$applyToCause(EventContextKeys.LOCATION, location)); } } @@ -200,21 +219,6 @@ public abstract class CommandSourceStackMixin implements CommandSourceStackBridg } } - @Inject(method = "hasPermission", at = @At(value = "HEAD"), cancellable = true) - private void impl$checkPermission(final int opLevel, final CallbackInfoReturnable cir) { - if (this.impl$potentialPermissionNode != null) { - final String perm = this.impl$potentialPermissionNode.get(); - // This will register the permission with the first op level we retrieve. - if (this.impl$permissionService != null) { - SpongePermissions.registerPermission(this.impl$permissionService, perm, opLevel); - } else if (Sponge.isServerAvailable()) { - SpongePermissions.registerPermission(Sponge.server().serviceProvider().permissionService(), perm, opLevel); - } - cir.setReturnValue(((CommandCause) this).hasPermission(perm)); - } - // fall through to the op level check if we haven't set a permission node. - } - @Override public void bridge$setPotentialPermissionNode(final @Nullable Supplier permission) { this.impl$potentialPermissionNode = permission; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index a854ee810ec..3d1b37ee9be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -231,7 +231,7 @@ public Subject subject() { target = "(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;ZJLjava/util/List;ZLnet/minecraft/world/RandomSequences;)Lnet/minecraft/server/level/ServerLevel;" ), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/core/Registry;getValue(Lnet/minecraft/resources/ResourceKey;)Ljava/lang/Object;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;readScoreboard(Lnet/minecraft/world/level/storage/DimensionDataStorage;)V") + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getDataStorage()Lnet/minecraft/world/level/storage/DimensionDataStorage;") )) private void impl$onCreateDefaultLevel(final CallbackInfo ci, @Local final ServerLevelData levelData, @Local final LevelStem levelStem) { ((PrimaryLevelDataBridge) levelData).bridge$populateFromLevelStem(levelStem); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java index 189bba4c36f..12c7981b095 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/ReloadableServerResourcesMixin.java @@ -35,6 +35,7 @@ import net.minecraft.server.ReloadableServerRegistries; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.flag.FeatureFlagSet; import org.spongepowered.api.Sponge; import org.spongepowered.api.registry.RegistryHolder; @@ -55,9 +56,12 @@ public abstract class ReloadableServerResourcesMixin { @SuppressWarnings({"unchecked", "rawtypes"}) @ModifyExpressionValue(method = "loadResources", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerRegistries;reload(Lnet/minecraft/core/LayeredRegistryAccess;Ljava/util/List;Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) - private static CompletableFuture impl$onLoadResources(final CompletableFuture original, - final ResourceManager $$0, final LayeredRegistryAccess $$1, final List> $$2, - final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final int $$5, final Executor $$6, final Executor $$7) { + private static CompletableFuture impl$onLoadResources( + final CompletableFuture original, final ResourceManager $$0, + final LayeredRegistryAccess $$1, final List> $$2, + final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final PermissionSet $$5, + final Executor $$6, final Executor $$7 + ) { return original.thenApply(r -> { final SpongeRegistryHolder spongeRegistryHolder = (SpongeRegistryHolder) $$0; spongeRegistryHolder.setRootMinecraftRegistry(r.layers().compositeAccess()); @@ -81,9 +85,12 @@ public abstract class ReloadableServerResourcesMixin { } @ModifyReturnValue(method = "loadResources", at = @At(value = "RETURN")) - private static CompletableFuture impl$onLoaded(final CompletableFuture original, - final ResourceManager $$0, final LayeredRegistryAccess $$1, final List> $$2, - final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final int $$5, final Executor $$6, final Executor $$7) { + private static CompletableFuture impl$onLoaded( + final CompletableFuture original, final ResourceManager $$0, + final LayeredRegistryAccess $$1, final List> $$2, + final FeatureFlagSet $$3, final Commands.CommandSelection $$4, final PermissionSet $$5, + final Executor $$6, final Executor $$7 + ) { return original.thenApply(r -> { Launch.instance().lifecycle().endEstablishServerRegistries((RegistryHolder) $$0); return r; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index b3b0d496578..cd3f395554e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -31,6 +31,9 @@ import com.mojang.datafixers.util.Pair; import net.minecraft.server.WorldLoader; import net.minecraft.server.packs.resources.CloseableResourceManager; +import net.minecraft.server.permissions.LevelBasedPermissionSet; +import net.minecraft.server.permissions.PermissionLevel; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryHolder; @@ -52,7 +55,11 @@ public abstract class WorldLoaderMixin { final Pair pair = original.call(instance); final CloseableResourceManager resourceManager = pair.getSecond(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - lifecycle.establishServerServices(resourceManager, $$0.functionCompilationLevel()); + var permLevel = $$0.functionCompilationPermissions() == PermissionSet.ALL_PERMISSIONS ? PermissionLevel.OWNERS : PermissionLevel.ALL; + if ($$0.functionCompilationPermissions() instanceof LevelBasedPermissionSet lbps) { + permLevel = lbps.level(); + } + lifecycle.establishServerServices(resourceManager, permLevel); lifecycle.setWorldDataConfiguration(pair.getFirst()); lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); return pair; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java index c54e3ae3e50..0237e7ccbbf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java @@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; import net.minecraft.server.commands.DifficultyCommand; import net.minecraft.world.Difficulty; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.storage.LevelData; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.asm.mixin.Final; @@ -38,7 +39,6 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.server.MinecraftServerAccessor; @Mixin(DifficultyCommand.class) public abstract class DifficultyCommandMixin { @@ -58,7 +58,7 @@ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty } else { final LevelData levelData = source.getLevel().getLevelData(); ((ServerWorldProperties) levelData).setDifficulty((org.spongepowered.api.world.difficulty.Difficulty) (Object) difficulty); - source.getLevel().setSpawnSettings(((MinecraftServerAccessor) SpongeCommon.server()).invoker$isSpawningMonsters()); + source.getLevel().setSpawnSettings(SpongeCommon.server().getWorldData().getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS)); source.getLevel().getPlayers(p -> true).forEach(p -> p.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()))); source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 5a9c64cfd6c..465cd94be95 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -49,12 +49,22 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.random.WeightedList; +import net.minecraft.world.DifficultyInstance; import net.minecraft.world.RandomSequences; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySpawnReason; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.ai.village.poi.PoiType; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.HangingEntity; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerExplosion; @@ -85,6 +95,8 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.Transaction; import org.spongepowered.api.effect.sound.music.MusicDisc; +import org.spongepowered.api.entity.EntityType; +import org.spongepowered.api.entity.projectile.EnderPearl; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -108,6 +120,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.accessor.world.entity.MobAccessor; +import org.spongepowered.common.accessor.world.entity.item.FallingBlockEntityAccessor; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.bridge.data.VanishableBridge; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; @@ -118,6 +132,7 @@ import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.bridge.world.ticks.LevelTicksBridge; import org.spongepowered.common.config.SpongeGameConfigs; +import org.spongepowered.common.entity.projectile.UnknownProjectileSource; import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseContext; @@ -129,6 +144,7 @@ import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; import org.spongepowered.common.world.server.SpongeServerLevelData; +import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3i; import java.util.List; @@ -153,6 +169,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow @Nullable private EndDragonFight dragonFight; @Shadow @Final List players; + @Shadow public abstract DifficultyInstance shadow$getCurrentDifficultyAt(BlockPos p_175649_1_); // @formatter:on @@ -567,4 +584,74 @@ public String toString() { // Weather is per world in Sponge. instance.broadcastAll(packet, this.shadow$dimension()); } + + + @Override + @SuppressWarnings("unchecked") + public E bridge$createEntity(final EntityType type, final Vector3d position, final boolean naturally) throws IllegalArgumentException, IllegalStateException { + if (type == net.minecraft.world.entity.EntityType.PLAYER) { + // Unable to construct these + throw new IllegalArgumentException("A Player cannot be created by the API!"); + } + + net.minecraft.world.entity.Entity entity = null; + final double x = position.x(); + final double y = position.y(); + final double z = position.z(); + final net.minecraft.world.level.Level thisWorld = (net.minecraft.world.level.Level) (Object) this; + // Not all entities have a single World parameter as their constructor + if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); + entity.snapTo(x, y, z); + ((LightningBolt) entity).setVisualOnly(false); + } + // TODO - archetypes should solve the problem of calling the correct constructor + if (type == net.minecraft.world.entity.EntityType.ENDER_PEARL) { + final ArmorStand tempEntity = new ArmorStand(thisWorld, x, y, z); + tempEntity.setPos(tempEntity.getX(), tempEntity.getY() - tempEntity.getEyeHeight(), tempEntity.getZ()); + entity = new ThrownEnderpearl(thisWorld, tempEntity, Items.ENDER_PEARL.getDefaultInstance()); + ((EnderPearl) entity).offer(Keys.SHOOTER, UnknownProjectileSource.UNKNOWN); + } + // Some entities need to have non-null fields (and the easiest way to + // set them is to use the more specialised constructor). + if (type == net.minecraft.world.entity.EntityType.FALLING_BLOCK) { + entity = FallingBlockEntityAccessor.invoker$new(thisWorld, x, y, z, Blocks.SAND.defaultBlockState()); + } + if (type == net.minecraft.world.entity.EntityType.ITEM) { + entity = new ItemEntity(thisWorld, x, y, z, new ItemStack(Blocks.STONE)); + } + + if (entity == null) { + final ResourceKey key = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getKey((net.minecraft.world.entity.EntityType) type); + try { + entity = ((net.minecraft.world.entity.EntityType) type).create(thisWorld, EntitySpawnReason.EVENT); + entity.snapTo(x, y, z); + } catch (final Exception e) { + throw new RuntimeException("There was an issue attempting to construct " + key, e); + } + } + + // TODO - replace this with an actual check + + if (entity instanceof HangingEntity) { + if (!((HangingEntity) entity).survives()) { + throw new IllegalArgumentException("Hanging entity does not survive at the given position: " + position); + } + } + + if (naturally && entity instanceof Mob) { + // Adding the default equipment + final DifficultyInstance difficulty = this.shadow$getCurrentDifficultyAt(new BlockPos((int) x, (int) y, (int) z)); + ((MobAccessor) entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty); + } + + if (entity instanceof Painting) { + // This is default when art is null when reading from NBT, could + // choose a random art instead? + // TODO ? ((Painting) entity).motive = Motive.KEBAB; + } + + return (E) entity; + } + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java index bc577d37306..105a33efbe6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/BaseCommandBlockMixin.java @@ -25,17 +25,12 @@ package org.spongepowered.common.mixin.core.world; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.MessageType; -import net.kyori.adventure.identity.Identity; -import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSource; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BaseCommandBlock; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.api.event.Cause; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import javax.annotation.Nullable; @@ -44,24 +39,8 @@ public abstract class BaseCommandBlockMixin implements CommandSourceProviderBridge, Audience { // @formatter:off - @Shadow public abstract CommandSourceStack createCommandSourceStack(CommandSource var1); - @Shadow @Nullable protected abstract BaseCommandBlock.CloseableCommandBlockSource shadow$createSource(); + @Shadow public abstract CommandSourceStack createCommandSourceStack(ServerLevel level, CommandSource var1); + @Shadow @Nullable protected abstract BaseCommandBlock.CloseableCommandBlockSource shadow$createSource(ServerLevel level); // @formatter:on - - - @Override - public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.createCommandSourceStack(this.shadow$createSource()); - } - - @Override - @SuppressWarnings({"deprecation", "UnstableApiUsage"}) - public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { - final var source = this.shadow$createSource(); - if (source == null) { - return; - } - source.sendSystemMessage(SpongeAdventure.asVanilla(message)); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 75b665d9049..86ef29443ac 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -26,6 +26,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.particles.ParticleOptions; @@ -68,7 +69,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.data.VanishableBridge; import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; @@ -274,10 +274,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "startUsingItem", cancellable = true, - locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", - target = "Lnet/minecraft/world/entity/LivingEntity;useItem:Lnet/minecraft/world/item/ItemStack;")) - private void impl$onSetActiveItemStack(final InteractionHand hand, final CallbackInfo ci, final ItemStack stack) { + target = "Lnet/minecraft/world/entity/LivingEntity;useItem:Lnet/minecraft/world/item/ItemStack;", + opcode = Opcodes.PUTFIELD + )) + private void impl$onSetActiveItemStack(final InteractionHand hand, final CallbackInfo ci, final @Local ItemStack stack) { if (this.shadow$level().isClientSide()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java index 35a889a05ac..b2e7acfcc76 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java @@ -34,7 +34,7 @@ public abstract class ZombifiedPiglinMixin extends MonsterMixin implements AggressiveEntityBridge { // @formatter:off - @Shadow private int remainingPersistentAngerTime; + @Shadow private long persistentAngerEndTime; // @formatter:on @Override @@ -45,9 +45,9 @@ public abstract class ZombifiedPiglinMixin extends MonsterMixin implements Aggre @Override public void bridge$setAngry(boolean angry) { if (angry) { - this.remainingPersistentAngerTime = 400 + this.random.nextInt(400); + this.persistentAngerEndTime = 400 + this.random.nextInt(400); } else { - this.remainingPersistentAngerTime = 0; + this.persistentAngerEndTime = 0; } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 04a0e4f4ba8..023d4477b4b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -31,6 +31,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.util.Unit; @@ -38,6 +39,7 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player.BedSleepingProblem; import net.minecraft.world.food.FoodData; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -94,18 +96,19 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G @Shadow @Final public InventoryMenu inventoryMenu; @Shadow @Final private GameProfile gameProfile; @Shadow public abstract boolean shadow$isSpectator(); - @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract int shadow$getXpNeededForNextLevel(); @Shadow public abstract FoodData shadow$getFoodData(); @Shadow public abstract boolean shadow$isCreative(); @Shadow public abstract String shadow$getScoreboardName(); @Shadow public abstract void shadow$awardStat(ResourceLocation stat); @Shadow public abstract Inventory shadow$getInventory(); + @Shadow public abstract PermissionSet shadow$permissions(); @Shadow public Either shadow$startSleepInBed(final BlockPos param0) { return null; // Shadowed } // @formatter: on + private boolean impl$affectsSpawning = true; protected final boolean impl$isFake = this.bridge$isFakePlayer(); @@ -216,12 +219,12 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G this.shadow$level().playSound(player, x, y, z, sound, category, volume, pitch); } - @Redirect(method = "canUseGameMasterBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getPermissionLevel()I")) - private int impl$checkPermissionForCommandBlock(final net.minecraft.world.entity.player.Player playerEntity) { + @Redirect(method = "canUseGameMasterBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;permissions()Lnet/minecraft/server/permissions/PermissionSet;")) + private PermissionSet impl$checkPermissionForCommandBlock(final Player playerEntity) { if (this instanceof Subject) { - return ((Subject) this).hasPermission(Constants.Permissions.COMMAND_BLOCK_PERMISSION) ? Constants.Permissions.COMMAND_BLOCK_LEVEL : 0; + return ((Subject) this).hasPermission(Constants.Permissions.COMMAND_BLOCK_PERMISSION) ? PermissionSet.ALL_PERMISSIONS : PermissionSet.NO_PERMISSIONS; } else { - return this.shadow$getPermissionLevel(); + return this.shadow$permissions(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index af6d938388c..22fc10c7cf3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -32,7 +32,6 @@ import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -41,7 +40,6 @@ import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.api.event.entity.AttackEntityEvent; @@ -103,7 +101,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 0, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;deflectProjectile(Lnet/minecraft/world/entity/Entity;)Z") )) private float attack$modifyBeforeBaseCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -112,7 +110,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;deflectProjectile(Lnet/minecraft/world/entity/Entity;)Z") )) private float attack$modifyAfterBaseCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -121,7 +119,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 1, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;deflectProjectile(Lnet/minecraft/world/entity/Entity;)Z") )) private float attack$modifyBeforeEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -130,14 +128,15 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 1, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;deflectProjectile(Lnet/minecraft/world/entity/Entity;)Z") )) private float attack$modifyAfterEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null ? damage : tracker.endStep(DamageStepTypes.ENCHANTMENT_COOLDOWN, damage); } - @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V"), slice = @Slice( + @Inject(method = "attack", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;makeSound(Lnet/minecraft/sounds/SoundEvent;)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 0), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"))) private void attack$captureStrongSprint(final Entity target, final CallbackInfo ci) { @@ -163,8 +162,8 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem } @ModifyVariable(method = "attack", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;canCriticalAttack(Lnet/minecraft/world/entity/Entity;)Z"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSweepAttack(ZZZ)Z") )) private float attack$modifyBeforeCriticalHit(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -172,8 +171,8 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem } @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;canCriticalAttack(Lnet/minecraft/world/entity/Entity;)Z"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSweepAttack(ZZZ)Z") )) private float attack$modifyAfterCriticalHit(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -204,9 +203,8 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @WrapWithCondition(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - private boolean attack$preventSound(final Level level, final Entity player, final double x, final double y, final double z, - final SoundEvent sound, final SoundSource source, final float volume, final float pitch) { + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) + private boolean attack$preventSound(Player instance, SoundEvent soundEvent) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null || !tracker.postEvent().isCancelled(); } @@ -218,7 +216,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem this.attack$trackers.removeLast(); } - @WrapOperation(method = "attack", + @WrapOperation(method = "doSweepAttack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D")) private double sweepAttack$fireEvents(final Player self, final Entity sweepTarget, final Operation operation) { @@ -269,14 +267,14 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return distanceSquared; } - @WrapOperation(method = "attack", + @WrapOperation(method = "doSweepAttack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) private float sweepAttack$cancelEnchantedDamage(final Player self, final Entity sweepTarget, final float damage, final DamageSource source, final Operation operation) { return damage; // We already did it above } - @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( + @WrapOperation(method = "doSweepAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;doPostAttackEffects(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)V"))) private void sweepAttack$knockbackModifier( @@ -288,7 +286,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem operation.call(sweepTarget, modifier, dirX, dirZ); } - @WrapOperation(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z"), + @WrapOperation(method = "doSweepAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"))) private boolean sweepAttack$finalDamage( final LivingEntity sweepTarget, final ServerLevel level, final DamageSource source, float damage, @@ -302,7 +300,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return result; } - @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V", shift = At.Shift.AFTER)) + @Inject(method = "itemAttackInteraction", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V", shift = At.Shift.AFTER)) private void attack$captureInventoryChange(final CallbackInfo ci) { PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext().getTransactor().logPlayerInventoryChange((Player) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD); this.inventoryMenu.broadcastChanges(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java index 1ad89d9829b..70ac4854a67 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java @@ -56,6 +56,9 @@ public abstract class MinecartCommandBlockMixin extends AbstractMinecartMixin im @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.commandBlock.createCommandSourceStack(SpongeCommon.server()); + if (this.level() instanceof net.minecraft.server.level.ServerLevel sl) { + return this.commandBlock.createCommandSourceStack(sl, SpongeCommon.server()); + } + return this.commandBlock.createCommandSourceStack(SpongeCommon.server().overworld(), SpongeCommon.server()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java index b1892560878..6eb7efd46ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java @@ -24,15 +24,23 @@ */ package org.spongepowered.common.mixin.core.world.entity.vehicle; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.SubjectProxy; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.mixin.core.world.BaseCommandBlockMixin; -@Mixin(MinecartCommandBlock.MinecartCommandBase.class) +@Mixin(targets = "net.minecraft.world.entity.vehicle.MinecartCommandBlock$MinecartCommandBase") public abstract class MinecartCommandBlock_MinecartCommandBaseMixin extends BaseCommandBlockMixin implements SubjectProxy { // @formatter:off @@ -43,4 +51,25 @@ public abstract class MinecartCommandBlock_MinecartCommandBaseMixin extends Base public Subject subject() { return (Subject) this.this$0; } + + @Override + public CommandSourceStack bridge$getCommandSource(final Cause cause) { + if (!(this.this$0.level() instanceof ServerLevel sl)) { + return null; + } + return this.createCommandSourceStack(sl, this.shadow$createSource(sl)); + } + + @Override + @SuppressWarnings({"deprecation", "UnstableApiUsage"}) + public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { + if (!(this.this$0.level() instanceof ServerLevel sl)) { + return; + } + final var source = this.shadow$createSource(sl); + if (source == null) { + return; + } + source.sendSystemMessage(SpongeAdventure.asVanilla(message)); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java index 6d2628e803d..b6fd2c3435d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java @@ -103,8 +103,8 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements this.impl$primeCause = damageSource; } - @Inject(method = "activateMinecart(IIIZ)V", at = @At("HEAD")) - private void impl$onActivateSetPrimeCauseNotifier(final int x, final int y, final int z, final boolean receivingPower, final CallbackInfo ci) { + @Inject(method = "activateMinecart(Lnet/minecraft/server/level/ServerLevel;IIIZ)V", at = @At("HEAD")) + private void impl$onActivateSetPrimeCauseNotifier(final ServerLevel level, final int x, final int y, final int z, final boolean receivingPower, final CallbackInfo ci) { if (((LevelBridge) this.shadow$level()).bridge$isFake()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index 56621141ff3..2b2139caaa4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -28,27 +28,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.util.ProblemReporter; import net.minecraft.util.RandomSource; import net.minecraft.util.datafix.DataFixers; import net.minecraft.util.datafix.fixes.References; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.entity.EntitySpawnReason; -import net.minecraft.world.entity.LightningBolt; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.decoration.HangingEntity; -import net.minecraft.world.entity.decoration.Painting; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.projectile.ThrownEnderpearl; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.dimension.DimensionType; @@ -58,12 +45,9 @@ import net.minecraft.world.phys.AABB; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.EntityType; -import org.spongepowered.api.entity.projectile.EnderPearl; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -73,13 +57,9 @@ import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.world.entity.MobAccessor; -import org.spongepowered.common.accessor.world.entity.item.FallingBlockEntityAccessor; import org.spongepowered.common.bridge.data.VanishableBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.data.persistence.NBTTranslator; -import org.spongepowered.common.entity.projectile.UnknownProjectileSource; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.DataUtil; import org.spongepowered.math.vector.Vector3d; @@ -105,7 +85,6 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { @Shadow public abstract net.minecraft.resources.ResourceKey shadow$dimension(); @Shadow public abstract DimensionType shadow$dimensionType(); @Shadow public abstract LevelChunk shadow$getChunkAt(BlockPos p_175726_1_); - @Shadow public abstract DifficultyInstance shadow$getCurrentDifficultyAt(BlockPos p_175649_1_); @Shadow public abstract boolean shadow$isRaining(); @Shadow public abstract net.minecraft.world.level.block.entity.@Nullable BlockEntity shadow$getBlockEntity(BlockPos p_175625_1_); @Shadow public abstract RegistryAccess shadow$registryAccess(); @@ -187,74 +166,6 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { return (E) createdEntity; } - @Override - @SuppressWarnings("unchecked") - public E bridge$createEntity(final EntityType type, final Vector3d position, final boolean naturally) throws IllegalArgumentException, IllegalStateException { - if (type == net.minecraft.world.entity.EntityType.PLAYER) { - // Unable to construct these - throw new IllegalArgumentException("A Player cannot be created by the API!"); - } - - net.minecraft.world.entity.Entity entity = null; - final double x = position.x(); - final double y = position.y(); - final double z = position.z(); - final net.minecraft.world.level.Level thisWorld = (net.minecraft.world.level.Level) (Object) this; - // Not all entities have a single World parameter as their constructor - if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { - entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); - entity.snapTo(x, y, z); - ((LightningBolt) entity).setVisualOnly(false); - } - // TODO - archetypes should solve the problem of calling the correct constructor - if (type == net.minecraft.world.entity.EntityType.ENDER_PEARL) { - final ArmorStand tempEntity = new ArmorStand(thisWorld, x, y, z); - tempEntity.setPos(tempEntity.getX(), tempEntity.getY() - tempEntity.getEyeHeight(), tempEntity.getZ()); - entity = new ThrownEnderpearl(thisWorld, tempEntity, Items.ENDER_PEARL.getDefaultInstance()); - ((EnderPearl) entity).offer(Keys.SHOOTER, UnknownProjectileSource.UNKNOWN); - } - // Some entities need to have non-null fields (and the easiest way to - // set them is to use the more specialised constructor). - if (type == net.minecraft.world.entity.EntityType.FALLING_BLOCK) { - entity = FallingBlockEntityAccessor.invoker$new(thisWorld, x, y, z, Blocks.SAND.defaultBlockState()); - } - if (type == net.minecraft.world.entity.EntityType.ITEM) { - entity = new ItemEntity(thisWorld, x, y, z, new ItemStack(Blocks.STONE)); - } - - if (entity == null) { - final ResourceKey key = (ResourceKey) (Object) SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getKey((net.minecraft.world.entity.EntityType) type); - try { - entity = ((net.minecraft.world.entity.EntityType) type).create(thisWorld, EntitySpawnReason.EVENT); - entity.snapTo(x, y, z); - } catch (final Exception e) { - throw new RuntimeException("There was an issue attempting to construct " + key, e); - } - } - - // TODO - replace this with an actual check - - if (entity instanceof HangingEntity) { - if (!((HangingEntity) entity).survives()) { - throw new IllegalArgumentException("Hanging entity does not survive at the given position: " + position); - } - } - - if (naturally && entity instanceof Mob) { - // Adding the default equipment - final DifficultyInstance difficulty = this.shadow$getCurrentDifficultyAt(new BlockPos((int) x, (int) y, (int) z)); - ((MobAccessor) entity).invoker$populateDefaultEquipmentSlots(this.random, difficulty); - } - - if (entity instanceof Painting) { - // This is default when art is null when reading from NBT, could - // choose a random art instead? - // TODO ? ((Painting) entity).motive = Motive.KEBAB; - } - - return (E) entity; - } - @Inject(method = { "getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;", "getEntities(Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java index 549e45c8cb1..5d0547ace32 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntityMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.world.level.block.entity; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BaseCommandBlock; import net.minecraft.world.level.block.entity.CommandBlockEntity; import org.spongepowered.api.event.Cause; @@ -33,15 +34,18 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.level.BaseCommandBlockAccessor; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.permissions.SubjectBridge; // TODO: dualspiral - should this go on the child CommandBlockLogic? @Mixin(CommandBlockEntity.class) -public abstract class CommandBlockEntityMixin implements SubjectBridge, CommandSourceProviderBridge { +public abstract class CommandBlockEntityMixin extends BlockEntityMixin implements SubjectBridge, CommandSourceProviderBridge { + // @formatter:off @Shadow @Final private BaseCommandBlock commandBlock; + // @formatter:on @Override public String bridge$getSubjectCollectionIdentifier() { @@ -55,7 +59,13 @@ public abstract class CommandBlockEntityMixin implements SubjectBridge, CommandS @Override public CommandSourceStack bridge$getCommandSource(final Cause cause) { - return this.commandBlock.createCommandSourceStack((((BaseCommandBlockAccessor) this.commandBlock).invoker$createSource())); + if (this.level instanceof ServerLevel sl) { + return this.commandBlock.createCommandSourceStack(sl, (((BaseCommandBlockAccessor) this.commandBlock).invoker$createSource(sl))); + } + return this.commandBlock.createCommandSourceStack( + SpongeCommon.server().overworld(), + (((BaseCommandBlockAccessor) this.commandBlock).invoker$createSource(SpongeCommon.server().overworld())) + ); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntity_Mixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntity_Mixin.java index 3d54e86e9f4..c3ab676dcb3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntity_Mixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CommandBlockEntity_Mixin.java @@ -24,12 +24,19 @@ */ package org.spongepowered.common.mixin.core.world.level.block.entity; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.level.block.entity.CommandBlockEntity; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.SubjectProxy; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.mixin.core.world.BaseCommandBlockMixin; @Mixin(targets = "net.minecraft.world.level.block.entity.CommandBlockEntity$1") @@ -43,4 +50,25 @@ public abstract class CommandBlockEntity_Mixin extends BaseCommandBlockMixin imp public Subject subject() { return (Subject) this.this$0; } + + @Override + public CommandSourceStack bridge$getCommandSource(final Cause cause) { + if (!(this.this$0.getLevel() instanceof net.minecraft.server.level.ServerLevel serverLevel)) { + return null; + } + return this.createCommandSourceStack(serverLevel, this.shadow$createSource(serverLevel)); + } + + @Override + @SuppressWarnings({"deprecation", "UnstableApiUsage"}) + public void sendMessage(final @NonNull Identity identity, final @NonNull Component message, final @NonNull MessageType type) { + if (!(this.this$0.getLevel() instanceof net.minecraft.server.level.ServerLevel serverLevel)) { + return; + } + final var source = this.shadow$createSource(serverLevel); + if (source == null) { + return; + } + source.sendSystemMessage(SpongeAdventure.asVanilla(message)); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index bee0076bc00..ca3971b549d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -47,6 +47,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -67,7 +68,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.accessor.server.MinecraftServerAccessor; import org.spongepowered.common.accessor.world.level.LevelSettingsAccessor; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; @@ -291,7 +291,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat } else if (server.isSingleplayer()) { level.setSpawnSettings(difficulty != Difficulty.PEACEFUL); } else { - level.setSpawnSettings(((MinecraftServerAccessor) server).invoker$isSpawningMonsters()); + level.setSpawnSettings(server.getWorldData().getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS)); } level.players().forEach(player -> player.connection.send(new ClientboundChangeDifficultyPacket(difficulty, isLocked))); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java index da8b8c93d59..337350d5276 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java @@ -24,10 +24,11 @@ */ package org.spongepowered.common.mixin.tracker.util.thread; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.util.thread.BlockableEventLoop; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.plugin.BasicPluginContext; import org.spongepowered.common.event.tracking.phase.plugin.PluginPhase; @@ -35,23 +36,23 @@ @Mixin(BlockableEventLoop.class) public abstract class BlockableEventLoopMixin_Tracker { - @Redirect(method = "execute", + @WrapOperation(method = "doRunTask", at = @At( value = "INVOKE", target = "Ljava/lang/Runnable;run()V", remap = false)) - private void tracker$callOnMainThreadWithPhaseState(final Runnable runnable) { + private void tracker$callOnMainThreadWithPhaseState(Runnable instance, Operation original) { // This method can be called async while server is stopping // TODO find why this cause a runaway phase during shutdown of the test server if (this.tracker$isServerAndIsServerStopped()/* && !PlatformHooks.INSTANCE.getGeneralHooks().onServerThread() */) { - runnable.run(); + original.call(instance); return; } try (final BasicPluginContext context = PluginPhase.State.SCHEDULED_TASK.createPhaseContext(PhaseTracker.getInstance()) - .source(runnable)) { + .source(instance)) { context.buildAndSwitch(); - runnable.run(); + original.call(instance); } } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 15355cba0b5..2c680abfd3a 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -200,6 +200,9 @@ "minecraft.world.entity.animal.horse.TraderLlamaMixin_API", "minecraft.world.entity.animal.horse.VariantMixin_API", "minecraft.world.entity.animal.horse.ZombieHorseMixin_API", + "minecraft.world.entity.animal.nautilus.AbstractNautilusMixin_API", + "minecraft.world.entity.animal.nautilus.NautilusMixin_API", + "minecraft.world.entity.animal.nautilus.ZombieNautilusMixin_API", "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.sniffer.SnifferMixin_API", "minecraft.world.entity.animal.wolf.WolfMixin_API", @@ -386,10 +389,10 @@ "minecraft.world.level.biome.MobSpawnSettings_MobSpawnCostMixin_API", "minecraft.world.level.biome.MultiNoiseBiomeSourceMixin_API", "minecraft.world.level.biome.TheEndBiomeSourceMixin_API", + "minecraft.world.level.block.CopperGolemStatueBlock_PoseMixin_API", "minecraft.world.level.block.MirrorMixin_API", "minecraft.world.level.block.PortalMixin_API", "minecraft.world.level.block.RotationMixin_API", - "minecraft.world.level.block.CopperGolemStatueBlock_PoseMixin_API", "minecraft.world.level.block.WeatheringCopper_WeatherStateMixin_API", "minecraft.world.level.block.entity.AbstractFurnaceBlockEntityMixin_API", "minecraft.world.level.block.entity.BannerBlockEntityMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 518e6d95987..11a55718acd 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -64,7 +64,6 @@ "server.bossevents.CustomBossEventMixin", "server.commands.BossBarCommandsMixin", "server.commands.DifficultyCommandMixin", - "server.commands.GameRuleCommandMixin", "server.commands.KickCommandMixin", "server.commands.SaveAllCommandMixin", "server.commands.TeleportCommandMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java index e1a7b2c7376..2710e82987a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java @@ -33,6 +33,7 @@ import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.flag.FeatureFlagSet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -44,11 +45,15 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Vanilla { - @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) - private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) + private static ReloadableServerResources impl$onCreateResources( + final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, + final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager + ) { final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); - if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + if (instance.getCommands().getDispatcher() instanceof + final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); } return instance; From 7efb04b38fec2cf11c1d483b69c258f8abecf9f0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 10 Oct 2025 19:59:57 -0400 Subject: [PATCH 392/586] chore(data): reformat and clean up `DataTest.java` --- .../org/spongepowered/test/data/DataTest.java | 101 +++++++++--------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index afaa8009f80..c3c4c1e3bfe 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -139,7 +139,7 @@ import java.util.Set; @Plugin("datatest") -public final class DataTest { +public final class DataTest { private final PluginContainer plugin; @@ -159,32 +159,32 @@ private void onRegisterCommand(final RegisterCommandEvent return CommandResult.success(); }) .build() - , "datatest"); + , "datatest"); final Parameter.Value mimicParameter = Parameter.string().key("mimic_username").optional().build(); event.register(this.plugin, Command - .builder() - .addParameter(mimicParameter) - .executor(context -> { - final ServerPlayer player = context.cause().first(ServerPlayer.class).get(); - final String mimicUsername = context.requireOne(mimicParameter); - this.setPlayerSkin(player, mimicUsername); - return CommandResult.success(); - }) - .build() - , "mimic" + .builder() + .addParameter(mimicParameter) + .executor(context -> { + final ServerPlayer player = context.cause().first(ServerPlayer.class).get(); + final String mimicUsername = context.requireOne(mimicParameter); + this.setPlayerSkin(player, mimicUsername); + return CommandResult.success(); + }) + .build() + , "mimic" ); event.register(this.plugin, Command - .builder() - .addParameter(mimicParameter) - .executor(context -> { - final ServerPlayer player = context.cause().first(ServerPlayer.class).get(); - this.mimic = context.requireOne(mimicParameter); - player.kick(); - return CommandResult.success(); - }) - .build() - , "mimickick" + .builder() + .addParameter(mimicParameter) + .executor(context -> { + final ServerPlayer player = context.cause().first(ServerPlayer.class).get(); + this.mimic = context.requireOne(mimicParameter); + player.kick(); + return CommandResult.success(); + }) + .build() + , "mimickick" ); } @@ -230,15 +230,15 @@ public void testData(final ServerPlayer player) { this.checkOfferData(minecartEntity, Keys.AIRBORNE_VELOCITY_MODIFIER, new Vector3d(2, 0.5, 2)); // falls at ~50% flies at -200% final Entity zombifiedPiglin = world.createEntity(EntityTypes.ZOMBIFIED_PIGLIN.get(), position); - this.checkGetData(zombifiedPiglin, Keys.ANGER_LEVEL, 0); - this.checkOfferData(zombifiedPiglin, Keys.ANGER_LEVEL, 10); + this.checkGetData(zombifiedPiglin, Keys.ANGER_LEVEL, (long) 0); + this.checkOfferData(zombifiedPiglin, Keys.ANGER_LEVEL, (long) 10); final ItemStack goldenApple = ItemStack.of(ItemTypes.ENCHANTED_GOLDEN_APPLE); final List notchAppleEffects = Arrays.asList( - PotionEffect.builder().potionType(PotionEffectTypes.REGENERATION).amplifier(1).ambient(false).duration(Ticks.of(400)).build(), - PotionEffect.builder().potionType(PotionEffectTypes.RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), - PotionEffect.builder().potionType(PotionEffectTypes.FIRE_RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), - PotionEffect.builder().potionType(PotionEffectTypes.ABSORPTION).amplifier(3).ambient(false).duration(Ticks.of(2400)).build()); + PotionEffect.builder().potionType(PotionEffectTypes.REGENERATION).amplifier(1).ambient(false).duration(Ticks.of(400)).build(), + PotionEffect.builder().potionType(PotionEffectTypes.RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), + PotionEffect.builder().potionType(PotionEffectTypes.FIRE_RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), + PotionEffect.builder().potionType(PotionEffectTypes.ABSORPTION).amplifier(3).ambient(false).duration(Ticks.of(2400)).build()); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.SHARPNESS, 5))); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.PROTECTION, 4))); @@ -274,10 +274,10 @@ public void testData(final ServerPlayer player) { final ItemStack shieldStack = ItemStack.of(ItemTypes.SHIELD); this.checkGetListData(shieldStack, Keys.BANNER_PATTERN_LAYERS, Collections.emptyList()); - this.checkOfferListData(shieldStack, Keys.BANNER_PATTERN_LAYERS,pattern); + this.checkOfferListData(shieldStack, Keys.BANNER_PATTERN_LAYERS, pattern); final ItemStack bannerStack = ItemStack.of(ItemTypes.RED_BANNER); - this.checkGetListData(bannerStack, Keys.BANNER_PATTERN_LAYERS, Collections.emptyList()); + this.checkGetListData(bannerStack, Keys.BANNER_PATTERN_LAYERS, Collections.emptyList()); this.checkOfferListData(bannerStack, Keys.BANNER_PATTERN_LAYERS, pattern); world.setBlock(blockPos, BlockTypes.RED_BANNER.get().defaultState()); @@ -286,8 +286,8 @@ public void testData(final ServerPlayer player) { // Keys.BASE_COLOR - this.checkGetData(sheep, Keys.BASE_SIZE, (double)0.9f); - this.checkGetData(player, Keys.BASE_SIZE, (double)0.6f); + this.checkGetData(sheep, Keys.BASE_SIZE, (double) 0.9f); + this.checkGetData(player, Keys.BASE_SIZE, (double) 0.6f); final Entity donkey = world.createEntity(EntityTypes.DONKEY.get(), position); final Entity wolf = world.createEntity(EntityTypes.WOLF.get(), position); @@ -313,7 +313,7 @@ public void testData(final ServerPlayer player) { // TODO Keys.BLOCK_LIGHT - final Entity fallingBlock = world.createEntity(EntityTypes.FALLING_BLOCK.get(), position.add(0,5,0)); + final Entity fallingBlock = world.createEntity(EntityTypes.FALLING_BLOCK.get(), position.add(0, 5, 0)); final BlockState sandState = BlockTypes.SAND.get().defaultState(); this.checkOfferData(fallingBlock, Keys.BLOCK_STATE, sandState); this.checkOfferData(minecartEntity, Keys.BLOCK_STATE, dirtState); @@ -485,14 +485,14 @@ public void testData(final ServerPlayer player) { // TODO DisplayNames include font this.checkGetData(jungleAxe, Keys.DISPLAY_NAME, - Component.translatable("chat.square_brackets").args(Component.empty().append(Component.text("Jungle Axe")).decorate(TextDecoration.ITALIC)) - .color(NamedTextColor.WHITE).hoverEvent(jungleAxe.asImmutable().asHoverEvent())); + Component.translatable("chat.square_brackets").args(Component.empty().append(Component.text("Jungle Axe")).decorate(TextDecoration.ITALIC)) + .color(NamedTextColor.WHITE).hoverEvent(jungleAxe.asImmutable().asHoverEvent())); this.checkGetData(shulkerBullet, Keys.DISPLAY_NAME, Component.text("Angry Shulker Bullet") - .hoverEvent(HoverEvent.showEntity(ResourceKey.minecraft("shulker_bullet"), shulkerBullet.uniqueId(), Component.text("Angry Shulker Bullet"))) - .insertion(shulkerBullet.uniqueId().toString())); + .hoverEvent(HoverEvent.showEntity(ResourceKey.minecraft("shulker_bullet"), shulkerBullet.uniqueId(), Component.text("Angry Shulker Bullet"))) + .insertion(shulkerBullet.uniqueId().toString())); this.checkGetData(sheep, Keys.DISPLAY_NAME, Component.text("A sheep") - .hoverEvent(HoverEvent.showEntity(ResourceKey.minecraft("sheep"), sheep.uniqueId(), Component.text("A sheep"))) - .insertion(sheep.uniqueId().toString())); // Set with CUSTOM_NAME + .hoverEvent(HoverEvent.showEntity(ResourceKey.minecraft("sheep"), sheep.uniqueId(), Component.text("A sheep"))) + .insertion(sheep.uniqueId().toString())); // Set with CUSTOM_NAME world.setBlock(blockPos, BlockTypes.CHEST.get().defaultState()); this.checkGetData(location, Keys.CUSTOM_NAME, null); this.checkGetData(location, Keys.DISPLAY_NAME, Component.translatable("container.chest")); @@ -554,8 +554,8 @@ public void testData(final ServerPlayer player) { this.checkOfferData(tntEntity, Keys.EXPLOSION_RADIUS, 1f); - this.checkGetData(player, Keys.EYE_HEIGHT, (double)1.62f); - this.checkGetData(sheep, Keys.EYE_HEIGHT, (double)(1.3f * 0.95f)); + this.checkGetData(player, Keys.EYE_HEIGHT, (double) 1.62f); + this.checkGetData(sheep, Keys.EYE_HEIGHT, (double) (1.3f * 0.95f)); this.checkGetData(sheep, Keys.EYE_POSITION, position.add(0, (double) (1.3f * 0.95f), 0)); @@ -594,7 +594,7 @@ public void testData(final ServerPlayer player) { // TODO Keys.FLUID_TANK_CONTENTS - this.checkGetData(player, Keys.FLYING_SPEED, (double)0.05f); + this.checkGetData(player, Keys.FLYING_SPEED, (double) 0.05f); this.checkOfferData(player, Keys.FOOD_LEVEL, 0); this.checkOfferData(player, Keys.FOOD_LEVEL, 20); @@ -1292,9 +1292,9 @@ public void testData(final ServerPlayer player) { // Keys.TRACKS_OUTPUT final TradeOffer tradeOffer = TradeOffer.builder() - .firstBuyingItem(ItemStack.of(ItemTypes.EMERALD)) - .sellingItem(jungleAxe) - .build(); + .firstBuyingItem(ItemStack.of(ItemTypes.EMERALD)) + .sellingItem(jungleAxe) + .build(); this.checkOfferListData(villager, Keys.TRADE_OFFERS, Arrays.asList(tradeOffer)); final Entity hooman = world.createEntity(EntityTypes.HUMAN.get(), position); @@ -1421,11 +1421,11 @@ private void checkGetWeightedData(final DataHolder holder, final Key actual = gotValue.get().get(new Random()); if (!Objects.deepEquals(actual.toArray(), expected.toArray())) { this.plugin.logger().error("Value differs on {} for {}.\nExpected: {}\nActual: {}", DataTest.getHolderName(holder), - key.key().asString(), expected, actual); + key.key().asString(), expected, actual); } } else { this.plugin.logger().error("Value is missing on {} for {}.\nExpected: {}", DataTest.getHolderName(holder), - key.key().asString(), expected); + key.key().asString(), expected); } } @@ -1449,7 +1449,7 @@ private void checkData(final DataHolder holder, final String key, final T ex if (actualValue != null) { if (!Objects.equals(actualValue, expectedValue)) { this.plugin.logger().error("Value differs on {} for {}.\nExpected: {}\nActual: {}", DataTest.getHolderName(holder), key, - expectedValue, actualValue); + expectedValue, actualValue); } } else if (expectedValue != null) { this.plugin.logger().error("Value is missing on {} for {}.\nExpected: {}", DataTest.getHolderName(holder), key, expectedValue); @@ -1466,11 +1466,10 @@ private static String getHolderName(final DataHolder holder) { return String.format("%s[%s]", holder.getClass().getSimpleName(), value); } - public void setPlayerSkin(final DataHolder.Mutable player, final String mimicUsername) - { + public void setPlayerSkin(final DataHolder.Mutable player, final String mimicUsername) { final GameProfile profile = Sponge.server().gameProfileManager().profile(mimicUsername).join(); final Optional skinProperty = - profile.properties().stream().filter(prop -> prop.name().equals(ProfileProperty.TEXTURES)).findFirst(); + profile.properties().stream().filter(prop -> prop.name().equals(ProfileProperty.TEXTURES)).findFirst(); player.offer(Keys.SKIN_PROFILE_PROPERTY, skinProperty.get()); } } From 4cbcea8bd5b272835946653e7e3f351d6cf57a8d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 10 Oct 2025 20:00:39 -0400 Subject: [PATCH 393/586] fix(server): fix player crash on login with effects Fixes: MC-302672 See: https://bugs.mojang.com/browse/MC-302672 --- .../mixin/core/server/level/ServerPlayerMixin.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index ec91e056274..fa85628ffaf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -1052,4 +1052,15 @@ private boolean isPvpAllowed() { private boolean impl$skipUnserializableRootVehicle(final Entity instance) { return instance.hasExactlyOnePlayerPassenger() && !((TransientBridge) instance).bridge$isTransient(); } + + /** + * Fixes MC-302672 + */ + @WrapOperation(method = "onEffectAdded", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) + private void impl$onEffectAdded(ServerGamePacketListenerImpl instance, Packet packet, Operation original) { + if (instance == null) { + return; + } + original.call(instance, packet); + } } From f9faf4050adf16a887c2f28bf3638b2fcf4cff49 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 13 Oct 2025 20:58:40 +0200 Subject: [PATCH 394/586] Update NeoForge (remove SecureJar). Fix #4246 --- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 38 +++++++++++++++++++ neoforge/gradle.properties | 2 +- .../SpongeNeoDependencyLocator.java | 6 +-- .../moddiscovery/SpongeNeoModLocator.java | 3 +- .../moddiscovery/reader/PluginFileParser.java | 5 +-- .../NeoAccessWidenerTransformer.java | 8 ++-- .../NeoSuperclassChangeTransformer.java | 8 ++-- 8 files changed, 54 insertions(+), 18 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2c2be61ec21..ddc350d40f9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ mixin = "0.8.7" mixinextras = "0.5.0" modlauncher = "10.2.2" securemodules = "2.2.22" -fancymodloader = "10.0.14" +fancymodloader = "10.0.21" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7ffdb41ee0c..1d64d4aec81 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3063,6 +3063,14 @@ + + + + + + + + @@ -6144,6 +6152,20 @@ + + + + + + + + + + + + + + @@ -6270,6 +6292,14 @@ + + + + + + + + @@ -6366,6 +6396,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index d0545202229..66656a03bc3 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.10.6-beta +neoForgeVersion=21.10.16-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java index b5817886024..21e9d21d1e3 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; -import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.locating.IDependencyLocator; @@ -71,9 +71,9 @@ public void scanMods(final List loadedMods, final IDiscoveryPipeline p final Path path = library.file(); SpongeNeoDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - final SecureJar jar; + final JarContents jar; try { - jar = SecureJar.from(path); + jar = JarContents.ofPath(path); } catch (IOException e) { throw new RuntimeException("Failed to create jar from " + path, e); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java index b7cdce0589f..15f591911cc 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java @@ -24,7 +24,6 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery; -import net.neoforged.fml.classloading.SecureJar; import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLPaths; @@ -84,7 +83,7 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) } catch (Exception ignored) {} if (modFile == null) { // fallback to game library - modFile = IModFile.create(SecureJar.from(jarContents), JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes); + modFile = IModFile.create(jarContents, JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes); } pipeline.addModFile(modFile); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java index 0cf129c9ad7..49db57a80a9 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java @@ -24,7 +24,6 @@ */ package org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader; -import net.neoforged.fml.classloading.SecureJar; import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.jarcontents.JarResource; import net.neoforged.fml.loading.moddiscovery.ModFile; @@ -79,8 +78,8 @@ public static IModFile newPluginInstance(final JarContents contents, final ModFi return null; } - final ModJarMetadata mjm = new ModJarMetadata(contents); - final IModFile modFile = IModFile.create(SecureJar.from(contents, mjm), PluginFileParser::parsePluginMetadata, attributes); + final ModJarMetadata mjm = new ModJarMetadata(); + final IModFile modFile = new ModFile(contents, mjm, PluginFileParser::parsePluginMetadata, attributes); mjm.setModFile(modFile); return modFile; } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java index dbfbb01d1a8..c9e40cb4a85 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoAccessWidenerTransformer.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.transformation; -import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.moddiscovery.ModFileInfo; import net.neoforged.neoforgespi.transformation.ClassProcessor; @@ -68,14 +68,14 @@ public ComputeFlags processClass(final TransformationContext context) { protected Collection collectResources() { final Collection resources = new ArrayList<>(); for (ModFileInfo fileInfo : FMLLoader.getCurrent().getLoadingModList().getModFiles()) { - final SecureJar jar = fileInfo.getFile().getSecureJar(); - final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + final JarContents jar = fileInfo.getFile().getContents(); + final Attributes attributes = jar.getManifest().getMainAttributes(); final String attribute = attributes.getValue(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); if (attribute != null) { for (final String path : attribute.split(",")) { try { - resources.add(jar.contents().findFile(path).get().toURL()); + resources.add(jar.findFile(path).get().toURL()); } catch (final Exception e) { LOGGER.warn("Failed to locate access widener {} from {}", path, fileInfo.getFile().getFileName(), e); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java index 240c1000fad..012ec22ad78 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/transformation/NeoSuperclassChangeTransformer.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.transformation; -import net.neoforged.fml.classloading.SecureJar; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.moddiscovery.ModFileInfo; import net.neoforged.neoforgespi.transformation.ClassProcessor; @@ -59,14 +59,14 @@ public ComputeFlags processClass(final TransformationContext context) { protected Collection collectResources() { final Collection resources = new ArrayList<>(); for (ModFileInfo fileInfo : FMLLoader.getCurrent().getLoadingModList().getModFiles()) { - final SecureJar jar = fileInfo.getFile().getSecureJar(); - final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); + final JarContents jar = fileInfo.getFile().getContents(); + final Attributes attributes = jar.getManifest().getMainAttributes(); final String attribute = attributes.getValue(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); if (attribute != null) { for (final String path : attribute.split(",")) { try { - resources.add(jar.contents().findFile(path).get().toURL()); + resources.add(jar.findFile(path).get().toURL()); } catch (final Exception e) { LOGGER.warn("Failed to locate superclass changer {} from {}", path, fileInfo.getFile().getFileName(), e); } From cc43c438b083f5779ba78666842da39729acffc8 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 17 Oct 2025 17:43:45 +0200 Subject: [PATCH 395/586] Pass loader close callback to FML --- .../neoforge/applaunch/plugin/NeoForgePluginPlatform.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java index 77e6a125c31..4daeaaabd44 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java @@ -24,6 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.plugin; +import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; import org.spongepowered.common.applaunch.AppLaunch; @@ -108,6 +109,6 @@ public List pluginDirectories() { @Override public void addLoaderCloseCallback(AutoCloseable closeable) { - // TODO FML + FMLLoader.getCurrent().addCloseCallback(closeable); } } From 0c84059a8541362612f7374691f62ccf9cc10282 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 17 Oct 2025 21:46:06 +0200 Subject: [PATCH 396/586] Update badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e5f5737eb1a..e76e13f6f01 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeVanilla 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeForge 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeNeo 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) ## Prerequisites From 1913408abb966785131f95747d259feba2e48885 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 18 Oct 2025 14:07:22 +0200 Subject: [PATCH 397/586] Fix plugins not receiving events on Forge We'll have to rework the dual bus too --- .../launch/plugin/PluginModContainer.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index dede8de6af1..e20021a86a3 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -25,7 +25,8 @@ package org.spongepowered.forge.launch.plugin; import com.google.inject.Injector; -import net.minecraftforge.eventbus.internal.Event; +import net.minecraftforge.eventbus.api.bus.BusGroup; +import net.minecraftforge.eventbus.api.bus.EventBus; import net.minecraftforge.fml.Logging; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; @@ -38,6 +39,7 @@ import net.minecraftforge.forgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.api.Sponge; import org.spongepowered.common.inject.plugin.PluginGuice; import org.spongepowered.common.launch.Launch; import org.spongepowered.plugin.metadata.model.PluginDependency; @@ -49,6 +51,7 @@ public final class PluginModContainer extends ModContainer { private static final Logger LOGGER = LogManager.getLogger(); private final ModFileScanData scanResults; + private final BusGroup eventBusGroup; private Object modInstance; private final Class modClass; private final CountDownLatch initializationLock; @@ -58,6 +61,7 @@ public PluginModContainer(IModInfo info, String className, ModFileScanData modFi LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", className); this.scanResults = modFileScanResults; this.activityMap.put(ModLoadingStage.CONSTRUCT, this::constructPlugin); + this.eventBusGroup = BusGroup.create("modBusFor" + info.getModId()); this.contextExtension = () -> null; this.initializationLock = new CountDownLatch(1); @@ -71,14 +75,6 @@ public PluginModContainer(IModInfo info, String className, ModFileScanData modFi } } - @Override - public void dispatchConfigEvent(IConfigEvent event) { - } - -// private void onEventFailed(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable) { -// LOGGER.error(new EventBusErrorMessage(event, i, iEventListeners, throwable)); -// } - private void constructPlugin() { try { LOGGER.trace(Logging.LOADING, "Loading plugin instance {} of type {}", getModId(), this.modClass.getName()); @@ -100,7 +96,7 @@ private void constructPlugin() { final Injector pluginInjector = PluginGuice.create(pluginContainer, this.modClass, Launch.instance().lifecycle().platformInjector()); this.modInstance = pluginInjector.getInstance(this.modClass); pluginContainer.setInjector(pluginInjector); -// ((ForgeEventManager) MinecraftForge.EVENT_BUS).registerListeners(pluginContainer, this.modInstance); + Sponge.eventManager().registerListeners(pluginContainer, this.modInstance); LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), this.modClass.getName()); @@ -130,9 +126,11 @@ public Object getMod() { return this.modInstance; } - protected void acceptEvent(final T e) { + @Override + protected void acceptEvent(final T e) { try { LOGGER.trace(Logging.LOADING, "Firing event for modid {} : {}", this.getModId(), e); + IModBusEvent.getBus(this.eventBusGroup, (Class) e.getClass()).post(e); LOGGER.trace(Logging.LOADING, "Fired event for modid {} : {}", this.getModId(), e); } catch (Throwable t) { LOGGER.error(Logging.LOADING, "Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); @@ -140,6 +138,11 @@ protected void acceptEvent(final T e) { } } + @Override + public void dispatchConfigEvent(final IConfigEvent event) { + EventBus.create(this.eventBusGroup, event.self().getClass()).post(event.self()); + } + private void waitForInitialization() { try { this.initializationLock.await(); From fba3c3abc23cfd28d4c1eb285bf2908155d57933 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 20 Oct 2025 18:16:00 +0300 Subject: [PATCH 398/586] Fix PufferfishMixin mistakenly checking for invisiblity rather than vanish --- .../mixin/core/world/entity/animal/PufferfishMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java index 00b5dad232d..69bdc94b064 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java @@ -43,7 +43,7 @@ public class PufferfishMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isCreative()Z")) private static boolean impl$considerVanishedPlayers(final Player player, final Operation operation) { if (player instanceof VanishableBridge vb) { - if (vb.bridge$isInvisible() && vb.bridge$vanishState().untargetable()) { + if (vb.bridge$vanishState().untargetable()) { return false; } } @@ -58,7 +58,7 @@ public class PufferfishMixin { final LivingEntity entity, final ServerLevel level ) { if (entity instanceof VanishableBridge vb) { - if (vb.bridge$isInvisible() && vb.bridge$vanishState().untargetable()) { + if (vb.bridge$vanishState().untargetable()) { // this is inverted because we want to return true to signify the "entity type is not scary" return true; } From 89fed143d12d663efad163b3892ff985ef287ae0 Mon Sep 17 00:00:00 2001 From: aromaa Date: Mon, 20 Oct 2025 18:17:35 +0300 Subject: [PATCH 399/586] Fix VanishedFilteringSynchronizer mistakenly checking for invisiblity rather than vanish --- .../common/data/datasync/VanishedFilteringSynchronizer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java index 79365096ecd..4e8b863a9ff 100644 --- a/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java +++ b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java @@ -41,7 +41,7 @@ public record VanishedFilteringSynchronizer( @Override public void sendToTrackingPlayers(Packet var1) { if (this.ref.get() instanceof VanishableBridge vb) { - if (!vb.bridge$isInvisible()) { + if (!vb.bridge$vanishState().invisible()) { this.proxy.sendToTrackingPlayers(var1); } return; @@ -52,7 +52,7 @@ public void sendToTrackingPlayers(Packet var1) @Override public void sendToTrackingPlayersAndSelf(Packet var1) { if (this.ref.get() instanceof VanishableBridge vb) { - if (!vb.bridge$isInvisible()) { + if (!vb.bridge$vanishState().invisible()) { this.proxy.sendToTrackingPlayersAndSelf(var1); } return; @@ -63,7 +63,7 @@ public void sendToTrackingPlayersAndSelf(Packet var1, Predicate var2) { if (this.ref.get() instanceof VanishableBridge vb) { - if (!vb.bridge$isInvisible()) { + if (!vb.bridge$vanishState().invisible()) { this.proxy.sendToTrackingPlayersFiltered(var1, var2); } return; From aa0fd795e77b7efdaa339799524b2c773a47c319 Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 21 Oct 2025 19:37:55 +0300 Subject: [PATCH 400/586] Fix ChunkManager#valid --- .../common/mixin/core/server/level/DistanceManagerMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java index ca4bf8767a8..f3ea9e10d29 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java @@ -62,7 +62,7 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { final var bridgeTicket = (TicketBridge) ticket; final var tickets = this.ticketStorage.getTickets(bridgeTicket.bridge$chunkPosition()); if (tickets != null && tickets.contains(nativeTicket)) { - return nativeTicket.isTimedOut(); + return !nativeTicket.isTimedOut(); } return false; } From e90cb4ae9c38cb5143fb4fceb95a0b16e790603b Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 21 Oct 2025 19:39:15 +0300 Subject: [PATCH 401/586] Fix TicketType flags --- .../common/world/server/SpongeTicketTypeBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java index 5abaf5ecb3b..9a522550451 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeTicketTypeBuilder.java @@ -77,8 +77,9 @@ public TicketType build() { if (this.comparator == null) { this.comparator = (v1, v2) -> 0; } - // This will load and simulate, but not persist nor keep the dimension active. - final var flag = 1 << 2 & 1 << 4; + final var flag = net.minecraft.server.level.TicketType.FLAG_LOADING + | net.minecraft.server.level.TicketType.FLAG_SIMULATION + | net.minecraft.server.level.TicketType.FLAG_KEEP_DIMENSION_ACTIVE; final var timeout = this.lifetime.isInfinite() ? Constants.ChunkTicket.INFINITE_TIMEOUT : this.lifetime.ticks(); return (TicketType) (Object) new net.minecraft.server.level.TicketType(timeout,flag); } From 54eb078f0ca9de45c0590b51014050b1687527a0 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 22 Oct 2025 22:23:13 +0200 Subject: [PATCH 402/586] Re-enable spotless CI for Forge --- .github/workflows/check-spotless.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-spotless.yaml b/.github/workflows/check-spotless.yaml index acbdc2e8064..5919a3117ef 100644 --- a/.github/workflows/check-spotless.yaml +++ b/.github/workflows/check-spotless.yaml @@ -11,5 +11,5 @@ jobs: uses: SpongePowered/.github/.github/workflows/shared-check-spotless.yaml@master with: runtime_version: 21 - extra_gradle_params: "-Pprojects=vanilla,neoforge,testplugins" + extra_gradle_params: "-Pprojects=vanilla,forge,neoforge,testplugins" secrets: inherit From 468c92b7284ff08f270a5b2b3c967d7cc539a84a Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Wed, 22 Oct 2025 23:51:30 +0300 Subject: [PATCH 403/586] Fix incorrect usages of MessageFormat.format (#4239) --- .../common/item/recipe/ingredient/SpongeIngredient.java | 3 +-- .../api/minecraft/server/packs/PackResourcesMixin_API.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index 85395c5ade9..0c264b19b9c 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -39,7 +39,6 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.item.util.ItemStackUtil; -import java.text.MessageFormat; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -152,7 +151,7 @@ public static SpongeIngredient spongeFromPredicate(ResourceKey key, Predicate resource(final PackType root, final ResourcePath path default Resource requireResource(final PackType root, final ResourcePath path) throws IOException { final Resource resource = this.api$createResource(root, path); if (resource == null) { - throw new NoSuchElementException(MessageFormat.format("Pack type {} does not contain a resource at {}", root, path)); + throw new NoSuchElementException(MessageFormat.format("Pack type {0} does not contain a resource at {1}", root, path)); } return resource; } From 2b2cadd489e27cd18395874ac81ef6cee35f4a22 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sat, 25 Oct 2025 19:09:21 +0300 Subject: [PATCH 404/586] Revert Keys.COLOR supports removal in 59f1841 --- .../common/data/provider/item/stack/PotionItemStackData.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java index f5e0c305659..77f83375f87 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/PotionItemStackData.java @@ -30,6 +30,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.PotionContents; import org.spongepowered.api.data.Keys; @@ -57,6 +58,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> Color.ofRgb(h.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor())) .set((h, v) -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.of(v.rgb()), contents.customEffects(), contents.customName()))) .delete(h -> h.update(DataComponents.POTION_CONTENTS, PotionContents.EMPTY, contents -> new PotionContents(contents.potion(), Optional.empty(), contents.customEffects(), contents.customName()))) + .supports(h -> h.getItem() == Items.POTION || h.getItem() == Items.SPLASH_POTION || h.getItem() == Items.LINGERING_POTION || h.getItem() == Items.TIPPED_ARROW) .create(Keys.CUSTOM_POTION_EFFECTS) .get(h -> { final List effects = h.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).customEffects(); From 5ff032c74bba61c52920b6f43f29852a3799f122 Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Sat, 25 Oct 2025 19:14:42 +0300 Subject: [PATCH 405/586] Push scoped holder for RegisterRegistryEvent default values populators (#4236) * push scoped holder for RegisterRegistryEvent default values populators * properly log exception --- .../AbstractRegisterRegistryEvent.java | 16 ++++++++++++++-- .../common/event/tracking/PhaseTracker.java | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java index a3e1bf2c4af..8b79eaa9d5b 100644 --- a/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java +++ b/src/main/java/org/spongepowered/common/event/lifecycle/AbstractRegisterRegistryEvent.java @@ -36,6 +36,8 @@ import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.registry.RegistryLoader; import org.spongepowered.common.registry.SpongeRegistryHolder; @@ -68,7 +70,7 @@ public RegistryType register(final ResourceKey key, final boolean isDynam final SpongeRegistryHolder holder = this.getHolder(); final RegistryType type = RegistryType.of(RegistryRoots.SPONGE, key); - holder.createRegistry(type, defaultValues, isDynamic); + holder.createRegistry(type, () -> this.wrapWithScopedHolder(type, holder, defaultValues), isDynamic); return type; } @@ -81,10 +83,20 @@ public RegistryType register(final ResourceKey key, final boolean isDynam final SpongeRegistryHolder holder = this.getHolder(); final RegistryType type = RegistryType.of(RegistryRoots.SPONGE, key); - holder.createRegistry(type, defaultValues, isDynamic, dependencies); + holder.createRegistry(type, actualHolder -> this.wrapWithScopedHolder(type, holder, () -> defaultValues.apply(actualHolder)), isDynamic, dependencies); return type; } + private Map wrapWithScopedHolder(final RegistryType registry, final SpongeRegistryHolder holder, final Supplier> defaultValues) { + return PhaseTracker.getInstance().switchStartupRegistryHolder( + holder, defaultValues, + (exception) -> { + // If we don't catch it, vanilla will shut the server with "Failed to load datapacks" + SpongeCommon.logger().error("Could not supply default values for registry {}", registry.toString(), exception); + return Map.of(); + }); + } + protected abstract SpongeRegistryHolder getHolder(); public static final class GameScopedImpl extends AbstractRegisterRegistryEvent implements RegisterRegistryEvent.GameScoped { diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 062626d1204..5fc3a98df9f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -82,6 +82,8 @@ import java.util.StringJoiner; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; +import java.util.function.Supplier; /** * The core state machine of Sponge. Acts a as proxy between various engine objects by processing actions through @@ -873,7 +875,22 @@ public CauseStackManager apiAccess() { return this.api; } - public void startupRegistryHolder(final RegistryHolder holder) { + public T switchStartupRegistryHolder( + final SpongeRegistryHolder holder, final Supplier valueSupplier, + final Function exceptionalValueSupplier + ) { + final @Nullable SpongeRegistryHolder previousHolder = this.startupRegistryHolder(); + try { + this.startupRegistryHolder(holder); + return valueSupplier.get(); + } catch (final RuntimeException e) { + return exceptionalValueSupplier.apply(e); + } finally { + this.startupRegistryHolder(previousHolder); + } + } + + public void startupRegistryHolder(final @Nullable RegistryHolder holder) { if (holder instanceof SpongeRegistryHolder srh) { this.startupRegistryHolder = srh; } else { From a6f85372cdf99f191841ca709674538b43799120 Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Sat, 25 Oct 2025 19:19:22 +0300 Subject: [PATCH 406/586] Fix SOE from ResourceKey#compareTo (#4238) * fix ResourceKey#compareTo SOE * overwrite ResourceLocation#compareTo to use adventure comparator * overwrite synthetic ResourceLocation#compareTo(Object) --- .../resources/ResourceLocationMixin_API.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java index 45fe71f93a4..d6ff707896e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java @@ -31,6 +31,7 @@ import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface.Remap; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @Mixin(ResourceLocation.class) @@ -45,6 +46,15 @@ public abstract class ResourceLocationMixin_API { @Shadow public abstract String shadow$getPath(); // @formatter:on + /** + * @author MrHell228 - October 6th, 2025 + * @reason Delegate synthetic method to #compareTo(Key) to avoid CCE in case Key is not a ResourceLocation + */ + @Overwrite + public int compareTo(final Object obj) { + return ((Key) this).compareTo((Key) obj); + } + public String adventure$namespace() { return this.shadow$getNamespace(); } @@ -52,8 +62,4 @@ public abstract class ResourceLocationMixin_API { public String adventure$value() { return this.shadow$getPath(); } - - public int adventure$compareTo(Key o) { - return -o.compareTo((Key) this); - } } From c099f1ae50fb2263b18eeed068215a4ea13bc775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Sat, 25 Oct 2025 21:01:41 +0300 Subject: [PATCH 407/586] Adapt modifications of GameProfile PropertyMap to the new immutable design (#4248) * Adapt modifications of GameProfile PropertyMap to the new immutable design * Add forgotten param 'final' --- .../world/entity/player/PlayerBridge.java | 3 ++ .../provider/entity/ServerPlayerData.java | 10 +++++- .../entity/living/human/HumanEntity.java | 34 +++++++++++++++---- .../core/world/entity/player/PlayerMixin.java | 8 ++++- ...oginPacketListenerImplMixin_IpForward.java | 8 ++++- 5 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/player/PlayerBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/player/PlayerBridge.java index 9fc379537ab..22a36c4021f 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/player/PlayerBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/player/PlayerBridge.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.bridge.world.entity.player; +import com.mojang.authlib.GameProfile; import net.kyori.adventure.bossbar.BossBar; public interface PlayerBridge { @@ -43,4 +44,6 @@ public interface PlayerBridge { void bridge$addActiveBossBar(BossBar bar); void bridge$removeActiveBossBar(BossBar bar); + + void bridge$setGameProfile(GameProfile profile); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java index 80048ed5607..86d6fedc4bd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ServerPlayerData.java @@ -24,7 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; +import com.google.common.collect.HashMultimap; +import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; @@ -48,6 +51,7 @@ import org.spongepowered.common.accessor.stats.StatsCounterAccessor; import org.spongepowered.common.bridge.server.level.ServerPlayerBridge; import org.spongepowered.common.bridge.server.level.ServerPlayerEntityHealthScaleBridge; +import org.spongepowered.common.bridge.world.entity.player.PlayerBridge; import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.profile.SpongeProfileProperty; @@ -81,7 +85,11 @@ public static void register(final DataProviderRegistrator registrator) { return new SpongeProfileProperty(properties.iterator().next()); }) .set((h ,v) -> { - h.getGameProfile().properties().replaceValues(ProfileProperty.TEXTURES, Collections.singletonList(((SpongeProfileProperty)v).asProperty())); + final var profile = h.getGameProfile(); + final var mutableProperties = HashMultimap.create(profile.properties()); + mutableProperties.replaceValues(ProfileProperty.TEXTURES, Collections.singletonList(((SpongeProfileProperty)v).asProperty())); + + ((PlayerBridge) h).bridge$setGameProfile(new GameProfile(profile.id(), profile.name(), new PropertyMap(mutableProperties))); ServerPlayerData.resendProfile(h); }) .create(Keys.SPECTATOR_TARGET) diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 4433905b18d..5ce21e78282 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -24,8 +24,11 @@ */ package org.spongepowered.common.entity.living.human; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import com.mojang.authlib.yggdrasil.ProfileResult; import com.mojang.serialization.DataResult; import net.kyori.adventure.text.Component; @@ -103,6 +106,7 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.UUID; +import java.util.function.Consumer; import java.util.stream.Stream; public final class HumanEntity extends PathfinderMob implements TeamMember, RangedAttackMob { @@ -331,7 +335,9 @@ public boolean getOrLoadSkin(final UUID minecraftAccount) { return false; } - this.fakeProfile.partialProfile().properties().replaceValues(ProfileProperty.TEXTURES, profile.properties().get(ProfileProperty.TEXTURES)); + this.modifyProperties(props -> { + props.replaceValues(ProfileProperty.TEXTURES, profile.properties().get(ProfileProperty.TEXTURES)); + }); if (this.isAliveAndInWorld()) { this.respawnOnClient(); } @@ -349,8 +355,11 @@ public boolean getOrLoadSkin(final String minecraftAccount) { return false; } - this.fakeProfile.partialProfile().properties().clear(); - this.fakeProfile.partialProfile().properties().putAll(profile.properties()); + this.modifyProperties(props -> { + props.clear(); + props.putAll(profile.properties()); + }); + if (this.isAliveAndInWorld()) { this.respawnOnClient(); } @@ -381,10 +390,10 @@ public SpongeProfileProperty getSkinProperty() { } public void setSkinProperty(final ProfileProperty property) { - this.fakeProfile.partialProfile().properties() - .replaceValues( - ProfileProperty.TEXTURES, - Collections.singletonList(((SpongeProfileProperty) property).asProperty())); + this.modifyProperties(props -> props.replaceValues( + ProfileProperty.TEXTURES, + Collections.singletonList(((SpongeProfileProperty) property).asProperty()) + )); if (this.isAliveAndInWorld()) { this.respawnOnClient(); @@ -403,6 +412,17 @@ private void respawnOnClient() { ))); } + private void modifyProperties(final Consumer> fn) { + final var mutable = HashMultimap.create(this.fakeProfile.partialProfile().properties()); + fn.accept(mutable); + + this.fakeProfile = ResolvableProfile.createResolved(new GameProfile( + this.fakeProfile.partialProfile().id(), + this.fakeProfile.partialProfile().name(), + new PropertyMap(mutable) + )); + } + /** * Can the fake profile be removed from the tab list immediately (i.e. as * soon as the human has spawned). diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 04a0e4f4ba8..10012b627b8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -56,6 +56,7 @@ import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -92,7 +93,7 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G @Shadow public float experienceProgress; @Shadow public AbstractContainerMenu containerMenu; @Shadow @Final public InventoryMenu inventoryMenu; - @Shadow @Final private GameProfile gameProfile; + @Shadow @Final @Mutable private GameProfile gameProfile; @Shadow public abstract boolean shadow$isSpectator(); @Shadow protected abstract int shadow$getPermissionLevel(); @Shadow public abstract int shadow$getXpNeededForNextLevel(); @@ -127,6 +128,11 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G return this.gameProfile; } + @Override + public void bridge$setGameProfile(final GameProfile profile) { + this.gameProfile = profile; + } + @Override public int bridge$getExperienceSinceLevel() { return this.totalExperience - ExperienceHolderUtil.xpAtLevel(this.experienceLevel); diff --git a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java index 4d63df41972..a256c6a977d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java +++ b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/network/ServerLoginPacketListenerImplMixin_IpForward.java @@ -25,8 +25,10 @@ package org.spongepowered.common.mixin.ipforward.server.network; +import com.google.common.collect.HashMultimap; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import net.minecraft.network.Connection; import net.minecraft.network.protocol.login.ServerboundHelloPacket; import net.minecraft.server.MinecraftServer; @@ -92,9 +94,13 @@ public abstract class ServerLoginPacketListenerImplMixin_IpForward { $$0 = new GameProfile(uuid, $$0.name()); if (((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedProfile() != null) { + final var mutableProperties = HashMultimap.create($$0.properties()); + for (final Property property : ((ConnectionBridge_IpForward) this.connection).bungeeBridge$getSpoofedProfile()) { - $$0.properties().put(property.name(), property); + mutableProperties.put(property.name(), property); } + + $$0 = new GameProfile($$0.id(), $$0.name(), new PropertyMap(mutableProperties)); } } From 274e2649ff6d5e1aad90860ae51cb13bc7dce154 Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Sat, 25 Oct 2025 21:04:12 +0300 Subject: [PATCH 408/586] Fix registering to builtin registries with dependencies (#4249) --- .../java/org/spongepowered/common/SpongeLifecycle.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 0ddc1a9d09d..c798b02e0b4 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -122,6 +122,7 @@ public void callRegisterBuilderEvent() { public void establishEarlyGlobalRegistries() { final SpongeRegistryHolder holder = (SpongeRegistryHolder) this.game; holder.setRootMinecraftRegistry((Registry>) BuiltInRegistries.REGISTRY); + holder.streamRegistries().forEach(r -> ((WritableRegistryBridge) r).bridge$setRegistryHolder(this.game)); SpongeRegistries.registerEarlyGlobalRegistries(holder); } @@ -136,8 +137,12 @@ public void establishGlobalRegistries() { // Freeze Sponge Root - Registries are now available holder.registryHolder().freezeSpongeRootRegistry(); - this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game, - holder.streamRegistries().collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())))); + final Map, org.spongepowered.api.registry.Registry> map = + holder.streamRegistries().collect(Collectors.toMap(org.spongepowered.api.registry.Registry::type, Function.identity())); + + this.game.eventManager().post(new AbstractRegisterRegistryValueEvent.GameScopedImpl(Cause.of(EventContext.empty(), this.game), this.game, map)); + map.values().forEach(r -> ((WritableRegistryBridge) r).bridge$markEventCalled()); + holder.registryHolder().freezeSpongeDynamicRegistries(false); } public void endEstablishGlobalRegistries() { From 1a43c70628a1ed538497ce9eec6849489c4540f9 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 6 Nov 2025 23:13:45 +0100 Subject: [PATCH 409/586] Fix badges pointing to wrong version --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e5f5737eb1a..7b4a6a2e5e4 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeVanilla 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*16.0.0*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeForge 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*16.0.0*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) +[![SpongeNeo 1.21.8](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.8&queryOpt=%3Aversion%3D1.21.8*16.0.0*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.8*) ## Prerequisites From e09cc34c63749319054b221aded733944fdc9abc Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 9 Nov 2025 17:27:46 +0100 Subject: [PATCH 410/586] Implement CHICKEN_VARIANT and COW_VARIANT keys --- SpongeAPI | 2 +- .../data/provider/entity/ChickenData.java | 9 ++++ .../common/data/provider/entity/CowData.java | 51 +++++++++++++++++++ .../provider/entity/EntityDataProviders.java | 1 + .../animal/ChickenVariantMixin_API.java | 32 ++++++++++++ .../entity/animal/CowVariantMixin_API.java | 32 ++++++++++++ src/mixins/resources/mixins.sponge.api.json | 2 + .../org/spongepowered/test/data/DataTest.java | 9 ++++ 8 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/CowData.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index 214a97c9174..f5fa07ca690 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 214a97c9174a315b226bc716c77d7a4d7c7091d2 +Subproject commit f5fa07ca6908fb4ea831975acb2c428260c47f51 diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java index 04e8dfd8bae..ddfe38d8e2f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java @@ -24,8 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.animal.Chicken; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ChickenVariant; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.SpongeTicks; @@ -47,6 +49,13 @@ public static void register(final DataProviderRegistrator registrator) { } h.eggTime = ticks; return true; + }) + .create(Keys.CHICKEN_VARIANT) + .get(h -> (ChickenVariant) (Object) h.getVariant().value()) + .set((h, v) -> { + final var holder = h.level().registryAccess().lookupOrThrow(Registries.CHICKEN_VARIANT) + .wrapAsHolder((net.minecraft.world.entity.animal.ChickenVariant) (Object) v); + h.setVariant(holder); }); } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java new file mode 100644 index 00000000000..a86cfcaf9d4 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java @@ -0,0 +1,51 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.animal.Cow; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.CowVariant; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public final class CowData { + + private CowData() { + } + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(Cow.class) + .create(Keys.COW_VARIANT) + .get(h -> (CowVariant) (Object) h.getVariant().value()) + .set((h, v) -> { + final var holder = h.level().registryAccess().lookupOrThrow(Registries.COW_VARIANT) + .wrapAsHolder((net.minecraft.world.entity.animal.CowVariant) (Object) v); + h.setVariant(holder); + }); + } + // @formatter:on +} diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 49351a84bee..b752a455468 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -117,6 +117,7 @@ public void registerProviders() { CatData.register(this.registrator); ChickenData.register(this.registrator); CommandBlockMinecartData.register(this.registrator); + CowData.register(this.registrator); CreakingData.register(this.registrator); CreeperData.register(this.registrator); DamagingProjectileData.register(this.registrator); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java new file mode 100644 index 00000000000..deded3ad5d8 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import net.minecraft.world.entity.animal.ChickenVariant; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ChickenVariant.class) +public abstract class ChickenVariantMixin_API implements org.spongepowered.api.data.type.ChickenVariant { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java new file mode 100644 index 00000000000..3b1c66dadec --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import net.minecraft.world.entity.animal.CowVariant; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CowVariant.class) +public abstract class CowVariantMixin_API implements org.spongepowered.api.data.type.CowVariant { +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 840a6f902da..364386683c8 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -151,7 +151,9 @@ "minecraft.world.entity.animal.CatMixin_API", "minecraft.world.entity.animal.CatVariantMixin_API", "minecraft.world.entity.animal.ChickenMixin_API", + "minecraft.world.entity.animal.ChickenVariantMixin_API", "minecraft.world.entity.animal.CodMixin_API", + "minecraft.world.entity.animal.CowVariantMixin_API", "minecraft.world.entity.animal.DolphinMixin_API", "minecraft.world.entity.animal.FlyingAnimalMixin_API", "minecraft.world.entity.animal.Fox_VariantMixin_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index afaa8009f80..e51c921fd01 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -51,6 +51,8 @@ import org.spongepowered.api.data.type.BoatTypes; import org.spongepowered.api.data.type.BodyParts; import org.spongepowered.api.data.type.CatTypes; +import org.spongepowered.api.data.type.ChickenVariants; +import org.spongepowered.api.data.type.CowVariants; import org.spongepowered.api.data.type.DyeColors; import org.spongepowered.api.data.type.FoxTypes; import org.spongepowered.api.data.type.FrogTypes; @@ -964,6 +966,13 @@ public void testData(final ServerPlayer player) { this.checkOfferData(frog, Keys.FROG_TYPE, FrogTypes.WARM.get()); this.checkGetData(frog, Keys.FROG_TYPE, FrogTypes.WARM.get()); + this.checkOfferData(chicken, Keys.CHICKEN_VARIANT, ChickenVariants.WARM.get()); + this.checkGetData(chicken, Keys.CHICKEN_VARIANT, ChickenVariants.WARM.get()); + + final Entity cow = world.createEntity(EntityTypes.COW.get(), position); + this.checkOfferData(cow, Keys.COW_VARIANT, CowVariants.WARM.get()); + this.checkGetData(cow, Keys.COW_VARIANT, CowVariants.WARM.get()); + // this.checkOfferData(panda, Keys.IS_UNHAPPY, true); this.checkWithData(acaciaStairs, Keys.IS_WATERLOGGED, true); From 5f22e1eabc07532f4e8f68cfa54e0a9f637f67e6 Mon Sep 17 00:00:00 2001 From: MrHell228 <82652479+MrHell228@users.noreply.github.com> Date: Thu, 13 Nov 2025 01:33:41 +0300 Subject: [PATCH 411/586] Implement item attributes (#4231) --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 8 ++ .../provider/item/stack/ItemStackData.java | 13 +- .../attribute/SpongeItemAttributeFactory.java | 52 ++++++++ .../registry/SpongeFactoryProvider.java | 3 + .../loader/VanillaRegistryLoader.java | 2 + ...ItemAttributeModifiers_EntryMixin_API.java | 64 +++++++++ ...EquipmentSlotGroupMixin_Inventory_API.java | 64 +++++++++ .../EquipmentSlotMixin_Inventory_API.java | 7 + src/mixins/resources/mixins.sponge.api.json | 1 + .../resources/mixins.sponge.inventory.json | 1 + .../test/data/AttributeDataTest.java | 124 ++++++++++++++++++ .../META-INF/sponge_plugins.json | 6 + 13 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/entity/attribute/SpongeItemAttributeFactory.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/ItemAttributeModifiers_EntryMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotGroupMixin_Inventory_API.java create mode 100644 testplugins/src/main/java/org/spongepowered/test/data/AttributeDataTest.java diff --git a/SpongeAPI b/SpongeAPI index 34622032e7b..01f256bd223 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 34622032e7bda623d9eff36cd00e7d1503cb2af6 +Subproject commit 01f256bd22344a1224fd76c3738477eb36a7b094 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index d99ca8c48f9..186a115dd67 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -28,6 +28,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.EquipmentSlotGroup; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.animal.Fox; import net.minecraft.world.entity.animal.MushroomCow; @@ -159,6 +160,13 @@ public static List enumEntries(final Context context) { "getSerializedName", "sponge" ), + new EnumEntriesValidator<>( + "item.inventory.equipment", + "EquipmentConditions", + EquipmentSlotGroup.class, + "getSerializedName", + "sponge" + ), new EnumEntriesValidator<>( "item.inventory.equipment", "EquipmentGroups", diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index eb411c5c0b7..4f1a9ba32c5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -43,6 +43,7 @@ import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.DamageResistant; import net.minecraft.world.item.component.DeathProtection; +import net.minecraft.world.item.component.ItemAttributeModifiers; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; @@ -56,6 +57,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ItemAction; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.entity.attribute.ItemAttribute; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.Inventory; @@ -82,7 +84,6 @@ private ItemStackData() { // @formatter:off public static void register(final DataProviderRegistrator registrator) { // TODO DataComponents.SUSPICIOUS_STEW_EFFECTS - // TODO maybe DataComponents.ATTRIBUTE_MODIFIERS as keys? // TODO DataComponents.BUNDLE_CONTENTS also check for Shulker Boxes? - removing the component prevents using the bundle // TODO DataComponents.CONTAINER_LOOT for containers with loottable data, also for blockentity? // TODO DataComponents.BLOCK_ENTITY_DATA maybe expose as raw DataContainer? (id MUST have block entity type) @@ -367,6 +368,16 @@ public static void register(final DataProviderRegistrator registrator) { return builder.build(); }) .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) + .create(Keys.ITEM_ATTRIBUTES) + .get(stack -> { + final var attributes = stack.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY).modifiers(); + return attributes.isEmpty() ? null : (List) (Object) List.copyOf(attributes); + }) + .set((stack, v) -> { + final var attributes = (List) (Object) List.copyOf(v); + stack.update(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY, p -> new ItemAttributeModifiers(attributes, p.showInTooltip())); + }) + .resetOnDelete(List.of()) ; } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/entity/attribute/SpongeItemAttributeFactory.java b/src/main/java/org/spongepowered/common/entity/attribute/SpongeItemAttributeFactory.java new file mode 100644 index 00000000000..cafaadd17c5 --- /dev/null +++ b/src/main/java/org/spongepowered/common/entity/attribute/SpongeItemAttributeFactory.java @@ -0,0 +1,52 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.entity.attribute; + +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.EquipmentSlotGroup; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.item.component.ItemAttributeModifiers; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.ItemAttribute; +import org.spongepowered.api.entity.attribute.type.AttributeType; +import org.spongepowered.api.item.inventory.equipment.EquipmentCondition; +import org.spongepowered.common.SpongeCommon; + +import java.util.Objects; + +public final class SpongeItemAttributeFactory implements ItemAttribute.Factory { + + @Override + public ItemAttribute of(final AttributeType type, final AttributeModifier modifier, final EquipmentCondition condition) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(modifier, "modifier"); + Objects.requireNonNull(condition, "condition"); + return (ItemAttribute) (Object) new ItemAttributeModifiers.Entry( + SpongeCommon.vanillaRegistry(Registries.ATTRIBUTE).wrapAsHolder((Attribute) type), + (net.minecraft.world.entity.ai.attributes.AttributeModifier) (Object) modifier, + (EquipmentSlotGroup) (Object) condition + ); + } +} diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index b39affb0bce..87dc9b84657 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -46,6 +46,7 @@ import org.spongepowered.api.data.value.Value; import org.spongepowered.api.effect.ForwardingViewer; import org.spongepowered.api.effect.VanishState; +import org.spongepowered.api.entity.attribute.ItemAttribute; import org.spongepowered.api.event.EventListenerRegistration; import org.spongepowered.api.event.cause.entity.damage.DamageStepType; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; @@ -123,6 +124,7 @@ import org.spongepowered.common.data.manipulator.MutableDataManipulatorFactory; import org.spongepowered.common.data.value.SpongeValueFactory; import org.spongepowered.common.effect.SpongeCustomForwardingViewer; +import org.spongepowered.common.entity.attribute.SpongeItemAttributeFactory; import org.spongepowered.common.entity.effect.SpongeVanishState; import org.spongepowered.common.event.SpongeEventListenerRegistration; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType; @@ -287,6 +289,7 @@ public void registerDefaultFactories() { .registerFactory(NaturalSpawner.Factory.class, new SpongeNaturalSpawnerFactory()) .registerFactory(ScoreFormat.Factory.class, new SpongeScoreFormatFactory()) .registerFactory(ToolRule.Factory.class, new SpongeToolRuleFactory()) + .registerFactory(ItemAttribute.Factory.class, new SpongeItemAttributeFactory()) .registerFactory(ItemAction.Factory.class, new SpongeItemActionFactory()) .registerFactory(PortalLogic.Factory.class, new SpongePortalLogicFactory()) .registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory()) diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 4727ac90857..31479222e40 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -36,6 +36,7 @@ import net.minecraft.world.damagesource.DamageScaling; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.EquipmentSlotGroup; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -183,6 +184,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.DYE_COLOR, DyeColor.values()); this.automaticName(RegistryTypes.DOOR_HINGE, DoorHingeSide.values()); this.automaticName(RegistryTypes.DRIPSTONE_SEGMENT, DripstoneThickness.values()); + this.automaticName(RegistryTypes.EQUIPMENT_CONDITION, EquipmentSlotGroup.values()); this.automaticName(RegistryTypes.EQUIPMENT_GROUP, EquipmentSlot.Type.values()); this.automaticName(RegistryTypes.EQUIPMENT_TYPE, EquipmentSlot.values()); this.automaticName(RegistryTypes.FOX_TYPE, Fox.Variant.values()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/ItemAttributeModifiers_EntryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/ItemAttributeModifiers_EntryMixin_API.java new file mode 100644 index 00000000000..14ad842499e --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/component/ItemAttributeModifiers_EntryMixin_API.java @@ -0,0 +1,64 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.component; + +import net.minecraft.core.Holder; +import net.minecraft.world.entity.EquipmentSlotGroup; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.item.component.ItemAttributeModifiers; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.ItemAttribute; +import org.spongepowered.api.entity.attribute.type.AttributeType; +import org.spongepowered.api.item.inventory.equipment.EquipmentCondition; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemAttributeModifiers.Entry.class) +@Implements(@Interface(iface = ItemAttribute.class, prefix = "attribute$")) +public abstract class ItemAttributeModifiers_EntryMixin_API implements ItemAttribute { + + @Shadow @Final private Holder attribute; + @Shadow @Final private net.minecraft.world.entity.ai.attributes.AttributeModifier modifier; + @Shadow @Final private EquipmentSlotGroup slot; + + @Override + public AttributeType type() { + return (AttributeType) this.attribute.value(); + } + + @Intrinsic + public AttributeModifier attribute$modifier() { + return (AttributeModifier) (Object) this.modifier; + } + + @Override + public EquipmentCondition condition() { + return (EquipmentCondition) (Object) this.slot; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotGroupMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotGroupMixin_Inventory_API.java new file mode 100644 index 00000000000..4f15254dc48 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotGroupMixin_Inventory_API.java @@ -0,0 +1,64 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.inventory.api.world.entity; + +import net.kyori.adventure.text.Component; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.EquipmentSlotGroup; +import org.spongepowered.api.item.inventory.equipment.EquipmentCondition; +import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; + +@Mixin(EquipmentSlotGroup.class) +public abstract class EquipmentSlotGroupMixin_Inventory_API implements EquipmentCondition { + + @Shadow public abstract boolean shadow$test(EquipmentSlot slot); + + @Shadow @Final private String key; + + private Component api$component; + + @Inject(method = "(Ljava/lang/String;IILjava/lang/String;Ljava/util/function/Predicate;)V", at = @At("RETURN")) + private void api$setComponent(final CallbackInfo ci) { + this.api$component = Component.translatable("item.modifiers." + this.key); + } + + @Override + public Component asComponent() { + return this.api$component; + } + + @Override + public boolean test(final EquipmentType type) { + return this.shadow$test((EquipmentSlot) (Object) Objects.requireNonNull(type, "type")); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotMixin_Inventory_API.java index f9ad70efbd4..1e5310f9c6c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotMixin_Inventory_API.java @@ -25,6 +25,8 @@ package org.spongepowered.common.mixin.inventory.api.world.entity; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.EquipmentSlotGroup; +import org.spongepowered.api.item.inventory.equipment.EquipmentCondition; import org.spongepowered.api.item.inventory.equipment.EquipmentGroup; import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.asm.mixin.Final; @@ -40,4 +42,9 @@ public abstract class EquipmentSlotMixin_Inventory_API implements EquipmentType public EquipmentGroup group() { return (EquipmentGroup) (Object) this.type; } + + @Override + public EquipmentCondition condition() { + return (EquipmentCondition) (Object) EquipmentSlotGroup.bySlot((EquipmentSlot) (Object) this); + } } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 835e8e57719..035f216ac18 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -332,6 +332,7 @@ "minecraft.world.item.ToolMaterialMixin_API", "minecraft.world.item.alchemy.PotionMixin_API", "minecraft.world.item.component.FireworkExplosionMixin_API", + "minecraft.world.item.component.ItemAttributeModifiers_EntryMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", "minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffectMixin_API", "minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffectMixin_API", diff --git a/src/mixins/resources/mixins.sponge.inventory.json b/src/mixins/resources/mixins.sponge.inventory.json index 0b4ba5ddbb6..6ea796e028c 100644 --- a/src/mixins/resources/mixins.sponge.inventory.json +++ b/src/mixins/resources/mixins.sponge.inventory.json @@ -18,6 +18,7 @@ "api.world.CompoundContainerMixin_Carrier_Inventory_API", "api.world.ContainerMixin_Inventory_API", "api.world.entity.EquipmentSlot_TypeMixin_Inventory_API", + "api.world.entity.EquipmentSlotGroupMixin_Inventory_API", "api.world.entity.EquipmentSlotMixin_Inventory_API", "api.world.entity.animal.horse.AbstractHorseMixin_Carrier_Inventory_API", "api.world.entity.monster.PillagerMixin_Carrier_Inventory_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/AttributeDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/AttributeDataTest.java new file mode 100644 index 00000000000..ce27e065d2c --- /dev/null +++ b/testplugins/src/main/java/org/spongepowered/test/data/AttributeDataTest.java @@ -0,0 +1,124 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.test.data; + +import com.google.inject.Inject; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.parameter.CommandContext; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.AttributeOperations; +import org.spongepowered.api.entity.attribute.ItemAttribute; +import org.spongepowered.api.entity.attribute.type.AttributeTypes; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.equipment.EquipmentConditions; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; +import org.spongepowered.test.LoadableModule; + +@Plugin("attributedata") +public class AttributeDataTest implements LoadableModule { + + private final PluginContainer plugin; + + @Inject + public AttributeDataTest(final PluginContainer plugin) { + this.plugin = plugin; + } + + @Override + public void enable(final CommandContext ctx) { + } + + @Listener + public void onRegisterCommand(final RegisterCommandEvent event) { + final Command.Builder builder = Command.builder(); + builder.addChild(Command.builder().executor(this::items).build(), "items"); + event.register(this.plugin, builder.build(), "attributedata"); + } + + private CommandResult items(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + final ItemStack stack1 = ItemStack.of(ItemTypes.DIAMOND_BOOTS); + stack1.offer(Keys.CUSTOM_NAME, Component.text("Speed when on feet, jump boost when in hand")); + stack1.offerSingle(Keys.ITEM_ATTRIBUTES, ItemAttribute.of( + AttributeTypes.MOVEMENT_SPEED, + AttributeModifier.of(ResourceKey.of(this.plugin, "boots_speed"), AttributeOperations.ADDITION, 1), + EquipmentConditions.FEET + )); + stack1.offerSingle(Keys.ITEM_ATTRIBUTES, ItemAttribute.of( + AttributeTypes.JUMP_STRENGTH, + AttributeModifier.of(ResourceKey.of(this.plugin, "boots_jump"), AttributeOperations.ADDITION, 1), + EquipmentConditions.HAND + )); + + final ItemStack stack2 = ItemStack.of(ItemTypes.NETHERITE_SWORD); + stack2.offer(Keys.CUSTOM_NAME, Component.text("Sword without damage")); + stack2.getValue(Keys.ITEM_ATTRIBUTES) + .map(Value::asMutable) + .map(v -> v.transform(list -> list.stream() + .filter(attribute -> attribute.type() != AttributeTypes.ATTACK_DAMAGE.get()) + .toList())) + .ifPresent(stack2::offer); + + // In vanilla only one modifier with the same + // key is applied within each attribute type. + // This is to ensure that vanilla accepts + // modifiers with the same key on the item. + final ItemStack stack3 = ItemStack.of(ItemTypes.SUGAR); + final ResourceKey sameKey = ResourceKey.of(this.plugin, "same_key"); + stack3.offer(Keys.CUSTOM_NAME, Component.text("Scale and one (out of 2) health boost")); + stack3.offerSingle(Keys.ITEM_ATTRIBUTES, ItemAttribute.of( + AttributeTypes.MAX_HEALTH, + AttributeModifier.of(sameKey, AttributeOperations.ADDITION, 10), + EquipmentConditions.MAINHAND + )); + stack3.offerSingle(Keys.ITEM_ATTRIBUTES, ItemAttribute.of( + AttributeTypes.MAX_HEALTH, + AttributeModifier.of(sameKey, AttributeOperations.ADDITION, 20), + EquipmentConditions.MAINHAND + )).ifNotSuccessful(RuntimeException::new); + stack3.offerSingle(Keys.ITEM_ATTRIBUTES, ItemAttribute.of( + AttributeTypes.SCALE, + AttributeModifier.of(sameKey, AttributeOperations.MULTIPLY_TOTAL, 1), + EquipmentConditions.MAINHAND + )); + + player.inventory().offer(stack1, stack2, stack3); + return CommandResult.success(); + } +} diff --git a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json index b0d8f7fcf9d..ea4cbd7e716 100644 --- a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json +++ b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json @@ -372,6 +372,12 @@ } ] }, + { + "id": "attributedata", + "name": "Attribute Data", + "entrypoint": "org.spongepowered.test.data.AttributeDataTest", + "description": "Attribute Data" + }, { "id": "decoratedpotdata", "name": "Decorated Pot Data", From e47cf43e2670797708cc17178ff83f3defee4992 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 12 Nov 2025 23:35:14 +0100 Subject: [PATCH 412/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 01f256bd223..8b4f93e72fe 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 01f256bd22344a1224fd76c3738477eb36a7b094 +Subproject commit 8b4f93e72fec84dcfee8f322e48a6f71cee96654 From 0aaf45518d65bacc799cea264d0561d7cd6d3e48 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 14 Nov 2025 18:17:50 +0100 Subject: [PATCH 413/586] Bump SpongeAPI again --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 8b4f93e72fe..e6532b3739c 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8b4f93e72fec84dcfee8f322e48a6f71cee96654 +Subproject commit e6532b3739c1615123a7fc3306e863fe25cb5905 From 9c0309030d375532ec0aefee54ace84f57f2ef3b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 16 Nov 2025 16:06:12 +0100 Subject: [PATCH 414/586] Remove deprecated BoatType and CommandCompletionProviders.ALL_RECIPES --- SpongeAPI | 2 +- .../registry/loader/CommandRegistryLoader.java | 1 - .../common/registry/RegistryTest.java | 15 +++++++++++---- .../command/raw/ClientSuggestionsRawCommand.java | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 038c60d38cb..8e3ee6360a5 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 038c60d38cb36129cded4e82c6311fe13536f2fc +Subproject commit 8e3ee6360a515386d66a7c1b843cda25b98be222 diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index 6c9d1bf04bf..d13734b80ff 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -221,7 +221,6 @@ public static RegistryLoader clientCompletionType() { public static RegistryLoader clientSuggestionProvider() { return RegistryLoader.of(l -> { // TODO based on SuggestionProviders.PROVIDERS_BY_NAME instead -// l.add(CommandCompletionProviders.ALL_RECIPES, k -> (CommandCompletionProvider) SuggestionProviders.ALL_RECIPES); l.add(CommandCompletionProviders.AVAILABLE_SOUNDS, k -> (CommandCompletionProvider) SuggestionProviders.AVAILABLE_SOUNDS); l.add(CommandCompletionProviders.SUMMONABLE_ENTITIES, k -> (CommandCompletionProvider) SuggestionProviders.SUMMONABLE_ENTITIES); }); diff --git a/src/test/java/org/spongepowered/common/registry/RegistryTest.java b/src/test/java/org/spongepowered/common/registry/RegistryTest.java index dee259942b5..d0cffa96138 100644 --- a/src/test/java/org/spongepowered/common/registry/RegistryTest.java +++ b/src/test/java/org/spongepowered/common/registry/RegistryTest.java @@ -33,9 +33,14 @@ import org.junit.jupiter.api.TestFactory; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.registrar.tree.CommandCompletionProviders; -import org.spongepowered.api.data.type.BoatTypes; -import org.spongepowered.api.registry.*; +import org.spongepowered.api.data.type.WolfSoundVariants; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryEntry; +import org.spongepowered.api.registry.RegistryRoots; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.scoreboard.CollisionRules; +import org.spongepowered.api.scoreboard.Visibilities; import org.spongepowered.api.util.annotation.CatalogedBy; import java.lang.reflect.Field; @@ -45,6 +50,7 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.Optional; +import java.util.Set; import java.util.stream.Stream; public class RegistryTest { @@ -92,10 +98,11 @@ private static Stream streamDefaultedReferenceFields() { @TestFactory public Stream generateDefaultedReferenceTests() { + final Set> ignored = Set.of(CollisionRules.class, Visibilities.class, WolfSoundVariants.class); // TODO fix return RegistryTest.streamDefaultedReferenceFields().map(field -> { - Assumptions.assumeFalse(field.getDeclaringClass() == BoatTypes.class || field.getDeclaringClass() == CommandCompletionProviders.class); final String name = "Field " + field.getDeclaringClass().getSimpleName() + "#" + field.getName(); return dynamicTest(name, () -> { + Assumptions.assumeFalse(ignored.contains(field.getDeclaringClass())); final DefaultedRegistryReference ref = (DefaultedRegistryReference) field.get(null); assertNotNull(ref.get()); }); diff --git a/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java b/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java index eee6d6f3372..c276276c9b6 100644 --- a/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java +++ b/testplugins/src/main/java/org/spongepowered/test/command/raw/ClientSuggestionsRawCommand.java @@ -81,7 +81,7 @@ public CommandTreeNode.Root commandTree(final RegistryHolder registryHolder) { return CommandTreeNode.root() .child("s1", CommandTreeNodeTypes.RESOURCE_LOCATION.get(registryHolder).createNode() .executable() - .completions(CommandCompletionProviders.ALL_RECIPES)); + .completions(CommandCompletionProviders.AVAILABLE_SOUNDS)); } } From 27ab590827c94f4f479fe2d9fc9d60beb4dddfb6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 20 Nov 2025 10:47:07 +0100 Subject: [PATCH 415/586] chore: update towards 16.1.0-SNAPSHOT --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 0c52c2e614d..98057912128 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 0c52c2e614dec96e8a8a289501a1129bff6db9c9 +Subproject commit 980579121281f6bd39b37808e2039d75be46797d From ab7b6577566a6af7163071b8b2ffc0f9b1a01a91 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 20 Nov 2025 10:47:24 +0100 Subject: [PATCH 416/586] chore: update towards 15.1.0-SNAPSHOT --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 8e3ee6360a5..4e59c90170d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8e3ee6360a515386d66a7c1b843cda25b98be222 +Subproject commit 4e59c90170d107a316b2333b121b9bcd649ab2eb From 64a534b7858c61617770e412152c763e48c08a55 Mon Sep 17 00:00:00 2001 From: Aapo Katila <81980535+abola2@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:56:51 +0200 Subject: [PATCH 417/586] Clean up old performTeleport overwrite (#4252) --- .../server/commands/TeleportCommandMixin.java | 186 +----------------- 1 file changed, 10 insertions(+), 176 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index ba17630718b..a565130de08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -24,197 +24,31 @@ */ package org.spongepowered.common.mixin.core.server.commands; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.core.BlockPos; -import net.minecraft.server.commands.LookAt; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.commands.TeleportCommand; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.TicketType; -import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntitySpawnReason; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.PathfinderMob; -import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.Relative; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.phys.Vec3; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.Sponge; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.cause.entity.MovementTypes; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.api.event.entity.MoveEntityEvent; -import org.spongepowered.api.event.entity.RotateEntityEvent; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.hooks.PlatformHooks; -import org.spongepowered.common.util.VecHelper; -import org.spongepowered.math.vector.Vector3d; import java.util.Set; @Mixin(TeleportCommand.class) public abstract class TeleportCommandMixin { - /** - * @author Zidane - * @reason Have the teleport command respect our events - */ - @Overwrite - // TODO check if this is still correct - check if we can get rid of the overwrite - private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, - Set relativeList, float yaw, float pitch, @Nullable LookAt facing) { - - double actualX = x; - double actualY = y; - double actualZ = z; - double actualYaw = yaw; - double actualPitch = pitch; - - if (!(entityIn instanceof ServerPlayer)) { - actualYaw = Mth.wrapDegrees(yaw); - actualPitch = Mth.wrapDegrees(pitch); - actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F); - } - - if (worldIn == entityIn.level()) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - - // TODO Should honor the relative list before the event.. - - if (ShouldFire.MOVE_ENTITY_EVENT) { - final MoveEntityEvent posEvent = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), - (org.spongepowered.api.entity.Entity) entityIn, VecHelper.toVector3d(entityIn.position()), - new Vector3d(x, y, z), new Vector3d(x, y, z)); - - if (SpongeCommon.post(posEvent)) { - return; - } - - actualX = posEvent.destinationPosition().x(); - actualY = posEvent.destinationPosition().y(); - actualZ = posEvent.destinationPosition().z(); - } - - if (ShouldFire.ROTATE_ENTITY_EVENT) { - final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), - (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(actualPitch, actualYaw, 0), - new Vector3d(pitch, yaw, 0)); - - SpongeCommon.post(rotateEvent); - actualYaw = rotateEvent.isCancelled() ? entityIn.getYRot() : rotateEvent.toRotation().y(); - actualPitch = rotateEvent.isCancelled() ? entityIn.getXRot() : rotateEvent.toRotation().x(); - } - - if (entityIn instanceof ServerPlayer sp) { - - ChunkPos chunkpos = new ChunkPos(new BlockPos((int) actualX, (int) actualY, (int) actualZ)); - worldIn.getChunkSource().addRegionTicket(TicketType.FORCED, chunkpos, 1, chunkpos); - - entityIn.stopRiding(); - - if (sp.isSleeping()) { - sp.stopSleepInBed(true, true); - } - - sp.connection.teleport( - new PositionMoveRotation(new Vec3( actualX, actualY, actualZ), Vec3.ZERO, (float) actualYaw, (float) actualPitch), relativeList); - } else { - entityIn.moveTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch); - } - - entityIn.setYHeadRot((float) actualYaw); - } - } else { - if (entityIn instanceof ServerPlayer sp) { - // To ensure mod code is caught, handling the world change for players happens in teleport - // Teleport will create a frame but we want to ensure it'll be the command movement type - // TODO check if this is still correct - PhaseTracker.getInstance().addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - sp.teleportTo(worldIn, x, y, z, relativeList, yaw, pitch, true); - PhaseTracker.getInstance().removeContext(EventContextKeys.MOVEMENT_TYPE); - } else { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - - final ServerLevel fromWorld = (ServerLevel) entityIn.getCommandSenderWorld(); - - final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(entityIn, - worldIn); - if (SpongeCommon.post(preEvent)) { - return; - } - - final ChangeEntityWorldEvent.Reposition posEvent = - SpongeEventFactory.createChangeEntityWorldEventReposition(frame.currentCause(), - (org.spongepowered.api.entity.Entity) entityIn, - (org.spongepowered.api.world.server.ServerWorld) entityIn.getCommandSenderWorld(), - VecHelper.toVector3d(entityIn.position()), new Vector3d(x, y, z), preEvent.originalDestinationWorld(), - new Vector3d(x, y, z), preEvent.destinationWorld()); - - if (SpongeCommon.post(posEvent)) { - return; - } - - entityIn.unRide(); - final Entity result = entityIn.getType().create(worldIn, EntitySpawnReason.DIMENSION_TRAVEL); - if (result == null) { - return; - } - - if (ShouldFire.ROTATE_ENTITY_EVENT) { - final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), - (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(entityIn.getXRot(), entityIn.getYRot(), 0), - new Vector3d(actualPitch, actualYaw, 0)); - - if (!SpongeCommon.post(rotateEvent)) { - actualYaw = Mth.wrapDegrees(rotateEvent.toRotation().y()); - actualPitch = Mth.wrapDegrees(rotateEvent.toRotation().x()); - actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F); - } else { - actualYaw = entityIn.getYRot(); - actualPitch = entityIn.getXRot(); - } - } - - result.restoreFrom(entityIn); - result.moveTo(posEvent.destinationPosition().x(), posEvent.destinationPosition().y(), - posEvent.destinationPosition().z(), (float) actualYaw, (float) actualPitch); - result.setYHeadRot((float) actualYaw); - worldIn.addDuringTeleport(result); - entityIn.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); - - Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost( - PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) result, - (ServerWorld) fromWorld, - preEvent.originalDestinationWorld(), - preEvent.destinationWorld() - )); - } - } - } - - if (facing != null) { - facing.perform(source, entityIn); - } - - if (!(entityIn instanceof LivingEntity) || !((LivingEntity)entityIn).isFallFlying()) { - entityIn.setDeltaMovement(entityIn.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); - entityIn.setOnGround(true); - } - - if (entityIn instanceof PathfinderMob) { - ((PathfinderMob)entityIn).getNavigation().stop(); + @WrapOperation(method = "performTeleport", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) + private static boolean impl$createCauseFrameForPerformTeleport( + final Entity instance, final ServerLevel level, final double x, final double y, final double z, + final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera, final Operation original) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); + return original.call(instance, level, x, y, z, relativeMovements, yRot, xRot, setCamera); } } } From ef75430f3801494297b69ff2783cf3dae4dd9279 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 28 Nov 2025 11:30:50 +0100 Subject: [PATCH 418/586] Refactor teleport events implementation - Remove overwrites - No longer ignore relative coordinates - Fix spectator not being able to spectate - Fix event context for spectator and spread command - Fix ChangeEntityWorldEvents firing once and then never again - Implement the event for all entities (was player only when not using API) - Cleanup a bunch of duplicated code and unclear method names - Setting the location via API now uses the vanilla teleport method rather than reinventing the wheel --- SpongeAPI | 2 +- .../SpreadPlayersCommandMixin_Forge.java | 53 --- .../resources/mixins.spongeforge.core.json | 1 - .../SpreadPlayersCommandMixin_Neo.java | 53 --- .../resources/mixins.spongeneo.core.json | 1 - .../bridge/world/entity/EntityBridge.java | 9 - .../phase/entity/TeleportContext.java | 11 - .../common/hooks/EventHooks.java | 14 - .../registry/loader/SpongeRegistryLoader.java | 3 +- .../spongepowered/common/util/Constants.java | 4 + .../commands/SpreadPlayersCommandMixin.java | 18 +- .../server/commands/TeleportCommandMixin.java | 2 +- .../core/server/level/ServerPlayerMixin.java | 311 ++------------- .../mixin/core/world/entity/EntityMixin.java | 368 +++++++++--------- .../world/entity/PortalProcessorMixin.java | 29 +- src/mixins/resources/mixins.sponge.core.json | 1 + .../test/movement/MovementTest.java | 3 + .../resources/mixins.spongevanilla.core.json | 1 - 18 files changed, 265 insertions(+), 619 deletions(-) delete mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/commands/SpreadPlayersCommandMixin_Forge.java delete mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/commands/SpreadPlayersCommandMixin_Neo.java rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java => src/mixins/java/org/spongepowered/common/mixin/core/server/commands/SpreadPlayersCommandMixin.java (72%) diff --git a/SpongeAPI b/SpongeAPI index 9475ca73e23..7774215ab95 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 9475ca73e23b259f75c0b36aa981c0be347a5086 +Subproject commit 7774215ab95cd4c2be70bb8ebb1d7d4fc334753b diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/commands/SpreadPlayersCommandMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/commands/SpreadPlayersCommandMixin_Forge.java deleted file mode 100644 index 6fa2c09674b..00000000000 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/commands/SpreadPlayersCommandMixin_Forge.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.mixin.core.server.commands; - -import net.minecraft.server.commands.SpreadPlayersCommand; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.event.entity.EntityTeleportEvent; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.cause.entity.MovementTypes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.event.tracking.PhaseTracker; - -@Mixin(SpreadPlayersCommand.class) -public abstract class SpreadPlayersCommandMixin_Forge { - - @Redirect(method = "setPlayerPositions", at = @At( - value = "INVOKE", - target = "Lnet/minecraftforge/event/ForgeEventFactory;onEntityTeleportSpreadPlayersCommand(Lnet/minecraft/world/entity/Entity;DDD)Lnet/minecraftforge/event/entity/EntityTeleportEvent$SpreadPlayersCommand;" - )) - private static EntityTeleportEvent.SpreadPlayersCommand vanilla$createCauseFrameForTeleport(Entity entity, double targetX, double targetY, double targetZ) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - - return ForgeEventFactory.onEntityTeleportSpreadPlayersCommand(entity, targetX, targetY, targetZ); - } - } -} diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 51b614af6cc..75933b2cdb9 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -25,7 +25,6 @@ "network.protocol.common.ServerboundCustomPayloadPacketMixin_Forge", "server.BootstrapMixin_Forge", "server.MinecraftServerMixin_Forge", - "server.commands.SpreadPlayersCommandMixin_Forge", "server.level.ServerPlayerMixin_Forge", "server.network.ServerGamePacketListenerImplMixin_Forge", "tags.TagLoaderMixin_Forge", diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/commands/SpreadPlayersCommandMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/commands/SpreadPlayersCommandMixin_Neo.java deleted file mode 100644 index 4dea593820d..00000000000 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/commands/SpreadPlayersCommandMixin_Neo.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.mixin.core.server.commands; - -import net.minecraft.server.commands.SpreadPlayersCommand; -import net.minecraft.world.entity.Entity; -import net.neoforged.neoforge.event.EventHooks; -import net.neoforged.neoforge.event.entity.EntityTeleportEvent; -import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.cause.entity.MovementTypes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.event.tracking.PhaseTracker; - -@Mixin(SpreadPlayersCommand.class) -public abstract class SpreadPlayersCommandMixin_Neo { - - @Redirect(method = "setPlayerPositions", at = @At( - value = "INVOKE", - target = "Lnet/neoforged/neoforge/event/EventHooks;onEntityTeleportSpreadPlayersCommand(Lnet/minecraft/world/entity/Entity;DDD)Lnet/neoforged/neoforge/event/entity/EntityTeleportEvent$SpreadPlayersCommand;" - )) - private static EntityTeleportEvent.SpreadPlayersCommand vanilla$createCauseFrameForTeleport(Entity entity, double targetX, double targetY, double targetZ) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - - return EventHooks.onEntityTeleportSpreadPlayersCommand(entity, targetX, targetY, targetZ); - } - } -} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index c87111685b1..d2ded564a1e 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -23,7 +23,6 @@ "network.protocol.common.ServerboundCustomPayloadPacketMixin_Neo", "server.BootstrapMixin_Neo", "server.MinecraftServerMixin_Neo", - "server.commands.SpreadPlayersCommandMixin_Neo", "server.level.ServerEntityMixin_Neo", "server.level.ServerPlayerMixin_Neo", "server.network.ServerGamePacketListenerImplMixin_Neo", diff --git a/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java b/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java index 038bd18db65..dd3e672ba4c 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/entity/EntityBridge.java @@ -25,11 +25,8 @@ package org.spongepowered.common.bridge.world.entity; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.portal.TeleportTransition; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.event.cause.entity.DismountType; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.common.event.tracking.phase.tick.EntityTickContext; import org.spongepowered.math.vector.Vector3d; @@ -69,10 +66,4 @@ public interface EntityBridge { } boolean bridge$dismountRidingEntity(DismountType type); - - Entity bridge$changeDimension(TeleportTransition transition); - - ChangeEntityWorldEvent.Reposition bridge$fireRepositionEvent(org.spongepowered.api.world.server.ServerWorld originalDestinationWorld, - org.spongepowered.api.world.server.ServerWorld targetWorld, - Vector3d destinationPosition); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/entity/TeleportContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/entity/TeleportContext.java index 45a1d716016..89886e58fa6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/entity/TeleportContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/entity/TeleportContext.java @@ -28,23 +28,12 @@ import org.spongepowered.common.event.tracking.PhaseTracker; public final class TeleportContext extends EntityContext { - - private boolean isPlayer; private boolean isWorldChange; public TeleportContext(final IPhaseState state, PhaseTracker tracker) { super(state, tracker); } - public boolean isPlayer() { - return this.isPlayer; - } - - public TeleportContext player() { - this.isPlayer = true; - return this; - } - public boolean isWorldChange() { return this.isWorldChange; } diff --git a/src/main/java/org/spongepowered/common/hooks/EventHooks.java b/src/main/java/org/spongepowered/common/hooks/EventHooks.java index af90ddb14a9..f12129607a7 100644 --- a/src/main/java/org/spongepowered/common/hooks/EventHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/EventHooks.java @@ -24,14 +24,8 @@ */ package org.spongepowered.common.hooks; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; -import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.event.tracking.PhaseTracker; /** * Event hooks for when there is no specific event translation between Sponge @@ -39,14 +33,6 @@ */ public interface EventHooks { - default ChangeEntityWorldEvent.Pre callChangeEntityWorldEventPre(final Entity entity, final ServerLevel toWorld) { - final ChangeEntityWorldEvent.Pre event = SpongeEventFactory.createChangeEntityWorldEventPre(PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) entity, (org.spongepowered.api.world.server.ServerWorld) entity.getCommandSenderWorld(), - (org.spongepowered.api.world.server.ServerWorld) toWorld, (org.spongepowered.api.world.server.ServerWorld) toWorld); - SpongeCommon.post(event); - return event; - } - default boolean callPlayerDestruction(ServerPlayer serverPlayer, DamageSource cause) { return false; } diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index b8f9f664823..0b0da93134f 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -290,7 +290,8 @@ public static RegistryLoader movementType() { MovementTypes.ENTITY_TELEPORT, MovementTypes.NATURAL, MovementTypes.PLUGIN, - MovementTypes.PORTAL + MovementTypes.PORTAL, + MovementTypes.SPECTATOR ))); } diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index 0982d657e62..d99304d31d4 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -40,6 +40,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.world.entity.Relative; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -81,6 +82,7 @@ import java.util.Comparator; import java.util.EnumSet; import java.util.Objects; +import java.util.Set; import java.util.function.Supplier; /** @@ -749,6 +751,8 @@ public static final class Entity { public static final DataQuery SCALE = of("Scale"); public static final DataQuery CUSTOM_NAME = of("CustomName"); + public static final Set RELATIVE_POSITION = EnumSet.of(Relative.X, Relative.Y, Relative.Z); + public static final class Ageable { public static final int ADULT = 6000; diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/SpreadPlayersCommandMixin.java similarity index 72% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java rename to src/mixins/java/org/spongepowered/common/mixin/core/server/commands/SpreadPlayersCommandMixin.java index 7025442efdc..3c0183b28e8 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/commands/SpreadPlayersCommandMixin_Vanilla.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/SpreadPlayersCommandMixin.java @@ -22,8 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.mixin.core.server.commands; +package org.spongepowered.common.mixin.core.server.commands; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.server.commands.SpreadPlayersCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -33,22 +35,20 @@ import org.spongepowered.api.event.cause.entity.MovementTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.Set; @Mixin(SpreadPlayersCommand.class) -public abstract class SpreadPlayersCommandMixin_Vanilla { +public abstract class SpreadPlayersCommandMixin { - @Redirect(method = "setPlayerPositions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) + @WrapOperation(method = "setPlayerPositions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) private static boolean vanilla$createCauseFrameForTeleport( - final Entity instance, final ServerLevel level, final double x, final double y, - final double z, final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + final Entity instance, final ServerLevel level, final double x, final double y, final double z, + final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera, final Operation original) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance(instance.level()).pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); - - return instance.teleportTo(level, x, y, z, relativeMovements, yRot, xRot, setCamera); + return original.call(instance, level, x, y, z, relativeMovements, yRot, xRot, setCamera); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java index a565130de08..e2a9ffa9a4f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/TeleportCommandMixin.java @@ -46,7 +46,7 @@ public abstract class TeleportCommandMixin { private static boolean impl$createCauseFrameForPerformTeleport( final Entity instance, final ServerLevel level, final double x, final double y, final double z, final Set relativeMovements, final float yRot, final float xRot, final boolean setCamera, final Operation original) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance(instance.level()).pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); return original.call(instance, level, x, y, z, relativeMovements, yRot, xRot, setCamera); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 803c1a35d49..1e654405287 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -26,8 +26,11 @@ import com.google.common.collect.ImmutableSet; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Cancellable; +import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Share; import com.llamalad7.mixinextras.sugar.ref.LocalRef; import com.mojang.datafixers.util.Either; @@ -40,45 +43,35 @@ import net.minecraft.network.chat.OutgoingChatMessage; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; -import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; -import net.minecraft.network.protocol.game.ClientboundGameEventPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; -import net.minecraft.network.protocol.game.ClientboundRespawnPacket; import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayerGameMode; -import net.minecraft.server.level.TicketType; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.PlayerList; import net.minecraft.stats.Stats; import net.minecraft.util.Unit; -import net.minecraft.util.profiling.Profiler; -import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.Relative; import net.minecraft.world.entity.animal.AbstractFish; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.portal.TeleportTransition; -import net.minecraft.world.level.storage.LevelData; -import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import org.checkerframework.checker.nullness.qual.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.api.Sponge; import org.spongepowered.api.adventure.Audiences; import org.spongepowered.api.block.BlockSnapshot; @@ -97,11 +90,8 @@ import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.cause.entity.MovementTypes; import org.spongepowered.api.event.data.ChangeDataHolderEvent; -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; import org.spongepowered.api.event.entity.DestructEntityEvent; import org.spongepowered.api.event.entity.InteractEntityEvent; -import org.spongepowered.api.event.entity.MoveEntityEvent; -import org.spongepowered.api.event.entity.RotateEntityEvent; import org.spongepowered.api.event.entity.living.player.KickPlayerEvent; import org.spongepowered.api.event.entity.living.player.PlayerChangeClientSettingsEvent; import org.spongepowered.api.event.entity.living.player.RespawnPlayerEvent; @@ -115,7 +105,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -143,18 +132,11 @@ import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.event.tracking.phase.entity.EntityPhase; -import org.spongepowered.common.event.tracking.phase.entity.TeleportContext; -import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.mixin.core.world.entity.player.PlayerMixin; import org.spongepowered.common.network.packet.SpongePacketHandler; import org.spongepowered.common.util.LocaleCache; -import org.spongepowered.common.util.VecHelper; import org.spongepowered.common.world.border.PlayerOwnBorderListener; -import org.spongepowered.math.vector.Vector3d; -import java.util.EnumSet; -import java.util.HashSet; import java.util.Locale; import java.util.Objects; import java.util.Set; @@ -169,14 +151,8 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Shadow @Final public ServerPlayerGameMode gameMode; @Shadow @Final public MinecraftServer server; @Shadow private int lastRecordedExperience; - @Shadow private boolean isChangingDimension; - @Shadow private net.minecraft.world.phys.Vec3 enteredNetherPosition; - @Shadow private int lastSentExp; - @Shadow private float lastSentHealth; - @Shadow private int lastSentFood; @Shadow public abstract ServerLevel shadow$serverLevel(); - @Shadow protected abstract void shadow$triggerDimensionChangeTriggers(ServerLevel serverworld); @Shadow public abstract void shadow$doCloseContainer(); @Shadow public abstract boolean shadow$setGameMode(GameType param0); @Shadow public abstract void shadow$setCamera(@org.jetbrains.annotations.Nullable final Entity $$0); @@ -224,31 +200,6 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr return Tristate.FALSE; } - @Override - protected final boolean impl$setLocation(final boolean isChangeOfWorld, final ServerLevel level, final Vector3d pos) { - if (this.shadow$isRemoved()) { - return false; - } - final var thisPlayer = ((net.minecraft.server.level.ServerPlayer) (Object) this); - - final ChunkPos chunkPos = new ChunkPos(VecHelper.toBlockPos(pos)); - level.getChunkSource().addRegionTicket(TicketType.FORCED, chunkPos, 1, chunkPos); - - thisPlayer.stopRiding(); - if (thisPlayer.isSleeping()) { - thisPlayer.stopSleepInBed(true, true); - } - - if (!isChangeOfWorld) { - this.connection.teleport(new PositionMoveRotation(VecHelper.toVanillaVector3d(pos), Vec3.ZERO, this.shadow$getYRot(), this.shadow$getXRot()), new HashSet<>()); - this.connection.resetPosition(); - } else { - this.bridge$changeDimension(new TeleportTransition(level, VecHelper.toVanillaVector3d(pos), thisPlayer.getKnownMovement(), - this.shadow$getYRot(), this.shadow$getXRot(), TeleportTransition.DO_NOTHING)); - } - return true; - } - @Override public void bridge$refreshExp() { this.lastRecordedExperience = -1; @@ -405,229 +356,48 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr this.connection.send(packet); } - /* - @Inject(method = "markPlayerActive()V", at = @At("HEAD")) - private void impl$onPlayerActive(final CallbackInfo ci) { - ((ServerPlayNetHandlerBridge) this.connection).bridge$resendLatestResourcePackRequest(); - } -*/ - - /** - * @author faithcaio - 2024-05-30 - MC 1.21 - * @reason Redirect all teleports through {@link #bridge$changeDimension} to fire our move/rotate/teleport events - */ - @Overwrite - public boolean teleportTo(final ServerLevel world, - final double x, - final double y, - final double z, - Set relative, - final float yaw, - final float pitch, - final boolean setCamera) { - if (setCamera) { - this.shadow$setCamera((net.minecraft.server.level.ServerPlayer) (Object) this); - } - final boolean hasMovementContext = PhaseTracker.getInstance().currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - if (!hasMovementContext) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - } - - return this.bridge$changeDimension(new TeleportTransition(world, new Vec3(x, y, z), Vec3.ZERO, yaw, pitch, relative, - e -> world.getChunkSource().addRegionTicket(TicketType.FORCED, e.chunkPosition(), 1, e.chunkPosition()))) != null; + @WrapOperation(method = "setCamera", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) + private boolean impl$onSpectatorTeleport( + final net.minecraft.server.level.ServerPlayer instance, final ServerLevel level, final double x, final double y, final double z, + final Set relatives, final float xRot, final float yRot, final boolean setCamera, final Operation original + ) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance(level).pushCauseFrame()) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.SPECTATOR); + return original.call(instance, level, x, y, z, relatives, xRot, yRot, setCamera); } } - /** - * This is effectively an overwrite of changeDimension and teleportTo. - * Handles {@link MoveEntityEvent} -> {@link RotateEntityEvent} for in dimension teleport - * Handles {@link ChangeEntityWorldEvent.Reposition} -> rotate -> {@link ChangeEntityWorldEvent.Post} - * {@link ChangeEntityWorldEvent.Pre} is handled at call sites. TODO only for known portals? - * For known portals {@link ChangeEntityWorldEvent.Reposition} is handled before at {@link Entity#handlePortal()} - * - * @return The {@link Entity} that is either this one, or replaces this one - */ - @Override - public net.minecraft.server.level.@Nullable ServerPlayer bridge$changeDimension(final TeleportTransition originalTransition) { - if (this.shadow$isRemoved()) { - return null; - } - - final var thisPlayer = (net.minecraft.server.level.ServerPlayer) (Object) this; - - if (originalTransition.missingRespawnBlock()) { // Player only code - this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); + @WrapMethod(method = "teleport(Lnet/minecraft/world/level/portal/TeleportTransition;)Lnet/minecraft/server/level/ServerPlayer;") + private net.minecraft.server.level.ServerPlayer impl$wrapTeleport(final TeleportTransition transition, Operation original) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(this.shadow$serverLevel()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { + frame.pushCause(this); + return original.call(transition); } + } - final var originalNewLevel = originalTransition.newLevel(); - final var oldLevel = this.shadow$serverLevel(); - - // SpongeStart - final var transition = this.impl$fireDimensionTransitionEvents(originalTransition, thisPlayer); + @ModifyVariable(method = "teleport(Lnet/minecraft/world/level/portal/TeleportTransition;)Lnet/minecraft/server/level/ServerPlayer;", argsOnly = true, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/portal/TeleportTransition;missingRespawnBlock()Z")) + private TeleportTransition impl$beforeTeleport(TeleportTransition transition, @Share("original-new-level") final LocalRef originalNewLevelRef, + @Cancellable final CallbackInfoReturnable cir) { + final ServerLevel originalNewLevel = transition.newLevel(); + originalNewLevelRef.set(originalNewLevel); + transition = originalNewLevel == this.shadow$serverLevel() ? this.impl$fireTeleportSameDimension(transition) : this.impl$fireTeleportCrossDimensionBefore(transition); if (transition == null) { - return null; - } - final var newLevel = transition.newLevel(); - // Sponge End - - if (newLevel.dimension() == oldLevel.dimension()) { // actually no dimension change - this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); - this.connection.resetPosition(); - transition.postTeleportTransition().onTransition(thisPlayer); - // TODO setYHeadRot after would rotate event result - return thisPlayer; - } - this.isChangingDimension = true; - LevelData lvlData = newLevel.getLevelData(); - this.connection.send(new ClientboundRespawnPacket(thisPlayer.createCommonSpawnInfo(newLevel), ClientboundRespawnPacket.KEEP_ALL_DATA)); - this.connection.send(new ClientboundChangeDifficultyPacket(lvlData.getDifficulty(), lvlData.isDifficultyLocked())); - PlayerList playerList = this.server.getPlayerList(); - playerList.sendPlayerPermissionLevel(thisPlayer); - oldLevel.removePlayerImmediately(thisPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - this.shadow$unsetRemoved(); - - final ProfilerFiller filler = Profiler.get(); - filler.push("moving"); - if (oldLevel.dimension() == Level.OVERWORLD && newLevel.dimension() == Level.NETHER) { - this.enteredNetherPosition = thisPlayer.position(); - } - filler.pop(); - - filler.push("placing"); - thisPlayer.setServerLevel(newLevel); - this.connection.teleport(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), transition.xRot()); - this.connection.resetPosition(); - newLevel.addDuringTeleport(thisPlayer); - filler.pop(); - - this.shadow$triggerDimensionChangeTriggers(oldLevel); // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic this was only done when using a portal - this.connection.send(new ClientboundPlayerAbilitiesPacket(thisPlayer.getAbilities())); - playerList.sendLevelInfo(thisPlayer, newLevel); - playerList.sendAllPlayerInfo(thisPlayer); - playerList.sendActivePlayerEffects(thisPlayer); - transition.postTeleportTransition().onTransition(thisPlayer); - // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic called bridge$getBossBarManager().onPlayerDisconnect(player); on both worlds - // TODO old sponge EntityUtil#performPostChangePlayerWorldLogic closed player.closeContainer(); when open - this.lastSentExp = -1; - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - // Sponge Start TODO cause/context like in impl$fireDimensionTransitionEvents - Sponge.eventManager().post( - SpongeEventFactory.createChangeEntityWorldEventPost( - PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) this, - (ServerWorld) oldLevel, - (ServerWorld) newLevel, - (ServerWorld) originalNewLevel - ) - ); - // Sponge End - return thisPlayer; - } - - @Unique - @Nullable - private TeleportTransition impl$fireDimensionTransitionEvents( - final TeleportTransition originalTransition, - final net.minecraft.server.level.ServerPlayer thisPlayer - ) { - var transition = originalTransition; - var isDimensionChange = transition.newLevel() != thisPlayer.serverLevel(); - - if (!this.impl$moveEventsFired) { - final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(thisPlayer.serverLevel()); - final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange() - .player(); - final boolean hasMovementContext = phaseTracker.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); - try (final TeleportContext context = contextToSwitchTo.buildAndSwitch(); - final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { - frame.pushCause(thisPlayer); - if (!hasMovementContext) { - // TODO we should be able to detect normal plugin code though - // add an unknown movement type? - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - } - - final var originalDest = VecHelper.toVector3d(transition.position()); - final @Nullable Vector3d newDest; - - if (isDimensionChange) { - if (transition.newLevel() != thisPlayer.level()) { - final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(thisPlayer, transition.newLevel()); - if (SpongeCommon.post(preEvent)) { - return null; - } - if (preEvent.destinationWorld() != preEvent.originalDestinationWorld()) { - transition = new TeleportTransition((ServerLevel) preEvent.destinationWorld(), - transition.position(), - transition.deltaMovement(), - transition.yRot(), transition.xRot(), - transition.missingRespawnBlock(), - transition.asPassenger(), - EnumSet.noneOf(Relative.class), - transition.postTeleportTransition()); - } - } - - final var reposition = this.bridge$fireRepositionEvent((ServerWorld) thisPlayer.serverLevel(), (ServerWorld) transition.newLevel(), originalDest); - if (reposition.isCancelled()) { - return null; // we did not move yet so just return - } - newDest = reposition.destinationPosition(); - } else { - if (ShouldFire.MOVE_ENTITY_EVENT) { // TODO move into impl$fireMoveEvent? - newDest = this.impl$fireMoveEvent(phaseTracker, originalDest); - if (newDest == null) { - return null; - } - } else { - newDest = originalDest; - } - } - if (newDest != originalDest) { - // if changed override the DimensionTransition - transition = new TeleportTransition(transition.newLevel(), - VecHelper.toVanillaVector3d(newDest), - transition.deltaMovement(), - transition.yRot(), transition.xRot(), - transition.missingRespawnBlock(), - transition.asPassenger(), - EnumSet.noneOf(Relative.class), - transition.postTeleportTransition()); - } - - final Vector3d toRot = new Vector3d(transition.xRot(), transition.yRot(), 0); - final Vector3d fromRot = new Vector3d(thisPlayer.getXRot(), thisPlayer.getYRot(), 0); - // TODO this skips with fuzzy rotation change check. Do we want this? - var newToRot = SpongeCommonEventFactory.callRotateEvent((org.spongepowered.api.entity.Entity) thisPlayer, fromRot, toRot); - if (newToRot == null) { - newToRot = fromRot; // Cancelled Rotate - Reset to original rotation - } - if (toRot != newToRot) { - transition = new TeleportTransition(transition.newLevel(), - transition.position(), - transition.deltaMovement(), - (float) newToRot.y(), (float) newToRot.x(), - transition.missingRespawnBlock(), - transition.asPassenger(), - EnumSet.noneOf(Relative.class), - transition.postTeleportTransition()); - } - - } - - } - - thisPlayer.setCamera(thisPlayer); - thisPlayer.stopRiding(); - if (thisPlayer.isSleeping()) { - thisPlayer.stopSleepInBed(true, true); + cir.setReturnValue(null); } - return transition; } + @Inject(method = "teleport(Lnet/minecraft/world/level/portal/TeleportTransition;)Lnet/minecraft/server/level/ServerPlayer;", + at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerPlayer;lastSentFood:I", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER)) + private void impl$afterTeleportCrossDimension( + final TeleportTransition transition, final CallbackInfoReturnable cir, + @Local(ordinal = 1) final ServerLevel oldLevel, @Share("original-new-level") LocalRef originalNewLevel + ) { + this.impl$fireTeleportCrossDimensionAfter(oldLevel, transition.newLevel(), originalNewLevel.get()); + } + @Redirect( method = {"openMenu", "openHorseInventory"}, at = @At( @@ -962,15 +732,6 @@ private boolean isPvpAllowed() { return ((ServerWorld) this.shadow$serverLevel()).properties().pvp(); } - /** - * @author gabizou - 1.21.2-pre1 - * @reason We route all teleportation through sponge's bridge for handling events - */ - @Overwrite - public net.minecraft.server.level.@Nullable ServerPlayer teleport(final TeleportTransition transition) { - return this.bridge$changeDimension(transition); - } - @Redirect(method = "findRespawnPositionAndUseSpawnBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getRespawnDimension()Lnet/minecraft/resources/ResourceKey;")) private ResourceKey impl$callRespawnPlayerSelectWorld(final net.minecraft.server.level.ServerPlayer player) { var playerRespawnDestination = this.server.getLevel(player.getRespawnDimension()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 18abded8d93..9388a4872d1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -26,7 +26,12 @@ import com.google.common.collect.ImmutableList; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.sugar.Cancellable; import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -41,15 +46,13 @@ import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; -import net.minecraft.util.profiling.Profiler; -import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityDimensions; -import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.PortalProcessor; +import net.minecraft.world.entity.Relative; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -94,6 +97,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -118,7 +122,8 @@ import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; -import org.spongepowered.common.hooks.PlatformHooks; +import org.spongepowered.common.event.tracking.phase.entity.EntityPhase; +import org.spongepowered.common.event.tracking.phase.entity.TeleportContext; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.DamageEventUtil; @@ -126,11 +131,7 @@ import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; @Mixin(Entity.class) public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, VanishableBridge, CommandSourceProviderBridge, DataCompoundHolder, TransientBridge { @@ -175,7 +176,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, @Shadow public abstract net.minecraft.world.phys.Vec3 shadow$getDeltaMovement(); @Shadow public abstract void shadow$setDeltaMovement(net.minecraft.world.phys.Vec3 motion); @Shadow public abstract void shadow$unRide(); - @Shadow protected abstract void shadow$removeAfterChangingDimensions(); + @Shadow public abstract boolean shadow$teleportTo(ServerLevel level, double x, double y, double z, Set relatives, float xRot, float yRot, boolean setCamera); @Shadow public abstract float shadow$getYRot(); @Shadow public abstract float shadow$getXRot(); @Shadow public abstract void shadow$setYRot(final float param0); @@ -198,7 +199,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, private boolean impl$isConstructing = true; private VanishState impl$vanishState = VanishState.unvanished(); protected boolean impl$transient = false; - protected boolean impl$moveEventsFired = false; + protected boolean impl$skipTeleportCrossDimensionBefore = false; protected boolean impl$hasCustomFireImmuneTicks = false; protected short impl$fireImmuneTicks = 0; private BlockPos impl$lastCollidedBlockPos; @@ -239,81 +240,20 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, return false; } - final ServerLevel originalWorld = (ServerLevel) this.shadow$level(); - final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(originalWorld); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()); try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - - final ServerLevel originalDestinationWorld = (ServerLevel) location.world(); - final ServerLevel destinationWorld; - final @org.checkerframework.checker.nullness.qual.Nullable Vector3d destinationPosition; - - final boolean isChangeOfWorld = this.shadow$level() != originalDestinationWorld; - if (isChangeOfWorld) { - final ChangeEntityWorldEvent.Pre event = PlatformHooks.INSTANCE.getEventHooks() - .callChangeEntityWorldEventPre((Entity) (Object) this, originalDestinationWorld); - if (event.isCancelled() || ((LevelBridge) event.destinationWorld()).bridge$isFake()) { - return false; - } - - destinationWorld = (ServerLevel) event.destinationWorld(); - final ChangeEntityWorldEvent.Reposition repositionEvent = - this.bridge$fireRepositionEvent(event.originalDestinationWorld(), event.destinationWorld(), location.position()); - if (repositionEvent.isCancelled()) { - return false; - } - destinationPosition = repositionEvent.destinationPosition(); - } else { - destinationWorld = (ServerLevel) this.shadow$level(); - destinationPosition = this.impl$fireMoveEvent(phaseTracker, location.position()); - if (destinationPosition == null) { - return false; - } - } - - final boolean completed = this.impl$setLocation(isChangeOfWorld, destinationWorld, destinationPosition); - - if (isChangeOfWorld) { - Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost( - phaseTracker.currentCause(), - (org.spongepowered.api.entity.Entity) this, - (ServerWorld) originalWorld, - (ServerWorld) originalDestinationWorld, - (ServerWorld) destinationWorld - )); - } - return completed; + return this.shadow$teleportTo((ServerLevel) location.world(), location.x(), location.y(), location.z(), Relative.ROTATION, 0, 0, true); } } - /** - * {@link Entity#teleportTo(double, double, double)} - * {@link Entity#teleportTo(ServerLevel, double, double, double, Set, float, float)} - */ - protected boolean impl$setLocation(final boolean isChangeOfWorld, final ServerLevel level, final Vector3d pos) { - // TODO post teleport ticket needed? - - if (!isChangeOfWorld) { - this.shadow$teleportTo(pos.x(), pos.y(), pos.z()); - return true; - } - - this.shadow$unRide(); - /*TODO old code had: - this.bridge$remove(Entity.RemovalReason.CHANGED_DIMENSION, true); // but via PlatformServerLevelBridge#bridge$removeEntity - this.bridge$revive(); - level.addDuringTeleport((Entity) (Object) this); - */ - var entity = this.shadow$getType().create(level, EntitySpawnReason.DIMENSION_TRAVEL); - if (entity == null) { - return false; + @WrapMethod(method = "teleport") + private Entity impl$wrapTeleport(final TeleportTransition transition, Operation original) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(this.shadow$level()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { + frame.pushCause(this); + return original.call(transition); } - entity.restoreFrom((Entity) (Object) this); - entity.moveTo(pos.x(), pos.y(), pos.z()); - this.shadow$setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); - level.addDuringTeleport(entity); - // TODO old code had reset empty time? on original/new world - return true; } @Override @@ -422,17 +362,6 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, return this.shadow$createCommandSourceStackForNameResolution((ServerLevel) this.shadow$level()); } - /** - * @author faithcaio - * @reason handle dimension change events see {@link #bridge$changeDimension(DimensionTransition)} - * - * TODO we may need to separate into Vanilla and Forge again - */ - @Overwrite - public Entity teleport(final TeleportTransition transition) { - return this.bridge$changeDimension(transition); - } - @Inject(method = "setAsInsidePortal", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;portalProcess:Lnet/minecraft/world/entity/PortalProcessor;")) public void impl$onCreatePortalProcessor(final Portal $$0, final BlockPos $$1, final CallbackInfo ci) { @@ -485,89 +414,205 @@ public Entity teleport(final TeleportTransition transition) { frame.addContext(EventContextKeys.PORTAL_LOGIC, (PortalLogic) portal); // TODO frame.addContext(EventContextKeys.PORTAL, transition); // TODO 2-dim portal? - this.impl$moveEventsFired = true; + this.impl$skipTeleportCrossDimensionBefore = true; return instance.teleport(transition); } finally { - this.impl$moveEventsFired = false; + this.impl$skipTeleportCrossDimensionBefore = false; } } - /** - * This is effectively an overwrite of changeDimension. - * - * @return The {@link Entity} that is either this one, or replaces this one - */ - @SuppressWarnings("ConstantConditions") - @Nullable - public Entity bridge$changeDimension(final TeleportTransition transition) { - final Entity thisEntity = (Entity) (Object) this; - if (!(thisEntity.level() instanceof ServerLevel oldLevel) || this.shadow$isRemoved()) { // Sponge inverted check - return null; + @ModifyVariable(method = "teleportCrossDimension", at = @At("HEAD"), argsOnly = true) + private TeleportTransition impl$beforeTeleportCrossDimension(TeleportTransition transition, @Cancellable final CallbackInfoReturnable cir) { + transition = this.impl$fireTeleportCrossDimensionBefore(transition); + if (transition == null) { + cir.setReturnValue(null); } + return transition; + } - // TODO context/events for non-players - var newLevel = transition.newLevel(); - var passengers = thisEntity.getPassengers(); - List recreatedPassengers = new ArrayList<>(); - this.shadow$unRide(); - for (final Entity passenger : passengers) { - var recreatedPassenger = passenger.teleport(transition); - if (recreatedPassenger != null) { - recreatedPassengers.add(recreatedPassenger); - } + @ModifyVariable(method = "teleportCrossDimension", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getPassengers()Ljava/util/List;"), argsOnly = true) + private ServerLevel impl$useChangeWorldEventLevel(final ServerLevel originalNewLevel, @Local(argsOnly = true) final TeleportTransition transition, + @Share("original-new-level") final LocalRef originalNewLevelRef) { + originalNewLevelRef.set(originalNewLevel); + return transition.newLevel(); + } + + @Inject(method = "teleportCrossDimension", at = @At("RETURN")) + private void impl$afterTeleportCrossDimension(final ServerLevel newLevel, final TeleportTransition transition, + final CallbackInfoReturnable cir, @Share("original-new-level") final LocalRef originalNewLevelRef) { + final Entity newEntity = cir.getReturnValue(); + ((EntityMixin) (Object) newEntity).impl$fireTeleportCrossDimensionAfter((ServerLevel) this.shadow$level(), newLevel, originalNewLevelRef.get()); + } + + + @ModifyVariable(method = "teleportSameDimension", at = @At("HEAD"), argsOnly = true) + private TeleportTransition impl$beforeTeleportSameDimension(TeleportTransition transition, @Cancellable final CallbackInfoReturnable cir) { + transition = this.impl$fireTeleportSameDimension(transition); + if (transition == null) { + cir.setReturnValue(null); + } + return transition; + } + + protected final @Nullable TeleportTransition impl$fireTeleportCrossDimensionBefore(TeleportTransition transition) { + if (this.impl$skipTeleportCrossDimensionBefore) { + return transition; } - ProfilerFiller filler = Profiler.get(); - filler.push("changeDimension"); + final ServerLevel originalLevel = (ServerLevel) this.shadow$level(); + final ServerLevel originalDestinationLevel = transition.newLevel(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(originalLevel); + try (final TeleportContext context = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange()) { + context.buildAndSwitch(); + + final ChangeEntityWorldEvent.Pre preEvent = SpongeEventFactory.createChangeEntityWorldEventPre( + phaseTracker.currentCause(), + (org.spongepowered.api.entity.Entity) this, + (ServerWorld) originalLevel, + (ServerWorld) originalDestinationLevel, + (ServerWorld) originalDestinationLevel); + if (SpongeCommon.post(preEvent)) { + return null; + } - var newEntity = oldLevel.dimension() == newLevel.dimension() ? thisEntity : thisEntity.getType().create(newLevel, EntitySpawnReason.DIMENSION_TRAVEL); - if (newEntity != null) { - if (thisEntity != newEntity) { - newEntity.restoreFrom(thisEntity); - this.shadow$removeAfterChangingDimensions(); + if (preEvent.destinationWorld() != originalDestinationLevel) { + transition = new TeleportTransition( + (ServerLevel) preEvent.destinationWorld(), + transition.position(), + transition.deltaMovement(), + transition.yRot(), transition.xRot(), + transition.missingRespawnBlock(), + transition.asPassenger(), + transition.relatives(), + transition.postTeleportTransition() + ); } - newEntity.moveTo(transition.position().x, transition.position().y, transition.position().z, transition.yRot(), newEntity.getXRot()); - newEntity.setDeltaMovement(transition.deltaMovement()); - if (thisEntity != newEntity) { - newLevel.addDuringTeleport(newEntity); + final Vector3d originalDestination = this.impl$absoluteDestinationPosition(transition); + final ChangeEntityWorldEvent.Reposition repositionEvent = SpongeEventFactory.createChangeEntityWorldEventReposition( + phaseTracker.currentCause(), + (org.spongepowered.api.entity.Entity) this, + (ServerWorld) originalLevel, + VecHelper.toVector3d(this.position), + originalDestination, + (ServerWorld) originalDestinationLevel, + originalDestination, + (ServerWorld) transition.newLevel() + ); + transition = this.impl$fireMove(transition, repositionEvent); + if (transition == null) { + return null; } - for (Entity recreatedPassenger : recreatedPassengers) { - recreatedPassenger.startRiding(newEntity, true); + return this.impl$fireRotate(transition); + } + } + + protected final void impl$fireTeleportCrossDimensionAfter(final ServerLevel originalLevel, final ServerLevel destinationLevel, final ServerLevel originalDestinationLevel) { + Sponge.eventManager().post( + SpongeEventFactory.createChangeEntityWorldEventPost( + PhaseTracker.getWorldInstance(destinationLevel).currentCause(), + (org.spongepowered.api.entity.Entity) this, + (ServerWorld) originalLevel, + (ServerWorld) destinationLevel, + (ServerWorld) originalDestinationLevel + ) + ); + } + + protected final @Nullable TeleportTransition impl$fireTeleportSameDimension(TeleportTransition transition) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()); + try (final TeleportContext context = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker)) { + context.buildAndSwitch(); + + if (ShouldFire.MOVE_ENTITY_EVENT) { + final Vector3d originalDestination = this.impl$absoluteDestinationPosition(transition); + final MoveEntityEvent moveEvent = SpongeEventFactory.createMoveEntityEvent( + phaseTracker.currentCause(), + (org.spongepowered.api.entity.Entity) this, + VecHelper.toVector3d(this.position), + originalDestination, + originalDestination + ); + transition = this.impl$fireMove(transition, moveEvent); + if (transition == null) { + return null; + } } - oldLevel.resetEmptyTime(); - newLevel.resetEmptyTime(); - transition.postTeleportTransition().onTransition(newEntity); + return this.impl$fireRotate(transition); + } + } + + private Vector3d impl$absoluteDestinationPosition(final TeleportTransition transition) { + final Vec3 origin = this.position; + final Vec3 pos = transition.position(); + final Set relatives = transition.relatives(); + return new Vector3d( + relatives.contains(Relative.X) ? origin.x + pos.x : pos.x, + relatives.contains(Relative.Y) ? origin.y + pos.y : pos.y, + relatives.contains(Relative.Z) ? origin.z + pos.z : pos.z + ); + } + + private @Nullable TeleportTransition impl$fireMove(final TeleportTransition transition, final MoveEntityEvent moveEvent) { + if (SpongeCommon.post(moveEvent)) { + return null; + } + if (moveEvent.destinationPosition().equals(moveEvent.originalDestinationPosition())) { + return transition; } - // TODO impl$fireMoveEvent when not changing dimensions (e.g. EndGateways) + final Set newRelatives = EnumSet.noneOf(Relative.class); + newRelatives.addAll(transition.relatives()); + newRelatives.removeAll(Constants.Entity.RELATIVE_POSITION); - filler.pop(); - return newEntity; + return new TeleportTransition( + transition.newLevel(), + VecHelper.toVanillaVector3d(moveEvent.destinationPosition()), + transition.deltaMovement(), + transition.yRot(), transition.xRot(), + transition.missingRespawnBlock(), + transition.asPassenger(), + newRelatives, + transition.postTeleportTransition() + ); } - @Override - public final ChangeEntityWorldEvent.Reposition bridge$fireRepositionEvent(final ServerWorld originalDestinationWorld, - final ServerWorld targetWorld, - final Vector3d destinationPosition) { + private TeleportTransition impl$fireRotate(final TeleportTransition transition) { + final Vector3d fromRot = new Vector3d(this.shadow$getXRot(), this.shadow$getYRot(), 0); - this.impl$moveEventsFired = true; - final ChangeEntityWorldEvent.Reposition reposition = SpongeEventFactory.createChangeEntityWorldEventReposition( - PhaseTracker.getInstance().currentCause(), - (org.spongepowered.api.entity.Entity) this, - (ServerWorld) this.shadow$level(), - VecHelper.toVector3d(this.position), - destinationPosition, - originalDestinationWorld, - destinationPosition, - targetWorld + final Set relatives = transition.relatives(); + final Vector3d toRot = new Vector3d( + relatives.contains(Relative.X_ROT) ? fromRot.x() + transition.xRot() : transition.xRot(), + relatives.contains(Relative.Y_ROT) ? fromRot.y() + transition.yRot() : transition.yRot(), + 0 ); - SpongeCommon.post(reposition); - return reposition; + @Nullable Vector3d newToRot = SpongeCommonEventFactory.callRotateEvent((org.spongepowered.api.entity.Entity) this, fromRot, toRot); + if (newToRot == null) { + newToRot = fromRot; // Cancelled, reset to original rotation + } + + if (newToRot.equals(toRot)) { + return transition; + } + + final Set newRelatives = EnumSet.noneOf(Relative.class); + newRelatives.addAll(transition.relatives()); + newRelatives.removeAll(Relative.ROTATION); + + return new TeleportTransition( + transition.newLevel(), + transition.position(), + transition.deltaMovement(), + (float) newToRot.y(), (float) newToRot.x(), + transition.missingRespawnBlock(), + transition.asPassenger(), + newRelatives, + transition.postTeleportTransition() + ); } @Override @@ -585,31 +630,6 @@ public Entity teleport(final TeleportTransition transition) { return NBTDataTypes.ENTITY; } - - protected final @org.checkerframework.checker.nullness.qual.Nullable Vector3d impl$fireMoveEvent( - final PhaseTracker phaseTracker, final Vector3d originalDestinationPosition) { - final boolean hasMovementContext = phaseTracker.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); - if (!hasMovementContext) { - phaseTracker.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - } - - final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(phaseTracker.currentCause(), - (org.spongepowered.api.entity.Entity) this, VecHelper.toVector3d(this.shadow$position()), - originalDestinationPosition, - originalDestinationPosition); - - if (!hasMovementContext) { - phaseTracker.popCause(); - phaseTracker.removeContext(EventContextKeys.MOVEMENT_TYPE); - } - - if (SpongeCommon.post(event)) { - return null; - } - - return event.destinationPosition(); - } - @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", at = @At( value = "FIELD", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java index 2e1e47c62fe..49ced1bac1f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/PortalProcessorMixin.java @@ -26,7 +26,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.PortalProcessor; import net.minecraft.world.entity.Relative; @@ -49,7 +48,6 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.entity.EntityPhase; import org.spongepowered.common.event.tracking.phase.entity.TeleportContext; -import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.util.VecHelper; import org.spongepowered.math.vector.Vector3d; @@ -78,16 +76,12 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { @Redirect(method = "getPortalDestination", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Portal;getPortalDestination(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/portal/TeleportTransition;")) public TeleportTransition impl$onGetPortalDestination(final Portal instance, final ServerLevel serverLevel, final Entity entity, final BlockPos blockPos) { - final var spongEntity = (org.spongepowered.api.entity.Entity) entity; - + final var spongeEntity = (org.spongepowered.api.entity.Entity) entity; var finalPortal = instance; - final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(PhaseTracker.getInstance()).worldChange(); - if (entity instanceof ServerPlayer) { - contextToSwitchTo.player(); - } - try (final TeleportContext context = contextToSwitchTo.buildAndSwitch(); - final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(serverLevel); + try (final TeleportContext context = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange().buildAndSwitch(); + final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(entity); var be = serverLevel.getBlockEntity(this.entryPosition); if (be != null) { @@ -101,7 +95,7 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { frame.addContext(EventContextKeys.MOVEMENT_TYPE, movementType); frame.addContext(EventContextKeys.PORTAL_LOGIC, (PortalLogic) portal); - var preEvent = SpongeEventFactory.createInvokePortalEventPrepare(frame.currentCause(), spongEntity, (PortalLogic) this.portal); + var preEvent = SpongeEventFactory.createInvokePortalEventPrepare(frame.currentCause(), spongeEntity, (PortalLogic) this.portal); if (SpongeCommon.post(preEvent)) { return null; } @@ -118,18 +112,23 @@ public abstract class PortalProcessorMixin implements PortalProcessorBridge { frame.pushCause(finalPortal); frame.addContext(EventContextKeys.PORTAL, (org.spongepowered.api.world.portal.Portal) this); - var preWorldChangeEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(entity, transition.newLevel()); + final var preWorldChangeEvent = SpongeEventFactory.createChangeEntityWorldEventPre( + frame.currentCause(), + (org.spongepowered.api.entity.Entity) entity, + (ServerWorld) entity.level(), + (ServerWorld) transition.newLevel(), + (ServerWorld) transition.newLevel()); if (preWorldChangeEvent.isCancelled()) { wrapperTransaction.markCancelled(); return null; } var tpEvent = SpongeEventFactory.createInvokePortalEventExecute(frame.currentCause(), - spongEntity, + spongeEntity, (ServerWorld) entity.level(), new Vector3d(transition.xRot(), transition.yRot(), 0), - spongEntity.position(), - spongEntity.rotation(), + spongeEntity.position(), + spongeEntity.rotation(), (ServerWorld) transition.newLevel(), VecHelper.toVector3d(transition.position()), VecHelper.toVector3d(transition.position()), diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index e850c287944..b91416ad6b2 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -68,6 +68,7 @@ "server.commands.GameRuleCommandMixin", "server.commands.KickCommandMixin", "server.commands.SaveAllCommandMixin", + "server.commands.SpreadPlayersCommandMixin", "server.commands.TeleportCommandMixin", "server.commands.WeatherCommandMixin", "server.commands.WorldBorderCommandMixin", diff --git a/testplugins/src/main/java/org/spongepowered/test/movement/MovementTest.java b/testplugins/src/main/java/org/spongepowered/test/movement/MovementTest.java index 73524955ac0..95d3460cb66 100644 --- a/testplugins/src/main/java/org/spongepowered/test/movement/MovementTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/movement/MovementTest.java @@ -193,6 +193,9 @@ public void onMovePlayer(final MoveEntityEvent event) { final Optional type = event.context().get(EventContextKeys.MOVEMENT_TYPE); final Logger logger = MovementTest.this.plugin.logger(); logger.info(MovementTest.marker, name + ": Movement Type: " + type.map(t -> RegistryTypes.MOVEMENT_TYPE.get().valueKey(t).toString()).orElse("?")); + if (type.isEmpty()) { + Thread.dumpStack(); + } if (MovementTest.this.cancelMovement) { event.setCancelled(true); diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index ca2b72e8874..bdb07cd785a 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -24,7 +24,6 @@ "registries.BuiltInRegistriesMixin_Vanilla", "server.BootstrapMixin_Vanilla", "server.MinecraftServerMixin_Vanilla", - "server.commands.SpreadPlayersCommandMixin_Vanilla", "server.level.ServerPlayerMixin_Vanilla", "server.network.ServerGamePacketListenerImplMixin_Vanilla", "server.packs.repository.PackRepositoryMixin_Vanilla", From 2943f8e1623a11275b6b122ac2e3e40b805e8ee0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 4 Dec 2025 21:55:08 -0800 Subject: [PATCH 419/586] feat(minecraft): update towards 25w42a Updated Minecraft version to 25w42a, incorporating upstream changes related to environment attribute mapping, biome attributes, and world rules. Adjusted various APIs and mixins to support new attribute-based configurations. --- gradle.properties | 2 +- .../data/provider/world/WorldTypeData.java | 12 +++--- .../data/provider/world/biome/BiomeData.java | 31 +++++++++++---- .../scoreboard/SpongeScoreFormatFactory.java | 4 +- .../world/biome/SpongeBiomeBuilder.java | 34 +++++++++++------ .../ambient/SpongeParticleConfigFactory.java | 4 +- .../ambient/SpongeSoundConfigFactory.java | 4 +- .../world/server/SpongeWorldTypeBuilder.java | 19 +++++++--- .../api/minecraft/sounds/MusicMixin_API.java | 4 +- .../AmbientAdditionsSettingsMixin_API.java | 4 +- .../AmbientMoodSettingsMixin_API.java | 4 +- .../AmbientParticleSettingsMixin_API.java | 12 +++--- .../mixin/core/block/BedBlockMixin.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 38 ++++++++----------- .../level/dimension/DimensionTypeMixin.java | 2 +- src/mixins/resources/mixins.sponge.api.json | 6 +-- .../client/gui/widget/MetadataPanel.java | 2 +- 17 files changed, 109 insertions(+), 77 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/{level/biome => attribute}/AmbientAdditionsSettingsMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/{level/biome => attribute}/AmbientMoodSettingsMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/{level/biome => attribute}/AmbientParticleSettingsMixin_API.java (87%) diff --git a/gradle.properties b/gradle.properties index 0730178be65..1555434b90c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=25w41a +minecraftVersion=25w42a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java index 70b27307881..6b47942df32 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java @@ -25,6 +25,8 @@ package org.spongepowered.common.data.provider.world; import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.attribute.BedRule; +import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -54,7 +56,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.WORLD_TYPE_EFFECT) .get(WorldTypeData::worldTypeEffect) .create(Keys.SCORCHING) - .get(DimensionType::ultraWarm) + .get(d -> d.attributes().applyModifier(EnvironmentAttributes.WATER_EVAPORATES, false)) .create(Keys.NATURAL_WORLD_TYPE) .get(DimensionType::natural) .create(Keys.COORDINATE_MULTIPLIER) @@ -64,17 +66,17 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.HAS_CEILING) .get(DimensionType::hasCeiling) .create(Keys.PIGLIN_SAFE) - .get(DimensionType::piglinSafe) + .get(d -> d.attributes().applyModifier(EnvironmentAttributes.NETHER_PORTAL_SPAWNS_PIGLINS, false)) .create(Keys.BEDS_USABLE) - .get(DimensionType::bedWorks) + .get(d -> d.attributes().applyModifier(EnvironmentAttributes.BED_RULE, BedRule.CAN_SLEEP_WHEN_DARK).explodes()) .create(Keys.RESPAWN_ANCHOR_USABLE) - .get(DimensionType::respawnAnchorWorks) + .get(d -> d.attributes().applyModifier(EnvironmentAttributes.RESPAWN_ANCHOR_WORKS, false)) .create(Keys.INFINIBURN) .get(dimensionType -> (Tag) (Object) dimensionType.infiniburn()) .create(Keys.WORLD_FLOOR) .get(DimensionType::minY) .create(Keys.HAS_RAIDS) - .get(DimensionType::hasRaids) + .get(d -> d.attributes().applyModifier(EnvironmentAttributes.CAN_START_RAID, true)) .create(Keys.WORLD_HEIGHT) .get(DimensionType::height) .create(Keys.WORLD_LOGICAL_HEIGHT) diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index 30a3bffb721..c9c8ade65a1 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -26,6 +26,8 @@ import net.minecraft.core.Holder; import net.minecraft.util.random.Weighted; +import net.minecraft.world.attribute.AmbientSounds; +import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeGenerationSettings; @@ -88,13 +90,22 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.NATURAL_SPAWNER_COST) .get(BiomeData::naturalSpawnerCost) .create(Keys.FOG_COLOR) - .get(h -> Color.ofRgb(h.getSpecialEffects().getFogColor())) + .get(h -> { + final var value = h.getAttributes().applyModifier(EnvironmentAttributes.FOG_COLOR, EnvironmentAttributes.FOG_COLOR.defaultValue()); + return Color.ofRgb(value); + }) .create(Keys.WATER_COLOR) .get(h -> Color.ofRgb(h.getSpecialEffects().getWaterColor())) .create(Keys.WATER_FOG_COLOR) - .get(h -> Color.ofRgb(h.getSpecialEffects().getWaterFogColor())) + .get(h -> { + final var value = h.getAttributes().applyModifier(EnvironmentAttributes.WATER_FOG_COLOR, EnvironmentAttributes.WATER_FOG_COLOR.defaultValue()); + return Color.ofRgb(value); + }) .create(Keys.SKY_COLOR) - .get(h -> Color.ofRgb(h.getSpecialEffects().getSkyColor())) + .get(h -> { + final var value = h.getAttributes().applyModifier(EnvironmentAttributes.SKY_COLOR, EnvironmentAttributes.SKY_COLOR.defaultValue()); + return Color.ofRgb(value); + }) .create(Keys.FOLIAGE_COLOR) .get(h -> h.getSpecialEffects().getFoliageColorOverride().map(Color::ofRgb).orElse(null)) .create(Keys.GRASS_COLOR) @@ -102,13 +113,19 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.GRASS_COLOR_MODIFIER) .get(h -> (GrassColorModifier) (Object) h.getSpecialEffects().getGrassColorModifier()) .create(Keys.BACKGROUND_MUSIC) - .get(h -> h.getSpecialEffects().getBackgroundMusic().map(a -> a.unwrap()).flatMap(e -> e.stream().findFirst().map(Weighted::value)).map(SoundConfig.BackgroundMusic.class::cast).orElse(null)) + .get(h -> { + final var value = h.getAttributes().applyModifier(EnvironmentAttributes.BACKGROUND_MUSIC, EnvironmentAttributes.BACKGROUND_MUSIC.defaultValue()); + return (SoundConfig.BackgroundMusic) (Object) value; + }) .create(Keys.AMBIENT_ADDITIONAL_SOUND) - .get(h -> h.getSpecialEffects().getAmbientAdditionsSettings().map(SoundConfig.Additional.class::cast).orElse(null)) + .get(h -> { + final var value = h.getAttributes().applyModifier(EnvironmentAttributes.AMBIENT_SOUNDS, EnvironmentAttributes.AMBIENT_SOUNDS.defaultValue()); + return (SoundConfig.Additional) (Object) value; + }) .create(Keys.AMBIENT_MOOD) - .get(h -> h.getSpecialEffects().getAmbientMoodSettings().map(SoundConfig.Mood.class::cast).orElse(null)) + .get(h -> h.getAttributes().applyModifier(EnvironmentAttributes.AMBIENT_SOUNDS, AmbientSounds.EMPTY).mood().map(SoundConfig.Mood.class::cast).orElse(null)) .create(Keys.AMBIENT_PARTICLE) - .get(h -> h.getSpecialEffects().getAmbientParticleSettings().map(ParticleConfig.class::cast).orElse(null)) + .get(h -> h.getAttributes().applyModifier(EnvironmentAttributes.AMBIENT_PARTICLES,List.of()).stream().findFirst().map(ParticleConfig.class::cast).orElse(null)) .asImmutable(BiomeAccessor.class) .create(Keys.HUMIDITY) .get(h -> (double) h.accessor$climateSettings().downfall()) diff --git a/src/main/java/org/spongepowered/common/scoreboard/SpongeScoreFormatFactory.java b/src/main/java/org/spongepowered/common/scoreboard/SpongeScoreFormatFactory.java index 083d6f73c6c..0fd6ad58f7c 100644 --- a/src/main/java/org/spongepowered/common/scoreboard/SpongeScoreFormatFactory.java +++ b/src/main/java/org/spongepowered/common/scoreboard/SpongeScoreFormatFactory.java @@ -41,11 +41,11 @@ public ScoreFormat blank() { @Override public ScoreFormat fixed(final Component component) { - return (ScoreFormat) new FixedFormat(SpongeAdventure.asVanilla(component)); + return (ScoreFormat) (Object) new FixedFormat(SpongeAdventure.asVanilla(component)); } @Override public ScoreFormat styled(final Style style) { - return (ScoreFormat) new StyledFormat(SpongeAdventure.asVanilla(style)); + return (ScoreFormat) (Object) new StyledFormat(SpongeAdventure.asVanilla(style)); } } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java index 179d1ced86d..785b867e02d 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeBuilder.java @@ -27,9 +27,14 @@ import net.minecraft.core.Holder; import net.minecraft.sounds.Music; import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.attribute.AmbientAdditionsSettings; +import net.minecraft.world.attribute.AmbientMoodSettings; +import net.minecraft.world.attribute.AmbientParticle; +import net.minecraft.world.attribute.AmbientSounds; +import net.minecraft.world.attribute.BackgroundMusic; +import net.minecraft.world.attribute.EnvironmentAttributeMap; +import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.level.biome.AmbientAdditionsSettings; -import net.minecraft.world.level.biome.AmbientParticleSettings; import net.minecraft.world.level.biome.BiomeGenerationSettings; import net.minecraft.world.level.biome.BiomeSpecialEffects; import net.minecraft.world.level.biome.MobSpawnSettings; @@ -117,19 +122,22 @@ public Biome build() { final Map> features = this.manipulator.getOrElse(Keys.FEATURES, Map.of()); final List carvers = this.manipulator.getOrElse(Keys.CARVERS, List.of()); + final var attributes = EnvironmentAttributeMap.builder(); + attributes.set(EnvironmentAttributes.FOG_COLOR, fogColor.rgb()) + .set(EnvironmentAttributes.WATER_FOG_COLOR, waterFogColor.rgb()) + .set(EnvironmentAttributes.SKY_COLOR, skyColor.rgb()); final BiomeSpecialEffects.Builder effectsBuilder = new BiomeSpecialEffects.Builder() - .fogColor(fogColor.rgb()) .waterColor(waterColor.rgb()) - .waterFogColor(waterFogColor.rgb()) - .skyColor(skyColor.rgb()) .grassColorModifier((BiomeSpecialEffects.GrassColorModifier) (Object) grassColorModifier); foliageColor.ifPresent(c -> effectsBuilder.foliageColorOverride(c.rgb())); grassColor.ifPresent(c -> effectsBuilder.grassColorOverride(c.rgb())); - particleSettings.ifPresent(ps -> effectsBuilder.ambientParticle((AmbientParticleSettings) (Object) ps)); - ambientSound.ifPresent(s -> effectsBuilder.ambientLoopSound(Holder.direct((SoundEvent) (Object) s))); - ambientMood.ifPresent(m -> effectsBuilder.ambientMoodSound((net.minecraft.world.level.biome.AmbientMoodSettings) (Object) m)); - additionalSound.ifPresent(s -> effectsBuilder.ambientAdditionsSound((AmbientAdditionsSettings) (Object) s)); - backgroundMusic.ifPresent(m -> effectsBuilder.backgroundMusic((Music) (Object) m)); + final var vanillaAmbientSound = new AmbientSounds( + ambientSound.map(SoundEvent.class::cast).map(Holder::direct), + ambientMood.map(AmbientMoodSettings.class::cast), + additionalSound.map(AmbientAdditionsSettings.class::cast).map(List::of).orElse(List.of())); + attributes.set(EnvironmentAttributes.AMBIENT_SOUNDS, vanillaAmbientSound); + + backgroundMusic.ifPresent(m -> attributes.set(EnvironmentAttributes.BACKGROUND_MUSIC, new BackgroundMusic((Music) (Object) m))); final MobSpawnSettings.Builder spawnerBuilder = new MobSpawnSettings.Builder() .creatureGenerationProbability(spawnChance.floatValue()); @@ -152,7 +160,11 @@ public Biome build() { .temperatureAdjustment((net.minecraft.world.level.biome.Biome.TemperatureModifier) (Object) temperatureModifier) .specialEffects(effectsBuilder.build()) .mobSpawnSettings(spawnerBuilder.build()) - .generationSettings(generationBuilder.build()); + .generationSettings(generationBuilder.build()) + .putAttributes(attributes.build()) + ; + particleSettings.ifPresent(ps -> vanillaBuilder.setAttribute(EnvironmentAttributes.AMBIENT_PARTICLES, List.of((AmbientParticle) (Object) ps))); + return (Biome) (Object) vanillaBuilder.build(); } } diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java index fb9455c541e..6bc1657f8dd 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeParticleConfigFactory.java @@ -25,7 +25,7 @@ package org.spongepowered.common.world.biome.ambient; import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.world.level.biome.AmbientParticleSettings; +import net.minecraft.world.attribute.AmbientParticle; import org.spongepowered.api.effect.particle.ParticleType; import org.spongepowered.api.world.biome.ambient.ParticleConfig; @@ -33,6 +33,6 @@ public class SpongeParticleConfigFactory implements ParticleConfig.Factory { @Override public ParticleConfig of(final ParticleType type, final float probability) { - return (ParticleConfig) (Object) new AmbientParticleSettings(((ParticleOptions) type), probability); + return (ParticleConfig) (Object) new AmbientParticle(((ParticleOptions) type), probability); } } diff --git a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java index 6d69000d327..7fcb108a956 100644 --- a/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/ambient/SpongeSoundConfigFactory.java @@ -27,8 +27,8 @@ import net.minecraft.core.Holder; import net.minecraft.sounds.Music; import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.level.biome.AmbientAdditionsSettings; -import net.minecraft.world.level.biome.AmbientMoodSettings; +import net.minecraft.world.attribute.AmbientAdditionsSettings; +import net.minecraft.world.attribute.AmbientMoodSettings; import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index acaee5eed11..b222d4f6358 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -26,6 +26,9 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.valueproviders.UniformInt; +import net.minecraft.world.attribute.BedRule; +import net.minecraft.world.attribute.EnvironmentAttributeMap; +import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.NonNull; @@ -45,7 +48,6 @@ import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; -import java.util.Optional; import java.util.OptionalLong; public final class SpongeWorldTypeBuilder implements WorldType.Builder { @@ -106,16 +108,23 @@ public WorldType.Builder from(final WorldType type) { final SpongeDimensionTypes.SpongeDataSection spongeData = new SpongeDimensionTypes.SpongeDataSection(createDragonFight); try { + final var attributes = EnvironmentAttributeMap.builder(); + attributes.set(EnvironmentAttributes.PIGLINS_ZOMBIFY, !piglinSafe); + attributes.set(EnvironmentAttributes.BED_RULE, bedsUsable ? BedRule.CAN_SLEEP_WHEN_DARK : BedRule.EXPLODES); + attributes.set(EnvironmentAttributes.RESPAWN_ANCHOR_WORKS, respawnAnchorsUsable); + attributes.set(EnvironmentAttributes.CAN_START_RAID, hasRaids); final DimensionType dimensionType = new DimensionType(fixedTime == null ? OptionalLong.empty() : OptionalLong.of(fixedTime.asTicks().ticks()), - hasSkylight, hasCeiling, scorching, natural, coordinateMultiplier, - bedsUsable, respawnAnchorsUsable, + hasSkylight, + hasCeiling, + natural, coordinateMultiplier, floor, height, logicalHeight, ((TagBridge) infiniburn).bridge$asVanillaTag(), (ResourceLocation) (Object) effect.key(), ambientLighting, - Optional.empty(), - new DimensionType.MonsterSettings(piglinSafe, hasRaids, monsterSpawnLightTest, monsterSpawnBlockLightLimit)); + new DimensionType.MonsterSettings(monsterSpawnLightTest, monsterSpawnBlockLightLimit), + attributes.build() + ); if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { bridge.bridge$decorateData(spongeData); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java index c865d062e76..4484c81e603 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/MusicMixin_API.java @@ -41,7 +41,7 @@ public abstract class MusicMixin_API implements SoundConfig.BackgroundMusic { // @formatter:off - @Shadow @Final private Holder event; + @Shadow @Final private Holder sound; @Shadow @Final private int minDelay; @Shadow @Final private int maxDelay; @Shadow @Final private boolean replaceCurrentMusic; @@ -49,7 +49,7 @@ public abstract class MusicMixin_API implements SoundConfig.BackgroundMusic { @Override public SoundType sound() { - return (SoundType) (Object) this.event.value(); + return (SoundType) (Object) this.sound.value(); } @Intrinsic diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientAdditionsSettingsMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientAdditionsSettingsMixin_API.java index 6aa511b938c..efa32f2585c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientAdditionsSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientAdditionsSettingsMixin_API.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.biome; +package org.spongepowered.common.mixin.api.minecraft.world.attribute; import net.minecraft.core.Holder; import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.level.biome.AmbientAdditionsSettings; +import net.minecraft.world.attribute.AmbientAdditionsSettings; import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientMoodSettingsMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientMoodSettingsMixin_API.java index fb02cb60796..8b6291acc0f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientMoodSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientMoodSettingsMixin_API.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.biome; +package org.spongepowered.common.mixin.api.minecraft.world.attribute; import net.minecraft.core.Holder; import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.level.biome.AmbientMoodSettings; +import net.minecraft.world.attribute.AmbientMoodSettings; import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.api.world.biome.ambient.SoundConfig; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientParticleSettingsMixin_API.java similarity index 87% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientParticleSettingsMixin_API.java index 3190132e2e9..48063b6e2da 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/biome/AmbientParticleSettingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/attribute/AmbientParticleSettingsMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.biome; +package org.spongepowered.common.mixin.api.minecraft.world.attribute; -import net.minecraft.world.level.biome.AmbientParticleSettings; +import net.minecraft.world.attribute.AmbientParticle; import org.spongepowered.api.effect.particle.ParticleType; import org.spongepowered.api.world.biome.ambient.ParticleConfig; import org.spongepowered.asm.mixin.Final; @@ -34,13 +34,13 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -@Mixin(AmbientParticleSettings.class) +@Mixin(AmbientParticle.class) @Implements(@Interface(iface = ParticleConfig.class, prefix = "api$")) public abstract class AmbientParticleSettingsMixin_API implements ParticleConfig { // @formatter:off @Shadow @Final private float probability; - @Shadow @Final private net.minecraft.core.particles.ParticleOptions options; + @Shadow @Final private net.minecraft.core.particles.ParticleOptions particle; // @formatter:on @Intrinsic @@ -50,10 +50,10 @@ public abstract class AmbientParticleSettingsMixin_API implements ParticleConfig @Override public ParticleType type() { - if (this.options instanceof ParticleType type) { + if (this.particle instanceof ParticleType type) { return type; } - throw new UnsupportedOperationException("Unsupported ParticleOptions: " + this.options.getClass().getSimpleName()); + throw new UnsupportedOperationException("Unsupported ParticleOptions: " + this.particle.getClass().getSimpleName()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java index eecb90a85df..dd3357b9c2e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java @@ -67,8 +67,8 @@ public class BedBlockMixin { final BlockSnapshot snapshot = ((ServerWorld) param1).createSnapshot(bedLocation.getX(), bedLocation.getY(), bedLocation.getZ()); if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventFailed(currentCause, snapshot, (Living) param3))) { param3.startSleepInBed(param2).ifLeft((param1x) -> { - if (param1x != null) { - param3.displayClientMessage(param1x.getMessage(), true); + if (param1x != null && param1x.message() != null) { + param3.displayClientMessage(param1x.message(), true); } }); cir.setReturnValue(InteractionResult.SUCCESS); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index fa85628ffaf..5b6ecd4e839 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -898,29 +898,21 @@ public void sendMessage(final OutgoingChatMessage $$0, final boolean $$1, final @Inject(method = "startSleepInBed", at = @At(value = "RETURN"), cancellable = true) private void impl$onReturnSleep(final BlockPos param0, final CallbackInfoReturnable> cir) { final Either returnValue = cir.getReturnValue(); - if (returnValue.left().isPresent()) { - switch (returnValue.left().get()) { - - case NOT_POSSIBLE_HERE: - case TOO_FAR_AWAY: - case NOT_POSSIBLE_NOW: - case OBSTRUCTED: - case NOT_SAFE: - final Cause currentCause = PhaseTracker.getInstance().currentCause(); - final BlockSnapshot snapshot = ((ServerWorld) this.shadow$level()).createSnapshot(param0.getX(), param0.getY(), param0.getZ()); - if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventFailed(currentCause, snapshot, (Living) this))) { - final Either var5 = super.shadow$startSleepInBed(param0).ifRight((param0x) -> { - this.shadow$awardStat(Stats.SLEEP_IN_BED); - CriteriaTriggers.SLEPT_IN_BED.trigger((net.minecraft.server.level.ServerPlayer) (Object) this); - }); - ((ServerLevel) this.shadow$level()).updateSleepingPlayerList(); - cir.setReturnValue(var5); - } - break; - case OTHER_PROBLEM: // ignore - break; + returnValue.ifLeft(problem -> { + if (problem.message() == null) { + return; } - } + final Cause currentCause = PhaseTracker.getInstance().currentCause(); + final BlockSnapshot snapshot = ((ServerWorld) this.shadow$level()).createSnapshot(param0.getX(), param0.getY(), param0.getZ()); + if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventFailed(currentCause, snapshot, (Living) this))) { + final Either var5 = super.shadow$startSleepInBed(param0).ifRight((param0x) -> { + this.shadow$awardStat(Stats.SLEEP_IN_BED); + CriteriaTriggers.SLEPT_IN_BED.trigger((net.minecraft.server.level.ServerPlayer) (Object) this); + }); + ((ServerLevel) this.shadow$level()).updateSleepingPlayerList(); + cir.setReturnValue(var5); + } + }); } @Override @@ -1056,7 +1048,7 @@ private boolean isPvpAllowed() { /** * Fixes MC-302672 */ - @WrapOperation(method = "onEffectAdded", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) + @WrapOperation(method = "onEffectAdded", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V")) private void impl$onEffectAdded(ServerGamePacketListenerImpl instance, Packet packet, Operation original) { if (instance == null) { return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/DimensionTypeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/DimensionTypeMixin.java index 0c8ac09926c..5b479180938 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/DimensionTypeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/dimension/DimensionTypeMixin.java @@ -58,7 +58,7 @@ public abstract class DimensionTypeMixin implements DimensionTypeBridge { return this.impl$createDragonFight; } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ExtraCodecs;catchDecoderException(Lcom/mojang/serialization/Codec;)Lcom/mojang/serialization/Codec;")) + @Redirect(method = "createDirectCodec", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ExtraCodecs;catchDecoderException(Lcom/mojang/serialization/Codec;)Lcom/mojang/serialization/Codec;")) private static Codec impl$onWrapCodec(final Codec codec) { return ExtraCodecs.catchDecoderException(SpongeDimensionTypes.injectCodec(codec)); } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 2c680abfd3a..357fcb09fb7 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -374,9 +374,9 @@ "minecraft.world.level.LevelWriterMixin_API", "minecraft.world.level.LightLayerMixin_API", "minecraft.world.level.ServerExplosionMixin_API", - "minecraft.world.level.biome.AmbientAdditionsSettingsMixin_API", - "minecraft.world.level.biome.AmbientMoodSettingsMixin_API", - "minecraft.world.level.biome.AmbientParticleSettingsMixin_API", + "minecraft.world.attribute.AmbientAdditionsSettingsMixin_API", + "minecraft.world.attribute.AmbientMoodSettingsMixin_API", + "minecraft.world.attribute.AmbientParticleSettingsMixin_API", "minecraft.world.level.biome.Biome_PrecipitationMixin_API", "minecraft.world.level.biome.Biome_TemperatureModifierMixin_API", "minecraft.world.level.biome.BiomeMixin_API", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 3b1f26849cc..66c37f503b4 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -290,7 +290,7 @@ public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated final Component component = entry.value; if (component != null) { - this.screen.handleComponentClicked(component.getStyle()); +// this.screen.handleComponentClicked(component.getStyle()); return true; } return super.mouseClicked(event, repeated); From 3134a3e145f3939c2ceeff1eac6a138eddfcd801 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 4 Dec 2025 23:26:41 -0800 Subject: [PATCH 420/586] feat(minecraft): update towards 25w44a Breaking changes: - GameRules are now registered and have therefor real IDs, so all field names are changed Notable Additions: - Added Parched - Added CamelHusk See https://minecraft.wiki/w/Java_Edition_25w44a --- SpongeAPI | 2 +- .../world/level/LevelDataRegistries.java | 20 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 429 +++++++++++++++++- .../world/level/GameRulesAccessor.java | 10 +- .../world/level/GameRules_ValueAccessor.java | 7 +- .../resources/mixins.sponge.accessors.json | 1 - .../provider/world/WorldPropertiesData.java | 4 +- .../data/provider/world/biome/BiomeData.java | 8 +- .../event/SpongeCommonEventFactory.java | 4 +- .../common/hooks/WorldGenerationHooks.java | 10 +- .../SpongeRandomEnchantmentListBuilder.java | 3 +- .../loader/VanillaRegistryLoader.java | 2 - .../common/server/PerWorldBorderListener.java | 2 +- .../world/border/PlayerOwnBorderListener.java | 2 +- .../world/server/SpongeWorldManager.java | 10 +- .../server/MinecraftServerMixin_API.java | 10 +- .../animal/camel/CamelHuskMixin_API.java} | 11 +- .../entity/animal/camel/CamelMixin_API.java | 2 +- .../entity/monster/ParchedMixin_API.java | 33 ++ .../projectile/LargeFireballMixin_API.java | 4 +- .../world/level/GameRules_KeyMixin_API.java | 47 +- .../storage/ServerLevelDataMixin_API.java | 38 +- .../commands/DifficultyCommandMixin.java | 4 +- .../core/server/level/ChunkMapMixin.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 18 +- .../boss/enderdragon/EnderDragonMixin.java | 2 +- .../world/level/border/WorldBorderMixin.java | 22 +- .../LegacyStructureDataHandlerMixin.java | 13 +- .../level/storage/PrimaryLevelDataMixin.java | 4 +- src/mixins/resources/mixins.sponge.api.json | 8 +- .../entity/animal/SnowGolemMixin_Vanilla.java | 9 +- 32 files changed, 586 insertions(+), 159 deletions(-) rename src/{accessors/java/org/spongepowered/common/accessor/world/level/chunk/storage/ChunkStorageAccessor.java => mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelHuskMixin_API.java} (78%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java diff --git a/SpongeAPI b/SpongeAPI index e8afabd156d..643c628d862 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit e8afabd156d6d8e68141439ddd3d737999e7deaf +Subproject commit 643c628d86206dd6562951b6be28267509bdebd7 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java index dd4262bcb91..4f10297e20f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java @@ -24,39 +24,23 @@ */ package org.spongepowered.vanilla.generator.world.level; -import com.google.common.base.CaseFormat; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.GameRules; import org.spongepowered.vanilla.generator.Context; import org.spongepowered.vanilla.generator.Generator; -import org.spongepowered.vanilla.generator.MapEntriesValidator; import org.spongepowered.vanilla.generator.RegistryEntriesGenerator; import org.spongepowered.vanilla.generator.RegistryEntriesValidator; import org.spongepowered.vanilla.generator.RegistryScope; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; public class LevelDataRegistries { public static List levelDataRegistries(final Context context) { return List.of( - new MapEntriesValidator<>( + new RegistryEntriesValidator<>( "world.gamerule", "GameRules", - GameRules.class, - "GAME_RULE_TYPES", - map -> { - final Map out = new HashMap<>(map.size()); - map.forEach((BiConsumer) (k, v) -> { - var key = (GameRules.Key) k; - out.put(ResourceLocation.fromNamespaceAndPath("sponge", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, key.getId())), v); - }); - return out; - } + Registries.GAME_RULE ), new RegistryEntriesGenerator<>( "map.decoration", diff --git a/gradle.properties b/gradle.properties index 1555434b90c..cdc97b4abd2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=25w42a +minecraftVersion=25w44a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9112c2d8d7d..7ea3f483efd 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -33,6 +33,14 @@ + + + + + + + + @@ -54,6 +62,24 @@ + + + + + + + + + + + + + + + + + + @@ -657,6 +683,14 @@ + + + + + + + + @@ -672,6 +706,19 @@ + + + + + + + + + + + + + @@ -793,6 +840,14 @@ + + + + + + + + @@ -834,6 +889,11 @@ + + + + + @@ -977,6 +1037,19 @@ + + + + + + + + + + + + + @@ -1072,6 +1145,16 @@ + + + + + + + + + + @@ -1130,6 +1213,14 @@ + + + + + + + + @@ -1203,6 +1294,14 @@ + + + + + + + + @@ -1248,6 +1347,16 @@ + + + + + + + + + + @@ -1317,6 +1426,14 @@ + + + + + + + + @@ -1438,6 +1555,14 @@ + + + + + + + + @@ -1486,6 +1611,14 @@ + + + + + + + + @@ -1622,6 +1755,14 @@ + + + + + + + + @@ -1714,6 +1855,14 @@ + + + + + + + + @@ -1962,6 +2111,14 @@ + + + + + + + + @@ -2556,6 +2713,14 @@ + + + + + + + + @@ -2580,6 +2745,22 @@ + + + + + + + + + + + + + + + + @@ -2588,6 +2769,14 @@ + + + + + + + + @@ -2612,6 +2801,14 @@ + + + + + + + + @@ -2636,6 +2833,14 @@ + + + + + + + + @@ -2651,6 +2856,11 @@ + + + + + @@ -2675,6 +2885,14 @@ + + + + + + + + @@ -2699,6 +2917,14 @@ + + + + + + + + @@ -2723,6 +2949,22 @@ + + + + + + + + + + + + + + + + @@ -2759,6 +3001,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -2783,6 +3047,14 @@ + + + + + + + + @@ -2820,6 +3092,14 @@ + + + + + + + + @@ -3196,6 +3476,14 @@ + + + + + + + + @@ -3228,6 +3516,14 @@ + + + + + + + + @@ -6868,6 +7164,14 @@ + + + + + + + + @@ -6905,6 +7209,14 @@ + + + + + + + + @@ -7031,6 +7343,11 @@ + + + + + @@ -7369,6 +7686,11 @@ + + + + + @@ -7435,6 +7757,14 @@ + + + + + + + + @@ -7443,12 +7773,12 @@ - - - + + + - - + + @@ -7499,6 +7829,11 @@ + + + + + @@ -7549,6 +7884,14 @@ + + + + + + + + @@ -7557,12 +7900,12 @@ - - - + + + - - + + @@ -7631,6 +7974,14 @@ + + + + + + + + @@ -8854,6 +9205,14 @@ + + + + + + + + @@ -9602,6 +9961,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -9992,6 +10383,14 @@ + + + + + + + + @@ -10018,6 +10417,11 @@ + + + + + @@ -10058,6 +10462,11 @@ + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRulesAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRulesAccessor.java index 0e2dbdfff3e..ff2d062861f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRulesAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRulesAccessor.java @@ -24,20 +24,16 @@ */ package org.spongepowered.common.accessor.world.level; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRuleMap; +import net.minecraft.world.level.gamerules.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.common.UntransformedAccessorError; -import java.util.Map; @Mixin(GameRules.class) public interface GameRulesAccessor { - @Accessor("rules") Map, GameRules.Value> accessor$rules(); + @Accessor("rules") GameRuleMap accessor$rules(); - @Accessor("GAME_RULE_TYPES") static Map, GameRules.Type> accessor$GAME_RULE_TYPES() { - throw new UntransformedAccessorError(); - } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRules_ValueAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRules_ValueAccessor.java index 9b0e219a7e6..476ad30520b 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRules_ValueAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/GameRules_ValueAccessor.java @@ -24,13 +24,14 @@ */ package org.spongepowered.common.accessor.world.level; -import net.minecraft.world.level.GameRules; +import com.mojang.serialization.DataResult; +import net.minecraft.world.level.gamerules.GameRule; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -@Mixin(GameRules.Value.class) +@Mixin(GameRule.class) public interface GameRules_ValueAccessor { - @Invoker("deserialize") void invoker$deserialize(final String serialized); + @Invoker("deserialize") DataResult invoker$deserialize(final String serialized); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index e3bfa53181a..ebfaea3563c 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -202,7 +202,6 @@ "world.level.chunk.LevelChunk$BoundTickingBlockEntityAccessor", "world.level.chunk.LevelChunk$RebindableTickingBlockEntityWrapperAccessor", "world.level.chunk.LevelChunkAccessor", - "world.level.chunk.storage.ChunkStorageAccessor", "world.level.chunk.storage.IOWorker$PendingStoreAccessor", "world.level.chunk.storage.RegionFileAccessor", "world.level.chunk.storage.SimpleRegionStorageAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index a7cc3be36db..467d744bbbd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -25,9 +25,9 @@ package org.spongepowered.common.data.provider.world; import net.minecraft.core.GlobalPos; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; @@ -88,7 +88,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.WORLD_TYPE) .get(h -> (WorldType) (Object) h.bridge$dimensionType()) .create(Keys.PVP) - .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().getWorldData().getGameRules().getBoolean(GameRules.RULE_PVP))) + .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().getWorldData().getGameRules().get(GameRules.PVP))) .create(Keys.SERIALIZATION_BEHAVIOR) .get(h -> h.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC)) .create(Keys.VIEW_DISTANCE) diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index c9c8ade65a1..e25b188ab68 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -95,7 +95,7 @@ public static void register(final DataProviderRegistrator registrator) { return Color.ofRgb(value); }) .create(Keys.WATER_COLOR) - .get(h -> Color.ofRgb(h.getSpecialEffects().getWaterColor())) + .get(h -> Color.ofRgb(h.getSpecialEffects().waterColor())) .create(Keys.WATER_FOG_COLOR) .get(h -> { final var value = h.getAttributes().applyModifier(EnvironmentAttributes.WATER_FOG_COLOR, EnvironmentAttributes.WATER_FOG_COLOR.defaultValue()); @@ -107,11 +107,11 @@ public static void register(final DataProviderRegistrator registrator) { return Color.ofRgb(value); }) .create(Keys.FOLIAGE_COLOR) - .get(h -> h.getSpecialEffects().getFoliageColorOverride().map(Color::ofRgb).orElse(null)) + .get(h -> h.getSpecialEffects().foliageColorOverride().map(Color::ofRgb).orElse(null)) .create(Keys.GRASS_COLOR) - .get(h -> h.getSpecialEffects().getGrassColorOverride().map(Color::ofRgb).orElse(null)) + .get(h -> h.getSpecialEffects().grassColorOverride().map(Color::ofRgb).orElse(null)) .create(Keys.GRASS_COLOR_MODIFIER) - .get(h -> (GrassColorModifier) (Object) h.getSpecialEffects().getGrassColorModifier()) + .get(h -> (GrassColorModifier) (Object) h.getSpecialEffects().grassColorModifier()) .create(Keys.BACKGROUND_MUSIC) .get(h -> { final var value = h.getAttributes().applyModifier(EnvironmentAttributes.BACKGROUND_MUSIC, EnvironmentAttributes.BACKGROUND_MUSIC.defaultValue()); diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 0c93973febf..0baf6706938 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -36,12 +36,12 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.DirectionalBlock; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.piston.PistonStructureResolver; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapIndex; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; @@ -515,7 +515,7 @@ public static DestructEntityEvent.Death callDestructEntityEventDeath(final Livin final DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(frame.currentCause(), originalChannel, Optional.of(originalChannel), originalMessage, originalMessage, (Living) entity, - ((ServerLevel) entity.level()).getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY), messageCancelled); + ((ServerLevel) entity.level()).getGameRules().get(GameRules.KEEP_INVENTORY), messageCancelled); SpongeCommon.post(event); return event; diff --git a/src/main/java/org/spongepowered/common/hooks/WorldGenerationHooks.java b/src/main/java/org/spongepowered/common/hooks/WorldGenerationHooks.java index d654f134225..33ceb1414cb 100644 --- a/src/main/java/org/spongepowered/common/hooks/WorldGenerationHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/WorldGenerationHooks.java @@ -25,6 +25,7 @@ package org.spongepowered.common.hooks; import com.google.common.collect.ImmutableList; +import com.mojang.datafixers.DataFixer; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; @@ -34,19 +35,20 @@ public interface WorldGenerationHooks { - default LegacyStructureDataHandler createLegacyStructureDataUtil(final ResourceKey dimensionType, final DimensionDataStorage savedData) { + default LegacyStructureDataHandler createLegacyStructureDataUtil(final ResourceKey dimensionType, final DimensionDataStorage savedData, final DataFixer fixer) { if (dimensionType == Level.OVERWORLD) { return new LegacyStructureDataHandler( savedData, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), - ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument") + ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument"), + fixer ); } else if (dimensionType == Level.NETHER) { final List keys = ImmutableList.of("Fortress"); - return new LegacyStructureDataHandler(savedData, keys, keys); + return new LegacyStructureDataHandler(savedData, keys, keys, fixer); } else if (dimensionType == Level.END) { final List keys = ImmutableList.of("EndCity"); - return new LegacyStructureDataHandler(savedData, keys, keys); + return new LegacyStructureDataHandler(savedData, keys, keys, fixer); } else { throw new RuntimeException(String.format("Unknown dimension type : %s", dimensionType)); } diff --git a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java index ac6a7a0ffa1..d7c5373d353 100644 --- a/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java +++ b/src/main/java/org/spongepowered/common/item/enchantment/SpongeRandomEnchantmentListBuilder.java @@ -26,7 +26,6 @@ import com.google.common.collect.Lists; -import net.minecraft.Util; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.util.RandomSource; @@ -119,7 +118,7 @@ private List basedOfFixedPool(final RandomSource randomIn, while (randomIn.nextInt(50) <= this.level) { - EnchantmentHelper.filterCompatibleEnchantments(list1, Util.lastOf(list)); + EnchantmentHelper.filterCompatibleEnchantments(list1, list.getLast()); if (list1.isEmpty()) { diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 3c35dce8dd3..cac12696ebb 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -111,7 +111,6 @@ import org.spongepowered.api.scoreboard.criteria.Criteria; import org.spongepowered.api.scoreboard.criteria.Criterion; import org.spongepowered.common.accessor.world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor; -import org.spongepowered.common.accessor.world.level.GameRulesAccessor; import org.spongepowered.common.registry.RegistryLoader; import org.spongepowered.common.registry.SpongeRegistryHolder; @@ -161,7 +160,6 @@ private void loadInstanceRegistries() { } this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); - this.knownName(RegistryTypes.GAME_RULE, GameRulesAccessor.accessor$GAME_RULE_TYPES().keySet(), rule -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, rule.getId())); this.holder.createRegistry(RegistryTypes.ITEM_TIER, VanillaRegistryLoader.itemTier()); } diff --git a/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java b/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java index b9d555897f8..ed8601ecd7e 100644 --- a/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java +++ b/src/main/java/org/spongepowered/common/server/PerWorldBorderListener.java @@ -49,7 +49,7 @@ public void onSetSize(final WorldBorder border, final double newSize) { } @Override - public void onLerpSize(final WorldBorder border, final double oldSize, final double newSize, final long time) { + public void onLerpSize(final WorldBorder border, final double oldSize, final double newSize, final long time, final long endTime) { this.sendWorldBorderActionPacket(new ClientboundSetBorderLerpSizePacket(border)); } diff --git a/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java b/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java index 2f80ec9259c..53ab10aa799 100644 --- a/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java +++ b/src/main/java/org/spongepowered/common/world/border/PlayerOwnBorderListener.java @@ -51,7 +51,7 @@ public void onSetSize(final WorldBorder border, final double newSize) { } @Override - public void onLerpSize(final WorldBorder border, final double oldSize, final double newSize, final long time) { + public void onLerpSize(WorldBorder border, double oldSize, double newSize, long time, long var8) { this.sendBorderPacket(new ClientboundSetBorderLerpSizePacket(border)); } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index c3a9249a9f1..69532bc8336 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -907,7 +907,15 @@ private ServerLevel createLevel( this.worlds.put(registryKey, world); // Ensure that the world border is registered. - levelData.getLegacyWorldBorderSettings().ifPresent(world.getWorldBorder()::applySettings); + levelData.getLegacyWorldBorderSettings().ifPresent(legacy -> { + final var border = world.getWorldBorder(); + border.setSize(legacy.size()); + border.setCenter(legacy.centerX(), legacy.centerZ()); + border.setSafeZone(legacy.safeZone()); + border.setDamagePerBlock(legacy.damagePerBlock()); + border.setWarningTime(legacy.warningTime()); + border.setWarningBlocks(legacy.warningBlocks()); + }); PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); return world; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index c03cfdee411..7b8631107ef 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -41,7 +41,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.PlayerList; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.levelgen.WorldDimensions; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.storage.LevelResource; @@ -248,17 +248,17 @@ public boolean isGameModeEnforced() { @Override public boolean isPVPEnabled() { - return this.worldData.getGameRules().getBoolean(GameRules.RULE_PVP); + return this.worldData.getGameRules().get(GameRules.PVP); } @Override public boolean areCommandBlocksEnabled() { - return this.worldData.getGameRules().getBoolean(GameRules.RULE_COMMAND_BLOCKS_ENABLED); + return this.worldData.getGameRules().get(GameRules.COMMAND_BLOCKS_WORK); } @Override public boolean isMonsterSpawnsEnabled() { - return this.worldData.getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS); + return this.worldData.getGameRules().get(GameRules.SPAWN_MONSTERS); } @Override @@ -271,7 +271,7 @@ public boolean isAnimalSpawnsEnabled() { */ @Override public boolean isMultiWorldEnabled() { - return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getWorldData().getGameRules().getBoolean(GameRules.RULE_ALLOW_NETHER); + return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getWorldData().getGameRules().get(GameRules.ALLOW_ENTERING_NETHER_USING_PORTALS); } @Override diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/storage/ChunkStorageAccessor.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelHuskMixin_API.java similarity index 78% rename from src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/storage/ChunkStorageAccessor.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelHuskMixin_API.java index ce533c3c8c3..b40ef8a9156 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/chunk/storage/ChunkStorageAccessor.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelHuskMixin_API.java @@ -22,15 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.level.chunk.storage; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.camel; -import net.minecraft.world.level.chunk.storage.ChunkStorage; -import net.minecraft.world.level.chunk.storage.IOWorker; +import net.minecraft.world.entity.animal.camel.CamelHusk; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ChunkStorage.class) -public interface ChunkStorageAccessor { +@Mixin(CamelHusk.class) +public abstract class CamelHuskMixin_API extends CamelMixin_API implements org.spongepowered.api.entity.living.animal.camel.CamelHusk { - @Accessor("worker") IOWorker accessor$worker(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java index 4ff0a35515b..6bd2c701383 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java @@ -29,6 +29,6 @@ import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse.AbstractHorseMixin_API; @Mixin(Camel.class) -public abstract class CamelMixin_API extends AbstractHorseMixin_API implements org.spongepowered.api.entity.living.animal.horse.Camel { +public abstract class CamelMixin_API extends AbstractHorseMixin_API implements org.spongepowered.api.entity.living.animal.camel.Camel { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java new file mode 100644 index 00000000000..c9f2db7934f --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; + +import org.spongepowered.api.entity.living.monster.skeleton.Parched; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(net.minecraft.world.entity.monster.Parched.class) +public abstract class ParchedMixin_API extends AbstractSkeletonMixin_API implements Parched { + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java index 9fdae239297..52af501a93a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java @@ -26,8 +26,8 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.projectile.LargeFireball; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; +import net.minecraft.world.level.gamerules.GameRules; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.explosive.fireball.ExplosiveFireball; @@ -44,7 +44,7 @@ public abstract class LargeFireballMixin_API extends FireballMixin_API implement @Override public void detonate() { - if (this.shadow$level() instanceof ServerLevel sl && sl.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + if (this.shadow$level() instanceof ServerLevel sl && sl.getGameRules().get(GameRules.MOB_GRIEFING)) { ((LargeFireballBridge) this).bridge$wrappedExplode(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), this.explosionPower, true, Level.ExplosionInteraction.MOB); } this.shadow$discard(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/GameRules_KeyMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/GameRules_KeyMixin_API.java index 39b2a935325..df194a26208 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/GameRules_KeyMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/GameRules_KeyMixin_API.java @@ -24,49 +24,42 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRuleType; import org.spongepowered.api.world.gamerule.GameRule; import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.accessor.world.level.GameRulesAccessor; import java.lang.reflect.Type; -@Mixin(GameRules.Key.class) -public class GameRules_KeyMixin_API implements GameRule { +@Mixin(net.minecraft.world.level.gamerules.GameRule.class) +@Implements(@Interface(iface = GameRule.class, prefix = "api$")) +public abstract class GameRules_KeyMixin_API implements GameRule { - @Shadow @Final private String id; + @Shadow public abstract String shadow$id(); + + @Shadow private @Final GameRuleType gameRuleType; + @Shadow @Final private T defaultValue; @Override public String name() { - return this.id; + return this.shadow$id(); } @Override public Type valueType() { - final GameRules.Type type = GameRulesAccessor.accessor$GAME_RULE_TYPES().get(this); - final GameRules.Value value = type.createRule(); - if (value instanceof GameRules.BooleanValue) { - return Boolean.class; - } - if (value instanceof GameRules.IntegerValue) { - return Integer.class; - } - throw new IllegalStateException("Unexpected GameRule.Value implementation " + value.getClass().getName()); + return switch (this.gameRuleType) { + case INT -> Integer.class; + case BOOL -> Boolean.class; + default -> throw new IllegalStateException("Unexpected GameRuleType " + this.gameRuleType); + }; } - @Override - @SuppressWarnings("unchecked") - public T defaultValue() { - final GameRules.Type type = GameRulesAccessor.accessor$GAME_RULE_TYPES().get(this); - final GameRules.Value value = type.createRule(); - if (value instanceof GameRules.BooleanValue) { - return (T) (Object)((GameRules.BooleanValue) value).get(); - } - if (value instanceof GameRules.IntegerValue) { - return (T)(Object)((GameRules.IntegerValue) value).get(); - } - throw new IllegalStateException("Unexpected GameRule.Value implementation " + value.getClass().getName()); + @Intrinsic + public T api$defaultValue() { + return this.defaultValue; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java index 38e6c17e0cc..d269ea28f49 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java @@ -24,7 +24,8 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRuleMap; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.ServerLevelData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -39,8 +40,8 @@ import org.spongepowered.api.world.weather.WeatherType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.level.GameRulesAccessor; -import org.spongepowered.common.accessor.world.level.GameRules_ValueAccessor; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; @@ -88,14 +89,9 @@ default UUID uniqueId() { @Override default V gameRule(GameRule gameRule) { - final GameRules.Value value = this.shadow$getGameRules().getRule((GameRules.Key) (Object) Objects.requireNonNull(gameRule, + final var value = this.shadow$getGameRules().get((net.minecraft.world.level.gamerules.GameRule) (Object) Objects.requireNonNull(gameRule, "gameRule")); - if (value instanceof GameRules.BooleanValue) { - return (V) Boolean.valueOf(((GameRules.BooleanValue) value).get()); - } else if (value instanceof GameRules.IntegerValue) { - return (V) Integer.valueOf(((GameRules.IntegerValue) value).get()); - } - return null; + return (V) value; } @Override @@ -103,31 +99,17 @@ default void setGameRule(final GameRule gameRule, final V value) { Objects.requireNonNull(gameRule, "gameRule"); Objects.requireNonNull(value, "value"); - final GameRules.Value mValue = this.shadow$getGameRules().getRule((GameRules.Key) (Object) gameRule); - ((GameRules_ValueAccessor) mValue).invoker$deserialize(value.toString()); + this.shadow$getGameRules().set((net.minecraft.world.level.gamerules.GameRule) (Object) gameRule, value, SpongeCommon.server()); } @Override default Map, ?> gameRules() { - final Map, GameRules.Value> rules = - ((GameRulesAccessor) this.shadow$getGameRules()).accessor$rules(); - + final GameRuleMap rules = ((GameRulesAccessor) this.shadow$getGameRules()).accessor$rules(); final Map, Object> apiRules = new HashMap<>(); - for (final Map.Entry, GameRules.Value> rule : rules.entrySet()) { - final GameRule key = (GameRule) (Object) rule.getKey(); - final GameRules.Value mValue = rule.getValue(); - Object value = null; - if (mValue instanceof GameRules.BooleanValue) { - value = ((GameRules.BooleanValue) mValue).get(); - } else if (mValue instanceof GameRules.IntegerValue) { - value = ((GameRules.IntegerValue) mValue).get(); - } - - if (value != null) { - apiRules.put(key, value); - } + for (final var rule : rules.keySet()) { + final GameRule key = (GameRule) (Object) rule; + apiRules.put(key, rules.get(rule)); } - return apiRules; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java index 0237e7ccbbf..8888c156c8e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java @@ -31,7 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; import net.minecraft.server.commands.DifficultyCommand; import net.minecraft.world.Difficulty; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.LevelData; import org.spongepowered.api.world.server.storage.ServerWorldProperties; import org.spongepowered.asm.mixin.Final; @@ -58,7 +58,7 @@ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty } else { final LevelData levelData = source.getLevel().getLevelData(); ((ServerWorldProperties) levelData).setDifficulty((org.spongepowered.api.world.difficulty.Difficulty) (Object) difficulty); - source.getLevel().setSpawnSettings(SpongeCommon.server().getWorldData().getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS)); + source.getLevel().setSpawnSettings(SpongeCommon.server().getWorldData().getGameRules().get(GameRules.SPAWN_MONSTERS)); source.getLevel().getPlayers(p -> true).forEach(p -> p.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()))); source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java index 25936a940a7..396f56ec85b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java @@ -51,7 +51,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.level.ServerChunkCacheAccessor; -import org.spongepowered.common.accessor.world.level.chunk.storage.ChunkStorageAccessor; +import org.spongepowered.common.accessor.world.level.chunk.storage.SimpleRegionStorageAccessor; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.DistanceManagerBridge; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; @@ -85,7 +85,7 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { @Inject(method = "", at = @At("RETURN")) private void impl$setIOWorkerDimension(final CallbackInfo ci) { - ((IOWorkerBridge) ((ChunkStorageAccessor) this).accessor$worker()).bridge$setDimension(SpongeIOWorkerType.CHUNK, this.level.dimension()); + ((IOWorkerBridge) ((SimpleRegionStorageAccessor) this).accessor$worker()).bridge$setDimension(SpongeIOWorkerType.CHUNK, this.level.dimension()); } @Redirect(method = "save", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 6151a192db6..9590730b9f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -65,10 +65,10 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.scores.PlayerTeam; import org.checkerframework.checker.nullness.qual.Nullable; @@ -295,7 +295,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @Override public boolean bridge$keepInventory() { - return Objects.requireNonNullElseGet(this.impl$keepInventory, () -> this.shadow$level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)); + return Objects.requireNonNullElseGet(this.impl$keepInventory, () -> this.shadow$level().getGameRules().get(GameRules.KEEP_INVENTORY)); } @Override @@ -450,19 +450,19 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @ModifyExpressionValue( method = "die", at = @At( - value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z" + value = "INVOKE", target = "Lnet/minecraft/world/level/gamerules/GameRules;get(Lnet/minecraft/world/level/gamerules/GameRule;)Ljava/lang/Object;" ), slice = @Slice( from = @At("HEAD"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/CombatTracker;getDeathMessage()Lnet/minecraft/network/chat/Component;") ) ) - private boolean impl$onlySendMessageIfEventCallsForIt( - boolean gameRules, + private Object impl$onlySendMessageIfEventCallsForIt( + Object gameRules, @Share("sponge-event") LocalRef event ) { final var spongeEvent = event.get(); - return gameRules && (spongeEvent == null || !spongeEvent.isMessageCancelled()); + return (Boolean) gameRules && (spongeEvent == null || !spongeEvent.isMessageCancelled()); } @ModifyExpressionValue( @@ -526,10 +526,10 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements SubjectBr @ModifyExpressionValue( method = "restoreFrom", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z") + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/gamerules/GameRules;get(Lnet/minecraft/world/level/gamerules/GameRule;)Ljava/lang/Object;") ) - private boolean tracker$useKeepFromBridge( - boolean original, + private Object tracker$useKeepFromBridge( + Object original, net.minecraft.server.level.ServerPlayer corpse, boolean wonGame ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java index 3661568aab3..b8374b0db17 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java @@ -58,7 +58,7 @@ public abstract class EnderDragonMixin extends MobMixin { slice = @Slice( from = @At( value = "FIELD", - target = "Lnet/minecraft/world/level/GameRules;RULE_MOBGRIEFING:Lnet/minecraft/world/level/GameRules$Key;" + target = "Lnet/minecraft/world/level/gamerules/GameRules;MOB_GRIEFING:Lnet/minecraft/world/level/gamerules/GameRule;" ), to = @At( value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java index 451758d8dba..9c9e020ec12 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java @@ -32,6 +32,7 @@ import org.spongepowered.api.event.world.ChangeWorldBorderEvent; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -82,7 +83,7 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { } @Inject(method = "lerpSizeBetween", at = @At(value = "HEAD"), cancellable = true) - private void impl$onLerping(final double initial, final double target, final long milliseconds, final CallbackInfo ci) { + private void impl$onLerping(final double initial, final double target, final long milliseconds, final long delay, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = () -> new SpongeWorldBorderBuilder().from(this) @@ -190,7 +191,7 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { @Override public org.spongepowered.api.world.border.@Nullable WorldBorder bridge$applyFrom(final org.spongepowered.api.world.border.WorldBorder worldBorder) { if (!this.impl$fireEvent) { - ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) (Object) worldBorder); + this.impl$applySettings((WorldBorder.Settings) (Object) worldBorder); return worldBorder; } @@ -208,9 +209,24 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { } this.impl$fireEvent = false; - ((WorldBorder) (Object) this).applySettings((WorldBorder.Settings) (Object) toSet); + this.impl$applySettings((WorldBorder.Settings) (Object) worldBorder); this.impl$fireEvent = true; return toSet; } + @Unique + private void impl$applySettings(WorldBorder.Settings worldBorder) { + ((WorldBorder) (Object) this).setCenter(worldBorder.centerX(), worldBorder.centerZ()); + ((WorldBorder) (Object) this).setDamagePerBlock(worldBorder.damagePerBlock()); + ((WorldBorder) (Object) this).setSafeZone(worldBorder.safeZone()); + ((WorldBorder) (Object) this).setWarningBlocks(worldBorder.warningBlocks()); + ((WorldBorder) (Object) this).setWarningTime(worldBorder.warningTime()); + if (worldBorder.lerpTime() > 0L) { + // TODO - figure out how to get the appropriate game time + ((WorldBorder) (Object) this).lerpSizeBetween(worldBorder.size(), worldBorder.lerpTarget(), worldBorder.lerpTime(), SpongeCommon.server().overworld().getGameTime()); + } else { + ((WorldBorder) (Object) this).setSize(worldBorder.size()); + } + } + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java index e93a9d76da2..f9c4861699d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java @@ -24,15 +24,18 @@ */ package org.spongepowered.common.mixin.core.world.level.levelgen.structure; +import com.mojang.datafixers.DataFixer; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.storage.LegacyTagFixer; import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; import net.minecraft.world.level.storage.DimensionDataStorage; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.common.hooks.PlatformHooks; +import java.util.function.Supplier; + @Mixin(LegacyStructureDataHandler.class) public abstract class LegacyStructureDataHandlerMixin { @@ -41,7 +44,11 @@ public abstract class LegacyStructureDataHandlerMixin { * @reason Allow the platform to determine how to create the legacy structure data updater */ @Overwrite - public static LegacyStructureDataHandler getLegacyStructureHandler(final ResourceKey dimension, final @Nullable DimensionDataStorage savedData) { - return PlatformHooks.INSTANCE.getWorldGenerationHooks().createLegacyStructureDataUtil(dimension, savedData); + public static Supplier getLegacyTagFixer( + final ResourceKey dimension, + final Supplier savedData, + final DataFixer fixer + ) { + return () -> PlatformHooks.INSTANCE.getWorldGenerationHooks().createLegacyStructureDataUtil(dimension, savedData.get(), fixer); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index ca3971b549d..c8932781dd1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -47,12 +47,12 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; -import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.levelgen.WorldDimensions; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions; @@ -291,7 +291,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat } else if (server.isSingleplayer()) { level.setSpawnSettings(difficulty != Difficulty.PEACEFUL); } else { - level.setSpawnSettings(server.getWorldData().getGameRules().getBoolean(GameRules.RULE_SPAWN_MONSTERS)); + level.setSpawnSettings(server.getWorldData().getGameRules().get(GameRules.SPAWN_MONSTERS)); } level.players().forEach(player -> player.connection.send(new ClientboundChangeDifficultyPacket(difficulty, isLocked))); diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 57543d3949e..c3036244af6 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -86,6 +86,9 @@ "minecraft.world.InteractionHandMixin_API", "minecraft.world.IWorldGenerationBaseReaderMixin_API", "minecraft.world.IWorldGenerationReaderMixin_API", + "minecraft.world.attribute.AmbientAdditionsSettingsMixin_API", + "minecraft.world.attribute.AmbientMoodSettingsMixin_API", + "minecraft.world.attribute.AmbientParticleSettingsMixin_API", "minecraft.world.damagesource.DamageEffectsMixin_API", "minecraft.world.damagesource.DamageScalingMixin_API", "minecraft.world.damagesource.DamageSourceMixin_API", @@ -186,6 +189,7 @@ "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlVariantMixin_API", + "minecraft.world.entity.animal.camel.CamelHuskMixin_API", "minecraft.world.entity.animal.camel.CamelMixin_API", "minecraft.world.entity.animal.frog.FrogMixin_API", "minecraft.world.entity.animal.frog.TadpoleMixin_API", @@ -249,6 +253,7 @@ "minecraft.world.entity.monster.IllusionerMixin_API", "minecraft.world.entity.monster.MagmaCubeMixin_API", "minecraft.world.entity.monster.MonsterMixin_API", + "minecraft.world.entity.monster.ParchedMixin_API", "minecraft.world.entity.monster.PatrollingMonsterMixin_API", "minecraft.world.entity.monster.Phantom_AttackPhaseMixin_API", "minecraft.world.entity.monster.PhantomMixin_API", @@ -377,9 +382,6 @@ "minecraft.world.level.LevelWriterMixin_API", "minecraft.world.level.LightLayerMixin_API", "minecraft.world.level.ServerExplosionMixin_API", - "minecraft.world.attribute.AmbientAdditionsSettingsMixin_API", - "minecraft.world.attribute.AmbientMoodSettingsMixin_API", - "minecraft.world.attribute.AmbientParticleSettingsMixin_API", "minecraft.world.level.biome.Biome_PrecipitationMixin_API", "minecraft.world.level.biome.Biome_TemperatureModifierMixin_API", "minecraft.world.level.biome.BiomeMixin_API", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java index 4e290a570d6..95b2c7ea3d0 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java @@ -26,7 +26,8 @@ import net.minecraft.world.entity.animal.SnowGolem; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRule; +import net.minecraft.world.level.gamerules.GameRules; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -36,8 +37,8 @@ public abstract class SnowGolemMixin_Vanilla { @Redirect(method = "aiStep()V", at = @At( - value = "INVOKE", target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z")) - private boolean impl$checkCanGrief(final GameRules gameRules, final GameRules.Key key) { - return gameRules.getBoolean(key) && ((GrieferBridge) this).bridge$canGrief(); + value = "INVOKE", target = "Lnet/minecraft/world/level/gamerules/GameRules;get(Lnet/minecraft/world/level/gamerules/GameRule;)Ljava/lang/Object;")) + private Object impl$checkCanGrief(final GameRules gameRules, final GameRule rule) { + return (Boolean) gameRules.get(rule) && ((GrieferBridge) this).bridge$canGrief(); } } From 6600bdf39cb3e4422ac765c248a3d4b9460fd0f8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 9 Dec 2025 20:24:51 -0800 Subject: [PATCH 421/586] feat(minecraft): update towards 25w45a Breaking changes: - Keys.FIXED_TIME doesn't apply to DimensionType anymore, it now applies to Level, but we don't have any handling for things like that yet. See https://github.com/SpongePowered/SpongeAPI/issues/2608 Notable additions: - Timelines are a thing, we may want to wrap a phase around them to handle any kind of events through them or link them as a Cause. Notable Changes: - ResourceLocation -> Identiifer - net.minecraft.Util -> net.minecraft.util.Util - critereon -> criterion See https://minecraft.wiki/w/Java_Edition_25w45a --- .../forge/hook/ForgeChannelHooks.java | 4 +-- .../registries/ForgeRegistryMixin_Forge.java | 6 ++-- .../RegistryManagerMixin_Forge.java | 4 +-- ...ntboundCustomPayloadPacketMixin_Forge.java | 4 +-- ...erboundCustomPayloadPacketMixin_Forge.java | 4 +-- .../mixin/core/tags/TagLoaderMixin_Forge.java | 4 +-- .../level/block/BlockMixin_Forge_Tracker.java | 4 +-- .../BlockBehaviorMixin_Forge_Tracker.java | 4 +-- .../generator/ClassFieldsValidator.java | 34 +++++++++---------- .../generator/EnumEntriesValidator.java | 24 ++++++------- .../vanilla/generator/GeneratorMain.java | 2 +- .../generator/MapEntriesValidator.java | 34 +++++++++---------- .../generator/RegistryEntriesGenerator.java | 4 +-- .../generator/RegistryEntriesValidator.java | 30 ++++++++-------- .../vanilla/generator/TagGenerator.java | 4 +-- .../vanilla/generator/Types.java | 4 +-- .../generator/item/ItemRegistries.java | 4 +-- .../world/entities/EntityRegistries.java | 4 +-- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 +++++ .../RegistrySnapshotAccessor_Neo.java | 4 +-- .../registries/RegistryManagerMixin_Neo.java | 4 +-- .../core/tags/TagLoaderMixin_NeoForge.java | 4 +-- .../entity/LivingEntityMixin_Neo_Damage.java | 2 +- .../entity/player/PlayerMixin_Neo_Damage.java | 2 +- .../level/block/BlockMixin_Neo_Tracker.java | 4 +-- .../state/BlockBehaviorMixin_Neo_Tracker.java | 4 +-- .../multiplayer/ClientLevelAccessor.java | 3 -- .../resources/ResourceKeyAccessor.java | 6 ++-- .../accessor/sounds/SoundEventAccessor.java | 4 +-- .../accessor/tags/TagEntryAccessor.java | 4 +-- .../item/AdventureModePredicateAccessor.java | 2 +- .../entity/SkullBlockEntityAccessor.java | 6 ++-- .../dimension/DimensionTypeAccessor.java | 3 -- .../advancement/SpongeAdvancementBuilder.java | 10 +++--- .../advancement/SpongeFilteredTrigger.java | 2 +- .../criterion/SpongeDummyTrigger.java | 6 ++-- .../criterion/SpongeScoreTrigger.java | 6 ++-- .../common/adventure/SpongeAdventure.java | 20 +++++------ .../common/block/SpongeBlockSnapshot.java | 4 +-- .../bridge/RegistryBackedTrackableBridge.java | 4 +-- .../AdvancementProgressBridge.java | 6 ++-- .../common/bridge/tags/TagLoaderBridge.java | 4 +-- .../command/brigadier/SpongeStringReader.java | 10 +++--- .../SpongeServerLocationValueParameter.java | 10 +++--- .../common/config/SpongeGameConfigs.java | 8 ++--- .../data/provider/block/entity/SkullData.java | 4 +-- .../data/provider/entity/EntityData.java | 4 +-- .../item/stack/ArmorItemStackData.java | 2 +- .../item/stack/BlockTypeItemStackData.java | 2 +- .../provider/item/stack/ItemStackData.java | 10 +++--- .../item/stack/SkullItemStackData.java | 4 +-- .../common/data/provider/map/MapInfoData.java | 6 ++-- .../world/ServerLevelDataProvider.java | 29 ++++++++++++++++ .../data/provider/world/WorldTypeData.java | 22 ++---------- .../data/type/SpongeArtTypeBuilder.java | 6 ++-- .../effect/sound/SpongeSoundBuilder.java | 4 +-- .../common/effect/util/ViewerPacketUtil.java | 6 ++-- .../common/entity/EntityUtil.java | 12 +++---- .../common/entity/SpongeEntityArchetype.java | 4 +-- .../common/entity/SpongeEntityTypes.java | 4 +-- .../SpongeAttributeModifierBuilder.java | 6 ++-- .../entity/living/human/HumanEntity.java | 4 +-- .../common/entity/player/SpongeUserData.java | 6 ++-- .../common/event/tracking/PhasePrinter.java | 4 +-- .../common/event/tracking/PhaseTracker.java | 6 ++-- .../common/event/tracking/UnwindingState.java | 2 +- ...reateNewTileEntityPostPlacementEffect.java | 2 +- .../inventory/ContainerBasedTransaction.java | 4 +-- .../inventory/CraftingPreviewTransaction.java | 2 +- .../inventory/PlaceRecipeTransaction.java | 4 +-- .../tracking/phase/general/CommandState.java | 2 +- .../tracking/phase/packet/PacketState.java | 4 +-- .../phase/tick/EntityTickPhaseState.java | 2 +- .../tick/LocationBasedTickPhaseState.java | 2 +- .../tracking/phase/tick/WorldTickState.java | 2 +- .../common/fluid/SpongeFluidStateBuilder.java | 4 +-- .../common/item/SpongeItemStack.java | 10 +++--- .../recipe/ingredient/IngredientUtil.java | 4 +-- .../recipe/ingredient/SpongeItemList.java | 2 +- .../SpongeMapDecorationBuilder.java | 4 +-- .../common/network/channel/ChannelUtils.java | 4 +-- .../common/network/channel/SpongeChannel.java | 4 +-- .../network/channel/SpongeChannelManager.java | 14 ++++---- .../network/channel/SpongeChannelPayload.java | 8 ++--- .../packet/SpongeBasicPacketChannel.java | 10 +++--- .../channel/packet/SpongePacketChannel.java | 18 +++++----- .../raw/SpongeRawLoginDataChannel.java | 6 ++-- .../packet/ChangeViewerEnvironmentPacket.java | 6 ++-- .../network/packet/SpongePacketHandler.java | 7 ---- .../common/registry/RegistryHolderLogic.java | 22 ++++++------ .../registry/SpongeResourceKeyBuilder.java | 10 +++--- .../registry/SpongeResourceKeyFactory.java | 22 ++++++------ .../loader/CommandRegistryLoader.java | 10 +++--- .../registry/loader/SpongeRegistryLoader.java | 2 +- .../loader/VanillaRegistryLoader.java | 6 ++-- .../provider/DimensionEffectProvider.java | 19 ++++++----- .../common/serialization/MathCodecs.java | 2 +- .../common/tag/SpongeTagFactory.java | 6 ++-- .../spongepowered/common/util/Constants.java | 6 ++-- .../world/SpongeDefaultWorldKeysFactory.java | 6 ++-- .../common/world/SpongeWorldTypeEffect.java | 8 ++--- .../biome/SpongeBiomeAttributesFactory.java | 10 +++--- .../biome/SpongeBiomeProviderFactory.java | 4 +-- .../flat/SpongeFlatGeneratorConfig.java | 4 +-- .../noise/SpongeSurfaceRulesFactory.java | 6 ++-- .../jigsaw/SpongeJigsawPoolBuilder.java | 8 ++--- .../world/server/SpongeWorldManager.java | 34 +++++++++---------- .../world/server/SpongeWorldTemplate.java | 6 ++-- .../world/server/SpongeWorldTypeBuilder.java | 20 ++++++----- .../teleport/ConfigTeleportHelperFilter.java | 10 +++--- .../advancements/AdvancementMixin_API.java | 4 +-- .../AdvancementNodeMixin_API.java | 8 ++--- .../CriterionProgressMixin_API.java | 6 ++-- .../EntitySelectorParserMixin_API.java | 2 +- .../core/MappedRegistryMixin_API.java | 8 ++--- .../api/minecraft/core/RegistryMixin.java | 16 ++++----- ...ixin_API.java => IdentifierMixin_API.java} | 8 ++--- .../server/level/ServerLevelMixin_API.java | 2 +- .../server/level/ServerPlayerMixin_API.java | 4 +-- .../server/level/WorldGenRegionMixin_API.java | 2 +- .../server/packs/PackResourcesMixin_API.java | 10 +++--- .../resources/ResourceManagerMixin_API.java | 12 +++---- .../minecraft/sounds/SoundEventMixin_API.java | 4 +-- .../api/minecraft/tags/TagKeyMixin_API.java | 6 ++-- .../world/entity/EntityMixin_API.java | 4 +-- .../world/entity/HumanoidArmMixin_API.java | 5 +-- .../AttributeInstanceMixin_API.java | 14 ++++---- .../AttributeModifierMixin_API.java | 4 +-- .../entity/player/ChatVisiblityMixin_API.java | 5 +-- .../world/item/ItemCooldownsMixin_API.java | 12 +++---- .../item/crafting/RecipeManagerMixin_API.java | 2 +- .../minecraft/world/level/LevelMixin_API.java | 2 +- .../level/chunk/LevelChunkMixin_API.java | 11 ++++-- .../dimension/DimensionTypeMixin_API.java | 4 +-- .../core/HolderLookup_ProviderMixin.java | 4 +-- .../core/advancements/AdvancementMixin.java | 4 +-- .../AdvancementProgressMixin.java | 8 ++--- .../common/mixin/core/adventure/KeyMixin.java | 4 +-- .../mixin/core/client/MinecraftMixin.java | 2 +- .../core/commands/CommandFunctionMixin.java | 4 +-- .../arguments/DimensionArgumentMixin.java | 10 +++--- .../mixin/core/core/MappedRegistryMixin.java | 16 ++++----- .../ClientboundCustomQueryPacketMixin.java | 4 +-- .../resources/RegistryDataLoaderMixin.java | 6 ++-- .../core/server/MinecraftServerMixin.java | 4 +-- .../server/ServerAdvancementManagerMixin.java | 6 ++-- .../core/server/level/ChunkHolderMixin.java | 6 ++-- .../core/server/level/ChunkMapMixin.java | 2 +- .../level/GenerationChunkHolderMixin.java | 2 +- .../core/server/level/ServerLevelMixin.java | 6 ++-- .../ServerGamePacketListenerImplMixin.java | 2 +- .../core/server/players/PlayerListMixin.java | 4 +-- .../mixin/core/tags/TagLoaderMixin.java | 20 +++++------ .../entity/LivingEntityMixin_Damage.java | 2 +- .../LivingEntityMixin_Shared_Damage.java | 6 ++-- .../core/world/entity/player/PlayerMixin.java | 4 +-- .../entity/player/PlayerMixin_Attack.java | 10 ++++-- .../player/PlayerMixin_Shared_Damage.java | 6 ++-- .../core/world/item/ItemCooldownsMixin.java | 18 +++++----- .../world/item/ServerItemCooldownsMixin.java | 8 ++--- .../item/crafting/RecipeManagerMixin.java | 8 ++--- .../level/block/NetherPortalBlockMixin.java | 2 +- .../AbstractFurnaceBlockEntityMixin.java | 4 +-- .../entity/CampfireBlockEntityMixin.java | 4 +-- .../level/chunk/ChunkStatusTasksMixin.java | 2 +- .../chunk/storage/EntityStorageMixin.java | 4 +-- .../level/chunk/storage/IOWorkerMixin.java | 4 +-- .../level/storage/PlayerDataStorageMixin.java | 2 +- .../level/storage/PrimaryLevelDataMixin.java | 6 ++-- .../EnchantmentContainerMixin_Inventory.java | 2 +- .../level/ServerPlayerMixin_Inventory.java | 9 +++-- ...andsPacket_ArgumentNodeStub_IpForward.java | 6 ++-- .../EntityActivationRange.java | 6 ++-- src/mixins/resources/mixins.sponge.api.json | 2 +- .../server/packs/PluginPackResources.java | 8 ++--- .../core/tags/TagLoaderMixin_Vanilla.java | 4 +-- .../LivingEntityMixin_Vanilla_Damage.java | 2 +- .../player/PlayerMixin_Vanilla_Damage.java | 2 +- ...stractFurnaceBlockEntityMixin_Vanilla.java | 8 ++--- 180 files changed, 628 insertions(+), 603 deletions(-) create mode 100644 src/main/java/org/spongepowered/common/data/provider/world/ServerLevelDataProvider.java rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/{ResourceLocationMixin_API.java => IdentifierMixin_API.java} (93%) diff --git a/forge/src/main/java/org/spongepowered/forge/hook/ForgeChannelHooks.java b/forge/src/main/java/org/spongepowered/forge/hook/ForgeChannelHooks.java index e2556d0d697..399375f877d 100644 --- a/forge/src/main/java/org/spongepowered/forge/hook/ForgeChannelHooks.java +++ b/forge/src/main/java/org/spongepowered/forge/hook/ForgeChannelHooks.java @@ -26,7 +26,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraftforge.network.ForgePayload; import org.spongepowered.api.ResourceKey; import org.spongepowered.common.hooks.ChannelHooks; @@ -46,6 +46,6 @@ public void registerPlatformChannels(final Consumer channels) { final FriendlyByteBuf payload = (FriendlyByteBuf) RegisterChannelUtil.encodePayload(channels); - return new ForgePayload((ResourceLocation) (Object) Constants.Channels.REGISTER_KEY, null, b -> b.writeBytes(payload)); + return new ForgePayload((Identifier) (Object) Constants.Channels.REGISTER_KEY, null, b -> b.writeBytes(payload)); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java index d382d4bd688..d00213424b6 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java @@ -26,7 +26,7 @@ import com.google.common.collect.Maps; import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.IForgeRegistry; import org.spongepowered.api.ResourceKey; @@ -55,8 +55,8 @@ public abstract class ForgeRegistryMixin_Forge { private final Map> forge$parents = Maps.newHashMap(); private boolean forge$warnedIfNoParent; - @Inject(method = "add(ILnet/minecraft/resources/ResourceLocation;Ljava/lang/Object;Ljava/lang/String;)I", at = @At("TAIL")) - public void forge$writeToParent(final int id, final ResourceLocation key, final V value, final String owner, final CallbackInfoReturnable cir) { + @Inject(method = "add(ILnet/minecraft/resources/Identifier;Ljava/lang/Object;Ljava/lang/String;)I", at = @At("TAIL")) + public void forge$writeToParent(final int id, final Identifier key, final V value, final String owner, final CallbackInfoReturnable cir) { final ResourceKey root = (ResourceKey) (Object) this.key.registry(); final ResourceKey location = (ResourceKey) (Object) this.key.location(); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/RegistryManagerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/RegistryManagerMixin_Forge.java index f591b0f1463..dfa9d45f21e 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/RegistryManagerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/RegistryManagerMixin_Forge.java @@ -24,7 +24,7 @@ */ package org.spongepowered.forge.mixin.core.minecraftforge.registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.RegistryManager; import org.spongepowered.asm.mixin.Mixin; @@ -39,7 +39,7 @@ public class RegistryManagerMixin_Forge { @SuppressWarnings("UnstableApiUsage") @Inject(method = "takeSnapshot", at = @At("RETURN")) - public void forge$dontSendSpongeDataToClient(boolean savingToDisc, CallbackInfoReturnable> cir) { + public void forge$dontSendSpongeDataToClient(boolean savingToDisc, CallbackInfoReturnable> cir) { if (savingToDisc) { return; } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ClientboundCustomPayloadPacketMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ClientboundCustomPayloadPacketMixin_Forge.java index be4df169def..6832fadbc81 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ClientboundCustomPayloadPacketMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ClientboundCustomPayloadPacketMixin_Forge.java @@ -28,7 +28,7 @@ import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraftforge.network.NetworkRegistry; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -49,7 +49,7 @@ public abstract class ClientboundCustomPayloadPacketMixin_Forge { // @formatter: on @Inject(method = { "lambda$static$0", "lambda$static$2" }, at = @At("HEAD"), cancellable = true) - private static void forge$getSpongeCustomPacketPayload(final ResourceLocation channelKey, final CallbackInfoReturnable> cir) { + private static void forge$getSpongeCustomPacketPayload(final Identifier channelKey, final CallbackInfoReturnable> cir) { if (NetworkRegistry.findTarget(channelKey) != null) { return; } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ServerboundCustomPayloadPacketMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ServerboundCustomPayloadPacketMixin_Forge.java index e5aa2980470..c58e94df499 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ServerboundCustomPayloadPacketMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/protocol/common/ServerboundCustomPayloadPacketMixin_Forge.java @@ -28,7 +28,7 @@ import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraftforge.network.NetworkRegistry; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -49,7 +49,7 @@ public abstract class ServerboundCustomPayloadPacketMixin_Forge { // @formatter: on @Inject(method = { "lambda$static$0" }, at = @At("HEAD"), cancellable = true) - private static void forge$getSpongeCustomPacketPayload(final ResourceLocation channelKey, final CallbackInfoReturnable> cir) { + private static void forge$getSpongeCustomPacketPayload(final Identifier channelKey, final CallbackInfoReturnable> cir) { if (NetworkRegistry.findTarget(channelKey) != null) { return; } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java index e4d63fa91af..3491bcf0d4c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java @@ -27,7 +27,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagLoader; import org.spongepowered.asm.mixin.Mixin; @@ -56,7 +56,7 @@ public abstract class TagLoaderMixin_Forge implements TagLoaderBridge { } @Inject(method = "lambda$build$6", at = @At("HEAD")) - private void forge$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final ResourceLocation $$2x, + private void forge$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java index 64005dd321a..5a85dc8a59c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java @@ -25,7 +25,7 @@ package org.spongepowered.forge.mixin.tracker.world.level.block; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -42,7 +42,7 @@ public abstract class BlockMixin_Forge_Tracker extends BlockBehaviorMixin_Forge_ //@formatter:on @Override - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { // TODO Not the best check but the tracker options only matter during block ticks... if (this.isRandomlyTicking(this.defaultBlockState())) { this.bridge$refreshTrackerStates(); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java index 973df0af53f..fbc5f1cb190 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java @@ -25,7 +25,7 @@ package org.spongepowered.forge.mixin.tracker.world.level.block.state; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -46,6 +46,6 @@ public abstract class BlockBehaviorMixin_Forge_Tracker { remap = false ) ) - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { } } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/ClassFieldsValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/ClassFieldsValidator.java index 058fc3ad58e..afa6de3b4fc 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/ClassFieldsValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/ClassFieldsValidator.java @@ -37,7 +37,7 @@ import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.javadoc.Javadoc; import com.github.javaparser.javadoc.description.JavadocDescription; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.tinylog.Logger; import java.util.ArrayList; @@ -55,21 +55,21 @@ public class ClassFieldsValidator implements Generator { private final String relativePackageName; private final String targetClassSimpleName; private final Class clazz; - private final Function mapping; + private final Function mapping; public ClassFieldsValidator( final String targetRelativePackage, final String targetClassSimpleName, final Class clazz ) { - this(targetRelativePackage, targetClassSimpleName, clazz, name -> ResourceLocation.tryBuild("sponge", name.toLowerCase(Locale.ROOT))); + this(targetRelativePackage, targetClassSimpleName, clazz, name -> Identifier.tryBuild("sponge", name.toLowerCase(Locale.ROOT))); } public ClassFieldsValidator( final String targetRelativePackage, final String targetClassSimpleName, final Class clazz, - final Function mapping + final Function mapping ) { this.relativePackageName = targetRelativePackage; this.targetClassSimpleName = targetClassSimpleName; @@ -92,7 +92,7 @@ public void generate(final Context ctx) { primaryTypeDeclaration.setJavadocComment(new Javadoc(JavadocDescription.parseText(Generator.GENERATED_FILE_JAVADOCS))); - final List map = new ArrayList<>(); + final List map = new ArrayList<>(); for (final var field : this.clazz.getDeclaredFields()) { if (!java.lang.reflect.Modifier.isPublic(field.getModifiers()) || !java.lang.reflect.Modifier.isStatic(field.getModifiers())) { @@ -107,7 +107,7 @@ public void generate(final Context ctx) { // Find index of first field member // Take out all field members from the members list final var members = primaryTypeDeclaration.getMembers(); - final var fields = new HashMap(); + final var fields = new HashMap(); int lastNonFieldIndex = -1; for (final var it = members.listIterator(); it.hasNext(); ) { final var node = it.next(); @@ -123,10 +123,10 @@ public void generate(final Context ctx) { } // Now, iterate the registry, discovering which fields were added and removed - final var added = new HashSet(); + final var added = new HashSet(); final var processedFields = new ArrayList(map.size()); - final Set allKeys = new HashSet<>(map); - for (final ResourceLocation key : allKeys) { + final Set allKeys = new HashSet<>(map); + for (final Identifier key : allKeys) { final FieldDeclaration existing = fields.remove(key); if (existing != null) { processedFields.add(existing); @@ -149,36 +149,36 @@ public void generate(final Context ctx) { } // Attempt to get a resource location from the field by parsing its initializer - private ResourceLocation extractFieldIdentifier(final FieldDeclaration declaration) { + private Identifier extractFieldIdentifier(final FieldDeclaration declaration) { if (declaration.getVariables().isEmpty()) { throw new IllegalStateException("No variables for " + declaration); } final VariableDeclarator var = declaration.getVariable(0); final Expression initializer = var.getInitializer().orElse(null); if (!(initializer instanceof MethodCallExpr) || ((MethodCallExpr) initializer).getArguments().size() != 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } final Expression argument = ((MethodCallExpr) initializer).getArgument(0); if (!(argument instanceof final MethodCallExpr keyInitializer) || keyInitializer.getArguments().size() < 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } if (keyInitializer.getArguments().size() == 1) { // method name as namespace - return ResourceLocation.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); + return Identifier.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); } else if (keyInitializer.getArguments().size() == 2) { // (namespace, path) - return ResourceLocation.fromNamespaceAndPath( + return Identifier.fromNamespaceAndPath( keyInitializer.getArgument(0).asStringLiteralExpr().asString(), keyInitializer.getArgument(1).asStringLiteralExpr().asString() ); } else { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } } - private FieldDeclaration makeField(final String ownType, final String factoryMethod, final ResourceLocation element) { + private FieldDeclaration makeField(final String ownType, final String factoryMethod, final Identifier element) { final FieldDeclaration fieldDeclaration = new FieldDeclaration(); final VariableDeclarator variable = new VariableDeclarator(StaticJavaParser.parseType("DefaultedRegistryReference"), Types.keyToFieldName(element.getPath())); fieldDeclaration.getVariables().add(variable); @@ -187,7 +187,7 @@ private FieldDeclaration makeField(final String ownType, final String factoryMet return fieldDeclaration; } - public static MethodCallExpr resourceKey(final ResourceLocation location) { + public static MethodCallExpr resourceKey(final Identifier location) { Objects.requireNonNull(location, "location"); final var resourceKey = new NameExpr("ResourceKey"); return switch (location.getNamespace()) { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java index 7b1ce767b13..fe97aea0807 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/EnumEntriesValidator.java @@ -37,7 +37,7 @@ import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.javadoc.Javadoc; import com.github.javaparser.javadoc.description.JavadocDescription; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.StringRepresentable; import org.tinylog.Logger; @@ -91,7 +91,7 @@ public void generate(final Context ctx) { // Find index of first field member // Take out all field members from the members list final var members = primaryTypeDeclaration.getMembers(); - final var fields = new HashMap(); + final var fields = new HashMap(); int lastNonFieldIndex = -1; for (final var it = members.listIterator(); it.hasNext();) { final var node = it.next(); @@ -107,7 +107,7 @@ public void generate(final Context ctx) { } // Now, iterate the registry, discovering which fields were added and removed - final var added = new HashSet(); + final var added = new HashSet(); final var processedFields = new ArrayList(map.length); for (final Enum f : map) { final String name; @@ -123,7 +123,7 @@ public void generate(final Context ctx) { } catch (Exception e) { throw new IllegalStateException("Failed to name for enum field in class " + this.clazz.getName(), e); } - final ResourceLocation key = ResourceLocation.fromNamespaceAndPath(this.namespace, name); + final Identifier key = Identifier.fromNamespaceAndPath(this.namespace, name); final FieldDeclaration existing = fields.remove(key); if (existing != null) { @@ -151,36 +151,36 @@ public void generate(final Context ctx) { } // Attempt to get a resource location from the field by parsing its initializer - private ResourceLocation extractFieldIdentifier(final FieldDeclaration declaration) { + private Identifier extractFieldIdentifier(final FieldDeclaration declaration) { if (declaration.getVariables().isEmpty()) { throw new IllegalStateException("No variables for " + declaration); } final VariableDeclarator var = declaration.getVariable(0); final Expression initializer = var.getInitializer().orElse(null); if (!(initializer instanceof MethodCallExpr) || ((MethodCallExpr) initializer).getArguments().size() != 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } final Expression argument = ((MethodCallExpr) initializer).getArgument(0); if (!(argument instanceof final MethodCallExpr keyInitializer) || keyInitializer.getArguments().size() < 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } if (keyInitializer.getArguments().size() == 1) { // method name as namespace - return ResourceLocation.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); + return Identifier.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); } else if (keyInitializer.getArguments().size() == 2) { // (namespace, path) - return ResourceLocation.fromNamespaceAndPath( + return Identifier.fromNamespaceAndPath( keyInitializer.getArgument(0).asStringLiteralExpr().asString(), keyInitializer.getArgument(1).asStringLiteralExpr().asString() ); } else { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } } - private FieldDeclaration makeField(final String ownType, final String factoryMethod, final ResourceLocation element) { + private FieldDeclaration makeField(final String ownType, final String factoryMethod, final Identifier element) { final FieldDeclaration fieldDeclaration = new FieldDeclaration(); final VariableDeclarator variable = new VariableDeclarator(StaticJavaParser.parseType("DefaultedRegistryReference"), Types.keyToFieldName(element.getPath())); fieldDeclaration.getVariables().add(variable); @@ -189,7 +189,7 @@ private FieldDeclaration makeField(final String ownType, final String factoryMet return fieldDeclaration; } - public static MethodCallExpr resourceKey(final ResourceLocation location) { + public static MethodCallExpr resourceKey(final Identifier location) { Objects.requireNonNull(location, "location"); final var resourceKey = new NameExpr("ResourceKey"); return switch (location.getNamespace()) { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 3da6cc3f97d..38fef394e64 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -27,7 +27,7 @@ import com.github.javaparser.utils.Log; import com.mojang.datafixers.util.Pair; import net.minecraft.SharedConstants; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.commands.Commands.CommandSelection; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/MapEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/MapEntriesValidator.java index e77780db0f6..8ca4527daed 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/MapEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/MapEntriesValidator.java @@ -37,7 +37,7 @@ import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.javadoc.Javadoc; import com.github.javaparser.javadoc.description.JavadocDescription; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.tinylog.Logger; import java.util.ArrayList; @@ -56,7 +56,7 @@ public class MapEntriesValidator implements Generator { private final String targetClassSimpleName; private final Class clazz; private final String registry; - private final Function, Map> mapping; + private final Function, Map> mapping; MapEntriesValidator( final String targetRelativePackage, @@ -64,7 +64,7 @@ public class MapEntriesValidator implements Generator { final Class clazz, final String registry ) { - this(targetRelativePackage, targetClassSimpleName, clazz, registry, map -> (Map) map); + this(targetRelativePackage, targetClassSimpleName, clazz, registry, map -> (Map) map); } public MapEntriesValidator( @@ -72,7 +72,7 @@ public MapEntriesValidator( final String targetClassSimpleName, final Class clazz, final String registry, - final Function, Map> mapping + final Function, Map> mapping ) { this.relativePackageName = targetRelativePackage; this.targetClassSimpleName = targetClassSimpleName; @@ -96,7 +96,7 @@ public void generate(final Context ctx) { primaryTypeDeclaration.setJavadocComment(new Javadoc(JavadocDescription.parseText(Generator.GENERATED_FILE_JAVADOCS))); - final Map map; + final Map map; try { final var f = this.clazz.getDeclaredField(this.registry); f.setAccessible(true); @@ -112,7 +112,7 @@ public void generate(final Context ctx) { // Find index of first field member // Take out all field members from the members list final var members = primaryTypeDeclaration.getMembers(); - final var fields = new HashMap(); + final var fields = new HashMap(); int lastNonFieldIndex = -1; for (final var it = members.listIterator(); it.hasNext();) { final var node = it.next(); @@ -128,10 +128,10 @@ public void generate(final Context ctx) { } // Now, iterate the registry, discovering which fields were added and removed - final var added = new HashSet(); + final var added = new HashSet(); final var processedFields = new ArrayList(map.keySet().size()); - final Set allKeys = new HashSet<>(map.keySet()); - for (final ResourceLocation key : allKeys) { + final Set allKeys = new HashSet<>(map.keySet()); + for (final Identifier key : allKeys) { final FieldDeclaration existing = fields.remove(key); if (existing != null) { processedFields.add(existing); @@ -154,36 +154,36 @@ public void generate(final Context ctx) { } // Attempt to get a resource location from the field by parsing its initializer - private ResourceLocation extractFieldIdentifier(final FieldDeclaration declaration) { + private Identifier extractFieldIdentifier(final FieldDeclaration declaration) { if (declaration.getVariables().isEmpty()) { throw new IllegalStateException("No variables for " + declaration); } final VariableDeclarator var = declaration.getVariable(0); final Expression initializer = var.getInitializer().orElse(null); if (!(initializer instanceof MethodCallExpr) || ((MethodCallExpr) initializer).getArguments().size() != 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } final Expression argument = ((MethodCallExpr) initializer).getArgument(0); if (!(argument instanceof final MethodCallExpr keyInitializer) || keyInitializer.getArguments().size() < 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } if (keyInitializer.getArguments().size() == 1) { // method name as namespace - return ResourceLocation.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); + return Identifier.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); } else if (keyInitializer.getArguments().size() == 2) { // (namespace, path) - return ResourceLocation.fromNamespaceAndPath( + return Identifier.fromNamespaceAndPath( keyInitializer.getArgument(0).asStringLiteralExpr().asString(), keyInitializer.getArgument(1).asStringLiteralExpr().asString() ); } else { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } } - private FieldDeclaration makeField(final String ownType, final String factoryMethod, final ResourceLocation element) { + private FieldDeclaration makeField(final String ownType, final String factoryMethod, final Identifier element) { final FieldDeclaration fieldDeclaration = new FieldDeclaration(); final VariableDeclarator variable = new VariableDeclarator(StaticJavaParser.parseType("DefaultedRegistryReference"), Types.keyToFieldName(element.getPath())); fieldDeclaration.getVariables().add(variable); @@ -192,7 +192,7 @@ private FieldDeclaration makeField(final String ownType, final String factoryMet return fieldDeclaration; } - public static MethodCallExpr resourceKey(final ResourceLocation location) { + public static MethodCallExpr resourceKey(final Identifier location) { Objects.requireNonNull(location, "location"); final var resourceKey = new NameExpr("ResourceKey"); return switch (location.getNamespace()) { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index bf578e919b0..27d363626b3 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -31,8 +31,8 @@ import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; @@ -152,7 +152,7 @@ public void generate(final Context ctx) throws IOException { ctx.compilationUnit(this.relativePackageName, this.targetClassSimpleName); } - private FieldSpec makeField(final String ownType, final TypeName fieldType, final MethodSpec factoryMethod, final ResourceLocation element, @Nullable final FeatureFlagSet featureFlagSet) { + private FieldSpec makeField(final String ownType, final TypeName fieldType, final MethodSpec factoryMethod, final Identifier element, @Nullable final FeatureFlagSet featureFlagSet) { final FieldSpec.Builder builder = FieldSpec.builder(fieldType, Types.keyToFieldName(element.getPath()), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java index 46d53c0ef3a..c3293a09dd2 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java @@ -39,8 +39,8 @@ import com.github.javaparser.javadoc.description.JavadocDescription; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import org.tinylog.Logger; import java.util.ArrayList; @@ -59,7 +59,7 @@ public class RegistryEntriesValidator implements Generator { private final String targetClassSimpleName; private final ResourceKey> registry; private final Predicate filter; - private final Set extraEntries; + private final Set extraEntries; public RegistryEntriesValidator( final String targetRelativePackage, @@ -74,7 +74,7 @@ public RegistryEntriesValidator( final String targetClassSimpleName, final ResourceKey> registry, final Predicate filter, - final Set extraEntries + final Set extraEntries ) { this.relativePackageName = targetRelativePackage; this.targetClassSimpleName = targetClassSimpleName; @@ -107,7 +107,7 @@ public void generate(final Context ctx) { // Find index of first field member // Take out all field members from the members list final var members = primaryTypeDeclaration.getMembers(); - final var fields = new HashMap(); + final var fields = new HashMap(); int lastNonFieldIndex = -1; for (final var it = members.listIterator(); it.hasNext();) { final var node = it.next(); @@ -123,11 +123,11 @@ public void generate(final Context ctx) { } // Now, iterate the registry, discovering which fields were added and removed - final var added = new HashSet(); + final var added = new HashSet(); final var processedFields = new ArrayList(registry.keySet().size()); - final Set allKeys = new HashSet<>(registry.keySet()); + final Set allKeys = new HashSet<>(registry.keySet()); allKeys.addAll(this.extraEntries); - for (final ResourceLocation key : allKeys) { + for (final Identifier key : allKeys) { if (!this.filter.test(registry.getValue(key))) { continue; } @@ -154,36 +154,36 @@ public void generate(final Context ctx) { } // Attempt to get a resource location from the field by parsing its initializer - private ResourceLocation extractFieldIdentifier(final FieldDeclaration declaration) { + private Identifier extractFieldIdentifier(final FieldDeclaration declaration) { if (declaration.getVariables().isEmpty()) { throw new IllegalStateException("No variables for " + declaration); } final VariableDeclarator var = declaration.getVariable(0); final Expression initializer = var.getInitializer().orElse(null); if (!(initializer instanceof MethodCallExpr) || ((MethodCallExpr) initializer).getArguments().size() != 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } final Expression argument = ((MethodCallExpr) initializer).getArgument(0); if (!(argument instanceof final MethodCallExpr keyInitializer) || keyInitializer.getArguments().size() < 1) { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } if (keyInitializer.getArguments().size() == 1) { // method name as namespace - return ResourceLocation.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); + return Identifier.fromNamespaceAndPath(keyInitializer.getNameAsString(), keyInitializer.getArgument(0).asStringLiteralExpr().asString()); } else if (keyInitializer.getArguments().size() == 2) { // (namespace, path) - return ResourceLocation.fromNamespaceAndPath( + return Identifier.fromNamespaceAndPath( keyInitializer.getArgument(0).asStringLiteralExpr().asString(), keyInitializer.getArgument(1).asStringLiteralExpr().asString() ); } else { - return ResourceLocation.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess + return Identifier.parse(var.getNameAsString().toLowerCase(Locale.ROOT)); // a best guess } } - private FieldDeclaration makeField(final String ownType, final String factoryMethod, final ResourceLocation element) { + private FieldDeclaration makeField(final String ownType, final String factoryMethod, final Identifier element) { final FieldDeclaration fieldDeclaration = new FieldDeclaration(); final VariableDeclarator variable = new VariableDeclarator(StaticJavaParser.parseType("DefaultedRegistryReference"), Types.keyToFieldName(element.getPath())); fieldDeclaration.getVariables().add(variable); @@ -192,7 +192,7 @@ private FieldDeclaration makeField(final String ownType, final String factoryMet return fieldDeclaration; } - public static MethodCallExpr resourceKey(final ResourceLocation location) { + public static MethodCallExpr resourceKey(final Identifier location) { Objects.requireNonNull(location, "location"); final var resourceKey = new NameExpr("ResourceKey"); return switch (location.getNamespace()) { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java index c1c8c1007fb..96b8e6f4a56 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/TagGenerator.java @@ -31,8 +31,8 @@ import com.squareup.javapoet.TypeName; import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import java.io.IOException; @@ -109,7 +109,7 @@ public void generate(final Context ctx) throws IOException { ctx.compilationUnit(this.relativePackageName, this.targetClassSimpleName); } - private FieldSpec makeField(final String ownType, final TypeName fieldType, final MethodSpec factoryMethod, final ResourceLocation element) { + private FieldSpec makeField(final String ownType, final TypeName fieldType, final MethodSpec factoryMethod, final Identifier element) { return FieldSpec.builder(fieldType, Types.keyToFieldName(element.getPath()), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .initializer("$L.$N($L)", ownType, factoryMethod, Types.resourceKey(element)) .build(); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java b/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java index bc7cf62220b..1a72118cdad 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/Types.java @@ -31,7 +31,7 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.WildcardTypeName; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.Locale; import java.util.Objects; @@ -111,7 +111,7 @@ static String keyToFieldName(final String key) { }; } - public static CodeBlock resourceKey(final ResourceLocation location) { + public static CodeBlock resourceKey(final Identifier location) { Objects.requireNonNull(location, "location"); return Types.resourceKey(location.getNamespace(), location.getPath()); } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java index 205a2cc1934..ed1abd33a8b 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java @@ -25,7 +25,7 @@ package org.spongepowered.vanilla.generator.item; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Rarity; @@ -134,7 +134,7 @@ public static List itemRegistries(final Context context) { "data.type", "ArmorMaterials", ArmorMaterials.class, - (s) -> ResourceLocation.withDefaultNamespace(s.toLowerCase(Locale.ROOT)) + (s) -> Identifier.withDefaultNamespace(s.toLowerCase(Locale.ROOT)) ) ); } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index 33143686f4a..a56cd09d1fa 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -25,7 +25,7 @@ package org.spongepowered.vanilla.generator.world.entities; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlotGroup; @@ -205,7 +205,7 @@ public static List registryEntries(final Context context) { "EntityTypes", Registries.ENTITY_TYPE, $ -> true, - Set.of(ResourceLocation.fromNamespaceAndPath("sponge", "human")) // Sponge's Human type is an extra addition + Set.of(Identifier.fromNamespaceAndPath("sponge", "human")) // Sponge's Human type is an extra addition ), new RegistryEntriesGenerator<>( "data.type", diff --git a/gradle.properties b/gradle.properties index cdc97b4abd2..818109668c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=25w44a +minecraftVersion=25w45a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7ea3f483efd..a4addc207b8 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1763,6 +1763,14 @@ + + + + + + + + diff --git a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/neoforge/registries/RegistrySnapshotAccessor_Neo.java b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/neoforge/registries/RegistrySnapshotAccessor_Neo.java index a3c22d65967..4b6cddb1cb7 100644 --- a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/neoforge/registries/RegistrySnapshotAccessor_Neo.java +++ b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/neoforge/registries/RegistrySnapshotAccessor_Neo.java @@ -25,7 +25,7 @@ package org.spongepowered.neoforge.accessor.neoforge.registries; import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.neoforged.neoforge.registries.RegistrySnapshot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -34,5 +34,5 @@ public interface RegistrySnapshotAccessor_Neo { @Accessor("ids") - Int2ObjectSortedMap accessor$ids(); + Int2ObjectSortedMap accessor$ids(); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/RegistryManagerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/RegistryManagerMixin_Neo.java index 390cfd4613b..b7b8f24f372 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/RegistryManagerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/registries/RegistryManagerMixin_Neo.java @@ -24,7 +24,7 @@ */ package org.spongepowered.neoforge.mixin.core.neoforge.registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.neoforged.neoforge.registries.RegistryManager; import net.neoforged.neoforge.registries.RegistrySnapshot; import org.spongepowered.asm.mixin.Mixin; @@ -40,7 +40,7 @@ public class RegistryManagerMixin_Neo { @Inject(method = "takeSnapshot", at = @At("RETURN")) - private static void neo$dontSendSpongeDataToClient(RegistryManager.SnapshotType snapshotType, CallbackInfoReturnable> cir) { + private static void neo$dontSendSpongeDataToClient(RegistryManager.SnapshotType snapshotType, CallbackInfoReturnable> cir) { if (snapshotType != RegistryManager.SnapshotType.SYNC_TO_CLIENT) { return; } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java index f7b9276052f..5cc7735bec8 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java @@ -27,7 +27,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagLoader; import org.spongepowered.asm.mixin.Mixin; @@ -56,7 +56,7 @@ public abstract class TagLoaderMixin_NeoForge implements TagLoaderBridge { } @Inject(method = "lambda$build$6", at = @At("HEAD")) - private void neo$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final ResourceLocation $$2x, + private void neo$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java index 52f9056e52b..053b1c6767d 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java @@ -71,7 +71,7 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg } @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) private float damage$firePostEvent_Living(final float damage) { return this.damage$firePostEvent(damage); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java index e25fc9102cd..a0c6b8c7cc6 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java @@ -63,7 +63,7 @@ public abstract class PlayerMixin_Neo_Damage extends LivingEntityMixin_Neo_Damag } @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) private float damage$firePostEvent_Player(final float damage) { return this.damage$firePostEvent(damage); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java index f9c274a8da3..dece1a48c8e 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java @@ -25,7 +25,7 @@ package org.spongepowered.neoforge.mixin.tracker.world.level.block; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -42,7 +42,7 @@ public abstract class BlockMixin_Neo_Tracker extends BlockBehaviorMixin_Neo_Trac //@formatter:on @Override - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { // TODO Not the best check but the tracker options only matter during block ticks... if (this.isRandomlyTicking(this.defaultBlockState())) { this.bridge$refreshTrackerStates(); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java index 7f7eaf032b2..b708e30d113 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java @@ -25,7 +25,7 @@ package org.spongepowered.neoforge.mixin.tracker.world.level.block.state; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -46,6 +46,6 @@ public abstract class BlockBehaviorMixin_Neo_Tracker { remap = false ) ) - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/client/multiplayer/ClientLevelAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/client/multiplayer/ClientLevelAccessor.java index d588cd5ff60..e1cea955966 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/client/multiplayer/ClientLevelAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/client/multiplayer/ClientLevelAccessor.java @@ -25,11 +25,9 @@ package org.spongepowered.common.accessor.client.multiplayer; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.entity.TransientEntitySectionManager; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(ClientLevel.class) @@ -37,5 +35,4 @@ public interface ClientLevelAccessor { @Accessor("entityStorage") TransientEntitySectionManager accessor$getEntityStorage(); - @Mutable @Accessor("effects") void accessor$effects(DimensionSpecialEffects effects); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/ResourceKeyAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/ResourceKeyAccessor.java index cf288ba96a5..999584f968d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/ResourceKeyAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/ResourceKeyAccessor.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.accessor.resources; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; @@ -34,9 +34,9 @@ @Mixin(ResourceKey.class) public interface ResourceKeyAccessor { - @Invoker("create") static ResourceKey invoker$create(final ResourceLocation p_240905_0_, final ResourceLocation p_240905_1_) { + @Invoker("create") static ResourceKey invoker$create(final Identifier p_240905_0_, final Identifier p_240905_1_) { throw new UntransformedInvokerError(); } - @Accessor("registryName") ResourceLocation accessor$registryName(); + @Accessor("registryName") Identifier accessor$registryName(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/sounds/SoundEventAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/sounds/SoundEventAccessor.java index 35ebdd5a590..1ca68b206a6 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/sounds/SoundEventAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/sounds/SoundEventAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.sounds; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @@ -34,7 +34,7 @@ public interface SoundEventAccessor { @Invoker("createVariableRangeEvent") - static SoundEvent accessor$createVariableRangeEvent(ResourceLocation $$0) { + static SoundEvent accessor$createVariableRangeEvent(Identifier $$0) { throw new UntransformedAccessorError(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/tags/TagEntryAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/tags/TagEntryAccessor.java index f4b86e2eea8..fbe72f7628d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/tags/TagEntryAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/tags/TagEntryAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.tags; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagEntry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -32,7 +32,7 @@ @Mixin(TagEntry.class) public interface TagEntryAccessor { - @Accessor("id") ResourceLocation accessor$id(); + @Accessor("id") Identifier accessor$id(); @Accessor("tag") boolean accessor$tag(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java index 4c0425100ce..7026e5ee36d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.world.item; -import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.advancements.criterion.BlockPredicate; import net.minecraft.world.item.AdventureModePredicate; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java index 28f76ba8277..2113216a8a7 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/block/entity/SkullBlockEntityAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.world.level.block.entity; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.entity.SkullBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -32,7 +32,7 @@ @Mixin(SkullBlockEntity.class) public interface SkullBlockEntityAccessor { - @Accessor("noteBlockSound") void accessor$noteBlockSound(final ResourceLocation location); + @Accessor("noteBlockSound") void accessor$noteBlockSound(final Identifier location); - @Accessor("noteBlockSound") ResourceLocation accessor$noteBlockSound(); + @Accessor("noteBlockSound") Identifier accessor$noteBlockSound(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/DimensionTypeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/DimensionTypeAccessor.java index d0f7d6f4fd3..e90a8dac1e0 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/DimensionTypeAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/DimensionTypeAccessor.java @@ -28,12 +28,9 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.OptionalLong; @Mixin(DimensionType.class) public interface DimensionTypeAccessor { - @Accessor("fixedTime") OptionalLong accessor$fixedTime(); - @Accessor("ambientLight") float accessor$ambientLight(); } diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index 505a182d0d2..5f9dda5e4a2 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -29,7 +29,7 @@ import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.Criterion; import net.minecraft.core.ClientAsset; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.Advancement; @@ -48,7 +48,7 @@ public final class SpongeAdvancementBuilder implements Advancement.Builder.RootStep { - private @Nullable ResourceLocation parent; + private @Nullable Identifier parent; private AdvancementCriterion criterion; private @Nullable DisplayInfo displayInfo; private @Nullable ClientAsset backgroundPath; @@ -59,7 +59,7 @@ public SpongeAdvancementBuilder() { @Override public Advancement.Builder parent(final ResourceKey parent) { - this.parent = (ResourceLocation) (Object) parent; + this.parent = (Identifier) (Object) parent; this.backgroundPath = null; return this; } @@ -72,7 +72,7 @@ public Advancement.Builder.RootStep root() { @Override public Advancement.Builder background(final ResourceKey backgroundPath) { - this.backgroundPath = new ClientAsset.ResourceTexture((ResourceLocation) (Object) backgroundPath); + this.backgroundPath = new ClientAsset.ResourceTexture((Identifier) (Object) backgroundPath); return this; } @@ -91,7 +91,7 @@ public Advancement.Builder displayInfo(final @Nullable DisplayInfo displayInfo) @Override public Advancement.Builder from(final Advancement value) { - this.parent = (ResourceLocation) (Object) value.parent().orElse(null); + this.parent = (Identifier) (Object) value.parent().orElse(null); this.criterion = value.criterion(); this.displayInfo = value.displayInfo().orElse(null); this.backgroundPath = ((net.minecraft.advancements.Advancement) (Object) value).display() diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java b/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java index 0a695d0e35d..705d5b3aa87 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java @@ -27,7 +27,7 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.advancements.critereon.CriterionValidator; +import net.minecraft.advancements.criterion.CriterionValidator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.api.advancement.criteria.trigger.FilteredTrigger; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java index e9c244445b1..67edf73cbb9 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java @@ -26,9 +26,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.advancements.critereon.ContextAwarePredicate; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.advancements.criterion.ContextAwarePredicate; +import net.minecraft.advancements.criterion.EntityPredicate; +import net.minecraft.advancements.criterion.SimpleCriterionTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java index cf02aad5240..dc748afd4ee 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java @@ -26,9 +26,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.advancements.critereon.ContextAwarePredicate; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.advancements.criterion.ContextAwarePredicate; +import net.minecraft.advancements.criterion.EntityPredicate; +import net.minecraft.advancements.criterion.SimpleCriterionTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index f6c7eaa7641..40c93f0b8e5 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -84,8 +84,8 @@ import net.minecraft.network.chat.contents.data.BlockDataSource; import net.minecraft.network.chat.contents.data.EntityDataSource; import net.minecraft.network.chat.contents.data.StorageDataSource; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerBossEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.world.BossEvent; @@ -223,7 +223,7 @@ public static TriState asAdventure(final Tristate state) { // ------------- // org.spongepowered.common.mixin.core.adventure.KeyMixin - public static Key asAdventure(final ResourceLocation key) { + public static Key asAdventure(final Identifier key) { return (Key) (Object) key; } @@ -520,7 +520,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv final var stack = si.item(); final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); yield HoverEvent.showItem( - SpongeAdventure.asAdventure(stack.getItemHolder().unwrap().map(ResourceKey::location, itemRegistry::getKey)), + SpongeAdventure.asAdventure(stack.getItemHolder().unwrap().map(ResourceKey::identifier, itemRegistry::getKey)), stack.getCount(), SpongeAdventure.asAdventure(stack.getComponentsPatch()) ); @@ -785,7 +785,7 @@ public static Map asAdventure(final DataComponentPatch Map map = new HashMap<>(); components.entrySet().forEach(entry -> { - final ResourceLocation key = BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(entry.getKey()); + final Identifier key = BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(entry.getKey()); map.put(SpongeAdventure.asAdventure(key), new SpongeDataComponentValue<>(entry.getValue())); }); return map; @@ -805,18 +805,18 @@ private record SpongeDataComponentValue(Optional value) implements DataCom // Key - public static ResourceLocation asVanilla(final Key key) { - if ((Object) key instanceof ResourceLocation) { - return (ResourceLocation) (Object) key; + public static Identifier asVanilla(final Key key) { + if ((Object) key instanceof Identifier) { + return (Identifier) (Object) key; } - return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value()); + return Identifier.fromNamespaceAndPath(key.namespace(), key.value()); } - public static @Nullable ResourceLocation asVanillaLocation(final @Nullable Key key) { + public static @Nullable Identifier asVanillaLocation(final @Nullable Key key) { if (key == null) { return null; } - return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value()); + return Identifier.fromNamespaceAndPath(key.namespace(), key.value()); } public static @Nullable FontDescription asVanillaFontDescription(final @Nullable Key key) { diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index b619c9f57d0..dc57279948b 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.block.Blocks; @@ -283,7 +283,7 @@ public Optional createArchetype() { return Optional.of(SpongeBlockEntityArchetypeBuilder.pooled() .state(this.state()) - .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).getOptional(ResourceLocation.tryParse(blockEntityID)).orElse(null)) + .blockEntity((BlockEntityType) SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE).getOptional(Identifier.tryParse(blockEntityID)).orElse(null)) .blockEntityData(NBTTranslator.INSTANCE.translate(compound)) .build()); } diff --git a/src/main/java/org/spongepowered/common/bridge/RegistryBackedTrackableBridge.java b/src/main/java/org/spongepowered/common/bridge/RegistryBackedTrackableBridge.java index 369e7f9c982..d565c971fa4 100644 --- a/src/main/java/org/spongepowered/common/bridge/RegistryBackedTrackableBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/RegistryBackedTrackableBridge.java @@ -25,7 +25,7 @@ package org.spongepowered.common.bridge; import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.common.config.tracker.NamespacedCategory; import org.spongepowered.common.config.tracker.TrackerCategory; @@ -38,7 +38,7 @@ public interface RegistryBackedTrackableBridge extends TrackableBridge { void bridge$saveTrackerConfig(); default void bridge$refreshTrackerStates() { - final ResourceLocation key = this.bridge$trackerRegistryBacking().getKey((T) (Object) this); + final Identifier key = this.bridge$trackerRegistryBacking().getKey((T) (Object) this); final String namespace = key.getNamespace(); final String path = key.getPath(); final NamespacedCategory namespacedCategory = this.bridge$trackerCategory().namespacedOrCreate(namespace); diff --git a/src/main/java/org/spongepowered/common/bridge/advancements/AdvancementProgressBridge.java b/src/main/java/org/spongepowered/common/bridge/advancements/AdvancementProgressBridge.java index c62d93423b6..d2a9f78d9b6 100644 --- a/src/main/java/org/spongepowered/common/bridge/advancements/AdvancementProgressBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/advancements/AdvancementProgressBridge.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.bridge.advancements; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.PlayerAdvancements; import org.spongepowered.api.advancement.Advancement; import org.spongepowered.common.advancement.criterion.ImplementationBackedCriterionProgress; @@ -35,13 +35,13 @@ public interface AdvancementProgressBridge { Advancement bridge$getAdvancement(); - ResourceLocation bridge$getAdvancementKey(); + Identifier bridge$getAdvancementKey(); PlayerAdvancements bridge$getPlayerAdvancements(); void bridge$setPlayerAdvancements(PlayerAdvancements playerAdvancements); - void bridge$setAdvancementId(ResourceLocation key); + void bridge$setAdvancementId(Identifier key); void bridge$invalidateAchievedState(); diff --git a/src/main/java/org/spongepowered/common/bridge/tags/TagLoaderBridge.java b/src/main/java/org/spongepowered/common/bridge/tags/TagLoaderBridge.java index b21fc88072c..7c4ab0e3aaa 100644 --- a/src/main/java/org/spongepowered/common/bridge/tags/TagLoaderBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/tags/TagLoaderBridge.java @@ -25,8 +25,8 @@ package org.spongepowered.common.bridge.tags; import net.minecraft.core.Registry; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagLoader; import org.checkerframework.checker.nullness.qual.Nullable; @@ -38,7 +38,7 @@ public interface TagLoaderBridge { void bridge$registryKey(ResourceKey> registryKey); - void bridge$buildingTagKey(@Nullable ResourceLocation key); + void bridge$buildingTagKey(@Nullable Identifier key); default boolean bridge$isAdd(final TagLoader.EntryWithSource entry) { return true; diff --git a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java index 212210a1187..b569a7998bc 100644 --- a/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java +++ b/src/main/java/org/spongepowered/common/command/brigadier/SpongeStringReader.java @@ -30,7 +30,7 @@ import net.kyori.adventure.text.Component; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.TagParser; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -147,12 +147,12 @@ public float parseFloat() throws ArgumentParseException { @Override public ResourceKey parseResourceKey() throws ArgumentParseException { - return this.readResourceLocation(null); + return this.readIdentifier(null); } @Override public ResourceKey parseResourceKey(final @NonNull String defaultNamespace) throws ArgumentParseException { - return this.readResourceLocation(defaultNamespace); + return this.readIdentifier(defaultNamespace); } @Override @@ -244,10 +244,10 @@ public void setState(final @NonNull ArgumentReader state) throws IllegalArgument return new ArgumentParseException(errorMessage, inner, this.input(), this.getCursor()); } - private ResourceKey readResourceLocation(final @Nullable String defaultNamespace) throws ArgumentParseException { + private ResourceKey readIdentifier(final @Nullable String defaultNamespace) throws ArgumentParseException { final int i = this.getCursor(); - while (this.canRead() && ResourceLocation.isAllowedInResourceLocation(this.peek())) { + while (this.canRead() && Identifier.isAllowedInIdentifier(this.peek())) { this.skip(); } diff --git a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java index d17fddc79b0..06cd38eec82 100644 --- a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java +++ b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeServerLocationValueParameter.java @@ -34,7 +34,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.coordinates.Coordinates; import net.minecraft.commands.arguments.coordinates.Vec3Argument; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.phys.Vec3; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.ResourceKey; @@ -87,11 +87,11 @@ private Stream complete(final String currentInput) { final ArgumentReader.Immutable state = reader.immutable(); ServerWorld serverWorld; try { - final ResourceKey resourceLocation = reader.parseResourceKey("minecraft"); + final ResourceKey Identifier = reader.parseResourceKey("minecraft"); serverWorld = SpongeCommon.game().server().worldManager() - .world(resourceLocation) + .world(Identifier) .orElseThrow(() -> reader.createException( - Component.text("Could not get world with key \"" + resourceLocation + "\""))); + Component.text("Could not get world with key \"" + Identifier + "\""))); } catch (final ArgumentParseException e) { final Optional location = cause.location(); if (location.isPresent()) { @@ -127,7 +127,7 @@ public CommandNode createSuggestions(final CommandNode> redirectionNodes, final boolean allowCustomSuggestionsOnTheFirstElement) { - final RequiredArgumentBuilder firstNode = + final RequiredArgumentBuilder firstNode = RequiredArgumentBuilder.argument(key, Constants.Command.RESOURCE_LOCATION_TYPE); if (allowCustomSuggestionsOnTheFirstElement) { firstNode.suggests((context, builder) -> { diff --git a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java index 492c4da3e9b..daaff9e848c 100644 --- a/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java +++ b/src/main/java/org/spongepowered/common/config/SpongeGameConfigs.java @@ -130,13 +130,13 @@ public static InheritableConfigHandle load(final DimensionType dime } } - @SuppressWarnings("EqualsBetweenInconvertibleTypes") // ResourceKey is ResourceLocation + @SuppressWarnings("EqualsBetweenInconvertibleTypes") // ResourceKey is Identifier private static @Nullable String getLegacyDimensionAndName(final ResourceKey world) { - if (world.equals(Level.OVERWORLD.location())) { + if (world.equals(Level.OVERWORLD.identifier())) { return "overworld/world"; - } else if (world.equals(Level.END.location())) { + } else if (world.equals(Level.END.identifier())) { return "the_end/DIM1"; - } else if (world.equals(Level.NETHER.location())) { + } else if (world.equals(Level.NETHER.identifier())) { return "nether/DIM-1"; } return null; diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java index 813eb4c98af..c7312c6f97a 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/SkullData.java @@ -26,7 +26,7 @@ import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.level.block.entity.SkullBlockEntity; import org.spongepowered.api.ResourceKey; @@ -64,7 +64,7 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(SkullBlockEntityAccessor.class) .create(Keys.NOTE_BLOCK_SOUND) .get(h -> (ResourceKey) (Object) h.accessor$noteBlockSound()) - .set((h, v) -> h.accessor$noteBlockSound((ResourceLocation) (Object) v)) + .set((h, v) -> h.accessor$noteBlockSound((Identifier) (Object) v)) .delete(h -> h.accessor$noteBlockSound(null)) ; } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java index 215697af97b..14cbe1bc57c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java @@ -170,8 +170,8 @@ public static void register(final DataProviderRegistrator registrator) { .get(Entity::isCustomNameVisible) .set(Entity::setCustomNameVisible) .create(Keys.IS_FLYING) - .get(h -> h.hasImpulse) - .set((h, v) -> h.hasImpulse = v) + .get(h -> h.needsSync) + .set((h, v) -> h.needsSync = v) .supports(h -> !(h instanceof Player)) .create(Keys.IS_GLOWING) .get(Entity::hasGlowingTag) diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index 6d216f2a99a..c39fe7b1e24 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -57,7 +57,7 @@ public static void register(final DataProviderRegistrator registrator) { return null; } return equippable.assetId() - .map(rl -> (ResourceKey) (Object) rl.location()) + .map(rl -> (ResourceKey) (Object) rl.identifier()) .flatMap(rk -> RegistryTypes.ARMOR_MATERIAL.get().findEntry(rk)) .map(RegistryEntry::value) .orElse(null); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java index f065fb38278..c211b0513b3 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.advancements.criterion.BlockPredicate; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponentType; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index fbb402d3f4b..c26c7d9207d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -28,7 +28,7 @@ import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; @@ -206,7 +206,7 @@ public static void register(final DataProviderRegistrator registrator) { .delete(h -> h.remove(DataComponents.MAX_STACK_SIZE)) .create(Keys.MODEL) .get(stack -> (ResourceKey) (Object) stack.get(DataComponents.ITEM_MODEL)) - .set((stack, model) -> stack.set(DataComponents.ITEM_MODEL, (ResourceLocation) (Object) model)) + .set((stack, model) -> stack.set(DataComponents.ITEM_MODEL, (Identifier) (Object) model)) .create(Keys.ITEM_DURABILITY) .get(stack -> stack.getMaxDamage() - stack.getDamageValue()) .set((stack, durability) -> stack.setDamageValue(stack.getMaxDamage() - durability)) @@ -298,7 +298,7 @@ public static void register(final DataProviderRegistrator registrator) { if (resist == null) { return false; } - return resist.types().location().equals(DamageTypes.IN_FIRE.location()); + return resist.types().location().equals(DamageTypes.IN_FIRE.identifier()); }) .set((h, value) -> { if (value) { @@ -333,7 +333,7 @@ public static void register(final DataProviderRegistrator registrator) { h.remove(DataComponents.USE_COOLDOWN); return; } - h.set(DataComponents.USE_COOLDOWN, new UseCooldown(1, Optional.of((ResourceLocation) (Object) value))); + h.set(DataComponents.USE_COOLDOWN, new UseCooldown(1, Optional.of((Identifier) (Object) value))); }) .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) .create(Keys.COOLDOWN) @@ -371,7 +371,7 @@ public static void register(final DataProviderRegistrator registrator) { .deleteAndGet(ItemStackData::deleteAndTransactUseCooldown) .create(Keys.TOOLTIP_STYLE) .get(h -> (ResourceKey) (Object) h.get(DataComponents.TOOLTIP_STYLE)) - .set((h, v) -> h.set(DataComponents.TOOLTIP_STYLE, (ResourceLocation) (Object) v)) + .set((h, v) -> h.set(DataComponents.TOOLTIP_STYLE, (Identifier) (Object) v)) .delete(h -> h.remove(DataComponents.TOOLTIP_STYLE)) .create(Keys.WEAPON_DAMAGE_PER_ATTACK) .get(h -> { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java index 78059b24ce8..8b9fb1255d0 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SkullItemStackData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.item.stack; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.PlayerHeadItem; import net.minecraft.world.item.component.ResolvableProfile; @@ -56,7 +56,7 @@ public static void register(final DataProviderRegistrator registrator) { .supports(h -> h.getItem() instanceof PlayerHeadItem) .create(Keys.NOTE_BLOCK_SOUND) .get(h -> (ResourceKey) (Object) h.get(DataComponents.NOTE_BLOCK_SOUND)) - .set((h, v) -> h.set(DataComponents.NOTE_BLOCK_SOUND, (ResourceLocation) (Object) v)) + .set((h, v) -> h.set(DataComponents.NOTE_BLOCK_SOUND, (Identifier) (Object) v)) .delete(h -> h.remove(DataComponents.NOTE_BLOCK_SOUND)) ; } diff --git a/src/main/java/org/spongepowered/common/data/provider/map/MapInfoData.java b/src/main/java/org/spongepowered/common/data/provider/map/MapInfoData.java index fab0ec7361e..983f9a6af8f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/map/MapInfoData.java +++ b/src/main/java/org/spongepowered/common/data/provider/map/MapInfoData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.map; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import org.apache.logging.log4j.LogManager; import org.spongepowered.api.ResourceKey; @@ -92,10 +92,10 @@ public static void register(final DataProviderRegistrator registrator) { return null; } - return (ResourceKey) (Object) mapData.dimension.location(); + return (ResourceKey) (Object) mapData.dimension.identifier(); }) .set((mapData, key) -> { - ((MapItemSavedDataAccessor) mapData).accessor$dimension(net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (ResourceLocation) (Object) key)); + ((MapItemSavedDataAccessor) mapData).accessor$dimension(net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (Identifier) (Object) key)); mapData.setDirty(); }) .asMutable(MapItemSavedDataBridge.class) diff --git a/src/main/java/org/spongepowered/common/data/provider/world/ServerLevelDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/world/ServerLevelDataProvider.java new file mode 100644 index 00000000000..7141a9c7cdc --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/world/ServerLevelDataProvider.java @@ -0,0 +1,29 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.world; + +public class ServerLevelDataProvider { + +} diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java index 6b47942df32..3eec96adf17 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java @@ -29,20 +29,15 @@ import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.data.Keys; import org.spongepowered.api.tag.Tag; -import org.spongepowered.api.util.MinecraftDayTime; import org.spongepowered.api.util.Range; import org.spongepowered.api.world.WorldTypeEffect; import org.spongepowered.common.accessor.world.level.dimension.DimensionTypeAccessor; import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.registry.provider.DimensionEffectProvider; -import org.spongepowered.common.util.SpongeMinecraftDayTime; - -import java.util.OptionalLong; public final class WorldTypeData { @@ -58,7 +53,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.SCORCHING) .get(d -> d.attributes().applyModifier(EnvironmentAttributes.WATER_EVAPORATES, false)) .create(Keys.NATURAL_WORLD_TYPE) - .get(DimensionType::natural) + .get(d -> d.attributes().contains(EnvironmentAttributes.BED_RULE)) .create(Keys.COORDINATE_MULTIPLIER) .get(DimensionType::coordinateScale) .create(Keys.HAS_SKYLIGHT) @@ -88,8 +83,6 @@ public static void register(final DataProviderRegistrator registrator) { .asImmutable(DimensionTypeAccessor.class) .create(Keys.AMBIENT_LIGHTING) .get(DimensionTypeAccessor::accessor$ambientLight) - .create(Keys.FIXED_TIME) - .get(WorldTypeData::fixedTime) .asImmutable(DimensionTypeBridge.class) .create(Keys.CREATE_DRAGON_FIGHT) .get(DimensionTypeBridge::bridge$createDragonFight) @@ -103,20 +96,11 @@ private static Range lightRange(IntProvider provider) { } private static WorldTypeEffect worldTypeEffect(final DimensionType type) { - final var key = (ResourceKey) (Object) type.effectsLocation(); - @Nullable final WorldTypeEffect effect = DimensionEffectProvider.INSTANCE.get(key); + @Nullable final WorldTypeEffect effect = DimensionEffectProvider.INSTANCE.get(type.skybox()); if (effect == null) { - throw new IllegalStateException(String.format("The effect '%s' has not been registered!", key)); + throw new IllegalStateException(String.format("The effect '%s' has not been registered!", type.skybox())); } return effect; } - @Nullable - private static MinecraftDayTime fixedTime(final DimensionTypeAccessor accessor) { - final OptionalLong fixedTime = accessor.accessor$fixedTime(); - if (!fixedTime.isPresent()) { - return null; - } - return new SpongeMinecraftDayTime(fixedTime.getAsLong()); - } } diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java index 154de888652..823a3e268d8 100644 --- a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.type; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.decoration.PaintingVariant; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -38,7 +38,7 @@ public final class SpongeArtTypeBuilder implements ArtType.Builder { private int width; private int height; - @Nullable private ResourceLocation assetId; + @Nullable private Identifier assetId; public SpongeArtTypeBuilder() { this.reset(); @@ -53,7 +53,7 @@ public ArtType.Builder dimensions(final int width, final int height) { @Override public ArtType.Builder asset(final ResourceKey assetId) { - this.assetId = (ResourceLocation) (Object) assetId; + this.assetId = (Identifier) (Object) assetId; return this; } diff --git a/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java b/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java index 9b99d2bfb6c..16258e5ef91 100644 --- a/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java +++ b/src/main/java/org/spongepowered/common/effect/sound/SpongeSoundBuilder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.effect.sound; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.effect.sound.SoundType; import org.spongepowered.common.accessor.sounds.SoundEventAccessor; import org.spongepowered.common.util.AbstractResourceKeyedBuilder; @@ -33,6 +33,6 @@ public final class SpongeSoundBuilder extends AbstractResourceKeyedBuilder resolveEvent(final @NonNull Sound sound) { - final ResourceLocation soundKey = SpongeAdventure.asVanilla(Objects.requireNonNull(sound, "sound").name()); + final Identifier soundKey = SpongeAdventure.asVanilla(Objects.requireNonNull(sound, "sound").name()); final var soundEventRegistry = SpongeCommon.vanillaRegistry(Registries.SOUND_EVENT); final SoundEvent event = soundEventRegistry.getOptional(soundKey) .orElseGet(() -> SoundEvent.createVariableRangeEvent(soundKey)); diff --git a/src/main/java/org/spongepowered/common/entity/EntityUtil.java b/src/main/java/org/spongepowered/common/entity/EntityUtil.java index 047ecb6a936..e5fb1382c26 100644 --- a/src/main/java/org/spongepowered/common/entity/EntityUtil.java +++ b/src/main/java/org/spongepowered/common/entity/EntityUtil.java @@ -26,7 +26,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; import net.minecraft.util.random.WeightedList; import net.minecraft.world.entity.Entity; @@ -183,9 +183,9 @@ public static boolean isUntargetable(final Entity from, final Entity target) { public static EntityArchetype toArchetype(final SpawnData logic) { final var tag = logic.entityToSpawn(); - final var resourceLocation = tag.getString(Constants.Entity.ENTITY_TYPE_ID); + final var identifier = tag.getString(Constants.Entity.ENTITY_TYPE_ID); final var entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - final var type = resourceLocation.flatMap(location -> entityTypeRegistry.getOptional(ResourceLocation.parse(location))) + final var type = identifier.flatMap(location -> entityTypeRegistry.getOptional(Identifier.parse(location))) .map(org.spongepowered.api.entity.EntityType.class::cast) .orElse(EntityTypes.PIG.get()); @@ -211,11 +211,11 @@ public static WeightedTable toWeightedArchetypes(final Weighted for (final var weightedEntity : spawnData.unwrap()) { final CompoundTag nbt = weightedEntity.value().entityToSpawn(); - final Optional resourceLocation = nbt.getString(Constants.Entity.ENTITY_TYPE_ID); - if (resourceLocation.isEmpty()) { + final Optional identifier = nbt.getString(Constants.Entity.ENTITY_TYPE_ID); + if (identifier.isEmpty()) { continue; } - final var mcType = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getOptional(ResourceLocation.parse(resourceLocation.get())); + final var mcType = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE).getOptional(Identifier.parse(identifier.get())); final var type = mcType.map(org.spongepowered.api.entity.EntityType.class::cast).orElse(EntityTypes.PIG.get()); final EntityArchetype archetype = SpongeEntityArchetypeBuilder.pooled() diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java index 516b2caeef7..c6788d69ae0 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java @@ -28,7 +28,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.ListTag; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; @@ -134,7 +134,7 @@ public Optional apply(final ServerLocation final org.spongepowered.api.world.server.ServerWorld spongeWorld = location.world(); final ServerLevel level = (ServerLevel) spongeWorld; - final ResourceLocation key = net.minecraft.world.entity.EntityType.getKey((net.minecraft.world.entity.EntityType) this.type); + final Identifier key = net.minecraft.world.entity.EntityType.getKey((net.minecraft.world.entity.EntityType) this.type); if (key == null) { return Optional.empty(); } diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityTypes.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityTypes.java index 84e34cbcdc1..170008b6ac8 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityTypes.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityTypes.java @@ -26,8 +26,8 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import org.spongepowered.common.entity.living.human.HumanEntity; @@ -40,7 +40,7 @@ public class SpongeEntityTypes { .sized(0.6F, 1.8F) .clientTrackingRange(Constants.Entity.Player.TRACKING_RANGE) .updateInterval(2) - .build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath("sponge", "human"))); + .build(ResourceKey.create(Registries.ENTITY_TYPE, Identifier.fromNamespaceAndPath("sponge", "human"))); public static void register(Registry> registry) { Registry.register(registry, HumanEntity.KEY, SpongeEntityTypes.HUMAN); diff --git a/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java b/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java index 5b29661f430..d5950911bb1 100644 --- a/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.entity.attribute; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.entity.attribute.AttributeModifier; import org.spongepowered.api.entity.attribute.AttributeOperation; @@ -35,14 +35,14 @@ public final class SpongeAttributeModifierBuilder implements AttributeModifier.B // Use a random id private AttributeOperation operation; private double amount; - private ResourceLocation key; + private Identifier key; public SpongeAttributeModifierBuilder() { } @Override public AttributeModifier.Builder key(final ResourceKey key) { - this.key = (ResourceLocation) (Object) key; + this.key = (Identifier) (Object) key; return this; } diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 5ce21e78282..e0922d877b2 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -43,8 +43,8 @@ import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -110,7 +110,7 @@ import java.util.stream.Stream; public final class HumanEntity extends PathfinderMob implements TeamMember, RangedAttackMob { - public static final ResourceKey> KEY = ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath("sponge", "human")); + public static final ResourceKey> KEY = ResourceKey.create(Registries.ENTITY_TYPE, Identifier.fromNamespaceAndPath("sponge", "human")); public static AttributeSupplier createAttributes() { return Mob.createMobAttributes() diff --git a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java index 21f11f430cd..8847ce8821d 100644 --- a/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java +++ b/src/main/java/org/spongepowered/common/entity/player/SpongeUserData.java @@ -31,7 +31,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.ProblemReporter; import net.minecraft.util.datafix.DataFixTypes; @@ -121,7 +121,7 @@ public final class SpongeUserData implements Identifiable, DataSerializable, Bed private final Map spawnLocations = Maps.newHashMap(); - private ResourceKey worldKey = (ResourceKey) (Object) Level.OVERWORLD.location(); + private ResourceKey worldKey = (ResourceKey) (Object) Level.OVERWORLD.identifier(); private double x; private double y; private double z; @@ -229,7 +229,7 @@ public void readCompound(final CompoundTag compound) { this.reset(); this.compound = compound; - compound.read(Constants.Sponge.World.WORLD_KEY, ResourceLocation.CODEC) + compound.read(Constants.Sponge.World.WORLD_KEY, Identifier.CODEC) .ifPresent(key -> this.worldKey = (ResourceKey) (Object) key); final var rotation = compound.read(Constants.Entity.ENTITY_ROTATION, Rotations.CODEC).orElse(new Rotations(0, 0, 0)); diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java b/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java index 9f4458ba773..f3e3883ef7f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java @@ -25,7 +25,7 @@ package org.spongepowered.common.event.tracking; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; import org.apache.logging.log4j.Level; @@ -152,7 +152,7 @@ static void printExceptionSpawningEntity(final PhaseTracker tracker, final Phase } static void printNullSourceBlockWithTile( - final BlockPos pos, final Block blockIn, final BlockPos otherPos, final ResourceLocation type, final boolean useTile, + final BlockPos pos, final Block blockIn, final BlockPos otherPos, final Identifier type, final boolean useTile, final NullPointerException e) { final PhaseTracker instance = PhaseTracker.getInstance(); final PrettyPrinter printer = new PrettyPrinter(60).add("Null Source Block on TileEntity!").centre().hr() diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index a69a929ef3b..eae4de2cdbf 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -29,7 +29,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Queues; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.LevelAccessor; @@ -179,9 +179,9 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world .map(BlockEntity::getType) .orElse(null); if (type != null) { - @Nullable ResourceLocation id = BlockEntityType.getKey(type); + @Nullable Identifier id = BlockEntityType.getKey(type); if (id == null) { - id = ResourceLocation.parse(source.getClass().getCanonicalName()); + id = Identifier.parse(source.getClass().getCanonicalName()); } final Map autoFixedTiles = trackerConfig.autoFixNullSourceBlockProvidingBlockEntities; final boolean contained = autoFixedTiles.containsKey(type.toString()); diff --git a/src/main/java/org/spongepowered/common/event/tracking/UnwindingState.java b/src/main/java/org/spongepowered/common/event/tracking/UnwindingState.java index 76c80f4ebcb..20ccedb4e1d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/UnwindingState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/UnwindingState.java @@ -90,7 +90,7 @@ public void unwind(final UnwindingPhaseContext context) { @Override public Supplier attemptWorldKey(UnwindingPhaseContext context) { - final Optional> o = context.getSource(Entity.class).map(s -> () -> (ResourceKey) (Object) s.level().dimension().location()); + final Optional> o = context.getSource(Entity.class).map(s -> () -> (ResourceKey) (Object) s.level().dimension().identifier()); return o.orElseThrow(() -> new IllegalStateException("Expected to be ticking an entity!")); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java index 985cea97629..62b3d3cab8d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateOrCreateNewTileEntityPostPlacementEffect.java @@ -61,7 +61,7 @@ public static UpdateOrCreateNewTileEntityPostPlacementEffect getInstance() { var maybeNewTileEntity = chunk.getBlockEntity(oldState.pos(), LevelChunk.EntityCreationType.CHECK); if (maybeNewTileEntity != null && !maybeNewTileEntity.isValidBlockState(newState)) { LevelChunkAccessor.accessor$LOGGER().warn( - "Found mismatched block entity @ {}: type = {}, state = {}", pos, maybeNewTileEntity.getType().builtInRegistryHolder().key().location(), newState + "Found mismatched block entity @ {}: type = {}, state = {}", pos, maybeNewTileEntity.getType().builtInRegistryHolder().key().identifier(), newState ); chunk.removeBlockEntity(pos); maybeNewTileEntity = null; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java index 3afcf2c413a..99a164311f1 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ContainerBasedTransaction.java @@ -273,7 +273,7 @@ private void handleCrafting(final Player player, final ClickContainerEvent event SpongeEventFactory.createCraftItemEventCraft(PhaseTracker.getInstance().currentCause(), ContainerUtil.fromNative(this.menu), craftedItem, this.craftingInventory, event.cursorTransaction(), Optional.ofNullable(this.onTakeRecipe).map(r -> (CraftingRecipe) r.value()), - Optional.ofNullable(this.onTakeRecipe).map(r -> (ResourceKey) (Object) r.id().location()), + Optional.ofNullable(this.onTakeRecipe).map(r -> (ResourceKey) (Object) r.id().identifier()), Optional.of(this.craftingInventory.result()), event.transactions()); SpongeCommon.post(craftEvent); this.handleEventResults(player, craftEvent); @@ -290,7 +290,7 @@ private void handleCraftingPreview(final Player player, final ClickContainerEven final SlotTransaction previewTransaction = this.getPreviewTransaction(this.craftingInventory.result(), event.transactions()); final var recipe = sp.level().recipeAccess().getRecipeFor(RecipeType.CRAFTING, this.craftingContainer.asCraftInput(), player.level()); final CraftItemEvent.Preview previewEvent = SpongeEventFactory.createCraftItemEventPreview(event.cause(), (Container) this.menu, this.craftingInventory, event.cursorTransaction(), previewTransaction, - recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(r -> (ResourceKey) (Object) r.id().location()), Optional.empty(), event.transactions()); + recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), recipe.map(r -> (ResourceKey) (Object) r.id().identifier()), Optional.empty(), event.transactions()); SpongeCommon.post(previewEvent); this.handleEventResults(player, previewEvent); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java index 7b488255d1d..daec1f0974d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CraftingPreviewTransaction.java @@ -80,7 +80,7 @@ Optional createInventoryEvent(final List s final CraftItemEvent.Preview event = SpongeEventFactory.createCraftItemEventPreview(currentCause, ContainerUtil.fromNative(this.menu), this.craftingInventory, new Transaction<>(cursor, cursor), previewTransaction, recipe.map(RecipeHolder::value).map(CraftingRecipe.class::cast), - recipe.map(r -> (ResourceKey) (Object) r.id().location()), + recipe.map(r -> (ResourceKey) (Object) r.id().identifier()), Optional.empty(), slotTransactions); return Optional.of(event); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java index 58be64b551a..1e6febe2a6f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java @@ -77,13 +77,13 @@ Optional createInventoryEvent( event = SpongeEventFactory.createClickContainerEventRecipeAll(cause, (Container) this.menu, this.craftingInventory, cursorTransaction, preview, Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().location()), + Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().identifier()), Optional.empty(), slotTransactions); } else { event = SpongeEventFactory.createClickContainerEventRecipeSingle(cause, (Container) this.menu, this.craftingInventory, cursorTransaction, preview, Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().location()), + Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().identifier()), Optional.empty(), slotTransactions); } return Optional.of(event); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java index d414a4320a6..33d3b450f6d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/CommandState.java @@ -98,7 +98,7 @@ public void unwind(final CommandPhaseContext phaseContext) { public Supplier attemptWorldKey(CommandPhaseContext context) { final Optional playerSource = context.getSource(net.minecraft.world.entity.player.Player.class); if (playerSource.isPresent()) { - return () -> (ResourceKey) (Object) playerSource.get().level().dimension().location(); + return () -> (ResourceKey) (Object) playerSource.get().level().dimension().identifier(); } return super.attemptWorldKey(context); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketState.java index e6c2cf7122f..c361f3e2fa1 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketState.java @@ -26,7 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.Packet; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.block.Block; @@ -93,7 +93,7 @@ public Supplier getSpawnTypeForTransaction( @Override public Supplier attemptWorldKey(final P context) { - final ResourceLocation worldKey = context.packetPlayer.level().dimension().location(); + final Identifier worldKey = context.packetPlayer.level().dimension().identifier(); return () -> (ResourceKey) (Object) worldKey; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java index a370479c4dd..6dfae53e538 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/EntityTickPhaseState.java @@ -115,7 +115,7 @@ public Supplier attemptWorldKey( throw new IllegalStateException("attempting a world key on the client???"); }; } - return () -> (ResourceKey) (Object) entity.level().dimension().location(); + return () -> (ResourceKey) (Object) entity.level().dimension().identifier(); } @Override diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java index c6c59b088f8..ecce9ee5019 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/LocationBasedTickPhaseState.java @@ -108,7 +108,7 @@ public void appendNotifierToBlockEvent( public Supplier attemptWorldKey(final T context) { return MemoizedSupplier.memoize(() -> { final World<@NonNull ?, @NonNull ?> world = this.getLocatableBlockSourceFromContext(context).world(); - return (ResourceKey) (Object) ((Level) world).dimension().location(); + return (ResourceKey) (Object) ((Level) world).dimension().identifier(); }); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/WorldTickState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/WorldTickState.java index 76068d6e12f..56eea3c6873 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/tick/WorldTickState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/tick/WorldTickState.java @@ -68,7 +68,7 @@ public void unwind(final WorldTickContext phaseContext) { public Supplier attemptWorldKey( final WorldTickContext context ) { - return () -> (ResourceKey) (Object) Objects.requireNonNull(context.serverWorld.get(), "ServerWorld reference lost during tick").dimension().location(); + return () -> (ResourceKey) (Object) Objects.requireNonNull(context.serverWorld.get(), "ServerWorld reference lost during tick").dimension().identifier(); } public static class WorldTickContext extends TickContext { diff --git a/src/main/java/org/spongepowered/common/fluid/SpongeFluidStateBuilder.java b/src/main/java/org/spongepowered/common/fluid/SpongeFluidStateBuilder.java index 446f781bfe3..6a9ee664dd9 100644 --- a/src/main/java/org/spongepowered/common/fluid/SpongeFluidStateBuilder.java +++ b/src/main/java/org/spongepowered/common/fluid/SpongeFluidStateBuilder.java @@ -32,7 +32,7 @@ import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.Fluid; @@ -126,7 +126,7 @@ private org.spongepowered.api.fluid.FluidState parseString(final String string) private Fluid readFluid(final StringReader reader) throws CommandSyntaxException { final int cursor = reader.getCursor(); - final ResourceLocation fluidKey = ResourceLocation.read(reader); + final Identifier fluidKey = Identifier.read(reader); final Registry fluidRegistry = SpongeCommon.vanillaRegistry(Registries.FLUID); return fluidRegistry.getOptional(fluidKey).orElseThrow(() -> { reader.setCursor(cursor); diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java index fd2224756c1..9253d64cdc6 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java @@ -35,8 +35,8 @@ import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; +import net.minecraft.resources.Identifier; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlotGroup; import net.minecraft.world.entity.ai.attributes.Attribute; @@ -193,7 +193,7 @@ public ItemStack.Builder fromBlockSnapshot(final BlockSnapshot blockSnapshot) { Objects.requireNonNull(blockSnapshot, "The snapshot was null!"); this.reset(); final BlockType blockType = blockSnapshot.state().type(); - final ResourceLocation blockTypeKey = SpongeCommon.vanillaRegistry(Registries.BLOCK).getKey((Block) blockType); + final Identifier blockTypeKey = SpongeCommon.vanillaRegistry(Registries.BLOCK).getKey((Block) blockType); final Optional itemType = blockType.item(); this.itemType(itemType.orElseThrow(() -> new IllegalArgumentException("ItemType not found for block type: " + blockTypeKey))); this.quantity(1); @@ -201,7 +201,7 @@ public ItemStack.Builder fromBlockSnapshot(final BlockSnapshot blockSnapshot) { sbs.getCompound().ifPresent(compoundTag -> { final var blockEntityTypes = SpongeCommon.vanillaRegistry(Registries.BLOCK_ENTITY_TYPE); final var blockEntityType = compoundTag.getString("id") - .map(ResourceLocation::parse) + .map(Identifier::parse) .flatMap(blockEntityTypes::getOptional); blockEntityType.ifPresent(beType -> { TypedEntityData> data = TypedEntityData.of(beType, compoundTag); @@ -227,7 +227,7 @@ public ItemStack.Builder fromBlockSnapshot(final BlockSnapshot blockSnapshot) { public ItemStack.Builder fromBlockState(final BlockState blockState) { Objects.requireNonNull(blockState, "blockState"); final BlockType blockType = blockState.type(); - final ResourceLocation blockTypeKey = SpongeCommon.vanillaRegistry(Registries.BLOCK).getKey((Block) blockType); + final Identifier blockTypeKey = SpongeCommon.vanillaRegistry(Registries.BLOCK).getKey((Block) blockType); this.itemType(blockType.item().orElseThrow(() -> new IllegalArgumentException("Missing valid ItemType for BlockType: " + blockTypeKey))); blockState.getValues().forEach(this::add); return this; @@ -282,7 +282,7 @@ public ItemStack empty() { @NotNull public static DataContainer getDataContainer(final net.minecraft.world.item.ItemStack mcStack) { - final ResourceLocation key = BuiltInRegistries.ITEM.getKey(mcStack.getItem()); + final Identifier key = BuiltInRegistries.ITEM.getKey(mcStack.getItem()); final DataContainer container = DataContainer.createNew() .set(Queries.CONTENT_VERSION, ((ItemStack) (Object) mcStack).contentVersion()) .set(Constants.ItemStack.TYPE, key) diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java index 228ba81923a..a1baea3bc60 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/IngredientUtil.java @@ -27,7 +27,7 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.Ingredient; @@ -60,7 +60,7 @@ public static org.spongepowered.api.item.recipe.crafting.Ingredient of(ItemType. } public static org.spongepowered.api.item.recipe.crafting.@Nullable Ingredient of(ResourceKey tagKey) { - final TagKey key = TagKey.create(Registries.ITEM, (ResourceLocation) (Object) tagKey); + final TagKey key = TagKey.create(Registries.ITEM, (Identifier) (Object) tagKey); var holderset = BuiltInRegistries.ITEM.get(key).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); return IngredientUtil.fromNative(Ingredient.of(holderset)); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java index 5ba2839a520..2eb5298c845 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java @@ -25,12 +25,12 @@ package org.spongepowered.common.item.recipe.ingredient; import com.mojang.datafixers.util.Either; -import net.minecraft.Util; import net.minecraft.core.Holder; import net.minecraft.core.HolderOwner; import net.minecraft.core.HolderSet; import net.minecraft.tags.TagKey; import net.minecraft.util.RandomSource; +import net.minecraft.util.Util; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java b/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java index 1b65b346685..dc088ee0b29 100644 --- a/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java +++ b/src/main/java/org/spongepowered/common/map/decoration/SpongeMapDecorationBuilder.java @@ -28,7 +28,7 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.persistence.DataQuery; @@ -125,7 +125,7 @@ public MapDecoration.Builder fromContainer(final DataView container) { final byte rot = this.getByteFromContainer(container, Constants.Map.DECORATION_ROTATION); - final var mcType = BuiltInRegistries.MAP_DECORATION_TYPE.getValue((ResourceLocation) (Object) type); + final var mcType = BuiltInRegistries.MAP_DECORATION_TYPE.getValue((Identifier) (Object) type); if (mcType == null) { throw new IllegalStateException("Missing a MapDecorationType, could not find one for Minecraft's MapDecoration.Type: " + type); } diff --git a/src/main/java/org/spongepowered/common/network/channel/ChannelUtils.java b/src/main/java/org/spongepowered/common/network/channel/ChannelUtils.java index 57514e417a1..f00b9f568f3 100644 --- a/src/main/java/org/spongepowered/common/network/channel/ChannelUtils.java +++ b/src/main/java/org/spongepowered/common/network/channel/ChannelUtils.java @@ -25,7 +25,7 @@ package org.spongepowered.common.network.channel; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.Sponge; import org.spongepowered.common.hooks.PlatformHooks; import org.spongepowered.common.util.Constants; @@ -34,7 +34,7 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public final class ChannelUtils { - public static final CustomPacketPayload.Type REGISTER = new CustomPacketPayload.Type<>((ResourceLocation) (Object) Constants.Channels.REGISTER_KEY); + public static final CustomPacketPayload.Type REGISTER = new CustomPacketPayload.Type<>((Identifier) (Object) Constants.Channels.REGISTER_KEY); public static ArrayList spongeChannelCodecs(final int maxPayloadSize) { ArrayList channels = new ArrayList<>(); diff --git a/src/main/java/org/spongepowered/common/network/channel/SpongeChannel.java b/src/main/java/org/spongepowered/common/network/channel/SpongeChannel.java index 0dabdf2ae4d..4430e5be015 100644 --- a/src/main/java/org/spongepowered/common/network/channel/SpongeChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/SpongeChannel.java @@ -26,7 +26,7 @@ import com.google.common.collect.Multimap; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -69,7 +69,7 @@ public SpongeChannel(final int type, final ResourceKey key, final SpongeChannelM this.key = key; this.manager = manager; this.logger = LogManager.getLogger("channel/" + key.formatted()); - this.payloadType = new CustomPacketPayload.Type<>((ResourceLocation) (Object) key); + this.payloadType = new CustomPacketPayload.Type<>((Identifier) (Object) key); } public int getType() { diff --git a/src/main/java/org/spongepowered/common/network/channel/SpongeChannelManager.java b/src/main/java/org/spongepowered/common/network/channel/SpongeChannelManager.java index 30ab1bb0711..5f1a74b15bb 100644 --- a/src/main/java/org/spongepowered/common/network/channel/SpongeChannelManager.java +++ b/src/main/java/org/spongepowered/common/network/channel/SpongeChannelManager.java @@ -31,7 +31,7 @@ import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -172,8 +172,8 @@ public CompletableFuture requestClientType(final EngineConnection connecti final Packet mcPacket = PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) Constants.Channels.SPONGE_CLIENT_TYPE; + public Identifier id() { + return (Identifier) (Object) Constants.Channels.SPONGE_CLIENT_TYPE; } @Override @@ -217,8 +217,8 @@ public CompletableFuture sendLoginChannelRegistry(final EngineConnection c final Consumer consumer = this.encodeChannelRegistry(); final Packet mcPacket = PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) Constants.Channels.SPONGE_CHANNEL_REGISTRY; + public Identifier id() { + return (Identifier) (Object) Constants.Channels.SPONGE_CHANNEL_REGISTRY; } @Override @@ -288,7 +288,7 @@ private void handleChannelRegistry(final EngineConnection connection, final Chan } } - public boolean handlePlayPayload(final EngineConnection connection, final EngineConnectionState state, final ResourceLocation channelKey, final Consumer payload) { + public boolean handlePlayPayload(final EngineConnection connection, final EngineConnectionState state, final Identifier channelKey, final Consumer payload) { final ChannelBuf buf = this.bufferAllocator.buffer(); payload.accept((FriendlyByteBuf) buf); @@ -334,7 +334,7 @@ private boolean handlePlayPayload(final EngineConnection connection, final Engin } } - public boolean handleLoginRequestPayload(final EngineConnection connection, final EngineConnectionState state, final ResourceLocation channelKey, final int transactionId, final Consumer payload) { + public boolean handleLoginRequestPayload(final EngineConnection connection, final EngineConnectionState state, final Identifier channelKey, final int transactionId, final Consumer payload) { // Server -> Client request final ChannelBuf buf = this.bufferAllocator.buffer(); payload.accept((FriendlyByteBuf) buf); diff --git a/src/main/java/org/spongepowered/common/network/channel/SpongeChannelPayload.java b/src/main/java/org/spongepowered/common/network/channel/SpongeChannelPayload.java index e76845f650c..d03e2351cc9 100644 --- a/src/main/java/org/spongepowered/common/network/channel/SpongeChannelPayload.java +++ b/src/main/java/org/spongepowered/common/network/channel/SpongeChannelPayload.java @@ -30,12 +30,12 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.function.Consumer; -public record SpongeChannelPayload(@Nullable Type type, @Nullable ResourceLocation id, Consumer consumer) implements CustomPacketPayload, CustomQueryPayload, CustomQueryAnswerPayload { +public record SpongeChannelPayload(@Nullable Type type, @Nullable Identifier id, Consumer consumer) implements CustomPacketPayload, CustomQueryPayload, CustomQueryAnswerPayload { public static StreamCodec streamCodec(final Type type, final int maxPayloadSize) { return CustomPacketPayload.codec( @@ -59,7 +59,7 @@ public Type type() { } @Override - public ResourceLocation id() { + public Identifier id() { return this.id; } @@ -67,7 +67,7 @@ public static SpongeChannelPayload fromType(final Type consumer) { + public static SpongeChannelPayload fromId(final Identifier id, final Consumer consumer) { return new SpongeChannelPayload(null, id, consumer); } diff --git a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java index 88e3b5db59e..f5349bd002c 100644 --- a/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/packet/SpongeBasicPacketChannel.java @@ -26,7 +26,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.network.ClientSideConnection; @@ -93,8 +93,8 @@ private

, R extends Packet> void sendRequestTo(final final net.minecraft.network.protocol.Packet mcPacket = PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) Constants.Channels.FML_LOGIN_WRAPPER_CHANNEL; + public Identifier id() { + return (Identifier) (Object) Constants.Channels.FML_LOGIN_WRAPPER_CHANNEL; } @Override @@ -139,8 +139,8 @@ private CompletableFuture sendNormalTo(final EngineConnection connection, final net.minecraft.network.protocol.Packet mcPacket = PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) key; + public Identifier id() { + return (Identifier) (Object) key; } @Override diff --git a/src/main/java/org/spongepowered/common/network/channel/packet/SpongePacketChannel.java b/src/main/java/org/spongepowered/common/network/channel/packet/SpongePacketChannel.java index 13011064d58..7ec82bee974 100644 --- a/src/main/java/org/spongepowered/common/network/channel/packet/SpongePacketChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/packet/SpongePacketChannel.java @@ -26,7 +26,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.network.EngineConnection; @@ -122,8 +122,8 @@ private

, R extends Packet> void sendRequestPacketTo( final ResourceKey key = this.key(); mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) key; + public Identifier id() { + return (Identifier) (Object) key; } @Override @@ -187,8 +187,8 @@ private

, R extends Packet> void sendResponsePacketTo final ResourceKey key = this.key(); mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) key; + public Identifier id() { + return (Identifier) (Object) key; } @Override @@ -216,8 +216,8 @@ public void write(FriendlyByteBuf var1) { final ResourceKey key = this.key(); mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) key; + public Identifier id() { + return (Identifier) (Object) key; } @Override @@ -269,8 +269,8 @@ private

void sendNormalPacketTo(final EngineConnection connec final ResourceKey key = this.key(); mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) key; + public Identifier id() { + return (Identifier) (Object) key; } @Override diff --git a/src/main/java/org/spongepowered/common/network/channel/raw/SpongeRawLoginDataChannel.java b/src/main/java/org/spongepowered/common/network/channel/raw/SpongeRawLoginDataChannel.java index 3a83d426443..35f88ea9784 100644 --- a/src/main/java/org/spongepowered/common/network/channel/raw/SpongeRawLoginDataChannel.java +++ b/src/main/java/org/spongepowered/common/network/channel/raw/SpongeRawLoginDataChannel.java @@ -27,7 +27,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.network.EngineConnection; import org.spongepowered.api.network.EngineConnectionState; @@ -170,8 +170,8 @@ public CompletableFuture sendTo(final EngineConnection connection, f final ResourceKey id = this.parent.key(); final Packet mcPacket = PacketUtil.createLoginPayloadRequest(new CustomQueryPayload() { @Override - public ResourceLocation id() { - return (ResourceLocation) (Object) id; + public Identifier id() { + return (Identifier) (Object) id; } @Override diff --git a/src/main/java/org/spongepowered/common/network/packet/ChangeViewerEnvironmentPacket.java b/src/main/java/org/spongepowered/common/network/packet/ChangeViewerEnvironmentPacket.java index 937a61543aa..b1d559c7cec 100644 --- a/src/main/java/org/spongepowered/common/network/packet/ChangeViewerEnvironmentPacket.java +++ b/src/main/java/org/spongepowered/common/network/packet/ChangeViewerEnvironmentPacket.java @@ -25,7 +25,7 @@ package org.spongepowered.common.network.packet; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.api.network.channel.ChannelBuf; import org.spongepowered.api.network.channel.packet.Packet; @@ -33,7 +33,7 @@ public final class ChangeViewerEnvironmentPacket implements Packet { - public ResourceLocation dimensionLogic; + public Identifier dimensionLogic; public ChangeViewerEnvironmentPacket() { } @@ -44,7 +44,7 @@ public ChangeViewerEnvironmentPacket(final DimensionType dimensionType) { @Override public void read(final ChannelBuf buf) { - this.dimensionLogic = ResourceLocation.parse(buf.readString()); + this.dimensionLogic = Identifier.parse(buf.readString()); } @Override diff --git a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java index 98aa8a2a3c9..951e17140a2 100644 --- a/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java +++ b/src/main/java/org/spongepowered/common/network/packet/SpongePacketHandler.java @@ -26,20 +26,16 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.DimensionSpecialEffects; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; -import net.minecraft.core.registries.Registries; import net.minecraft.server.players.NameAndId; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.network.ClientConnectionState; import org.spongepowered.api.network.EngineConnectionStates; import org.spongepowered.api.network.channel.packet.PacketChannel; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.client.multiplayer.ClientLevelAccessor; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.network.channel.SpongeChannelManager; @@ -99,9 +95,6 @@ public static void init(final SpongeChannelManager registry) { if (world == null) { return; } - - final DimensionType dimensionType = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE).getValue(packet.dimensionLogic); - ((ClientLevelAccessor) world).accessor$effects(DimensionSpecialEffects.forType(dimensionType)); } ); } diff --git a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java index 4d07c196be6..d6838c10da4 100644 --- a/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java +++ b/src/main/java/org/spongepowered/common/registry/RegistryHolderLogic.java @@ -32,7 +32,7 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.DependencySorter; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; @@ -66,11 +66,11 @@ public RegistryHolderLogic() { this.roots.put( RegistryRoots.MINECRAFT, new MappedRegistry<>( - net.minecraft.resources.ResourceKey.createRegistryKey((ResourceLocation) (Object) RegistryRoots.MINECRAFT), + net.minecraft.resources.ResourceKey.createRegistryKey((Identifier) (Object) RegistryRoots.MINECRAFT), Lifecycle.experimental() ) ); - final ResourceLocation sponge = (ResourceLocation) (Object) RegistryRoots.SPONGE; + final Identifier sponge = (Identifier) (Object) RegistryRoots.SPONGE; this.roots.put( (ResourceKey) (Object) sponge, new MappedRegistry<>( @@ -106,7 +106,7 @@ public void setRootMinecraftRegistry(final net.minecraft.core.Registry( - net.minecraft.resources.ResourceKey.createRegistryKey((ResourceLocation) (Object) RegistryRoots.MINECRAFT), + net.minecraft.resources.ResourceKey.createRegistryKey((Identifier) (Object) RegistryRoots.MINECRAFT), Lifecycle.experimental() ); registryAccess.registries().forEach(r -> rootRegistry.register(r.key(), r.value(), RegistrationInfo.BUILT_IN)); @@ -190,18 +190,18 @@ public Registry createRegistry(final RegistryType type, final @Nullabl if (root == null) { throw new ValueNotFoundException(String.format("No '%s' root registry has been defined", type.root())); } - var registry = root.getValue((ResourceLocation) (Object) type.location()); + var registry = root.getValue((Identifier) (Object) type.location()); final boolean exists = registry != null; if (exists) { throw new DuplicateRegistrationException(String.format("Registry '%s' in root '%s' has already been defined", type.location(), type.root())); } final net.minecraft.resources.ResourceKey> key; if (Registries.ROOT_REGISTRY_NAME.equals(type.root())) { - key = net.minecraft.resources.ResourceKey.createRegistryKey((ResourceLocation) (Object) type.location()); + key = net.minecraft.resources.ResourceKey.createRegistryKey((Identifier) (Object) type.location()); } else { key = ResourceKeyAccessor.invoker$create( - (ResourceLocation) (Object) RegistryRoots.SPONGE, - (ResourceLocation) (Object) type.location() + (Identifier) (Object) RegistryRoots.SPONGE, + (Identifier) (Object) type.location() ); } registry = registrySupplier.apply(key); @@ -210,7 +210,7 @@ public Registry createRegistry(final RegistryType type, final @Nullabl final MappedRegistry mr = (MappedRegistry) registry; defaultValues.forEach((vk, vi, vv) -> { mr.register( - net.minecraft.resources.ResourceKey.create(key, (ResourceLocation) (Object) vk), + net.minecraft.resources.ResourceKey.create(key, (Identifier) (Object) vk), vv, RegistrationInfo.BUILT_IN ); @@ -256,13 +256,13 @@ public void featureFlagSet(final FeatureFlagSet featureFlagSet) { @Override public Stream>> listRegistryKeys() { return this.streamRegistries().map(k -> - ResourceKeyAccessor.invoker$create((ResourceLocation) (Object) k.type().root(), (ResourceLocation) (Object) k.type().location())); + ResourceKeyAccessor.invoker$create((Identifier) (Object) k.type().root(), (Identifier) (Object) k.type().location())); } @SuppressWarnings({"unchecked", "rawtypes"}) @Override public Optional> lookup( final net.minecraft.resources.ResourceKey> resourceKey) { - return (Optional) this.findRegistry(RegistryType.of((ResourceKey) (Object) resourceKey.registry(), (ResourceKey) (Object) resourceKey.location())); + return (Optional) this.findRegistry(RegistryType.of((ResourceKey) (Object) resourceKey.registry(), (ResourceKey) (Object) resourceKey.identifier())); } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyBuilder.java b/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyBuilder.java index 87c23eab65e..09849a23159 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyBuilder.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyBuilder.java @@ -25,8 +25,8 @@ package org.spongepowered.common.registry; -import net.minecraft.ResourceLocationException; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.IdentifierException; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.common.util.Preconditions; @@ -57,9 +57,9 @@ public ResourceKey build() throws IllegalStateException { Preconditions.checkState(this.value != null, "Value cannot be empty"); try { - final ResourceLocation resourceLocation = ResourceLocation.fromNamespaceAndPath(this.namespace, this.value); - return (ResourceKey) (Object) resourceLocation; - } catch (ResourceLocationException e) { + final Identifier id = Identifier.fromNamespaceAndPath(this.namespace, this.value); + return (ResourceKey) (Object) id; + } catch (IdentifierException e) { throw new IllegalStateException(e); } } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyFactory.java b/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyFactory.java index 325fd990a89..a57d6da7ca2 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyFactory.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeResourceKeyFactory.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.registry; -import net.minecraft.ResourceLocationException; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.IdentifierException; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.plugin.PluginContainer; @@ -34,9 +34,9 @@ public final class SpongeResourceKeyFactory implements ResourceKey.Factory { @Override public ResourceKey of(final String namespace, final String value) { try { - final ResourceLocation resourceLocation = ResourceLocation.fromNamespaceAndPath(namespace, value); - return (ResourceKey) (Object) resourceLocation; - } catch (ResourceLocationException e) { + final Identifier id = Identifier.fromNamespaceAndPath(namespace, value); + return (ResourceKey) (Object) id; + } catch (IdentifierException e) { throw new IllegalStateException(e); } } @@ -44,9 +44,9 @@ public ResourceKey of(final String namespace, final String value) { @Override public ResourceKey of(final PluginContainer plugin, final String value) { try { - final ResourceLocation resourceLocation = ResourceLocation.fromNamespaceAndPath(plugin.metadata().id(), value); - return (ResourceKey) (Object) resourceLocation; - } catch (ResourceLocationException e) { + final Identifier id = Identifier.fromNamespaceAndPath(plugin.metadata().id(), value); + return (ResourceKey) (Object) id; + } catch (IdentifierException e) { throw new IllegalStateException(e); } } @@ -54,9 +54,9 @@ public ResourceKey of(final PluginContainer plugin, final String value) { @Override public ResourceKey resolve(final String formatted) { try { - final ResourceLocation resourceLocation = ResourceLocation.parse(formatted); - return (ResourceKey) (Object) resourceLocation; - } catch (ResourceLocationException e) { + final Identifier id = Identifier.parse(formatted); + return (ResourceKey) (Object) id; + } catch (IdentifierException e) { throw new IllegalStateException(e); } } diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index d13734b80ff..79bff7ba900 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -40,7 +40,7 @@ import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.GameProfileArgument; -import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.commands.arguments.IdentifierArgument; import net.minecraft.commands.arguments.ScoreHolderArgument; import net.minecraft.commands.arguments.TimeArgument; import net.minecraft.commands.arguments.UuidArgument; @@ -60,7 +60,7 @@ import net.minecraft.commands.synchronization.brigadier.LongArgumentInfo; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.phys.Vec2; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -164,7 +164,7 @@ public static RegistryLoader> valueParameter() { l.add(ResourceKeyedValueParameters.PLAYER, k -> ClientNativeArgumentParser.createConverter(k, EntityArgument.player(), (reader, cause, selector) -> (Player) selector.findSinglePlayer((CommandSourceStack) cause))); l.add(ResourceKeyedValueParameters.PLUGIN, SpongePluginContainerValueParameter::new); l.add(ResourceKeyedValueParameters.REMAINING_JOINED_STRINGS, k -> ClientNativeArgumentParser.createIdentity(k, StringArgumentType.greedyString())); - l.add(ResourceKeyedValueParameters.RESOURCE_KEY, k -> ClientNativeArgumentParser.createConverter(k, ResourceLocationArgument.id(), (reader, cause, resourceLocation) -> (ResourceKey) (Object) resourceLocation)); + l.add(ResourceKeyedValueParameters.RESOURCE_KEY, k -> ClientNativeArgumentParser.createConverter(k, IdentifierArgument.id(), (reader, cause, Identifier) -> (ResourceKey) (Object) Identifier)); l.add(ResourceKeyedValueParameters.ROTATION, k -> ClientNativeArgumentParser.createConverter(k, RotationArgument.rotation(), (reader, cause, coords) -> { final Vec2 rotation = coords.getRotation((CommandSourceStack) cause); return new Vector3d(rotation.x, rotation.y, 0); @@ -212,7 +212,7 @@ public static RegistryLoader clientCompletionType() { l.add(ClientCompletionTypes.SNBT, k -> new SpongeClientCompletionType(CompoundTagArgument.compoundTag())); l.add(ClientCompletionTypes.NONE, k -> SpongeClientCompletionType.NONE); l.add(ClientCompletionTypes.REMAINING_JOINED_STRINGS, k -> new SpongeClientCompletionType(StringArgumentType.greedyString())); - l.add(ClientCompletionTypes.RESOURCE_KEY, k -> new SpongeClientCompletionType(ResourceLocationArgument.id())); + l.add(ClientCompletionTypes.RESOURCE_KEY, k -> new SpongeClientCompletionType(IdentifierArgument.id())); l.add(ClientCompletionTypes.STRING, k -> new SpongeClientCompletionType(StringArgumentType.string())); l.add(ClientCompletionTypes.WHOLE_NUMBER, k -> new SpongeClientCompletionType(LongArgumentType.longArg())); }); @@ -296,7 +296,7 @@ public static RegistryLoader> commandRegistrarType() { // Helper static ArgumentType argumentTypeFromKey(ResourceKey key, CommandBuildContext ctx) { - final ArgumentTypeInfo argumentTypeInfo = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getValue((ResourceLocation) (Object) key); + final ArgumentTypeInfo argumentTypeInfo = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getValue((Identifier) (Object) key); if (argumentTypeInfo instanceof SingletonArgumentInfo s) { return s.unpack(null).instantiate(ctx); } diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java index 0b0da93134f..619bf64f024 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeRegistryLoader.java @@ -587,7 +587,7 @@ public static RegistryLoader noiseConfig() { public static RegistryLoader flatGeneratorConfig(RegistryHolder registryAccess) { final RegistryType registryType = RegistryType.of( - (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.registry(), (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.location()); + (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.registry(), (ResourceKey) (Object) Registries.FLAT_LEVEL_GENERATOR_PRESET.identifier()); final Registry registry = registryAccess.registry(registryType); return RegistryLoader.of(l -> registry.streamEntries().forEach(e -> diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index cac12696ebb..59bb0878af7 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -28,7 +28,7 @@ import net.minecraft.advancements.AdvancementType; import net.minecraft.core.FrontAndTop; import net.minecraft.core.MappedRegistry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.StringRepresentable; import net.minecraft.world.Difficulty; import net.minecraft.world.InteractionHand; @@ -156,7 +156,7 @@ private void loadInstanceRegistries() { ArmorMaterials.TURTLE_SCUTE,ArmorMaterials.NETHERITE, ArmorMaterials.ARMADILLO_SCUTE, ArmorMaterials.COPPER, }; for (final ArmorMaterial armorMaterial : knownMaterials) { - materials.put(armorMaterial, armorMaterial.assetId().location().toString()); + materials.put(armorMaterial, armorMaterial.assetId().identifier().toString()); } this.naming(RegistryTypes.ARMOR_MATERIAL, materials.keySet().toArray(new ArmorMaterial[]{}), materials); @@ -340,7 +340,7 @@ private Registry naming(final RegistryType type, final int values, // To address Vanilla shortcomings, some mods will manually prefix their modid onto values they put into Vanilla registry-like // registrars. We need to account for that possibility if (rawId.contains(":")) { - map.put((ResourceKey) (Object) ResourceLocation.parse(rawId), (A) value.getKey()); + map.put((ResourceKey) (Object) Identifier.parse(rawId), (A) value.getKey()); } else { map.put(ResourceKey.sponge(rawId), (A) value.getKey()); } diff --git a/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java b/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java index 3f173a268ea..d9bb0869565 100644 --- a/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java +++ b/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java @@ -26,6 +26,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.world.WorldTypeEffect; @@ -37,27 +38,27 @@ public final class DimensionEffectProvider { public static DimensionEffectProvider INSTANCE = new DimensionEffectProvider(); - private static final SpongeWorldTypeEffect OVERWORLD = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.OVERWORLD_EFFECTS); - private static final SpongeWorldTypeEffect NETHER = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.NETHER_EFFECTS); - private static final SpongeWorldTypeEffect END = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.END_EFFECTS); + private static final SpongeWorldTypeEffect OVERWORLD = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.OVERWORLD); + private static final SpongeWorldTypeEffect NETHER = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.NETHER); + private static final SpongeWorldTypeEffect END = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.END); static { - DimensionEffectProvider.INSTANCE.register(OVERWORLD.key(), OVERWORLD); - DimensionEffectProvider.INSTANCE.register(NETHER.key(), NETHER); - DimensionEffectProvider.INSTANCE.register(END.key(), END); + DimensionEffectProvider.INSTANCE.register(DimensionType.Skybox.OVERWORLD, OVERWORLD); + DimensionEffectProvider.INSTANCE.register(DimensionType.Skybox.NONE, NETHER); + DimensionEffectProvider.INSTANCE.register(DimensionType.Skybox.END, END); } - private final Map mappings; + private final Map mappings; private DimensionEffectProvider() { this.mappings = new Object2ObjectOpenHashMap<>(); } - public @Nullable WorldTypeEffect get(final ResourceKey key) { + public @Nullable WorldTypeEffect get(final DimensionType.Skybox key) { return this.mappings.get(key); } - public void register(final ResourceKey key, final WorldTypeEffect effect) { + public void register(final DimensionType.Skybox key, final WorldTypeEffect effect) { this.mappings.put(key, effect); } } diff --git a/src/main/java/org/spongepowered/common/serialization/MathCodecs.java b/src/main/java/org/spongepowered/common/serialization/MathCodecs.java index 6cee207e581..de6e2ff66e4 100644 --- a/src/main/java/org/spongepowered/common/serialization/MathCodecs.java +++ b/src/main/java/org/spongepowered/common/serialization/MathCodecs.java @@ -25,7 +25,7 @@ package org.spongepowered.common.serialization; import com.mojang.serialization.Codec; -import net.minecraft.Util; +import net.minecraft.util.Util; import org.spongepowered.math.vector.Vector3i; import java.util.stream.IntStream; diff --git a/src/main/java/org/spongepowered/common/tag/SpongeTagFactory.java b/src/main/java/org/spongepowered/common/tag/SpongeTagFactory.java index 66238de5e2f..6b9ea2cb690 100644 --- a/src/main/java/org/spongepowered/common/tag/SpongeTagFactory.java +++ b/src/main/java/org/spongepowered/common/tag/SpongeTagFactory.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.tag; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.RegistryType; @@ -37,8 +37,8 @@ public class SpongeTagFactory implements Tag.Factory { @SuppressWarnings("unchecked") public Tag of(final RegistryType registryType, final ResourceKey key) { final net.minecraft.resources.ResourceKey> regKey = - ResourceKeyAccessor.invoker$create((ResourceLocation) (Object) registryType.root(), (ResourceLocation) (Object) registryType.location()); + ResourceKeyAccessor.invoker$create((Identifier) (Object) registryType.root(), (Identifier) (Object) registryType.location()); // TagKey.create returns interned tag-keys - return (Tag) (Object) TagKey.create(regKey, ((ResourceLocation) (Object) key)); + return (Tag) (Object) TagKey.create(regKey, ((Identifier) (Object) key)); } } diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index ce4ec4e8dc4..d2009d24335 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -32,9 +32,8 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.serialization.Codec; -import net.minecraft.Util; import net.minecraft.commands.arguments.CompoundTagArgument; -import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.commands.arguments.IdentifierArgument; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; @@ -43,6 +42,7 @@ import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.permissions.PermissionLevel; +import net.minecraft.util.Util; import net.minecraft.world.entity.Relative; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.level.Level; @@ -1377,7 +1377,7 @@ public static final class Command { public static final ArgumentType STANDARD_STRING_ARGUMENT_TYPE = StringArgumentType.string(); public static final ArgumentType GREEDY_STRING_ARGUMENT_TYPE = StringArgumentType.greedyString(); public static final ArgumentType NBT_ARGUMENT_TYPE = CompoundTagArgument.compoundTag(); - public static final ResourceLocationArgument RESOURCE_LOCATION_TYPE = ResourceLocationArgument.id(); + public static final IdentifierArgument RESOURCE_LOCATION_TYPE = IdentifierArgument.id(); public static final String COMMAND_BLOCK_COMMAND = ""; public static final String SELECTOR_COMMAND = "@"; public static final String SPONGE_HELP_COMMAND = "sponge:help"; diff --git a/src/main/java/org/spongepowered/common/world/SpongeDefaultWorldKeysFactory.java b/src/main/java/org/spongepowered/common/world/SpongeDefaultWorldKeysFactory.java index 10761e0865a..c47fbcb8d6e 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeDefaultWorldKeysFactory.java +++ b/src/main/java/org/spongepowered/common/world/SpongeDefaultWorldKeysFactory.java @@ -32,16 +32,16 @@ public final class SpongeDefaultWorldKeysFactory implements DefaultWorldKeys.Fac @Override public ResourceKey defaultWorld() { - return (ResourceKey) (Object) Level.OVERWORLD.location(); + return (ResourceKey) (Object) Level.OVERWORLD.identifier(); } @Override public ResourceKey theNether() { - return (ResourceKey) (Object) Level.NETHER.location(); + return (ResourceKey) (Object) Level.NETHER.identifier(); } @Override public ResourceKey theEnd() { - return (ResourceKey) (Object) Level.END.location(); + return (ResourceKey) (Object) Level.END.identifier(); } } diff --git a/src/main/java/org/spongepowered/common/world/SpongeWorldTypeEffect.java b/src/main/java/org/spongepowered/common/world/SpongeWorldTypeEffect.java index 9f0193fafe2..8c77a994a16 100644 --- a/src/main/java/org/spongepowered/common/world/SpongeWorldTypeEffect.java +++ b/src/main/java/org/spongepowered/common/world/SpongeWorldTypeEffect.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.world; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.world.WorldTypeEffect; import org.spongepowered.common.AbstractResourceKeyed; @@ -49,17 +49,17 @@ public static final class FactoryImpl implements WorldTypeEffect.Factory { @Override public WorldTypeEffect overworld() { - return DimensionEffectProvider.INSTANCE.get((ResourceKey) (Object) BuiltinDimensionTypes.OVERWORLD_EFFECTS); + return DimensionEffectProvider.INSTANCE.get(DimensionType.Skybox.OVERWORLD); } @Override public WorldTypeEffect nether() { - return DimensionEffectProvider.INSTANCE.get((ResourceKey) (Object) BuiltinDimensionTypes.NETHER_EFFECTS); + return DimensionEffectProvider.INSTANCE.get(DimensionType.Skybox.NONE); } @Override public WorldTypeEffect end() { - return DimensionEffectProvider.INSTANCE.get((ResourceKey) (Object) BuiltinDimensionTypes.END_EFFECTS); + return DimensionEffectProvider.INSTANCE.get(DimensionType.Skybox.END); } } } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeAttributesFactory.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeAttributesFactory.java index 930a81c26e3..63036a76f74 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeAttributesFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeAttributesFactory.java @@ -85,13 +85,13 @@ public Optional defaultAttributes(final RegistryReference>> list = ImmutableList.builder(); ((OverworldBiomeBuilderAccessor) (Object) new OverworldBiomeBuilder()).accessor$addBiomes(list::add); for (final var pair : list.build()) { - DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) pair.getSecond().location(), (BiomeAttributes) (Object) pair.getFirst()); + DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) pair.getSecond().identifier(), (BiomeAttributes) (Object) pair.getFirst()); } // MultiNoiseBiomeSource.Preset#NETHER - DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.SOUL_SAND_VALLEY.location(), (BiomeAttributes) (Object) Climate.parameters(0.0F, -0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); - DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.CRIMSON_FOREST.location(), (BiomeAttributes) (Object) Climate.parameters(0.4F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); - DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.WARPED_FOREST.location(), (BiomeAttributes) (Object) Climate.parameters(0.0F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.375F)); - DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.BASALT_DELTAS.location(), (BiomeAttributes) (Object) Climate.parameters(-0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.175F)); + DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.SOUL_SAND_VALLEY.identifier(), (BiomeAttributes) (Object) Climate.parameters(0.0F, -0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); + DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.CRIMSON_FOREST.identifier(), (BiomeAttributes) (Object) Climate.parameters(0.4F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); + DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.WARPED_FOREST.identifier(), (BiomeAttributes) (Object) Climate.parameters(0.0F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.375F)); + DEFAULT_ATTRIBUTES.put((ResourceKey) (Object) Biomes.BASALT_DELTAS.identifier(), (BiomeAttributes) (Object) Climate.parameters(-0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.175F)); } return Optional.ofNullable(SpongeBiomeAttributesFactory.DEFAULT_ATTRIBUTES.get(biome.location())); } diff --git a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java index 5e41f562610..515a576fc3e 100644 --- a/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java +++ b/src/main/java/org/spongepowered/common/world/biome/SpongeBiomeProviderFactory.java @@ -29,8 +29,8 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.CheckerboardColumnBiomeSource; import net.minecraft.world.level.biome.Climate.ParameterList; @@ -114,6 +114,6 @@ private Registry registry() { } private Holder biomeHolder(final RegistryReference biome) { - return this.registry().getOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) biome.location())); + return this.registry().getOrThrow(ResourceKey.create(Registries.BIOME, (Identifier) (Object) biome.location())); } } diff --git a/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java b/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java index cc437a298d2..9a7c5823751 100644 --- a/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java +++ b/src/main/java/org/spongepowered/common/world/generation/config/flat/SpongeFlatGeneratorConfig.java @@ -30,8 +30,8 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.placement.MiscOverworldPlacements; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.flat.FlatLayerInfo; import net.minecraft.world.level.levelgen.placement.PlacedFeature; @@ -142,7 +142,7 @@ public FlatGeneratorConfig.Builder from(final FlatGeneratorConfig value) { final HolderLookup.RegistryLookup placedFeatureRegistryLookup = SpongeCommon.vanillaRegistry(Registries.PLACED_FEATURE); final Holder.Reference biome = - biomeRegistry.getOrThrow(ResourceKey.create(Registries.BIOME, (ResourceLocation) (Object) this.biome.location())); + biomeRegistry.getOrThrow(ResourceKey.create(Registries.BIOME, (Identifier) (Object) this.biome.location())); return (FlatGeneratorConfig) FlatLevelGeneratorSettingsAccessor.invoker$new( this.structureSets == null ? Optional.empty() : Optional.of(HolderSet.direct((Function) Holder::direct, this.structureSets)), (List) (Object) this.layers, diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java index 1b66e7ef852..dcdab39802b 100644 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java @@ -26,7 +26,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.SurfaceRuleData; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.levelgen.SurfaceRules; import net.minecraft.world.level.levelgen.VerticalAnchor; import net.minecraft.world.level.levelgen.placement.CaveSurface; @@ -109,7 +109,7 @@ public SurfaceRule.Condition liquidDepthFromSurface(final int offset, final int @Override public SurfaceRule.Condition biome(final List> biomes) { final var stream = biomes.stream() - .map(r -> net.minecraft.resources.ResourceKey.create(Registries.BIOME, ((ResourceLocation) (Object) r.location()))); + .map(r -> net.minecraft.resources.ResourceKey.create(Registries.BIOME, ((Identifier) (Object) r.location()))); final net.minecraft.resources.ResourceKey[] keys = stream.toArray(net.minecraft.resources.ResourceKey[]::new); return (SurfaceRule.Condition) SurfaceRules.isBiome(keys); } @@ -193,7 +193,7 @@ public SurfaceRule.Condition surfaceAbove(final SurfaceRule.VerticalAnchor ancho @Override public SurfaceRule.Condition noiseThreshold(final RegistryReference noise, final double min, final double max) { - final net.minecraft.resources.ResourceKey key = net.minecraft.resources.ResourceKey.create(Registries.NOISE, ((ResourceLocation) (Object) noise.location())); + final net.minecraft.resources.ResourceKey key = net.minecraft.resources.ResourceKey.create(Registries.NOISE, ((Identifier) (Object) noise.location())); return (SurfaceRule.Condition) SurfaceRules.noiseCondition(key, min, max); } diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java index a94ab0b917c..4db93fa2b70 100644 --- a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeJigsawPoolBuilder.java @@ -62,26 +62,26 @@ public JigsawPool.Builder add(final JigsawPoolElement element, final int weight) @Override public JigsawPool.Builder name(final ResourceKey name) { -// TODO this.name = (ResourceLocation) (Object) name; +// TODO this.name = (Identifier) (Object) name; return this; } @Override public JigsawPool.Builder fallback(final RegistryReference fallback) { -// TODO this.fallback = (ResourceLocation) (Object) fallback.location(); +// TODO this.fallback = (Identifier) (Object) fallback.location(); return this; } @Override public JigsawPool.Builder fallback(final JigsawPool fallback) { -// TODO this.fallback = (ResourceLocation) (Object) fallback.key(); +// TODO this.fallback = (Identifier) (Object) fallback.key(); return this; } @Override public JigsawPool.Builder reset() { // TODO this.name = null; - // TODO this.fallback = new ResourceLocation("empty"); + // TODO this.fallback = new Identifier("empty"); this.templates = new ArrayList<>(); return this; } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 69532bc8336..4d34b4b0199 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -30,19 +30,19 @@ import it.unimi.dsi.fastutil.longs.LongIterator; import net.minecraft.CrashReport; import net.minecraft.ReportedException; -import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.MiscOverworldFeatures; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.LevelLoadListener; import net.minecraft.server.level.progress.LoggingLevelLoadListener; import net.minecraft.util.TimeUtil; +import net.minecraft.util.Util; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; import net.minecraft.world.entity.npc.WanderingTraderSpawner; @@ -308,7 +308,7 @@ private CompletableFuture> loadWorld0(final net.minecraft. try { world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); } catch (final Exception e) { - return FutureUtil.completedWithException(new RuntimeException(String.format("Failed to create level data for world '%s'!", registryKey.location()), e)); + return FutureUtil.completedWithException(new RuntimeException(String.format("Failed to create level data for world '%s'!", registryKey.identifier()), e)); } return SpongeCommon.asyncScheduler().submit(() -> this.prepareLevel(world)).thenApply(w -> { @@ -615,7 +615,7 @@ public CompletableFuture deleteWorld(final ResourceKey key) { final ServerLevel loadedWorld = this.worlds.get(registryKey); if (loadedWorld != null) { if (!loadedWorld.getPlayers(p -> true).isEmpty()) { - return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()))); + return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.identifier()))); } final boolean disableLevelSaving = loadedWorld.noSave; @@ -675,7 +675,7 @@ private CompletableFuture unloadWorld0(final ServerLevel level) { final net.minecraft.resources.ResourceKey registryKey = level.dimension(); if (!level.getPlayers(p -> true).isEmpty()) { - return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()))); + return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.identifier()))); } // We first tell the world to save without flushing @@ -684,10 +684,10 @@ private CompletableFuture unloadWorld0(final ServerLevel level) { return ((IOWorkerBridge) level.getChunkSource().chunkMap.chunkScanner()).bridge$onIdle().thenComposeAsync($ -> { if (!level.getPlayers(p -> true).isEmpty()) { - return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()))); + return CompletableFuture.failedFuture(new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.identifier()))); } - SpongeCommon.logger().info("Unloading world '{}'", registryKey.location()); + SpongeCommon.logger().info("Unloading world '{}'", registryKey.identifier()); final UnloadWorldEvent unloadWorldEvent = SpongeEventFactory.createUnloadWorldEvent(PhaseTracker.getInstance().currentCause(), (ServerWorld) level); SpongeCommon.post(unloadWorldEvent); @@ -783,21 +783,21 @@ private T initializeLevelData(final ResourceKey key, final Supplier loade private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) throws IOException { - try (final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess((ResourceKey) (Object) registryKey.location())) { + try (final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess((ResourceKey) (Object) registryKey.identifier())) { return this.loadLevelData(storageSource, registryKey, loadOperation); } } private Optional loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { - return this.initializeLevelDataOptional((ResourceKey) (Object) registryKey.location(), () -> + return this.initializeLevelDataOptional((ResourceKey) (Object) registryKey.identifier(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) .map(t -> this.readLevelData(registryKey, t, loadOperation))); } private LevelDataLoadResult loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey, final Supplier defaultSupplier) { - return this.initializeLevelData((ResourceKey) (Object) registryKey.location(), () -> + return this.initializeLevelData((ResourceKey) (Object) registryKey.identifier(), () -> Optional.ofNullable(this.loadLevelTag(storageSource)) .map(t -> this.readLevelData(registryKey, t, null)) .orElseGet(defaultSupplier)); @@ -863,7 +863,7 @@ private static WorldArchetype resolveWorldArchetype(final LevelDataAndDimensions private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, final WorldArchetype archetype) { final LevelStem levelStem = (LevelStem) (Object) archetype.type(); final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.location())); + final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.identifier())); return new LevelDataLoadResult( new PrimaryLevelData(levelSettings, (WorldOptions) archetype.generationConfig().orElse((WorldGenerationConfig) defaultLevelData.worldGenOptions()), SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem); @@ -886,7 +886,7 @@ private ServerLevel createLevel( final LevelStorageSource.LevelStorageAccess storageSource, final PrimaryLevelData levelData) { - final ResourceKey worldKey = (ResourceKey) (Object) registryKey.location(); + final ResourceKey worldKey = (ResourceKey) (Object) registryKey.identifier(); MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); @@ -955,7 +955,7 @@ private ServerLevel prepareLevel(final ServerLevel level) { ((MinecraftServerAccessor) this.server).invoker$setupDebugLevel(worldData); } } catch (final Throwable throwable) { - final CrashReport crashReport = CrashReport.forThrowable(throwable, "Exception initializing world '" + level.dimension().location() + "'"); + final CrashReport crashReport = CrashReport.forThrowable(throwable, "Exception initializing world '" + level.dimension().identifier() + "'"); try { level.fillReportDetails(crashReport); } catch (final Throwable ignore) { @@ -982,7 +982,7 @@ private ServerLevel prepareLevel(final ServerLevel level) { * Same as loadSpawnChunks but async and without listener. */ private CompletableFuture loadSpawnChunksAsync(final ServerLevel level) { - MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().location()); + MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().identifier()); final ServerChunkCache chunkSource = level.getChunkSource(); final var respawnData = level.getRespawnData(); @@ -994,7 +994,7 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel le Sponge.server().scheduler().submit(Task.builder().plugin(Launch.instance().platformPlugin()).execute(() -> generationFuture.complete(level)).build()); // Notify the future that we are done task.cancel(); // And cancel this task - MinecraftServerAccessor.accessor$LOGGER().info("Done preparing start region for dimension {}", level.dimension().location()); + MinecraftServerAccessor.accessor$LOGGER().info("Done preparing start region for dimension {}", level.dimension().identifier()); }).interval(10, TimeUnit.MILLISECONDS).build() ); @@ -1008,7 +1008,7 @@ private CompletableFuture loadSpawnChunksAsync(final ServerLevel le * Mimic MinecraftServer#prepareLevels */ private void loadSpawnChunks(final ServerLevel level) { - MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().location()); + MinecraftServerAccessor.accessor$LOGGER().info("Preparing start region for dimension {}", level.dimension().identifier()); final var respawnData = level.getRespawnData(); final ServerChunkCache chunkSource = level.getChunkSource(); @@ -1038,7 +1038,7 @@ private static void updateForcedChunks(final ServerLevel level, final ServerChun } public static net.minecraft.resources.ResourceKey createRegistryKey(final ResourceKey key) { - return net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (ResourceLocation) (Object) key); + return net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (Identifier) (Object) key); } private String getDirectoryName(final ResourceKey key) { diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java index a04501c75b5..71665c9ac17 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java @@ -28,7 +28,7 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.kyori.adventure.text.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Difficulty; import net.minecraft.world.level.GameType; import net.minecraft.world.level.dimension.LevelStem; @@ -50,8 +50,8 @@ public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem) { .create(r -> r .group( SpongeAdventure.STRING_CODEC.optionalFieldOf("display_name").forGetter(v -> Optional.ofNullable(v.displayName)), - ResourceLocation.CODEC.optionalFieldOf("game_mode").forGetter(v -> Optional.ofNullable(v.gameMode).map(t -> ResourceLocation.fromNamespaceAndPath("sponge", t.getName()))), - ResourceLocation.CODEC.optionalFieldOf("difficulty").forGetter(v -> Optional.ofNullable(v.difficulty).map(t -> ResourceLocation.fromNamespaceAndPath("sponge", t.getKey()))), + Identifier.CODEC.optionalFieldOf("game_mode").forGetter(v -> Optional.ofNullable(v.gameMode).map(t -> Identifier.fromNamespaceAndPath("sponge", t.getName()))), + Identifier.CODEC.optionalFieldOf("difficulty").forGetter(v -> Optional.ofNullable(v.difficulty).map(t -> Identifier.fromNamespaceAndPath("sponge", t.getKey()))), EnumCodec.create(SerializationBehavior.class).optionalFieldOf("serialization_behavior") .forGetter(v -> Optional.ofNullable(v.serializationBehavior)), Codec.INT.optionalFieldOf("view_distance").forGetter(v -> Optional.ofNullable(v.viewDistance)), diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index b222d4f6358..d05db9aaf4c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.world.server; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.HolderSet; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.attribute.BedRule; import net.minecraft.world.attribute.EnvironmentAttributeMap; @@ -48,7 +48,6 @@ import org.spongepowered.common.data.SpongeDataManager; import org.spongepowered.common.data.provider.DataProviderLookup; -import java.util.OptionalLong; public final class SpongeWorldTypeBuilder implements WorldType.Builder { @@ -114,17 +113,22 @@ public WorldType.Builder from(final WorldType type) { attributes.set(EnvironmentAttributes.RESPAWN_ANCHOR_WORKS, respawnAnchorsUsable); attributes.set(EnvironmentAttributes.CAN_START_RAID, hasRaids); final DimensionType dimensionType = - new DimensionType(fixedTime == null ? OptionalLong.empty() : OptionalLong.of(fixedTime.asTicks().ticks()), + new DimensionType( + fixedTime != null, hasSkylight, hasCeiling, - natural, coordinateMultiplier, - floor, height, logicalHeight, + coordinateMultiplier, + floor, + height, + logicalHeight, ((TagBridge) infiniburn).bridge$asVanillaTag(), - (ResourceLocation) (Object) effect.key(), ambientLighting, new DimensionType.MonsterSettings(monsterSpawnLightTest, monsterSpawnBlockLightLimit), - attributes.build() - ); + DimensionType.Skybox.OVERWORLD, + DimensionType.CardinalLightType.DEFAULT, + attributes.build(), + HolderSet.empty() + ); if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { bridge.bridge$decorateData(spongeData); } diff --git a/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java b/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java index c26932e7c45..c7b4d28208d 100644 --- a/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java +++ b/src/main/java/org/spongepowered/common/world/teleport/ConfigTeleportHelperFilter.java @@ -26,7 +26,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.block.Block; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -66,26 +66,26 @@ private static void updateCacheIfNecessary() { final TeleportHelperCategory teleportHelperCat = SpongeConfigs.getCommon().get().teleportHelper; ConfigTeleportHelperFilter.floorBlockTypes = teleportHelperCat.unsafeFloorBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> (BlockType) blockRegistry.getValue((ResourceLocation) (Object) x)) + .map(x -> (BlockType) blockRegistry.getValue((Identifier) (Object) x)) .filter(Objects::nonNull) .collect(Collectors.toList()); ConfigTeleportHelperFilter.floorBlockStates = teleportHelperCat.unsafeFloorBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> blockRegistry.getOptional((ResourceLocation) (Object) x).map(b -> (BlockType) b) + .map(x -> blockRegistry.getOptional((Identifier) (Object) x).map(b -> (BlockType) b) .map(StateContainer::defaultState).orElse(null)) .filter(Objects::nonNull) .collect(Collectors.toList()); ConfigTeleportHelperFilter.bodyBlockTypes = teleportHelperCat.unsafeBlockBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> (BlockType) blockRegistry.getValue((ResourceLocation) (Object) x)) + .map(x -> (BlockType) blockRegistry.getValue((Identifier) (Object) x)) .filter(Objects::nonNull) .collect(Collectors.toList()); ConfigTeleportHelperFilter.bodyBlockStates = teleportHelperCat.unsafeBlockBlocks.stream() .map(x -> ResourceKey.resolve(x.toLowerCase(Locale.ENGLISH))) - .map(x -> blockRegistry.getOptional((ResourceLocation) (Object) x).map(b -> (BlockType) b) + .map(x -> blockRegistry.getOptional((Identifier) (Object) x).map(b -> (BlockType) b) .map(StateContainer::defaultState).orElse(null)) .filter(Objects::nonNull) .collect(Collectors.toList()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java index cc5d46c9762..a2bb2249470 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java @@ -30,7 +30,7 @@ import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.Criterion; import net.minecraft.advancements.DisplayInfo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.api.data.persistence.DataContainer; @@ -49,7 +49,7 @@ @Mixin(Advancement.class) public abstract class AdvancementMixin_API implements org.spongepowered.api.advancement.Advancement { - @Shadow @Final private Optional parent; + @Shadow @Final private Optional parent; @Shadow @Final private Optional display; @Shadow @Final private AdvancementRewards rewards; @Shadow @Final private Map> criteria; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java index 328ea086457..0fe2090c472 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementNodeMixin_API.java @@ -28,7 +28,7 @@ import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.AdvancementNode; import net.minecraft.advancements.DisplayInfo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.Advancement; import org.spongepowered.api.advancement.AdvancementTree; @@ -101,14 +101,14 @@ public Optional layoutElement(final Advancement advancement) @Override public Optional layoutElement(final ResourceKey advancementKey) { - return this.impl$element(((ResourceLocation) (Object) advancementKey)); + return this.impl$element(((Identifier) (Object) advancementKey)); } - private Optional impl$element(final ResourceLocation loc) { + private Optional impl$element(final Identifier loc) { return this.impl$findElementInfo((AdvancementNode) (Object) this, loc).map(TreeLayoutElement.class::cast); } - private Optional impl$findElementInfo(AdvancementNode node, ResourceLocation key) { + private Optional impl$findElementInfo(AdvancementNode node, Identifier key) { if (node.holder().id().equals(key)) { return node.advancement().display(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionProgressMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionProgressMixin_API.java index 134a08854fc..c60287fe7b0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionProgressMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionProgressMixin_API.java @@ -27,7 +27,7 @@ import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.CriterionProgress; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.advancement.AdvancementProgress; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; @@ -65,7 +65,7 @@ public Instant grant() { return this.obtained; } final AdvancementProgress advancementProgress = ((CriterionProgressBridge) this).bridge$getAdvancementProgress(); - final ResourceLocation key = ((AdvancementProgressBridge) advancementProgress).bridge$getAdvancementKey(); + final Identifier key = ((AdvancementProgressBridge) advancementProgress).bridge$getAdvancementKey(); final org.spongepowered.api.advancement.Advancement advancement = advancementProgress.advancement(); final AdvancementHolder holder = new AdvancementHolder(key, (Advancement) (Object) advancement); ((AdvancementProgressBridge) advancementProgress).bridge$getPlayerAdvancements().award(holder, this.criterion().name()); @@ -79,7 +79,7 @@ public Optional revoke() { } final Instant instant = this.obtained; final AdvancementProgress advancementProgress = ((CriterionProgressBridge) this).bridge$getAdvancementProgress(); - final ResourceLocation key = ((AdvancementProgressBridge) advancementProgress).bridge$getAdvancementKey(); + final Identifier key = ((AdvancementProgressBridge) advancementProgress).bridge$getAdvancementKey(); final org.spongepowered.api.advancement.Advancement advancement = advancementProgress.advancement(); final AdvancementHolder holder = new AdvancementHolder(key, (Advancement) (Object) advancement); ((AdvancementProgressBridge) advancementProgress).bridge$getPlayerAdvancements().revoke(holder, this.criterion().name()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java index da4b71e6e5f..889e363d0ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java @@ -29,7 +29,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; -import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.advancements.criterion.MinMaxBounds; import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.commands.arguments.selector.EntitySelectorParser; import net.minecraft.core.registries.Registries; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java index 033b74fe337..62455d8f24e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/MappedRegistryMixin_API.java @@ -28,7 +28,7 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.MappedRegistry; import net.minecraft.core.RegistrationInfo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.Registry; @@ -57,7 +57,7 @@ public abstract class MappedRegistryMixin_API implements Registry { @Shadow public abstract net.minecraft.resources.ResourceKey> shadow$key(); - private ResourceLocation impl$getKey(final T value) { + private Identifier impl$getKey(final T value) { return ((net.minecraft.core.Registry) this).getKey(value); } @@ -78,7 +78,7 @@ public RegistryType type() { public ResourceKey valueKey(final T value) { Objects.requireNonNull(value, "value"); - final ResourceLocation key = this.impl$getKey(value); + final Identifier key = this.impl$getKey(value); if (key == null) { throw new IllegalStateException(String.format("No key was found for '%s'!", value)); } @@ -155,7 +155,7 @@ public Optional> register(final ResourceKey key, Objects.requireNonNull(value, "value"); if (this.isDynamic()) { - final net.minecraft.resources.ResourceKey mcKey = net.minecraft.resources.ResourceKey.create(this.shadow$key(), (ResourceLocation) (Object) key); + final net.minecraft.resources.ResourceKey mcKey = net.minecraft.resources.ResourceKey.create(this.shadow$key(), (Identifier) (Object) key); this.shadow$register(mcKey, value, RegistrationInfo.BUILT_IN); return ((RegistryBridge) this).bridge$get(key); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java index 58a3621b0e6..6e40f5569f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/core/RegistryMixin.java @@ -25,8 +25,8 @@ package org.spongepowered.common.mixin.api.minecraft.core; import net.minecraft.core.Registry; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import org.spongepowered.api.registry.RegistryEntry; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.registry.ValueNotFoundException; @@ -44,15 +44,15 @@ public interface RegistryMixin extends org.spongepowered.api.registry.Registr @Shadow ResourceKey> shadow$key(); - @Shadow @Nullable ResourceLocation shadow$getKey(T object); + @Shadow @Nullable Identifier shadow$getKey(T object); - @Shadow Optional shadow$getOptional(@org.jetbrains.annotations.Nullable ResourceLocation arg); + @Shadow Optional shadow$getOptional(@org.jetbrains.annotations.Nullable Identifier arg); - @Shadow @Nullable T shadow$getValue(@org.jetbrains.annotations.Nullable ResourceLocation arg); + @Shadow @Nullable T shadow$getValue(@org.jetbrains.annotations.Nullable Identifier arg); @Override default RegistryType type() { - return RegistryType.of((org.spongepowered.api.ResourceKey) (Object) this.shadow$key().registry(), (org.spongepowered.api.ResourceKey) (Object) this.shadow$key().location()); + return RegistryType.of((org.spongepowered.api.ResourceKey) (Object) this.shadow$key().registry(), (org.spongepowered.api.ResourceKey) (Object) this.shadow$key().identifier()); } @Override @@ -67,18 +67,18 @@ default Optional findValueKey(final T value) @Override default Optional> findEntry(final org.spongepowered.api.ResourceKey key) { - return this.shadow$getOptional((ResourceLocation) (Object) Objects.requireNonNull(key, "key")).map(e -> + return this.shadow$getOptional((Identifier) (Object) Objects.requireNonNull(key, "key")).map(e -> new SpongeRegistryEntry<>((RegistryType) this.type(), key, (V) e)); } @Override default Optional findValue(final org.spongepowered.api.ResourceKey key) { - return (Optional) this.shadow$getOptional((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + return (Optional) this.shadow$getOptional((Identifier) (Object) Objects.requireNonNull(key, "key")); } @Override default V value(final org.spongepowered.api.ResourceKey key) { - final V value = (V) this.shadow$getValue((ResourceLocation) (Object) Objects.requireNonNull(key, "key")); + final V value = (V) this.shadow$getValue((Identifier) (Object) Objects.requireNonNull(key, "key")); if (value != null) { return value; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/IdentifierMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/IdentifierMixin_API.java index d6ff707896e..e5b73b0e2f6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/ResourceLocationMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/resources/IdentifierMixin_API.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.resources; import net.kyori.adventure.key.Key; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -34,12 +34,12 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -@Mixin(ResourceLocation.class) +@Mixin(Identifier.class) @Implements(value = { @Interface(iface = Key.class, prefix = "adventure$", remap = Remap.NONE), @Interface(iface = ResourceKey.class, prefix = "resourceKey$", remap = Remap.NONE) }) -public abstract class ResourceLocationMixin_API { +public abstract class IdentifierMixin_API { // @formatter:off @Shadow public abstract String shadow$getNamespace(); @@ -48,7 +48,7 @@ public abstract class ResourceLocationMixin_API { /** * @author MrHell228 - October 6th, 2025 - * @reason Delegate synthetic method to #compareTo(Key) to avoid CCE in case Key is not a ResourceLocation + * @reason Delegate synthetic method to #compareTo(Key) to avoid CCE in case Key is not a Identifier */ @Overwrite public int compareTo(final Object obj) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 1972c935181..3e743c7b442 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -183,7 +183,7 @@ public ChunkGenerator generator() { @Override public ResourceKey key() { - return (ResourceKey) (Object) this.shadow$dimension().location(); + return (ResourceKey) (Object) this.shadow$dimension().identifier(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java index 07fa31df462..e438dd44399 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerPlayerMixin_API.java @@ -40,7 +40,7 @@ import net.minecraft.network.chat.PlayerChatMessage; import net.minecraft.network.protocol.game.ClientboundDeleteChatPacket; import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerAdvancements; import net.minecraft.server.level.ServerBossEvent; @@ -244,7 +244,7 @@ public CooldownTracker cooldownTracker() { @Override public AdvancementProgress progress(final org.spongepowered.api.advancement.Advancement advancement) { Objects.requireNonNull(advancement, "advancement"); - final AdvancementHolder holder = new AdvancementHolder((ResourceLocation) (Object) advancement.key(RegistryTypes.ADVANCEMENT), (Advancement) (Object) advancement); + final AdvancementHolder holder = new AdvancementHolder((Identifier) (Object) advancement.key(RegistryTypes.ADVANCEMENT), (Advancement) (Object) advancement); return (AdvancementProgress) this.advancements.getOrStartProgress(holder); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/WorldGenRegionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/WorldGenRegionMixin_API.java index 5f48b94a501..cd756c968a8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/WorldGenRegionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/WorldGenRegionMixin_API.java @@ -70,7 +70,7 @@ public abstract class WorldGenRegionMixin_API implements GenerationRegion { @Inject(method = "", at = @At("RETURN")) private void api$getWorldKeyOnConstruction(final ServerLevel $$0, final StaticCache2D $$1, final ChunkStep $$2, final ChunkAccess $$3, final CallbackInfo ci) { - this.api$serverWorldKey = (ResourceKey) (Object) $$0.dimension().location(); + this.api$serverWorldKey = (ResourceKey) (Object) $$0.dimension().identifier(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/PackResourcesMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/PackResourcesMixin_API.java index 793eb7c39e5..8cea7dddbad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/PackResourcesMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/PackResourcesMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.server.packs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackResources; import net.minecraft.server.packs.resources.IoSupplier; import org.checkerframework.checker.nullness.qual.Nullable; @@ -55,7 +55,7 @@ public interface PackResourcesMixin_API extends PackContents { // @formatter:off @Shadow String shadow$packId(); - @Shadow IoSupplier shadow$getResource(net.minecraft.server.packs.PackType var1, ResourceLocation var2) throws IOException; + @Shadow IoSupplier shadow$getResource(net.minecraft.server.packs.PackType var1, Identifier var2) throws IOException; @Shadow Set shadow$getNamespaces(net.minecraft.server.packs.PackType var1); @Shadow void shadow$listResources(net.minecraft.server.packs.PackType var1, String var2, String var3, PackResources.ResourceOutput var4); @@ -83,7 +83,7 @@ default Resource requireResource(final PackType root, final ResourcePath path) t @Nullable default Resource api$createResource(final PackType root, final ResourcePath path) throws IOException { final net.minecraft.server.packs.PackType packType = (net.minecraft.server.packs.PackType) (Object) Objects.requireNonNull(root, "root"); - final ResourceLocation loc = (ResourceLocation) (Object) Objects.requireNonNull(path, "path").key(); + final Identifier loc = (Identifier) (Object) Objects.requireNonNull(path, "path").key(); final IoSupplier ioSupplier = this.shadow$getResource(packType, loc); return new SpongeResource(path, ioSupplier.get()); } @@ -93,7 +93,7 @@ default Collection paths(final PackType root, final String namespa Objects.requireNonNull(filter, "filter"); final net.minecraft.server.packs.PackType packType = (net.minecraft.server.packs.PackType) (Object) Objects.requireNonNull(root, "root"); - final Collection resources = new HashSet<>(); + final Collection resources = new HashSet<>(); this.shadow$listResources(packType, Objects.requireNonNull(namespace, "namespace"), Objects.requireNonNull(prefix, "prefix"), (loc, stream) -> { if (filter.test((ResourceKey) (Object) loc)) { @@ -110,7 +110,7 @@ default Collection paths(final PackType root, final String namespa default boolean exists(final PackType root, final ResourcePath path) { try { final net.minecraft.server.packs.PackType packType = (net.minecraft.server.packs.PackType) (Object) Objects.requireNonNull(root, "root"); - final ResourceLocation loc = (ResourceLocation) (Object) Objects.requireNonNull(path, "path").key(); + final Identifier loc = (Identifier) (Object) Objects.requireNonNull(path, "path").key(); final IoSupplier ioSupplier = this.shadow$getResource(packType, loc); return ioSupplier != null; } catch (IOException ignored) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/ResourceManagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/ResourceManagerMixin_API.java index 90c8e37125f..f9153d508a0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/ResourceManagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/packs/resources/ResourceManagerMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.server.packs.resources; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceProvider; import org.spongepowered.api.ResourceKey; @@ -49,13 +49,13 @@ public interface ResourceManagerMixin_API extends org.spongepowered.api.resource.ResourceManager { // @formatter:off - @Shadow List shadow$getResourceStack(ResourceLocation var1); - @Shadow Map shadow$listResources(String var1, Predicate var2); + @Shadow List shadow$getResourceStack(Identifier var1); + @Shadow Map shadow$listResources(String var1, Predicate var2); // @formatter:on @Override default Resource load(final ResourcePath path) throws IOException { - final ResourceLocation loc = (ResourceLocation) (Object) Objects.requireNonNull(path, "path").key(); + final Identifier loc = (Identifier) (Object) Objects.requireNonNull(path, "path").key(); final net.minecraft.server.packs.resources.Resource resource = ((ResourceProvider) this).getResourceOrThrow(loc); // TODO pass optional up to API? return new SpongeResource(resource, path); @@ -63,7 +63,7 @@ default Resource load(final ResourcePath path) throws IOException { @Override default Stream streamAll(final ResourcePath path) { - final ResourceLocation loc = (ResourceLocation) (Object) Objects.requireNonNull(path, "path").key(); + final Identifier loc = (Identifier) (Object) Objects.requireNonNull(path, "path").key(); return (Stream) (Object) this.shadow$getResourceStack(loc).stream(); } @@ -72,7 +72,7 @@ default Collection find(final String pathPrefix, final Predicate mapped = this.shadow$listResources(pathPrefix, loc -> pathFilter.test(loc.getPath())).keySet(); // TODO check filter + final Set mapped = this.shadow$listResources(pathPrefix, loc -> pathFilter.test(loc.getPath())).keySet(); // TODO check filter return mapped.stream() .map(r -> new SpongeResourcePath((ResourceKey) (Object) r)) .collect(Collectors.toList()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/SoundEventMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/SoundEventMixin_API.java index 741f8b1de44..7d956dd57d7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/SoundEventMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/sounds/SoundEventMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.sounds; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundEvent; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.effect.sound.SoundType; @@ -36,7 +36,7 @@ public abstract class SoundEventMixin_API implements SoundType { //@formatter:off - @Shadow @Final private ResourceLocation location; + @Shadow @Final private Identifier location; //@formatter:on @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java index d4f3c45fd30..0d9ffcb60c7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/tags/TagKeyMixin_API.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.tags; import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.RegistryHolder; @@ -45,12 +45,12 @@ public abstract class TagKeyMixin_API implements Tag { // @formatter:off @Shadow @Final private net.minecraft.resources.ResourceKey> registry; - @Shadow @Final private ResourceLocation location; + @Shadow @Final private Identifier location; // @formatter:on @Override public RegistryType registry() { - return RegistryType.of((ResourceKey) (Object) this.registry.registry(), (ResourceKey) (Object) this.registry.location()); + return RegistryType.of((ResourceKey) (Object) this.registry.registry(), (ResourceKey) (Object) this.registry.identifier()); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index 8762ae965b4..e96531d90c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -30,7 +30,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.ProblemReporter; @@ -351,7 +351,7 @@ public EntityArchetype createArchetype() { @Override public HoverEvent asHoverEvent(final UnaryOperator op) { final Registry> entityTypeRegistry = SpongeCommon.vanillaRegistry(Registries.ENTITY_TYPE); - final ResourceLocation entityTypeKey = entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()); + final Identifier entityTypeKey = entityTypeRegistry.getKey((net.minecraft.world.entity.EntityType) this.type()); return HoverEvent.showEntity(op.apply(HoverEvent.ShowEntity.showEntity((Key) (Object) entityTypeKey, this.uniqueId(), this.displayName().get()))); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/HumanoidArmMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/HumanoidArmMixin_API.java index 3f60eab0e26..2c06dd309bb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/HumanoidArmMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/HumanoidArmMixin_API.java @@ -30,16 +30,17 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.adventure.SpongeAdventure; @Mixin(HumanoidArm.class) public abstract class HumanoidArmMixin_API implements HandPreference { // @formatter:off - @Shadow @Final private String translationKey; + @Shadow @Final private net.minecraft.network.chat.Component caption; // @formatter:on @Override public Component asComponent() { - return Component.translatable(this.translationKey); + return SpongeAdventure.asAdventure(this.caption); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeInstanceMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeInstanceMixin_API.java index 214bcf05b37..92c9e8c6c86 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeInstanceMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeInstanceMixin_API.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity.ai.attributes; import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.entity.attribute.Attribute; @@ -59,11 +59,11 @@ public abstract class AttributeInstanceMixin_API implements Attribute { @Shadow public abstract double shadow$getValue(); @Shadow protected abstract void shadow$addModifier(net.minecraft.world.entity.ai.attributes.AttributeModifier modifier); @Shadow public abstract void shadow$removeModifier(net.minecraft.world.entity.ai.attributes.AttributeModifier modifier); - @Shadow public abstract boolean shadow$removeModifier(ResourceLocation $$0); + @Shadow public abstract boolean shadow$removeModifier(Identifier $$0); @Shadow abstract Map shadow$getModifiers(net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation p_225504_1_); @Shadow public abstract Set shadow$getModifiers(); - @Shadow public abstract boolean shadow$hasModifier(final ResourceLocation $$0); - @Shadow @Nullable public abstract net.minecraft.world.entity.ai.attributes.AttributeModifier shadow$getModifier(final ResourceLocation $$0); + @Shadow public abstract boolean shadow$hasModifier(final Identifier $$0); + @Shadow @Nullable public abstract net.minecraft.world.entity.ai.attributes.AttributeModifier shadow$getModifier(final Identifier $$0); // @formatter:on @@ -99,7 +99,7 @@ public Collection modifiers(final AttributeOperation operatio @Override public boolean hasModifier(final AttributeModifier modifier) { - return this.shadow$hasModifier((ResourceLocation) (Object) modifier.key()); + return this.shadow$hasModifier((Identifier) (Object) modifier.key()); } @Override @@ -114,12 +114,12 @@ public void removeModifier(final AttributeModifier modifier) { @Override public void removeModifier(ResourceKey key) { - this.shadow$removeModifier((ResourceLocation) (Object) key); + this.shadow$removeModifier((Identifier) (Object) key); } @Override public Optional modifier(final ResourceKey key) { - return Optional.ofNullable((AttributeModifier) (Object) this.shadow$getModifier((ResourceLocation) (Object) Objects.requireNonNull(key, "uniqueId"))); + return Optional.ofNullable((AttributeModifier) (Object) this.shadow$getModifier((Identifier) (Object) Objects.requireNonNull(key, "uniqueId"))); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeModifierMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeModifierMixin_API.java index 766744c19ee..5eda287243c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeModifierMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/ai/attributes/AttributeModifierMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.ai.attributes; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.entity.attribute.AttributeModifier; @@ -39,7 +39,7 @@ public abstract class AttributeModifierMixin_API implements AttributeModifier { // @formatter:off @Shadow @Final private double amount; @Shadow @Final private Operation operation; - @Shadow @Final private ResourceLocation id; + @Shadow @Final private Identifier id; // @formatter:on diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/ChatVisiblityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/ChatVisiblityMixin_API.java index 22d8a0c06de..3e54cb6d300 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/ChatVisiblityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/ChatVisiblityMixin_API.java @@ -29,17 +29,18 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.adventure.SpongeAdventure; @Mixin(ChatVisiblity.class) public abstract class ChatVisiblityMixin_API implements org.spongepowered.api.entity.living.player.chat.ChatVisibility { // @formatter:off - @Shadow @Final private String key; + @Shadow @Final private net.minecraft.network.chat.Component caption; // @formatter:on @Override public Component asComponent() { - return Component.translatable(this.key); + return SpongeAdventure.asAdventure(this.caption); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java index 6296ba85737..ae0caccdded 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemCooldownsMixin_API.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.world.item; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemCooldowns; import net.minecraft.world.item.ItemStack; @@ -53,13 +53,13 @@ public abstract class ItemCooldownsMixin_API implements org.spongepowered.api.en @Shadow public abstract boolean shadow$isOnCooldown(ItemStack stack); @Shadow public abstract float shadow$getCooldownPercent(ItemStack stack, float partialTicks); @Shadow public abstract void shadow$addCooldown(final ItemStack stack, final int ticks); - @Shadow public abstract void shadow$addCooldown(final ResourceLocation group, final int ticks); - @Shadow @Final private Map cooldowns; + @Shadow public abstract void shadow$addCooldown(final Identifier group, final int ticks); + @Shadow @Final private Map cooldowns; // @formatter:on - @Shadow public abstract ResourceLocation getCooldownGroup(final ItemStack $$0); + @Shadow public abstract Identifier getCooldownGroup(final ItemStack $$0); @Override public boolean hasCooldown(final org.spongepowered.api.item.inventory.ItemStack stack) { @@ -77,7 +77,7 @@ public boolean hasCooldown(final ResourceKey group) { } private float impl$getCooldownPercent(final Object group) { - final var cooldown = this.cooldowns.get((ResourceLocation) group); + final var cooldown = this.cooldowns.get((Identifier) group); if (cooldown != null) { float $$4 = (float)(cooldown.accessor$endTime() - cooldown.accessor$startTime()); float $$5 = (float)cooldown.accessor$endTime() - ((float)this.tickCount); @@ -117,7 +117,7 @@ public boolean setCooldown(final org.spongepowered.api.item.inventory.ItemStack @Override public boolean setCooldown(final ResourceKey group, final Ticks ticks) { Objects.requireNonNull(group, "group cannot be null!"); - this.shadow$addCooldown((ResourceLocation) (Object) group, SpongeTicks.toSaturatedIntOrInfinite(ticks)); + this.shadow$addCooldown((Identifier) (Object) group, SpongeTicks.toSaturatedIntOrInfinite(ticks)); return ((ItemCooldownsBridge) this).bridge$getSetCooldownResult(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java index 1eb8039ebb7..6d3cbc4d74f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeManagerMixin_API.java @@ -67,7 +67,7 @@ public Optional> byKey(final ResourceKey key) { Objects.requireNonNull(key); // TODO - figure out how to do this better for (var entry : ((RecipeMapAccessor) this.recipes).accessor$byKey().entrySet()) { - if (entry.getKey().location().equals(key)) { + if (entry.getKey().identifier().equals(key)) { return Optional.of(entry.getValue()).map(RecipeHolder::value).map(Recipe.class::cast); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 0bd8ef3729c..400760a2411 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -241,7 +241,7 @@ public Vector3i size() { @Override public Context context() { if (this.api$context == null) { - this.api$context = new Context(Context.WORLD_KEY, this.shadow$dimension().location().toString()); + this.api$context = new Context(Context.WORLD_KEY, this.shadow$dimension().identifier().toString()); } return this.api$context; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index 96fae23ca05..1c70a77c8e5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Tuple; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.level.BlockGetter; @@ -177,14 +178,20 @@ public Vector3i chunkPosition() { @Override public double regionalDifficultyFactor() { + if (!(this.level instanceof ServerLevel sl)) { + return 0; + } return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), - this.inhabitedTime().ticks(), this.level.getMoonBrightness()).getEffectiveDifficulty(); + this.inhabitedTime().ticks(), sl.getMoonBrightness(sl.getRespawnData().pos())).getEffectiveDifficulty(); } @Override public double regionalDifficultyPercentage() { + if (!(this.level instanceof ServerLevel sl)) { + return 0; + } return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), - this.inhabitedTime().ticks(), this.level.getMoonBrightness()).getSpecialMultiplier(); + this.inhabitedTime().ticks(), sl.getMoonBrightness(sl.getRespawnData().pos())).getSpecialMultiplier(); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java index f1cba73ef1e..c59ccf7f553 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/dimension/DimensionTypeMixin_API.java @@ -26,7 +26,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.persistence.DataContainer; @@ -57,7 +57,7 @@ public Context context() { } @Nullable - private ResourceLocation api$location() { + private Identifier api$location() { final Registry registry = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE); return registry.getKey((DimensionType) (Object) this); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java index 6fa56d0aac3..61f7398dca1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/HolderLookup_ProviderMixin.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core; import net.minecraft.core.HolderLookup; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryHolder; @@ -54,7 +54,7 @@ default Registry registry(final RegistryType type) { @SuppressWarnings({"rawtypes", "unchecked"}) @Override default Optional> findRegistry(final RegistryType type) { - return (Optional) this.shadow$lookup(ResourceKeyAccessor.invoker$create((ResourceLocation) (Object) type.root(), (ResourceLocation) (Object) type.location())); + return (Optional) this.shadow$lookup(ResourceKeyAccessor.invoker$create((Identifier) (Object) type.root(), (Identifier) (Object) type.location())); } @SuppressWarnings({"rawtypes", "unchecked"}) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java index 23cabe709b7..4cc18f889b7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java @@ -33,7 +33,7 @@ import net.minecraft.advancements.AdvancementType; import net.minecraft.advancements.Criterion; import net.minecraft.advancements.DisplayInfo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.api.advancement.criteria.AndCriterion; @@ -74,7 +74,7 @@ public abstract class AdvancementMixin implements AdvancementBridge { @SuppressWarnings({"ConstantConditions"}) @Inject(method = "(Ljava/util/Optional;Ljava/util/Optional;Lnet/minecraft/advancements/AdvancementRewards;Ljava/util/Map;Lnet/minecraft/advancements/AdvancementRequirements;Z)V", at = @At("RETURN")) - private void impl$setUpSpongeFields(final Optional parent, final Optional displayInfo, final AdvancementRewards $$2, + private void impl$setUpSpongeFields(final Optional parent, final Optional displayInfo, final AdvancementRewards $$2, final Map> criteria, final AdvancementRequirements requirements, final boolean sendsTelemetryEvent, final CallbackInfo ci) { displayInfo.ifPresent(info -> ((DisplayInfoBridge) info).bridge$setAdvancement((org.spongepowered.api.advancement.Advancement) this)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementProgressMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementProgressMixin.java index 256d15b6fc3..f259e49a37d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementProgressMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementProgressMixin.java @@ -28,7 +28,7 @@ import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.AdvancementProgress; import net.minecraft.advancements.AdvancementRequirements; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.PlayerAdvancements; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -81,7 +81,7 @@ public abstract class AdvancementProgressMixin implements AdvancementProgressBri // @formatter:on @Nullable private Map impl$progressMap; - @Nullable private ResourceLocation impl$advancementKey; + @Nullable private Identifier impl$advancementKey; @Nullable private PlayerAdvancements impl$playerAdvancements; @Override @@ -97,7 +97,7 @@ public abstract class AdvancementProgressMixin implements AdvancementProgressBri } @Override - public ResourceLocation bridge$getAdvancementKey() { + public Identifier bridge$getAdvancementKey() { Preconditions.checkState(this.impl$advancementKey != null, "The advancement is not yet initialized"); return this.impl$advancementKey; } @@ -116,7 +116,7 @@ public abstract class AdvancementProgressMixin implements AdvancementProgressBri } @Override - public void bridge$setAdvancementId(ResourceLocation key) { + public void bridge$setAdvancementId(Identifier key) { Preconditions.checkState(PlatformHooks.INSTANCE.getGeneralHooks().onServerThread()); this.impl$advancementKey = key; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/KeyMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/KeyMixin.java index 44b643db01a..89bff5d64d4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/KeyMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/KeyMixin.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.adventure; import net.kyori.adventure.key.Key; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.ResourceKey; import org.spongepowered.asm.mixin.Mixin; @@ -40,6 +40,6 @@ public interface KeyMixin { */ @Overwrite static @NonNull Key key(final @NonNull String namespace, final @NonNull String value) { - return (ResourceKey) (Object) ResourceLocation.fromNamespaceAndPath(namespace, value); + return (ResourceKey) (Object) Identifier.fromNamespaceAndPath(namespace, value); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index 2d1259ad4fa..1dfa562ce15 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -121,7 +121,7 @@ public MinecraftMixin(String param0) { } } - @Inject(method = "close", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;shutdownExecutors()V")) + @Inject(method = "close", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Util;shutdownExecutors()V")) private void impl$callStoppedGame(final CallbackInfo ci) { Launch.instance().lifecycle().callStoppedGameEvent(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java index 88cd8826d2b..1251b726baa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandFunctionMixin.java @@ -29,7 +29,7 @@ import com.mojang.brigadier.CommandDispatcher; import net.minecraft.commands.ExecutionCommandSource; import net.minecraft.commands.functions.CommandFunction; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.service.permission.PermissionService; @@ -45,7 +45,7 @@ public interface CommandFunctionMixin { @WrapMethod(method = "fromLines") private static > CommandFunction impl$onFromLines( - final ResourceLocation $$0, final CommandDispatcher $$1, final T $$2, final List $$3, final Operation> original) { + final Identifier $$0, final CommandDispatcher $$1, final T $$2, final List $$3, final Operation> original) { if ($$1 instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(delegatingCommandDispatcher.permissionService().newSubjectReference(PermissionService.SUBJECTS_FUNCTION, $$0.toString()).resolve().join()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/DimensionArgumentMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/DimensionArgumentMixin.java index 73adc701a2b..a4dd0601e21 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/DimensionArgumentMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/DimensionArgumentMixin.java @@ -26,17 +26,17 @@ import com.mojang.brigadier.arguments.ArgumentType; import net.minecraft.commands.arguments.DimensionArgument; -import net.minecraft.commands.arguments.ResourceLocationArgument; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.commands.arguments.IdentifierArgument; +import net.minecraft.resources.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.bridge.commands.arguments.CompletionsArgumentTypeBridge; @Mixin(DimensionArgument.class) -public abstract class DimensionArgumentMixin implements CompletionsArgumentTypeBridge { +public abstract class DimensionArgumentMixin implements CompletionsArgumentTypeBridge { @Override - public ArgumentType bridge$clientSideCompletionType() { - return ResourceLocationArgument.id(); + public ArgumentType bridge$clientSideCompletionType() { + return IdentifierArgument.id(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java index 5a1e8c58bf0..112a355627f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/core/MappedRegistryMixin.java @@ -31,7 +31,7 @@ import net.minecraft.core.MappedRegistry; import net.minecraft.core.RegistrationInfo; import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.api.ResourceKey; @@ -73,7 +73,7 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa @Shadow private boolean frozen; @Shadow @Final private ObjectList> byId; @Shadow @Final private Reference2IntMap toId; - @Shadow @Final private Map> byLocation; + @Shadow @Final private Map> byLocation; @Shadow @Final private Map, Holder.Reference> byKey; @Shadow @Final private Map> byValue; @Shadow @Final private Map, RegistrationInfo> registrationInfos; @@ -108,7 +108,7 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa private void impl$setType(final net.minecraft.resources.ResourceKey> key, final Lifecycle lifecycle, boolean $$2, final CallbackInfo ci) { this.impl$type = new SpongeRegistryType((ResourceKey) (Object) ((ResourceKeyAccessor) key).accessor$registryName(), - (ResourceKey) (Object) key.location()); + (ResourceKey) (Object) key.identifier()); } @@ -118,9 +118,9 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa final net.minecraft.resources.ResourceKey> resourceKey = ((MappedRegistry) (Object) this).key(); final ResourceKey root = (ResourceKey) (Object) ((ResourceKeyAccessor) resourceKey).accessor$registryName(); - final ResourceKey location = (ResourceKey) (Object) resourceKey.location(); + final ResourceKey location = (ResourceKey) (Object) resourceKey.identifier(); this.bridge$register(new SpongeRegistryEntry<>(new SpongeRegistryType<>(root, location), - (ResourceKey) (Object) $$0.location(), $$1)); + (ResourceKey) (Object) $$0.identifier(), $$1)); } @Override @@ -157,10 +157,10 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa for (int i = id; i < this.byId.size(); i++) { this.toId.put(this.byId.get(i).value(), i); } - this.byLocation.remove(key.location()); + this.byLocation.remove(key.identifier()); this.byValue.remove(value.value()); this.registrationInfos.remove(key); - this.impl$entries.remove((ResourceKey) (Object) key.location()); + this.impl$entries.remove((ResourceKey) (Object) key.identifier()); } @Inject(method = "freeze", at = @At(value = "FIELD", target = "Lnet/minecraft/core/MappedRegistry;frozen:Z", opcode = Opcodes.PUTFIELD)) @@ -195,7 +195,7 @@ public abstract class MappedRegistryMixin implements RegistryBridge, Writa private void impl$appendRegister(final Supplier> supplier) { supplier.get().forEach((vk, vi, vv) -> this.shadow$register( - net.minecraft.resources.ResourceKey.create(this.key, (ResourceLocation) (Object) vk), + net.minecraft.resources.ResourceKey.create(this.key, (Identifier) (Object) vk), vv, RegistrationInfo.BUILT_IN )); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/protocol/login/ClientboundCustomQueryPacketMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/protocol/login/ClientboundCustomQueryPacketMixin.java index 2c3111d5464..874d59b41eb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/protocol/login/ClientboundCustomQueryPacketMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/protocol/login/ClientboundCustomQueryPacketMixin.java @@ -27,7 +27,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -44,7 +44,7 @@ public abstract class ClientboundCustomQueryPacketMixin { // @formatter: on @Inject(method = "readPayload", at = @At("HEAD"), cancellable = true) - private static void impl$onReadUnknownPayload(final ResourceLocation $$0, final FriendlyByteBuf $$1, final CallbackInfoReturnable cir) { + private static void impl$onReadUnknownPayload(final Identifier $$0, final FriendlyByteBuf $$1, final CallbackInfoReturnable cir) { final int readableBytes = $$1.readableBytes(); if (readableBytes >= 0 && readableBytes <= ClientboundCustomQueryPacketMixin.MAX_PAYLOAD_SIZE) { final var payload = $$1.readBytes(readableBytes); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index 85e36189f3a..f580294ca6b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -30,10 +30,10 @@ import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ChatTypeDecoration; +import net.minecraft.resources.Identifier; import net.minecraft.resources.RegistryDataLoader; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import org.spongepowered.api.adventure.ChatTypes; import org.spongepowered.asm.mixin.Mixin; @@ -58,8 +58,8 @@ public class RegistryDataLoaderMixin { { if (Registries.CHAT_TYPE.equals($$2.key())) { final ChatTypeDecoration narration = ChatTypeDecoration.withSender("chat.type.text.narrate"); - $$2.register(ResourceKey.create($$2.key(), (ResourceLocation) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); - $$2.register(ResourceKey.create($$2.key(), (ResourceLocation) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); + $$2.register(ResourceKey.create($$2.key(), (Identifier) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); + $$2.register(ResourceKey.create($$2.key(), (Identifier) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 3d1b37ee9be..7985beaa640 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -177,7 +177,7 @@ protected boolean shouldRun(@NonNull Runnable runnable) { final @Nullable ServerLevel level = this.shadow$getLevel(SpongeWorldManager.createRegistryKey(k)); if (level != null) { if (log) { - MinecraftServerMixin.LOGGER.info("Saving chunks for level '{}'/{}", level, level.dimension().location()); + MinecraftServerMixin.LOGGER.info("Saving chunks for level '{}'/{}", level, level.dimension().identifier()); } level.save(null, false, level.noSave); return true; @@ -412,7 +412,7 @@ public boolean saveAllChunks(final boolean suppressLog, final boolean flush, fin // Sponge end if (autoSave.log) { - LOGGER.info("Saving chunks for level '{}'/{}", level, level.dimension().location()); + LOGGER.info("Saving chunks for level '{}'/{}", level, level.dimension().identifier()); } level.save(null, flush, level.noSave && !isForced); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java index bb1e1a3c9f2..9b835c58b54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/ServerAdvancementManagerMixin.java @@ -29,7 +29,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementNode; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.ServerAdvancementManager; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; @@ -59,7 +59,7 @@ public abstract class ServerAdvancementManagerMixin { @SuppressWarnings({"unchecked"}) @WrapMethod(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V") - private void impl$onApply(final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2, final Operation original) { + private void impl$onApply(final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2, final Operation original) { final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$1).registryHolder(); final Registry registry = (Registry) (Object) registryHolder.registry(RegistryTypes.ADVANCEMENT); $$0.forEach((k, v) -> registry.register((ResourceKey) (Object) k, v)); @@ -70,7 +70,7 @@ public abstract class ServerAdvancementManagerMixin { @WrapOperation(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/TreeNodePosition;run(Lnet/minecraft/advancements/AdvancementNode;)V")) private void impl$onLayout(final AdvancementNode instance, final Operation original, - final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2) { + final Map $$0, final ResourceManager $$1, final ProfilerFiller $$2) { original.call(instance); final Cause cause = PhaseTracker.getInstance().currentCause(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java index 6b3535cd498..02072e21807 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java @@ -66,7 +66,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolderMixin { if (ShouldFire.CHUNK_EVENT_LOAD) { final Vector3i chunkPos = VecHelper.toVector3i(chunk.getPos()); final ChunkEvent.Load event = SpongeEventFactory.createChunkEventLoad(PhaseTracker.getInstance().currentCause(), - (WorldChunk) chunk, chunkPos, (ResourceKey) (Object) chunk.getLevel().dimension().location()); + (WorldChunk) chunk, chunkPos, (ResourceKey) (Object) chunk.getLevel().dimension().identifier()); SpongeCommon.post(event); } }); @@ -78,7 +78,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolderMixin { if (this.impl$loadedChunk != null && ShouldFire.CHUNK_EVENT_UNLOAD_PRE) { final Vector3i chunkPos = VecHelper.toVector3i(this.impl$loadedChunk.getPos()); final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPre(PhaseTracker.getInstance().currentCause(), - (WorldChunk) this.impl$loadedChunk, chunkPos, (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().location()); + (WorldChunk) this.impl$loadedChunk, chunkPos, (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().identifier()); SpongeCommon.post(event); } } @@ -88,7 +88,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolderMixin { if (this.impl$loadedChunk != null && ShouldFire.CHUNK_EVENT_UNLOAD_POST) { final Vector3i chunkPos = VecHelper.toVector3i(this.impl$loadedChunk.getPos()); final ChunkEvent.Unload event = SpongeEventFactory.createChunkEventUnloadPost(PhaseTracker.getInstance().currentCause(), chunkPos, - (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().location()); + (ResourceKey) (Object) this.impl$loadedChunk.getLevel().dimension().identifier()); SpongeCommon.post(event); } this.impl$loadedChunk = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java index 396f56ec85b..ba9890194a2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java @@ -136,7 +136,7 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { if (ShouldFire.CHUNK_EVENT_BLOCKS_SAVE_PRE) { final Vector3i chunkPos = VecHelper.toVector3i(var1.getPos()); final ChunkEvent.Blocks.Save.Pre postSave = SpongeEventFactory.createChunkEventBlocksSavePre(PhaseTracker.getInstance().currentCause(), - ((BlockChunk) var1), chunkPos, (ResourceKey) (Object) this.level.dimension().location()); + ((BlockChunk) var1), chunkPos, (ResourceKey) (Object) this.level.dimension().identifier()); SpongeCommon.post(postSave); if (postSave.isCancelled()) { cir.setReturnValue(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/GenerationChunkHolderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/GenerationChunkHolderMixin.java index 20809321a9f..eef54ef2c0f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/GenerationChunkHolderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/GenerationChunkHolderMixin.java @@ -74,7 +74,7 @@ public abstract class GenerationChunkHolderMixin { final Vector3i chunkPos = VecHelper.toVector3i(chunk.getPos()); final ChunkEvent.Generated event = SpongeEventFactory.createChunkEventGenerated( PhaseTracker.getInstance().currentCause(), chunkPos, - (ResourceKey) (Object) chunk.getLevel().dimension().location() + (ResourceKey) (Object) chunk.getLevel().dimension().identifier() ); SpongeCommon.post(event); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 465cd94be95..3aab053803f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -29,7 +29,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Share; import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; -import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.particles.BlockParticleOption; @@ -38,7 +37,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.bossevents.CustomBossEvents; import net.minecraft.server.level.ServerChunkCache; @@ -48,6 +47,7 @@ import net.minecraft.server.players.PlayerList; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Util; import net.minecraft.util.random.WeightedList; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.RandomSequences; @@ -309,7 +309,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel ParticleOptions particleData = new BlockParticleOption(ParticleTypes.BLOCK, Blocks.AIR.defaultBlockState()); // "no" particle particleData = packet.explosionParticle(); // TODO control sound in API - var soundEvent = Holder.direct(new SoundEvent(ResourceLocation.parse("sponge:none"), Optional.of(0f))); // "no" sound + var soundEvent = Holder.direct(new SoundEvent(Identifier.parse("sponge:none"), Optional.of(0f))); // "no" sound soundEvent = packet.explosionSound(); // TODO apiExplosion.shouldPlaySmoke() is not initialized correctly var newPacket = new ClientboundExplodePacket(packet.center(), packet.radius(), packet.blockCount(), packet.playerKnockback(), particleData, soundEvent, packet.blockParticles()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 90495ff6d64..0fc1f133681 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -423,7 +423,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } - @Inject(method = "handlePlayerAction", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Z)Z")) + @Inject(method = "handlePlayerAction", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Z)V")) public void impl$dropItem(final ServerboundPlayerActionPacket p_147345_1_, final CallbackInfo ci) { this.impl$ignorePackets++; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index 24fa09a364c..cbe81f39195 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -46,8 +46,8 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.common.ClientboundDisconnectPacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; import net.minecraft.server.bossevents.CustomBossEvents; @@ -605,7 +605,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { return; } - boundChatType = ChatType.bind(ResourceKey.create(Registries.CHAT_TYPE, (ResourceLocation) (Object) event.chatType().location()), + boundChatType = ChatType.bind(ResourceKey.create(Registries.CHAT_TYPE, (Identifier) (Object) event.chatType().location()), this.server.registryAccess(), SpongeAdventure.asVanilla(event.sender())); if (event.target().isPresent()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java index 4950eca4a53..51d2af3fda0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java @@ -30,7 +30,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.WritableRegistry; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagLoader; @@ -69,20 +69,20 @@ public abstract class TagLoaderMixin implements TagLoaderBridge { private @MonotonicNonNull RegistryType impl$registryType; private @MonotonicNonNull Map> impl$modifiers; - private ResourceLocation impl$buildingTagKey; + private Identifier impl$buildingTagKey; @SuppressWarnings({"unchecked", "rawtypes"}) @Inject(method = "load", at = @At("TAIL")) - private void impl$onLoad(final ResourceManager $$0, final CallbackInfoReturnable>> cir) { + private void impl$onLoad(final ResourceManager $$0, final CallbackInfoReturnable>> cir) { final SpongePluginTags tags = ((ResourceManagerBridge) $$0).bridge$pluginProvidedTags(); tags.get(this.impl$registryType).ifPresent(m -> { this.impl$modifiers = (Map) m; m.forEach((tagKey, modifiers) -> { - final List entries = cir.getReturnValue().computeIfAbsent((ResourceLocation) (Object) tagKey, $ -> new ArrayList<>()); + final List entries = cir.getReturnValue().computeIfAbsent((Identifier) (Object) tagKey, $ -> new ArrayList<>()); modifiers.append().forEach((k, v) -> { final TagLoader.EntryWithSource entry = new TagLoader.EntryWithSource(k.tag() - ? TagEntry.optionalTag((ResourceLocation) (Object) k.key()) - : TagEntry.optionalElement((ResourceLocation) (Object) k.key()), "sponge"); + ? TagEntry.optionalTag((Identifier) (Object) k.key()) + : TagEntry.optionalElement((Identifier) (Object) k.key()), "sponge"); ((TagLoader_EntryWithSourceBridge) (Object) entry).bridge$predicates((Set) v); entries.add(entry); }); @@ -126,7 +126,7 @@ public abstract class TagLoaderMixin implements TagLoaderBridge { final Tag tag = Tag.of(this.impl$registryType, (ResourceKey) (Object) ((TagEntryAccessor) e.entry()).accessor$id()); for (final T value : values) { - final ResourceKey key = (ResourceKey) (Object) ((Holder.Reference) value).key().location(); + final ResourceKey key = (ResourceKey) (Object) ((Holder.Reference) value).key().identifier(); final DefaultedRegistryReference reference = RegistryKey.of(this.impl$registryType, key).asDefaultedReference(Sponge::game); for (final SpongePluginTagPredicate predicate : filters) { if (predicate.apply(reference, tag) == Tristate.TRUE) { @@ -148,7 +148,7 @@ public abstract class TagLoaderMixin implements TagLoaderBridge { } else if (((TagEntryAccessor) instance).accessor$tag()) { final Tag tag = Tag.of(this.impl$registryType, (ResourceKey) (Object) ((TagEntryAccessor) instance).accessor$id()); return original.accept(instance, lookup, i -> { - final ResourceKey key = (ResourceKey) (Object) ((Holder.Reference) i).key().location(); + final ResourceKey key = (ResourceKey) (Object) ((Holder.Reference) i).key().identifier(); final DefaultedRegistryReference reference = RegistryKey.of(this.impl$registryType, key).asDefaultedReference(Sponge::game); for (final SpongePluginTagPredicate predicate : modifier.filters()) { if (predicate.apply(reference, tag) == Tristate.FALSE) { @@ -208,11 +208,11 @@ public abstract class TagLoaderMixin implements TagLoaderBridge { @Override public void bridge$registryKey(final net.minecraft.resources.ResourceKey> registryKey) { this.impl$registryType = - RegistryType.of((ResourceKey) (Object) registryKey.registry(), (ResourceKey) (Object) registryKey.location()); + RegistryType.of((ResourceKey) (Object) registryKey.registry(), (ResourceKey) (Object) registryKey.identifier()); } @Override - public void bridge$buildingTagKey(final @Nullable ResourceLocation key) { + public void bridge$buildingTagKey(final @Nullable Identifier key) { this.impl$buildingTagKey = key; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index f5f25bf49ef..fc5ba2de9ca 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -220,7 +220,7 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li @ModifyVariable(method = "getDamageAfterMagicAbsorb", at = @At("STORE"), argsOnly = true, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getEffect(Lnet/minecraft/core/Holder;)Lnet/minecraft/world/effect/MobEffectInstance;"), - to = @At(value = "FIELD", target = "Lnet/minecraft/stats/Stats;DAMAGE_RESISTED:Lnet/minecraft/resources/ResourceLocation;"))) + to = @At(value = "FIELD", target = "Lnet/minecraft/stats/Stats;DAMAGE_RESISTED:Lnet/minecraft/resources/Identifier;"))) private float damage$modifyAfterDefensivePotionEffect(final float damage) { final SpongeDamageTracker tracker = this.damage$tracker(); return tracker == null ? damage : tracker.endStep(DamageStepTypes.DEFENSIVE_POTION_EFFECT, damage); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java index a37119cd297..0b4c0cde3e3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Shared_Damage.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; @@ -65,8 +65,8 @@ public abstract class LivingEntityMixin_Shared_Damage implements TrackedDamageBr return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } - @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V")) - private boolean damage$skipAbsorptionStat(final ServerPlayer self, final ResourceLocation stat, final int amount) { + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/Identifier;I)V")) + private boolean damage$skipAbsorptionStat(final ServerPlayer self, final Identifier stat, final int amount) { final SpongeDamageTracker tracker = this.damage$tracker(); return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 5c2c9fe1070..8af4121ddf0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -29,7 +29,7 @@ import net.kyori.adventure.bossbar.BossBar; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.permissions.PermissionSet; import net.minecraft.sounds.SoundEvent; @@ -101,7 +101,7 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G @Shadow public abstract FoodData shadow$getFoodData(); @Shadow public abstract boolean shadow$isCreative(); @Shadow public abstract String shadow$getScoreboardName(); - @Shadow public abstract void shadow$awardStat(ResourceLocation stat); + @Shadow public abstract void shadow$awardStat(Identifier stat); @Shadow public abstract Inventory shadow$getInventory(); @Shadow public abstract PermissionSet shadow$permissions(); @Shadow public Either shadow$startSleepInBed(final BlockPos param0) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index 22fc10c7cf3..bc777208c54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -77,8 +77,12 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return this.attack$trackers.peekLast(); } - @ModifyVariable(method = "attack", at = @At("LOAD"), - slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0))) + @ModifyVariable( + method = "attack(Lnet/minecraft/world/entity/Entity;)V", + ordinal = 1, + at = @At(value = "LOAD", ordinal = 0), + slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) + ) private float attack$firePreEvent(final float damage, @Local(argsOnly = true) final Entity target, @Local final DamageSource source, @Local final ItemStack weapon, final @Cancellable CallbackInfo ci) { final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); if (tracker == null) { @@ -203,7 +207,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @WrapWithCondition(method = "attack", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;makeSound(Lnet/minecraft/sounds/SoundEvent;)V")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;playServerSideSound(Lnet/minecraft/sounds/SoundEvent;)V")) private boolean attack$preventSound(Player instance, SoundEvent soundEvent) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null || !tracker.postEvent().isCancelled(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java index 1dd64ca7ac7..4d5b7f1dd1e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Shared_Damage.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity.player; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Player; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; @@ -53,10 +53,10 @@ public abstract class PlayerMixin_Shared_Damage extends LivingEntityMixin_Damage return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } - @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), slice = @Slice( + @WrapWithCondition(method = "actuallyHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;I)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;setAbsorptionAmount(F)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) - private boolean damage$skipAbsorptionStat(final Player self, final ResourceLocation stat, final int amount) { + private boolean damage$skipAbsorptionStat(final Player self, final Identifier stat, final int amount) { final SpongeDamageTracker tracker = this.damage$tracker(); return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java index 113ff390aef..ca570f63e46 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemCooldownsMixin.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.item; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemCooldowns; import net.minecraft.world.item.ItemStack; @@ -50,7 +50,7 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { // @formatter:off @Shadow @Final private Map cooldowns; - @Shadow public abstract ResourceLocation shadow$getCooldownGroup(final ItemStack $$0); + @Shadow public abstract Identifier shadow$getCooldownGroup(final ItemStack $$0); // @formatter:on @@ -58,7 +58,7 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { private int impl$lastSetCooldownResult; @Inject( - method = "addCooldown(Lnet/minecraft/resources/ResourceLocation;I)V", + method = "addCooldown(Lnet/minecraft/resources/Identifier;I)V", at = @At( value = "HEAD", remap = false @@ -66,7 +66,7 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) - private void impl$throwEventOnSetAndTrackResult(final ResourceLocation group, final int ticks, final CallbackInfo ci) { + private void impl$throwEventOnSetAndTrackResult(final Identifier group, final int ticks, final CallbackInfo ci) { this.impl$lastSetCooldownResult = this.impl$throwSetCooldownEvent(group, ticks); if (this.impl$lastSetCooldownResult == Constants.Sponge.Entity.Player.ITEM_COOLDOWN_CANCELLED) { ci.cancel(); @@ -74,7 +74,7 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { } @ModifyVariable( - method = "addCooldown(Lnet/minecraft/resources/ResourceLocation;I)V", + method = "addCooldown(Lnet/minecraft/resources/Identifier;I)V", at = @At( value = "HEAD", remap = false @@ -86,16 +86,16 @@ public abstract class ItemCooldownsMixin implements ItemCooldownsBridge { } @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;", remap = false)) - private Object onTick(final Map.Entry entry) { + private Object onTick(final Map.Entry entry) { this.impl$throwEndCooldownEvent(entry.getKey()); return entry.getKey(); } - protected int impl$throwSetCooldownEvent(final ResourceLocation group, final int ticks) { + protected int impl$throwSetCooldownEvent(final Identifier group, final int ticks) { return 0; } - protected void impl$throwEndCooldownEvent(final ResourceLocation group) { + protected void impl$throwEndCooldownEvent(final Identifier group) { } @@ -106,7 +106,7 @@ private Object onTick(final Map.Entry entry) { @Inject(method = "getCooldownPercent", at = @At("HEAD"), cancellable = true) private void impl$getCooldownPercentInfiniteCooldown(final ItemStack $$0, final float $$1, final CallbackInfoReturnable cir) { - ResourceLocation $$2 = this.shadow$getCooldownGroup($$0); + Identifier $$2 = this.shadow$getCooldownGroup($$0); final ItemCooldowns_CooldownInstanceAccessor cooldown = (ItemCooldowns_CooldownInstanceAccessor) this.cooldowns.get($$0); if (cooldown != null && cooldown.accessor$endTime() == cooldown.accessor$startTime() - 1) { cir.setReturnValue(1.0F); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java index 44695146492..3799930c8be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ServerItemCooldownsMixin.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.item; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.ServerItemCooldowns; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; @@ -50,11 +50,11 @@ public abstract class ServerItemCooldownsMixin extends ItemCooldownsMixin { // @formmater:off @Shadow @Final private net.minecraft.server.level.ServerPlayer player; - @Shadow protected abstract void shadow$onCooldownStarted(ResourceLocation group, int ticksIn); + @Shadow protected abstract void shadow$onCooldownStarted(Identifier group, int ticksIn); // @formmater:on @Override - protected int impl$throwSetCooldownEvent(final ResourceLocation group, final int ticks) { + protected int impl$throwSetCooldownEvent(final Identifier group, final int ticks) { if (ticks == 0) { return 0; } @@ -71,7 +71,7 @@ public abstract class ServerItemCooldownsMixin extends ItemCooldownsMixin { } @Override - protected void impl$throwEndCooldownEvent(final ResourceLocation group) { + protected void impl$throwEndCooldownEvent(final Identifier group) { final CooldownEvent.End event = SpongeEventFactory.createCooldownEventEnd(PhaseTracker.getInstance().currentCause(), (ResourceKey) (Object) group, (ServerPlayer) this.player); Sponge.eventManager().post(event); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java index 99704db7bef..15907a1612b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java @@ -33,8 +33,8 @@ import com.mojang.serialization.DynamicOps; import net.minecraft.core.HolderLookup; import net.minecraft.resources.FileToIdConverter; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; @@ -81,13 +81,13 @@ public abstract class RecipeManagerMixin { @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/world/item/crafting/RecipeMap;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V")) private void impl$onPrepare(final ResourceManager $$0, final FileToIdConverter $$1, final DynamicOps $$2, final Codec> $$3, - final Map> $$4, final Operation original) { - SortedMap> result = new TreeMap<>(); + final Map> $$4, final Operation original) { + SortedMap> result = new TreeMap<>(); original.call($$0, $$1, $$2, $$3, result); final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$0).registryHolder(); final Registry> registry = (Registry>) (Object) registryHolder.registry(RegistryTypes.RECIPE); result.forEach((k, v) -> registry.register((org.spongepowered.api.ResourceKey) (Object) k, v)); Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$0, Stream.of(registry)); - registry.streamEntries().forEach(e -> $$4.put((ResourceLocation) (Object) e.key(), e.value())); + registry.streamEntries().forEach(e -> $$4.put((Identifier) (Object) e.key(), e.value())); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NetherPortalBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NetherPortalBlockMixin.java index 8a39171148b..b96a261afa0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NetherPortalBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/NetherPortalBlockMixin.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.mixin.core.world.level.block; -import net.minecraft.BlockUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.BlockUtil; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.ai.village.poi.PoiRecord; import net.minecraft.world.entity.ai.village.poi.PoiTypes; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index c3763b9df18..40a3a3a8be7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -85,7 +85,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock final SlotTransaction transaction = new SlotTransaction(((FurnaceBlockEntity) entity).inventory().slot(1).get(), fuel, shrinkedFuel); final var recipe = ((AbstractFurnaceBlockEntityMixin) (Object) entity).bridge$getCurrentRecipe(); final CookingEvent.ConsumeFuel event = SpongeEventFactory.createCookingEventConsumeFuel(cause, (FurnaceBlockEntity) entity, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location()), Collections.singletonList(transaction)); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier()), Collections.singletonList(transaction)); SpongeCommon.post(event); if (event.isCancelled()) { ((AbstractFurnaceBlockEntityMixin) (Object) entity).cookingTotalTime = 0; @@ -143,7 +143,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock final Cause cause = PhaseTracker.getInstance().currentCause(); final var recipe = this.bridge$getCurrentRecipe(); final CookingEvent.Interrupt event = SpongeEventFactory.createCookingEventInterrupt(cause, (FurnaceBlockEntity) this, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java index af2c801e379..157515157e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java @@ -89,7 +89,7 @@ public abstract class CampfireBlockEntityMixin { final ItemStackSnapshot stack = ItemStackUtil.snapshotOf(mixinSelf.items.get(i)); final RecipeHolder recipe = mixinSelf.impl$cookingRecipe[i]; final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (Campfire) self, stack, Optional.empty(), - Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().location())); + Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); if (event.isCancelled()) { mixinSelf.cookingProgress[i]--; @@ -109,7 +109,7 @@ public abstract class CampfireBlockEntityMixin { final SlotTransaction transaction = new SlotTransaction(((Campfire) self).inventory().slot(i).get(), ItemStackUtil.snapshotOf(itemStack1), ItemStackSnapshot.empty()); final RecipeHolder recipe = mixinSelf.impl$cookingRecipe[i]; final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, (Campfire) self, - Optional.empty(), Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().location()), + Optional.empty(), Optional.ofNullable(recipe).map(r -> (CookingRecipe) r.value()), Optional.ofNullable(recipe).map(r -> (ResourceKey) (Object) r.id().identifier()), Collections.singletonList(transaction)); SpongeCommon.post(event); mixinSelf.impl$cookingRecipe[i] = null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java index 0575009f31d..1f69cbbc2d0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java @@ -101,7 +101,7 @@ static CompletableFuture generateBiomes(final WorldGenContext conte final Vector3i chunkPos = VecHelper.toVector3i(levelChunk.getPos()); if (ShouldFire.CHUNK_EVENT_BLOCKS_LOAD) { final ChunkEvent.Blocks.Load loadEvent = SpongeEventFactory.createChunkEventBlocksLoad(PhaseTracker.getInstance().currentCause(), - ((BlockChunk) levelChunk), chunkPos, (ResourceKey) (Object) levelChunk.getLevel().dimension().location()); + ((BlockChunk) levelChunk), chunkPos, (ResourceKey) (Object) levelChunk.getLevel().dimension().identifier()); SpongeCommon.post(loadEvent); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/EntityStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/EntityStorageMixin.java index 5eecfb80900..bf43ea2cd64 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/EntityStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/EntityStorageMixin.java @@ -77,7 +77,7 @@ public abstract class EntityStorageMixin { final Vector3i chunkPos = VecHelper.toVector3i($$0x); final SpongeEntityChunk entities = new SpongeEntityChunk(this.level, chunkPos, cir.getReturnValue().getEntities().collect(Collectors.toList())); final ChunkEvent.Entities.Load loadEvent = SpongeEventFactory.createChunkEventEntitiesLoad(PhaseTracker.getInstance().currentCause(), - entities, chunkPos, (ResourceKey) (Object) this.level.dimension().location()); + entities, chunkPos, (ResourceKey) (Object) this.level.dimension().identifier()); SpongeCommon.post(loadEvent); @@ -94,7 +94,7 @@ public abstract class EntityStorageMixin { final SpongeEntityChunk entities = new SpongeEntityChunk(this.level, chunkPos, $$0.getEntities().collect(Collectors.toList())); final ChunkEvent.Entities.Save.Pre saveEvent = SpongeEventFactory.createChunkEventEntitiesSavePre(PhaseTracker.getInstance().currentCause(), - entities, chunkPos, (ResourceKey) (Object) this.level.dimension().location()); + entities, chunkPos, (ResourceKey) (Object) this.level.dimension().identifier()); if (SpongeCommon.post(saveEvent)) { return null; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java index 9bac19268b8..dae1f194012 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java @@ -101,7 +101,7 @@ public abstract class IOWorkerMixin implements IOWorkerBridge { if (ShouldFire.CHUNK_EVENT_BLOCKS_SAVE_POST) { final Vector3i chunkPos = new Vector3i(param0.x, 0, param0.z); final ChunkEvent.Blocks.Save.Post postSave = SpongeEventFactory.createChunkEventBlocksSavePost(PhaseTracker.getInstance().currentCause(), chunkPos, - (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.location()); + (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.identifier()); SpongeCommon.post(postSave); } } @@ -109,7 +109,7 @@ else if (this.impl$type == SpongeIOWorkerType.ENTITY) { if (ShouldFire.CHUNK_EVENT_ENTITIES_SAVE_POST) { final Vector3i chunkPos = new Vector3i(param0.x, 0, param0.z); final ChunkEvent.Entities.Save.Post postSave = SpongeEventFactory.createChunkEventEntitiesSavePost(PhaseTracker.getInstance().currentCause(), chunkPos, - (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.location()); + (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.identifier()); SpongeCommon.post(postSave); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java index b695562105d..5853fe9133d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PlayerDataStorageMixin.java @@ -48,7 +48,7 @@ public abstract class PlayerDataStorageMixin { @Inject(method = "save", at = @At(value = "INVOKE", - target = "Lnet/minecraft/Util;safeReplaceFile(Ljava/nio/file/Path;Ljava/nio/file/Path;Ljava/nio/file/Path;)V", + target = "Lnet/minecraft/util/Util;safeReplaceFile(Ljava/nio/file/Path;Ljava/nio/file/Path;Ljava/nio/file/Path;)V", shift = At.Shift.AFTER)) private void impl$saveSpongePlayerData(final Player player, final CallbackInfo callbackInfo) { ((SpongeServer) SpongeCommon.server()).getPlayerDataManager().deleteLegacyPlayerData((ServerPlayer) player); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index c8932781dd1..7f91e1ac0d6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -42,8 +42,8 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; +import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; @@ -312,7 +312,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat public void bridge$readSpongeLevelData(final Dynamic dynamic) { dynamic.get(Constants.Sponge.Data.V2.SPONGE_DATA).get().ifSuccess(v2 -> { v2.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(this.impl$spongeData::setUniqueId); - v2.get(Constants.Sponge.World.WORLD_KEY).read(ResourceLocation.CODEC).result() + v2.get(Constants.Sponge.World.WORLD_KEY).read(Identifier.CODEC).result() .map(org.spongepowered.api.ResourceKey.class::cast).ifPresent(this.impl$spongeData::setKey); v2.get(Constants.Map.MAP_UUID_INDEX).readMap(Codec.STRING, UUIDUtil.CODEC).result().ifPresent(value -> { @@ -399,7 +399,7 @@ public String toString() { .listElements() .collect(Collectors.toMap(Holder.Reference::key, Holder.Reference::value)); if (this.impl$dimensionType != null && this.impl$chunkGenerator != null) { - dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (ResourceLocation) (Object) this.impl$spongeData.key()), + dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (Identifier) (Object) this.impl$spongeData.key()), $ -> new LevelStem($$2.lookupOrThrow(Registries.DIMENSION_TYPE).wrapAsHolder(this.impl$dimensionType), this.impl$chunkGenerator)); } return WorldGenSettings.encode($$0, $$1, new WorldDimensions(dimensions)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java index e3a0315872f..f0b824647be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java @@ -93,7 +93,7 @@ public abstract class EnchantmentContainerMixin_Inventory { // enchantItem lambda @Inject(method = "lambda$clickMenuButton$1", cancellable = true, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;)V"), require = 1) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;)V"), require = 1) private void impl$afterEnchantItem(final ItemStack itemstack, final int id, final Player playerIn, final int i, final ItemStack itemstack1, final Level arg5, final BlockPos arg6, final CallbackInfo ci) { final ItemStackSnapshot newItem = ItemStackUtil.snapshotOf(this.enchantSlots.getItem(0)); final ItemStackSnapshot newLapis = ItemStackUtil.snapshotOf(this.enchantSlots.getItem(1)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 6476ad1c7ba..85edb4588c2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -62,7 +62,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.entity.EntityBridge; import org.spongepowered.common.bridge.world.entity.player.PlayerInventoryBridge; @@ -121,17 +120,17 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory } } - @Inject(method = "drop(Z)Z", + @Inject(method = "drop(Z)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;removeFromSelected(Z)Lnet/minecraft/world/item/ItemStack;")) - protected void impl$beforeRemoveItem(final boolean param0, final CallbackInfoReturnable cir) { + protected void impl$beforeRemoveItem(final boolean param0, final CallbackInfo cir) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); this.inventory$effectTransactor = transactor.logDropFromPlayerInventory((ServerPlayer) (Object) this, param0); } - @Inject(method = "drop(Z)Z", + @Inject(method = "drop(Z)V", at = @At(value = "RETURN")) - protected void impl$onPlayerDrop(final boolean param0, final CallbackInfoReturnable cir) { + protected void impl$onPlayerDrop(final boolean param0, final CallbackInfo cir) { try (final EffectTransactor ignored = this.inventory$effectTransactor) { this.containerMenu.broadcastChanges(); // for capture } finally { diff --git a/src/mixins/java/org/spongepowered/common/mixin/ipforward/network/protocol/game/ClientboundCommandsPacket_ArgumentNodeStub_IpForward.java b/src/mixins/java/org/spongepowered/common/mixin/ipforward/network/protocol/game/ClientboundCommandsPacket_ArgumentNodeStub_IpForward.java index bacf15322f2..eb926802337 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/ipforward/network/protocol/game/ClientboundCommandsPacket_ArgumentNodeStub_IpForward.java +++ b/src/mixins/java/org/spongepowered/common/mixin/ipforward/network/protocol/game/ClientboundCommandsPacket_ArgumentNodeStub_IpForward.java @@ -29,7 +29,7 @@ import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -59,7 +59,7 @@ public final class ClientboundCommandsPacket_ArgumentNodeStub_IpForward { @Inject(method = "serializeCap(Lnet/minecraft/network/FriendlyByteBuf;Lnet/minecraft/commands/synchronization/ArgumentTypeInfo;Lnet/minecraft/commands/synchronization/ArgumentTypeInfo$Template;)V", at = @At("HEAD"), cancellable = true) private static , T extends ArgumentTypeInfo.Template> void ipForward$onSerializeCap( final FriendlyByteBuf buf, final ArgumentTypeInfo $$1, final ArgumentTypeInfo.Template $$2, final CallbackInfo ci) { - final @Nullable ResourceLocation key = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getKey($$1); + final @Nullable Identifier key = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getKey($$1); if (key == null || ClientboundCommandsPacket_ArgumentNodeStub_IpForward.ipForward$isVanillaArgument(key)) { return; } @@ -75,7 +75,7 @@ public final class ClientboundCommandsPacket_ArgumentNodeStub_IpForward { buf.writeBytes(commandData); } - private static boolean ipForward$isVanillaArgument(final ResourceLocation key) { + private static boolean ipForward$isVanillaArgument(final Identifier key) { return switch (key.getNamespace()) { case "brigadier" -> true; case "minecraft" -> switch (key.getPath()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index dbf675e3c3e..6efeb3485e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.plugin.entityactivation; import com.google.common.collect.ImmutableMap; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; @@ -153,7 +153,7 @@ public static void initializeEntityActivationState(final Entity entity) { final EntityActivationRangeCategory config = configAdapter.get().entityActivationRange; final EntityTypeBridge type = (EntityTypeBridge) entity.getType(); - final ResourceLocation key = EntityType.getKey(entity.getType()); + final Identifier key = EntityType.getKey(entity.getType()); final byte activationType = spongeEntity.activation$getActivationType(); final String activationTypeName = EntityActivationRange.activationTypeMappings.getOrDefault(activationType, "misc"); if (!type.bridge$isActivationRangeInitialized()) { @@ -409,7 +409,7 @@ public static boolean checkIfActive(final Entity entity) { } public static void addEntityToConfig( - final boolean autoPopulate, final ResourceLocation key, final byte activationType, final String activationTypeName + final boolean autoPopulate, final Identifier key, final byte activationType, final String activationTypeName ) { final InheritableConfigHandle globalConfig = SpongeGameConfigs.getGlobalInheritable(); final EntityActivationRangeCategory activationConfig = globalConfig.get().entityActivationRange; diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index c3036244af6..2772f46d459 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -42,7 +42,7 @@ "minecraft.network.protocol.status.ServerStatus_PlayersMixin_API", "minecraft.network.protocol.status.ServerStatus_VersionMixin_API", "minecraft.network.protocol.status.ServerStatusMixin_API", - "minecraft.resources.ResourceLocationMixin_API", + "minecraft.resources.IdentifierMixin_API", "minecraft.server.MinecraftServerMixin_API", "minecraft.server.ServerScoreboardMixin_API", "minecraft.server.level.ChunkMapMixin_API", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java index 88c8c8ffe37..c1038dd41b0 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java @@ -26,7 +26,7 @@ import com.mojang.logging.LogUtils; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.AbstractPackResources; import net.minecraft.server.packs.PackLocationInfo; import net.minecraft.server.packs.PackType; @@ -82,7 +82,7 @@ private IoSupplier getResource(final String rawPath) { } @Override - public IoSupplier getResource(final PackType type, final ResourceLocation loc) { + public IoSupplier getResource(final PackType type, final Identifier loc) { return this.getResource(String.format(Locale.ROOT, "%s/%s/%s", type.getDirectory(), loc.getNamespace(), loc.getPath())); } @@ -105,9 +105,9 @@ public void listResources(final PackType type, final String namespace, final Str } @Nullable - private ResourceLocation convertResourcePath(final String namespace, final Path resourcePath) { + private Identifier convertResourcePath(final String namespace, final Path resourcePath) { final String path = resourcePath.toString(); - final ResourceLocation location = ResourceLocation.tryBuild(namespace, path); + final Identifier location = Identifier.tryBuild(namespace, path); if (location == null) LOGGER.warn("Invalid path in plugin pack: {}:{}, ignoring", namespace, path); return location; diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java index c9195edbf28..ccc98e5e9cc 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java @@ -27,7 +27,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagLoader; import org.spongepowered.asm.mixin.Mixin; @@ -53,7 +53,7 @@ public abstract class TagLoaderMixin_Vanilla implements TagLoaderBridge { } @Inject(method = "lambda$build$5", at = @At("HEAD")) - private void vanilla$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final ResourceLocation $$2x, + private void vanilla$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java index e62415ed374..cc0ae1270e8 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla_Damage.java @@ -42,7 +42,7 @@ public abstract class LivingEntityMixin_Vanilla_Damage implements TrackedDamageBridge { @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) private float damage$firePostEvent_Living(final float damage) { return this.damage$firePostEvent(damage); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java index 26e6c1fb227..927f3c36760 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/player/PlayerMixin_Vanilla_Damage.java @@ -35,7 +35,7 @@ public abstract class PlayerMixin_Vanilla_Damage extends LivingEntityMixin_Vanilla_Damage { @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/ResourceLocation;I)V"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) private float damage$firePostEvent_Player(final float damage) { return this.damage$firePostEvent(damage); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 704ddefeb7b..8fb75d67d7f 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -95,13 +95,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final Cause cause = PhaseTracker.getInstance().currentCause(); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -120,7 +120,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -180,7 +180,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { From 3630664fe2a3adc30af867a854eb70eb1dfffd30 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 9 Dec 2025 20:27:01 -0800 Subject: [PATCH 422/586] feat(minecraft): update to 25w45a - Added `spear_mobs` trigger. - Added `netherite_horse_armor` item type. - Added `spawns_coral_variant_zombie_nautilus` biome tag. - Removed `without_patrol_spawns` biome tag. See https://minecraft.wiki/w/Java_Edition_25w45a --- SpongeAPI | 2 +- .../vanilla/generator/RegistryEntriesGenerator.java | 4 ++-- .../vanilla/generator/RegistryEntriesValidator.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 643c628d862..11cdb7039c9 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 643c628d86206dd6562951b6be28267509bdebd7 +Subproject commit 11cdb7039c99df92222c249a6f68e3a6060ac892 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java index 27d363626b3..97c04fbe46c 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesGenerator.java @@ -109,7 +109,7 @@ public RegistryEntriesGenerator(final String relativePackageName, @Override public String name() { - return "elements of registry " + this.registry.location(); + return "elements of registry " + this.registry.identifier(); } @Override @@ -122,7 +122,7 @@ public void generate(final Context ctx) throws IOException { clazz.addAnnotation(Types.suppressWarnings("unused")); final RegistryScope scopeType; - Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()).map(Holder.Reference::value).orElse(null); + Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.identifier()).map(Holder.Reference::value).orElse(null); if (registry == null) { registry = ctx.registries().lookup(this.registry).orElse(null); if (registry == null) { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java index c3293a09dd2..bf6202c06b1 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/RegistryEntriesValidator.java @@ -85,7 +85,7 @@ public RegistryEntriesValidator( @Override public String name() { - return "elements of registry " + this.registry.location(); + return "elements of registry " + this.registry.identifier(); } @Override @@ -98,7 +98,7 @@ public void generate(final Context ctx) { Registry registry = ctx.registries().lookup(this.registry).orElse(null); if (registry == null) { - registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.location()) + registry = (Registry) BuiltInRegistries.REGISTRY.get(this.registry.identifier()) .orElseThrow(() -> new IllegalArgumentException("Unknown registry " + this.registry)); } From a6ac4f1a699c37c35f0eb69b28f1b93ec631a5f7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 9 Dec 2025 22:15:03 -0800 Subject: [PATCH 423/586] feat(minecraft): update to 25w46a Notable Changes: - AbstractMount for carrier handling for Horses and Nautili(sp?) See https://minecraft.wiki/w/Java_Edition_25w46a --- SpongeAPI | 2 +- .../vanilla/generator/GeneratorMain.java | 2 +- gradle.properties | 2 +- ...java => AbstractMountInventoryMenuAccessor.java} | 10 +++++----- .../resources/mixins.sponge.accessors.json | 2 +- .../common/inventory/util/ContainerUtil.java | 6 +++--- .../animal/nautilus/AbstractNautilusMixin_API.java | 13 +++++++++++++ .../world/entity/player/PlayerMixin_Attack.java | 2 +- .../server/level/ServerPlayerMixin_Inventory.java | 4 ++-- .../impl/TraitMixin_ContainerBridge_Inventory.java | 4 ++-- 10 files changed, 30 insertions(+), 17 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/world/inventory/{HorseInventoryMenuAccessor.java => AbstractMountInventoryMenuAccessor.java} (84%) diff --git a/SpongeAPI b/SpongeAPI index 11cdb7039c9..b0b09001136 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 11cdb7039c99df92222c249a6f68e3a6060ac892 +Subproject commit b0b09001136e6d81e8c15698778d56b35b5514f2 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 38fef394e64..e8f3505e0d1 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -27,7 +27,6 @@ import com.github.javaparser.utils.Log; import com.mojang.datafixers.util.Pair; import net.minecraft.SharedConstants; -import net.minecraft.util.Util; import net.minecraft.commands.Commands.CommandSelection; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; @@ -44,6 +43,7 @@ import net.minecraft.server.packs.resources.MultiPackResourceManager; import net.minecraft.server.permissions.LevelBasedPermissionSet; import net.minecraft.tags.TagLoader; +import net.minecraft.util.Util; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.vanilla.generator.item.ItemRegistries; import org.spongepowered.vanilla.generator.world.TagRegistries; diff --git a/gradle.properties b/gradle.properties index 818109668c2..82c3d4e0d6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=25w45a +minecraftVersion=25w46a recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/HorseInventoryMenuAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractMountInventoryMenuAccessor.java similarity index 84% rename from src/accessors/java/org/spongepowered/common/accessor/world/inventory/HorseInventoryMenuAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractMountInventoryMenuAccessor.java index 045f703fb0d..f676a038854 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/inventory/HorseInventoryMenuAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/inventory/AbstractMountInventoryMenuAccessor.java @@ -24,14 +24,14 @@ */ package org.spongepowered.common.accessor.world.inventory; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.inventory.HorseInventoryMenu; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.inventory.AbstractMountInventoryMenu; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(HorseInventoryMenu.class) -public interface HorseInventoryMenuAccessor { +@Mixin(AbstractMountInventoryMenu.class) +public interface AbstractMountInventoryMenuAccessor { - @Accessor("horse") AbstractHorse accessor$horse(); + @Accessor("mount") LivingEntity accessor$mount(); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index ebfaea3563c..ab6f9cd2478 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -138,7 +138,7 @@ "world.inventory.BrewingStandMenuAccessor", "world.inventory.DispenserMenuAccessor", "world.inventory.HopperMenuAccessor", - "world.inventory.HorseInventoryMenuAccessor", + "world.inventory.AbstractMountInventoryMenuAccessor", "world.inventory.ItemCombinerMenuAccessor", "world.inventory.MerchantMenuAccessor", "world.inventory.ResultSlotAccessor", diff --git a/src/main/java/org/spongepowered/common/inventory/util/ContainerUtil.java b/src/main/java/org/spongepowered/common/inventory/util/ContainerUtil.java index 87c3aa91285..480ed8b004e 100644 --- a/src/main/java/org/spongepowered/common/inventory/util/ContainerUtil.java +++ b/src/main/java/org/spongepowered/common/inventory/util/ContainerUtil.java @@ -49,11 +49,11 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.inventory.AbstractContainerMenuAccessor; import org.spongepowered.common.accessor.world.inventory.AbstractFurnaceMenuAccessor; +import org.spongepowered.common.accessor.world.inventory.AbstractMountInventoryMenuAccessor; import org.spongepowered.common.accessor.world.inventory.BeaconMenuAccessor; import org.spongepowered.common.accessor.world.inventory.BrewingStandMenuAccessor; import org.spongepowered.common.accessor.world.inventory.DispenserMenuAccessor; import org.spongepowered.common.accessor.world.inventory.HopperMenuAccessor; -import org.spongepowered.common.accessor.world.inventory.HorseInventoryMenuAccessor; import org.spongepowered.common.accessor.world.inventory.ItemCombinerMenuAccessor; import org.spongepowered.common.accessor.world.inventory.MerchantMenuAccessor; import org.spongepowered.common.accessor.world.inventory.ResultSlotAccessor; @@ -291,8 +291,8 @@ private static Lens generateAdapterLens(final SlotLensProvider slots, final int return ContainerUtil.carrierOrNull(((BrewingStandMenuAccessor) container).accessor$brewingStand()); } else if (container instanceof BeaconMenu) { return new SpongeBlockEntityCarrier(((BeaconMenuAccessor) container).accessor$access().evaluate(Level::getBlockEntity).orElse(null), container); - } else if (container instanceof HorseInventoryMenuAccessor) { - return (Carrier) ((HorseInventoryMenuAccessor) container).accessor$horse(); + } else if (container instanceof AbstractMountInventoryMenuAccessor) { + return (Carrier) ((AbstractMountInventoryMenuAccessor) container).accessor$mount(); } else if (container instanceof MerchantMenuAccessor && ((MerchantMenuAccessor) container).accessor$trader() instanceof Carrier) { return (Carrier) ((MerchantMenuAccessor) container).accessor$trader(); } else if (container instanceof ItemCombinerMenuAccessor) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java index 017fc3a1fac..9104f1b2163 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/nautilus/AbstractNautilusMixin_API.java @@ -24,11 +24,16 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.nautilus; +import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.animal.nautilus.AbstractNautilus; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.NautilusLike; +import org.spongepowered.api.item.inventory.Carrier; +import org.spongepowered.api.item.inventory.type.CarriedInventory; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.mixin.api.minecraft.world.entity.TamableAnimalMixin_API; import java.util.Set; @@ -36,6 +41,8 @@ @Mixin(AbstractNautilus.class) public abstract class AbstractNautilusMixin_API extends TamableAnimalMixin_API implements NautilusLike { + @Shadow protected SimpleContainer inventory; + @Override protected Set> api$getVanillaValues() { final Set> values = super.api$getVanillaValues(); @@ -47,4 +54,10 @@ public abstract class AbstractNautilusMixin_API extends TamableAnimalMixin_API i return values; } + + + @Override + public CarriedInventory inventory() { + return InventoryUtil.carriedWrapperInventory(this.inventory, this); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index bc777208c54..620c915aae9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -140,7 +140,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem } @Inject(method = "attack", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;makeSound(Lnet/minecraft/sounds/SoundEvent;)V"), slice = @Slice( + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;playServerSideSound(Lnet/minecraft/sounds/SoundEvent;)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 0), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"))) private void attack$captureStrongSprint(final Entity target, final CallbackInfo ci) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 85edb4588c2..e785812bec4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -29,7 +29,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Cancellable; import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundHorseScreenOpenPacket; +import net.minecraft.network.protocol.game.ClientboundMountScreenOpenPacket; import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -226,7 +226,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory ci.cancel(); return menu; } - this.connection.send(new ClientboundHorseScreenOpenPacket(menu.containerId, $$4, $$3.getId())); + this.connection.send(new ClientboundMountScreenOpenPacket(menu.containerId, $$4, $$3.getId())); return menu; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ContainerBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ContainerBridge_Inventory.java index 240d7dbafec..36727641425 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ContainerBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ContainerBridge_Inventory.java @@ -27,6 +27,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractFurnaceMenu; +import net.minecraft.world.inventory.AbstractMountInventoryMenu; import net.minecraft.world.inventory.BeaconMenu; import net.minecraft.world.inventory.BrewingStandMenu; import net.minecraft.world.inventory.ChestMenu; @@ -34,7 +35,6 @@ import net.minecraft.world.inventory.DispenserMenu; import net.minecraft.world.inventory.EnchantmentMenu; import net.minecraft.world.inventory.HopperMenu; -import net.minecraft.world.inventory.HorseInventoryMenu; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.inventory.ItemCombinerMenu; import net.minecraft.world.inventory.MenuType; @@ -60,7 +60,7 @@ ItemCombinerMenu.class, BrewingStandMenu.class, BeaconMenu.class, - HorseInventoryMenu.class, + AbstractMountInventoryMenu.class, MerchantMenu.class, InventoryMenu.class, CraftingMenu.class From 4779343b9d05cc1eea452a4238eceec9619d3dbb Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 10 Dec 2025 00:09:22 -0800 Subject: [PATCH 424/586] feat(minecraft): update to 1.21.11-pre1 Notable Changes: - Entity classes were reshuffled in packages Additions: - Added sound event See https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_1 --- SpongeAPI | 2 +- .../world/entities/EntityRegistries.java | 22 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 14 ++ .../AbstractChestedHorseEntityAccessor.java | 4 +- .../AbstractMinecartAccessor.java | 4 +- .../animal/{ => cow}/MooshroomAccessor.java | 4 +- .../AbstractHorseAccessor.java | 4 +- .../{horse => equine}/HorseAccessor.java | 4 +- .../{horse => equine}/LlamaAccessor.java | 4 +- .../TraderLlamaAccessor.java | 4 +- .../animal/{ => feline}/CatAccessor.java | 6 +- .../animal/{ => feline}/OcelotAccessor.java | 4 +- .../animal/{ => fish}/PufferfishAccessor.java | 4 +- .../{ => fish}/TropicalFishAccessor.java | 4 +- .../entity/animal/{ => fox}/FoxAccessor.java | 4 +- .../animal/{ => panda}/PandaAccessor.java | 4 +- .../animal/{ => parrot}/ParrotAccessor.java | 4 +- .../entity/animal/{ => pig}/PigAccessor.java | 6 +- .../animal/{ => rabbit}/RabbitAccessor.java | 4 +- .../animal/{ => turtle}/TurtleAccessor.java | 4 +- .../{ => painting}/PaintingAccessor.java | 6 +- .../monster/{ => illager}/EvokerAccessor.java | 4 +- .../{ => illager}/PillagerAccessor.java | 4 +- .../SpellcasterIllagerAccessor.java | 4 +- .../{ => illager}/VindicatorAccessor.java | 4 +- .../{ => zombie}/ZombifiedPiglinAccessor.java | 4 +- .../AbstractVillagerAccessor.java | 4 +- .../{ => arrow}/AbstractArrowAccessor.java | 4 +- .../projectile/{ => arrow}/ArrowAccessor.java | 4 +- .../{ => boat}/AbstractBoatAccessor.java | 4 +- .../MinecartFurnaceAccessor.java | 4 +- .../resources/mixins.sponge.accessors.json | 56 ++--- .../provider/entity/AbstractArrowData.java | 4 +- .../entity/AbstractChestedHorseData.java | 2 +- .../provider/entity/AbstractHorseData.java | 4 +- .../provider/entity/AbstractMinecartData.java | 4 +- .../provider/entity/AbstractVillagerData.java | 2 +- .../data/provider/entity/ArrowData.java | 4 +- .../common/data/provider/entity/BoatData.java | 6 +- .../common/data/provider/entity/CatData.java | 6 +- .../data/provider/entity/ChickenData.java | 4 +- .../entity/CommandBlockMinecartData.java | 2 +- .../common/data/provider/entity/CowData.java | 4 +- .../entity/DamagingProjectileData.java | 2 +- .../data/provider/entity/DolphinData.java | 2 +- .../data/provider/entity/EvokerData.java | 2 +- .../common/data/provider/entity/FoxData.java | 4 +- .../provider/entity/FurnaceMinecartData.java | 2 +- .../data/provider/entity/HorseData.java | 4 +- .../data/provider/entity/IronGolemData.java | 2 +- .../data/provider/entity/LlamaData.java | 4 +- .../data/provider/entity/MooshroomData.java | 4 +- .../data/provider/entity/OcelotData.java | 2 +- .../data/provider/entity/PaintingData.java | 6 +- .../data/provider/entity/PandaData.java | 4 +- .../data/provider/entity/ParrotData.java | 4 +- .../common/data/provider/entity/PigData.java | 6 +- .../data/provider/entity/PillagerData.java | 4 +- .../data/provider/entity/PolarBearData.java | 2 +- .../data/provider/entity/PotionData.java | 2 +- .../data/provider/entity/PufferfishData.java | 4 +- .../data/provider/entity/RabbitData.java | 4 +- .../data/provider/entity/SalmonData.java | 2 +- .../entity/SpellcastingIllagerData.java | 4 +- .../data/provider/entity/SpiderData.java | 2 +- .../entity/ThrowableItemProjectileData.java | 2 +- .../data/provider/entity/TraderLlamaData.java | 2 +- .../provider/entity/TropicalFishData.java | 4 +- .../data/provider/entity/TurtleData.java | 4 +- .../data/provider/entity/VillagerData.java | 10 +- .../data/provider/entity/VindicatorData.java | 2 +- .../data/provider/entity/ZombieData.java | 2 +- .../provider/entity/ZombieVillagerData.java | 6 +- .../provider/entity/ZombifiedPiglinData.java | 2 +- .../data/provider/world/biome/BiomeData.java | 4 +- .../data/type/SpongeArtTypeBuilder.java | 2 +- .../SpongeRunAroundLikeCrazyAIBuilder.java | 2 +- .../entity/living/human/HumanEntity.java | 2 +- .../entity/projectile/ProjectileUtil.java | 26 +- .../inventory/InventoryEventFactory.java | 6 +- .../phase/packet/PacketPhaseUtil.java | 4 +- .../common/hooks/EntityHooks.java | 2 +- .../SpongeViewableInventoryBuilder.java | 4 +- .../inventory/lens/impl/LensRegistrar.java | 8 +- .../merchant/TradeOfferGeneratorWrapper.java | 2 +- .../loader/VanillaRegistryLoader.java | 24 +- .../world/server/SpongeWorldManager.java | 2 +- src/main/resources/common.accesswidener | 3 +- .../world/entity/SaddleableMixin_API.java | 2 +- .../entity/animal/{ => bee}/BeeMixin_API.java | 5 +- .../entity/animal/camel/CamelMixin_API.java | 2 +- .../{ => chicken}/ChickenMixin_API.java | 5 +- .../ChickenVariantMixin_API.java | 4 +- .../{ => cow}/AbstractCowMixin_API.java | 5 +- .../animal/{ => cow}/CowVariantMixin_API.java | 4 +- .../{ => cow}/MushroomCowMixin_API.java | 4 +- .../MushroomCow_MushroomTypeMixin_API.java | 4 +- .../{ => dolphin}/DolphinMixin_API.java | 5 +- .../AbstractChestedHorseMixin_API.java | 4 +- .../AbstractHorseMixin_API.java | 4 +- .../{horse => equine}/DonkeyMixin_API.java | 4 +- .../{horse => equine}/HorseMixin_API.java | 4 +- .../LLama_VariantMixin_API.java | 4 +- .../{horse => equine}/LlamaMixin_API.java | 4 +- .../{horse => equine}/MarkingsMixin_API.java | 4 +- .../{horse => equine}/MuleMixin_API.java | 4 +- .../SkeletonHorseMixin_API.java | 4 +- .../TraderLlamaMixin_API.java | 4 +- .../{horse => equine}/VariantMixin_API.java | 4 +- .../ZombieHorseMixin_API.java | 4 +- .../animal/{ => feline}/CatMixin_API.java | 4 +- .../{ => feline}/CatVariantMixin_API.java | 4 +- .../animal/{ => feline}/OcelotMixin_API.java | 5 +- .../{ => fish}/AbstractFishMixin_API.java | 4 +- .../AbstractSchoolingFishMixin_API.java | 4 +- .../animal/{ => fish}/CodMixin_API.java | 4 +- .../{ => fish}/PufferfishMixin_API.java | 4 +- .../animal/{ => fish}/SalmonMixin_API.java | 4 +- .../{ => fish}/SalmonVariantMixin_API.java | 4 +- .../{ => fish}/TropicalFishMixin_API.java | 4 +- .../TropicalFish_PatternMixin_API.java | 4 +- .../{ => fish}/WaterAnimalMixin_API.java | 4 +- .../entity/animal/{ => fox}/FoxMixin_API.java | 5 +- .../{ => fox}/Fox_VariantMixin_API.java | 4 +- .../{ => frog}/FrogVariantMixin_API.java | 2 +- .../entity/animal/frog/TadpoleMixin_API.java | 2 +- .../{ => golem}/AbstractGolemMixin_API.java | 4 +- .../animal/golem/CopperGolemMixin_API.java | 34 +++ .../{ => golem}/IronGolemMixin_API.java | 4 +- .../{ => golem}/SnowGolemMixin_API.java | 4 +- .../animal/{ => panda}/PandaMixin_API.java | 5 +- .../{ => panda}/Panda_GeneMixin_API.java | 4 +- .../animal/{ => parrot}/ParrotMixin_API.java | 4 +- .../{ => parrot}/Parrot_VariantMixin_API.java | 4 +- .../ShoulderRidingEntityMixin_API.java | 4 +- .../entity/animal/{ => pig}/PigMixin_API.java | 5 +- .../animal/{ => pig}/PigVariantMixin_API.java | 4 +- .../{ => polarbear}/PolarBearMixin_API.java | 5 +- .../animal/{ => rabbit}/RabbitMixin_API.java | 5 +- .../{ => rabbit}/Rabbit_VariantMixin_API.java | 4 +- .../squid}/GlowSquidMixin_API.java | 4 +- .../animal/{ => squid}/SquidMixin_API.java | 5 +- .../animal/{ => turtle}/TurtleMixin_API.java | 5 +- .../enderdragon/EnderDragonMixin_API.java | 4 +- .../EnderDragonPartMixin_API.java | 4 +- .../{ => painting}/PaintingMixin_API.java | 5 +- .../PaintingVariantMixin_API.java | 6 +- .../entity/monster/ShulkerMixin_API.java | 2 +- .../monster/{ => breeze}/BreezeMixin_API.java | 3 +- .../monster/{ => hoglin}/HoglinMixin_API.java | 2 +- .../AbstractIllagerMixin_API.java | 4 +- .../{ => illager}/EvokerMixin_API.java | 4 +- .../{ => illager}/IllusionerMixin_API.java | 4 +- .../{ => illager}/PillagerMixin_API.java | 4 +- .../SpellcasterIllagerMixin_API.java | 4 +- ...llcasterIllager_IllagerSpellMixin_API.java | 4 +- .../{ => illager}/VindicatorMixin_API.java | 4 +- .../{ => piglin}/AbstractPiglinMixin_API.java | 2 +- .../{ => piglin}/PiglinBruteMixin_API.java | 2 +- .../monster/{ => piglin}/PiglinMixin_API.java | 2 +- .../AbstractSkeletonMixin_API.java | 5 +- .../{ => skeleton}/BoggedMixin_API.java | 4 +- .../{ => skeleton}/ParchedMixin_API.java | 4 +- .../{ => skeleton}/SkeletonMixin_API.java | 4 +- .../{ => skeleton}/StrayMixin_API.java | 4 +- .../WitherSkeletonMixin_API.java | 4 +- .../{ => spider}/CaveSpiderMixin_API.java | 4 +- .../monster/{ => spider}/SpiderMixin_API.java | 5 +- .../{ => zombie}/DrownedMixin_API.java | 4 +- .../monster/{ => zombie}/HuskMixin_API.java | 4 +- .../monster/{ => zombie}/ZombieMixin_API.java | 5 +- .../{ => zombie}/ZombieVillagerMixin_API.java | 4 +- .../ZombifiedPiglinMixin_API.java | 4 +- .../AbstractVillagerMixin_API.java | 4 +- .../npc/{ => villager}/VillagerMixin_API.java | 4 +- .../VillagerProfessionMixin_API.java | 4 +- .../VillagerTrades_ItemListingMixin_API.java | 4 +- .../{ => villager}/VillagerTypeMixin_API.java | 4 +- .../WanderingTraderMixin_API.java | 5 +- .../{ => arrow}/AbstractArrowMixin_API.java | 5 +- .../AbstractArrow_PickupMixin_API.java | 4 +- .../{ => arrow}/ArrowMixin_API.java | 4 +- .../{ => arrow}/SpectralArrowMixin_API.java | 4 +- .../{ => arrow}/ThrownTridentMixin_API.java | 4 +- .../AbstractHurtingProjectileMixin_API.java | 5 +- .../DragonFireballMixin_API.java | 4 +- .../FireballMixin_API.java | 4 +- .../LargeFireballMixin_API.java | 4 +- .../SmallFireballMixin_API.java | 4 +- .../WitherSkullMixin_API.java | 4 +- .../AbstractWindChargeMixin_API.java | 4 +- .../windcharge/BreezeWindChargeMixin_API.java | 4 +- .../windcharge/WindChargeMixin_API.java | 4 +- .../SnowballMixin_API.java | 4 +- .../ThrowableItemProjectileMixin_API.java | 5 +- .../ThrownEggMixin_API.java | 4 +- .../ThrownEnderpearlMixin_API.java | 4 +- .../ThrownExperienceBottleMixin_API.java | 4 +- .../ThrownPotionMixin_API.java | 4 +- .../{ => boat}/AbstractBoatMixin_API.java | 4 +- .../AbstractChestBoatMixin_API.java | 4 +- .../AbstractMinecartContainerMixin_API.java | 4 +- .../AbstractMinecartMixin_API.java | 4 +- .../MinecartChestMixin_API.java | 4 +- .../MinecartCommandBlockMixin_API.java | 4 +- .../MinecartFurnaceMixin_API.java | 4 +- .../MinecartHopperMixin_API.java | 4 +- .../{ => minecart}/MinecartMixin_API.java | 4 +- .../MinecartSpawnerMixin_API.java | 4 +- .../{ => minecart}/MinecartTNTMixin_API.java | 4 +- .../service/permission/SubjectMixin_API.java | 2 +- .../core/server/level/ServerLevelMixin.java | 4 +- .../core/server/level/ServerPlayerMixin.java | 2 +- .../ServerGamePacketListenerImplMixin.java | 2 +- .../core/service/permission/SubjectMixin.java | 2 +- .../core/world/entity/EntityMaxAirMixin.java | 2 +- .../core/world/entity/GrieferBridgeMixin.java | 6 +- .../ai/behavior/HarvestFarmlandMixin.java | 4 +- .../ai/goal/RunAroundLikeCrazyGoalMixin.java | 6 +- .../{horse => equine}/AbstractHorseMixin.java | 4 +- .../Cat_CatRelaxOnOwnerGoalMixin.java | 10 +- .../animal/{ => feline}/OcelotMixin.java | 4 +- .../animal/{ => fish}/PufferfishMixin.java | 4 +- .../animal/{ => parrot}/ParrotMixin.java | 4 +- .../Rabbit_RaidGardenGoalMixin.java | 6 +- .../{ => zombie}/ZombifiedPiglinMixin.java | 5 +- .../{ => villager}/AbstractVillagerMixin.java | 4 +- .../npc/{ => villager}/VillagerMixin.java | 4 +- .../WanderingTraderMixin.java | 4 +- .../{ => arrow}/AbstractArrowMixin.java | 7 +- .../{ => arrow}/ThrownTridentMixin.java | 5 +- .../AbstractHurtingProjectileMixin.java | 7 +- .../LargeFireballMixin.java | 4 +- .../SmallFireballMixin.java | 4 +- .../WitherSkullMixin.java | 6 +- .../SnowballMixin.java | 5 +- .../ThrownEggMixin.java | 5 +- .../ThrownEnderpearlMixin.java | 5 +- .../vehicle/{ => boat}/AbstractBoatMixin.java | 4 +- .../AbstractMinecartContainerMixin.java | 4 +- .../{ => minecart}/AbstractMinecartMixin.java | 5 +- .../MinecartCommandBlockMixin.java | 4 +- ...CommandBlock_MinecartCommandBaseMixin.java | 6 +- .../{ => minecart}/MinecartFurnaceMixin.java | 4 +- .../{ => minecart}/MinecartTNTMixin.java | 6 +- .../OldMinecartBehaviourMixin.java | 8 +- ...ractArrowEntityMixin_EntityActivation.java | 4 +- .../TraitMixin_Viewable_Inventory_API.java | 4 +- ...tractHorseMixin_Carrier_Inventory_API.java | 4 +- .../PillagerMixin_Carrier_Inventory_API.java | 4 +- ...ctVillagerMixin_Carrier_Inventory_API.java | 4 +- ...tContainerMixin_Carried_Inventory_API.java | 4 +- ...tContainerMixin_Carrier_Inventory_API.java | 4 +- .../level/ServerPlayerMixin_Inventory.java | 4 +- .../TraitMixin_InventoryBridge_Inventory.java | 2 +- .../TraitMixin_ViewableBridge_Inventory.java | 4 +- ...raitMixin_TrackedMenuBridge_Inventory.java | 4 +- ...MenuMixin_TrackedMenuBridge_Inventory.java | 2 +- .../EntityActivationRange.java | 10 +- src/mixins/resources/mixins.sponge.api.json | 233 +++++++++--------- src/mixins/resources/mixins.sponge.core.json | 54 ++-- .../mixins.sponge.entityactivation.json | 2 +- .../resources/mixins.sponge.inventory.json | 10 +- .../{ => golem}/SnowGolemMixin_Vanilla.java | 4 +- .../{ => boat}/AbstractBoatMixin_Vanilla.java | 4 +- .../resources/mixins.spongevanilla.core.json | 4 +- 267 files changed, 793 insertions(+), 714 deletions(-) rename src/accessors/java/org/spongepowered/common/accessor/entity/{passive => animal/equine}/AbstractChestedHorseEntityAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/{ => minecart}/AbstractMinecartAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => cow}/MooshroomAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{horse => equine}/AbstractHorseAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{horse => equine}/HorseAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{horse => equine}/LlamaAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{horse => equine}/TraderLlamaAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => feline}/CatAccessor.java (90%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => feline}/OcelotAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => fish}/PufferfishAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => fish}/TropicalFishAccessor.java (94%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => fox}/FoxAccessor.java (95%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => panda}/PandaAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => parrot}/ParrotAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => pig}/PigAccessor.java (89%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => rabbit}/RabbitAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/{ => turtle}/TurtleAccessor.java (94%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/{ => painting}/PaintingAccessor.java (91%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/{ => illager}/EvokerAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/{ => illager}/PillagerAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/{ => illager}/SpellcasterIllagerAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/{ => illager}/VindicatorAccessor.java (91%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/{ => zombie}/ZombifiedPiglinAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/{ => villager}/AbstractVillagerAccessor.java (92%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/{ => arrow}/AbstractArrowAccessor.java (95%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/{ => arrow}/ArrowAccessor.java (96%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/{ => boat}/AbstractBoatAccessor.java (91%) rename src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/{ => minecart}/MinecartFurnaceAccessor.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => bee}/BeeMixin_API.java (90%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => chicken}/ChickenMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => chicken}/ChickenVariantMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => cow}/AbstractCowMixin_API.java (89%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => cow}/CowVariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => cow}/MushroomCowMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => cow}/MushroomCow_MushroomTypeMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => dolphin}/DolphinMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/AbstractChestedHorseMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/AbstractHorseMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/DonkeyMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/HorseMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/LLama_VariantMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/LlamaMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/MarkingsMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/MuleMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/SkeletonHorseMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/TraderLlamaMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/VariantMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{horse => equine}/ZombieHorseMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => feline}/CatMixin_API.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => feline}/CatVariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => feline}/OcelotMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/AbstractFishMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/AbstractSchoolingFishMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/CodMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/PufferfishMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/SalmonMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/SalmonVariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/TropicalFishMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/TropicalFish_PatternMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fish}/WaterAnimalMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fox}/FoxMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => fox}/Fox_VariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => frog}/FrogVariantMixin_API.java (99%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => golem}/AbstractGolemMixin_API.java (95%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => golem}/IronGolemMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => golem}/SnowGolemMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => panda}/PandaMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => panda}/Panda_GeneMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => parrot}/ParrotMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => parrot}/Parrot_VariantMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => parrot}/ShoulderRidingEntityMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => pig}/PigMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => pig}/PigVariantMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => polarbear}/PolarBearMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => rabbit}/RabbitMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => rabbit}/Rabbit_VariantMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/{ => animal/squid}/GlowSquidMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => squid}/SquidMixin_API.java (89%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/{ => turtle}/TurtleMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/{ => enderdragon}/EnderDragonPartMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/{ => painting}/PaintingMixin_API.java (90%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/{ => painting}/PaintingVariantMixin_API.java (87%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => breeze}/BreezeMixin_API.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => hoglin}/HoglinMixin_API.java (98%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/AbstractIllagerMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/EvokerMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/IllusionerMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/PillagerMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/SpellcasterIllagerMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/SpellcasterIllager_IllagerSpellMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => illager}/VindicatorMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => piglin}/AbstractPiglinMixin_API.java (98%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => piglin}/PiglinBruteMixin_API.java (98%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => piglin}/PiglinMixin_API.java (98%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/AbstractSkeletonMixin_API.java (89%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/BoggedMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/ParchedMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/SkeletonMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/StrayMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => skeleton}/WitherSkeletonMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => spider}/CaveSpiderMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => spider}/SpiderMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => zombie}/DrownedMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => zombie}/HuskMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => zombie}/ZombieMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => zombie}/ZombieVillagerMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => zombie}/ZombifiedPiglinMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => villager}/AbstractVillagerMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => villager}/VillagerMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => villager}/VillagerProfessionMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => villager}/VillagerTrades_ItemListingMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => villager}/VillagerTypeMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/{ => wanderingtrader}/WanderingTraderMixin_API.java (90%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => arrow}/AbstractArrowMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => arrow}/AbstractArrow_PickupMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => arrow}/ArrowMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => arrow}/SpectralArrowMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => arrow}/ThrownTridentMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/AbstractHurtingProjectileMixin_API.java (89%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/DragonFireballMixin_API.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/FireballMixin_API.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/LargeFireballMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/SmallFireballMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/WitherSkullMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/windcharge/AbstractWindChargeMixin_API.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/windcharge/BreezeWindChargeMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => hurtingprojectile}/windcharge/WindChargeMixin_API.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/SnowballMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/ThrowableItemProjectileMixin_API.java (88%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/ThrownEggMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/ThrownEnderpearlMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/ThrownExperienceBottleMixin_API.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/{ => throwableitemprojectile}/ThrownPotionMixin_API.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => boat}/AbstractBoatMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => boat}/AbstractChestBoatMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/AbstractMinecartContainerMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/AbstractMinecartMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartChestMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartCommandBlockMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartFurnaceMixin_API.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartHopperMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartSpawnerMixin_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/{ => minecart}/MinecartTNTMixin_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{horse => equine}/AbstractHorseMixin.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => feline}/Cat_CatRelaxOnOwnerGoalMixin.java (86%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => feline}/OcelotMixin.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => fish}/PufferfishMixin.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => parrot}/ParrotMixin.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/{ => rabbit}/Rabbit_RaidGardenGoalMixin.java (92%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/{ => zombie}/ZombifiedPiglinMixin.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/{ => villager}/AbstractVillagerMixin.java (91%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/{ => villager}/VillagerMixin.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/{ => wanderingtrader}/WanderingTraderMixin.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => arrow}/AbstractArrowMixin.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => arrow}/ThrownTridentMixin.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => hurtingprojectile}/AbstractHurtingProjectileMixin.java (86%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => hurtingprojectile}/LargeFireballMixin.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => hurtingprojectile}/SmallFireballMixin.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => hurtingprojectile}/WitherSkullMixin.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => throwableitemprojectile}/SnowballMixin.java (90%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => throwableitemprojectile}/ThrownEggMixin.java (90%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/{ => throwableitemprojectile}/ThrownEnderpearlMixin.java (93%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => boat}/AbstractBoatMixin.java (98%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/AbstractMinecartContainerMixin.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/AbstractMinecartMixin.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/MinecartCommandBlockMixin.java (97%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/MinecartCommandBlock_MinecartCommandBaseMixin.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/MinecartFurnaceMixin.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/MinecartTNTMixin.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/{ => minecart}/OldMinecartBehaviourMixin.java (88%) rename src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/{ => arrow}/AbstractArrowEntityMixin_EntityActivation.java (95%) rename src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/{horse => equine}/AbstractHorseMixin_Carrier_Inventory_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/{ => illager}/PillagerMixin_Carrier_Inventory_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/{ => villager}/AbstractVillagerMixin_Carrier_Inventory_API.java (96%) rename src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/{ => minecart}/AbstractMinecartContainerMixin_Carried_Inventory_API.java (94%) rename src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/{ => minecart}/AbstractMinecartContainerMixin_Carrier_Inventory_API.java (94%) rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/{ => golem}/SnowGolemMixin_Vanilla.java (96%) rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/{ => boat}/AbstractBoatMixin_Vanilla.java (96%) diff --git a/SpongeAPI b/SpongeAPI index b0b09001136..307eddfad1f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b0b09001136e6d81e8c15698778d56b35b5514f2 +Subproject commit 307eddfad1f2a9b84071039bb10949f8d138c8dd diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java index a56cd09d1fa..cc947bd5e67 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java @@ -30,18 +30,18 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlotGroup; import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.animal.Fox; -import net.minecraft.world.entity.animal.MushroomCow; -import net.minecraft.world.entity.animal.Panda; -import net.minecraft.world.entity.animal.Parrot; -import net.minecraft.world.entity.animal.Rabbit; -import net.minecraft.world.entity.animal.Salmon; -import net.minecraft.world.entity.animal.TropicalFish; import net.minecraft.world.entity.animal.axolotl.Axolotl; -import net.minecraft.world.entity.animal.horse.Llama; -import net.minecraft.world.entity.animal.horse.Markings; -import net.minecraft.world.entity.animal.horse.Variant; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.animal.cow.MushroomCow; +import net.minecraft.world.entity.animal.equine.Llama; +import net.minecraft.world.entity.animal.equine.Markings; +import net.minecraft.world.entity.animal.equine.Variant; +import net.minecraft.world.entity.animal.fish.Salmon; +import net.minecraft.world.entity.animal.fish.TropicalFish; +import net.minecraft.world.entity.animal.fox.Fox; +import net.minecraft.world.entity.animal.panda.Panda; +import net.minecraft.world.entity.animal.parrot.Parrot; +import net.minecraft.world.entity.animal.rabbit.Rabbit; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import org.spongepowered.vanilla.generator.Context; import org.spongepowered.vanilla.generator.EnumEntriesValidator; import org.spongepowered.vanilla.generator.Generator; diff --git a/gradle.properties b/gradle.properties index 82c3d4e0d6d..b5c947e420d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=25w46a +minecraftVersion=1.21.11-pre1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a4addc207b8..94cd74e12d1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1811,6 +1811,20 @@ + + + + + + + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/passive/AbstractChestedHorseEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/equine/AbstractChestedHorseEntityAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/entity/passive/AbstractChestedHorseEntityAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/entity/animal/equine/AbstractChestedHorseEntityAccessor.java index da4386c2b96..45d68eaf136 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/entity/passive/AbstractChestedHorseEntityAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/animal/equine/AbstractChestedHorseEntityAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.entity.passive; +package org.spongepowered.common.accessor.entity.animal.equine; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.animal.equine.AbstractChestedHorse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.common.UntransformedAccessorError; diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/minecart/AbstractMinecartAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/minecart/AbstractMinecartAccessor.java index 49108ce7dcb..a95b583c59f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/AbstractMinecartAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/vehicle/minecart/AbstractMinecartAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.entity.vehicle; +package org.spongepowered.common.accessor.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/cow/MooshroomAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/cow/MooshroomAccessor.java index 90a3a1b3400..2a0c87e9d7f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/MooshroomAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/cow/MooshroomAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.cow; -import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.animal.cow.MushroomCow; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/AbstractHorseAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/AbstractHorseAccessor.java index db34c538344..1d66b24c54b 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/AbstractHorseAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/AbstractHorseAccessor.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal.horse; +package org.spongepowered.common.accessor.world.entity.animal.equine; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/HorseAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/HorseAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/HorseAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/HorseAccessor.java index 3e51d825acc..44c8194f034 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/HorseAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/HorseAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal.horse; +package org.spongepowered.common.accessor.world.entity.animal.equine; -import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.animal.equine.Horse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/LlamaAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/LlamaAccessor.java index 71dbf4dce10..5b00f50fa55 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/LlamaAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/LlamaAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal.horse; +package org.spongepowered.common.accessor.world.entity.animal.equine; -import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.animal.equine.Llama; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/TraderLlamaAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/TraderLlamaAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/TraderLlamaAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/TraderLlamaAccessor.java index 68de982a58d..52bbd33c7cc 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/horse/TraderLlamaAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/equine/TraderLlamaAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal.horse; +package org.spongepowered.common.accessor.world.entity.animal.equine; -import net.minecraft.world.entity.animal.horse.TraderLlama; +import net.minecraft.world.entity.animal.equine.TraderLlama; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/CatAccessor.java similarity index 90% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/CatAccessor.java index 22d4b2e3cf4..25a48474b53 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/CatAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/CatAccessor.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.feline; import net.minecraft.core.Holder; -import net.minecraft.world.entity.animal.Cat; -import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.feline.Cat; +import net.minecraft.world.entity.animal.feline.CatVariant; import net.minecraft.world.item.DyeColor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/OcelotAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/OcelotAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/OcelotAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/OcelotAccessor.java index 79c98363632..1ede97ac4d1 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/OcelotAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/feline/OcelotAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.feline; -import net.minecraft.world.entity.animal.Ocelot; +import net.minecraft.world.entity.animal.feline.Ocelot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PufferfishAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/PufferfishAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PufferfishAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/PufferfishAccessor.java index e3ae8be5138..5060c719199 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PufferfishAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/PufferfishAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.fish; -import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.fish.Pufferfish; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/TropicalFishAccessor.java similarity index 94% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/TropicalFishAccessor.java index 1da1181ff1a..13f3b955bb4 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TropicalFishAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fish/TropicalFishAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.fish; -import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.fish.TropicalFish; import net.minecraft.world.item.DyeColor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fox/FoxAccessor.java similarity index 95% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fox/FoxAccessor.java index 60245abf302..140de226c25 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/FoxAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/fox/FoxAccessor.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.fox; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.fox.Fox; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PandaAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/panda/PandaAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PandaAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/panda/PandaAccessor.java index 108632523f4..399206e5794 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PandaAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/panda/PandaAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.panda; -import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.panda.Panda; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/parrot/ParrotAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/parrot/ParrotAccessor.java index 2a8964e32ee..a22b68a2e17 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/ParrotAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/parrot/ParrotAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.parrot; -import net.minecraft.world.entity.animal.Parrot; +import net.minecraft.world.entity.animal.parrot.Parrot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/pig/PigAccessor.java similarity index 89% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/pig/PigAccessor.java index dfaef2f422e..e0ad6acb08d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/PigAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/pig/PigAccessor.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.pig; import net.minecraft.core.Holder; -import net.minecraft.world.entity.animal.Pig; -import net.minecraft.world.entity.animal.PigVariant; +import net.minecraft.world.entity.animal.pig.Pig; +import net.minecraft.world.entity.animal.pig.PigVariant; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/rabbit/RabbitAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/rabbit/RabbitAccessor.java index 167e4e0ef4d..8bc5ce21117 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/RabbitAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/rabbit/RabbitAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.rabbit; -import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.rabbit.Rabbit; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/turtle/TurtleAccessor.java similarity index 94% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/turtle/TurtleAccessor.java index 1ade4b94020..84408ef5102 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/TurtleAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/animal/turtle/TurtleAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.animal; +package org.spongepowered.common.accessor.world.entity.animal.turtle; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.animal.Turtle; +import net.minecraft.world.entity.animal.turtle.Turtle; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/painting/PaintingAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/painting/PaintingAccessor.java index c9f442fadfa..eb4b8a1f96d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/PaintingAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/decoration/painting/PaintingAccessor.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.decoration; +package org.spongepowered.common.accessor.world.entity.decoration.painting; import net.minecraft.core.Holder; -import net.minecraft.world.entity.decoration.Painting; -import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.decoration.painting.Painting; +import net.minecraft.world.entity.decoration.painting.PaintingVariant; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/EvokerAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/EvokerAccessor.java index 0c4d871b379..29293ef376c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/EvokerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/EvokerAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.monster; +package org.spongepowered.common.accessor.world.entity.monster.illager; import net.minecraft.world.entity.animal.sheep.Sheep; -import net.minecraft.world.entity.monster.Evoker; +import net.minecraft.world.entity.monster.illager.Evoker; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/PillagerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/PillagerAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/PillagerAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/PillagerAccessor.java index 7096fe2af7c..328797e1e1c 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/PillagerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/PillagerAccessor.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.monster; +package org.spongepowered.common.accessor.world.entity.monster.illager; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.world.entity.monster.Pillager; +import net.minecraft.world.entity.monster.illager.Pillager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.common.UntransformedAccessorError; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SpellcasterIllagerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/SpellcasterIllagerAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SpellcasterIllagerAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/SpellcasterIllagerAccessor.java index 9ef5b5fa2f0..456016fb8b8 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SpellcasterIllagerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/SpellcasterIllagerAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.monster; +package org.spongepowered.common.accessor.world.entity.monster.illager; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/VindicatorAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/VindicatorAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/VindicatorAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/VindicatorAccessor.java index 4cfb51723b1..afedae4c32e 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/VindicatorAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/illager/VindicatorAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.monster; +package org.spongepowered.common.accessor.world.entity.monster.illager; -import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.monster.illager.Vindicator; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/zombie/ZombifiedPiglinAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/zombie/ZombifiedPiglinAccessor.java index 644030a22c0..321b56e95aa 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/ZombifiedPiglinAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/zombie/ZombifiedPiglinAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.monster; +package org.spongepowered.common.accessor.world.entity.monster.zombie; -import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.monster.zombie.ZombifiedPiglin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/AbstractVillagerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/villager/AbstractVillagerAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/AbstractVillagerAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/villager/AbstractVillagerAccessor.java index 3bcb04f866b..4f78ae7cfd8 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/AbstractVillagerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/villager/AbstractVillagerAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.npc; +package org.spongepowered.common.accessor.world.entity.npc.villager; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.item.trading.MerchantOffers; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/AbstractArrowAccessor.java similarity index 95% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/AbstractArrowAccessor.java index 812c3a52ca9..b1933f77215 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/AbstractArrowAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/AbstractArrowAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.projectile; +package org.spongepowered.common.accessor.world.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ArrowAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/ArrowAccessor.java similarity index 96% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ArrowAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/ArrowAccessor.java index 7e197ba4819..a8b2151b4d6 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/ArrowAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/projectile/arrow/ArrowAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.projectile; +package org.spongepowered.common.accessor.world.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.Arrow; +import net.minecraft.world.entity.projectile.arrow.Arrow; import net.minecraft.world.item.alchemy.PotionContents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/boat/AbstractBoatAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/boat/AbstractBoatAccessor.java index 36f4de0698a..21008dca1ce 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/AbstractBoatAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/boat/AbstractBoatAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.vehicle; +package org.spongepowered.common.accessor.world.entity.vehicle.boat; -import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/MinecartFurnaceAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/minecart/MinecartFurnaceAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/MinecartFurnaceAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/minecart/MinecartFurnaceAccessor.java index 12dbc06a13e..b60733608e3 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/MinecartFurnaceAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/vehicle/minecart/MinecartFurnaceAccessor.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity.vehicle; +package org.spongepowered.common.accessor.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.entity.vehicle.minecart.MinecartFurnace; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index ab6f9cd2478..f2abde481fd 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -18,8 +18,8 @@ "commands.arguments.selector.options.EntitySelectorOptionsAccessor", "core.MappedRegistryAccessor", "entity.animal.frog.FrogAccessor", - "entity.passive.AbstractChestedHorseEntityAccessor", - "entity.vehicle.AbstractMinecartAccessor", + "entity.animal.equine.AbstractChestedHorseEntityAccessor", + "entity.vehicle.minecart.AbstractMinecartAccessor", "network.ConnectionAccessor", "network.chat.StyleAccessor", "network.protocol.game.ClientboundAddEntityPacketAccessor", @@ -75,22 +75,22 @@ "world.entity.PortalProcessorAccessor", "world.entity.ai.targeting.TargetingConditionsAccessor", "world.entity.animal.AnimalAccessor", - "world.entity.animal.CatAccessor", - "world.entity.animal.FoxAccessor", - "world.entity.animal.MooshroomAccessor", - "world.entity.animal.OcelotAccessor", - "world.entity.animal.PandaAccessor", - "world.entity.animal.ParrotAccessor", - "world.entity.animal.PigAccessor", - "world.entity.animal.PufferfishAccessor", - "world.entity.animal.RabbitAccessor", - "world.entity.animal.TropicalFishAccessor", - "world.entity.animal.TurtleAccessor", + "world.entity.animal.feline.CatAccessor", + "world.entity.animal.fox.FoxAccessor", + "world.entity.animal.cow.MooshroomAccessor", + "world.entity.animal.feline.OcelotAccessor", + "world.entity.animal.panda.PandaAccessor", + "world.entity.animal.parrot.ParrotAccessor", + "world.entity.animal.pig.PigAccessor", + "world.entity.animal.fish.PufferfishAccessor", + "world.entity.animal.rabbit.RabbitAccessor", + "world.entity.animal.fish.TropicalFishAccessor", + "world.entity.animal.turtle.TurtleAccessor", "world.entity.animal.frog.TadpoleAccessor", - "world.entity.animal.horse.AbstractHorseAccessor", - "world.entity.animal.horse.HorseAccessor", - "world.entity.animal.horse.LlamaAccessor", - "world.entity.animal.horse.TraderLlamaAccessor", + "world.entity.animal.equine.AbstractHorseAccessor", + "world.entity.animal.equine.HorseAccessor", + "world.entity.animal.equine.LlamaAccessor", + "world.entity.animal.equine.TraderLlamaAccessor", "world.entity.animal.sheep.SheepAccessor", "world.entity.animal.wolf.WolfAccessor", "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", @@ -98,29 +98,29 @@ "world.entity.decoration.ArmorStandAccessor", "world.entity.decoration.HangingEntityAccessor", "world.entity.decoration.ItemFrameAccessor", - "world.entity.decoration.PaintingAccessor", + "world.entity.decoration.painting.PaintingAccessor", "world.entity.item.FallingBlockEntityAccessor", "world.entity.item.PrimedTntAccessor", "world.entity.monster.BlazeAccessor", "world.entity.monster.CreeperAccessor", "world.entity.monster.EnderManAccessor", "world.entity.monster.EndermiteAccessor", - "world.entity.monster.EvokerAccessor", + "world.entity.monster.illager.EvokerAccessor", "world.entity.monster.GuardianAccessor", "world.entity.monster.PatrollingMonsterAccessor", "world.entity.monster.PhantomAccessor", - "world.entity.monster.PillagerAccessor", + "world.entity.monster.illager.PillagerAccessor", "world.entity.monster.RavagerAccessor", "world.entity.monster.SlimeAccessor", - "world.entity.monster.SpellcasterIllagerAccessor", + "world.entity.monster.illager.SpellcasterIllagerAccessor", "world.entity.monster.VexAccessor", - "world.entity.monster.VindicatorAccessor", - "world.entity.monster.ZombifiedPiglinAccessor", - "world.entity.npc.AbstractVillagerAccessor", + "world.entity.monster.illager.VindicatorAccessor", + "world.entity.monster.zombie.ZombifiedPiglinAccessor", + "world.entity.npc.villager.AbstractVillagerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", - "world.entity.projectile.AbstractArrowAccessor", - "world.entity.projectile.ArrowAccessor", + "world.entity.projectile.arrow.AbstractArrowAccessor", + "world.entity.projectile.arrow.ArrowAccessor", "world.entity.projectile.EyeOfEnderAccessor", "world.entity.projectile.FireworkRocketEntityAccessor", "world.entity.projectile.FishingHookAccessor", @@ -128,8 +128,8 @@ "world.entity.raid.RaidAccessor", "world.entity.raid.RaiderAccessor", "world.entity.raid.RaidsAccessor", - "world.entity.vehicle.AbstractBoatAccessor", - "world.entity.vehicle.MinecartFurnaceAccessor", + "world.entity.vehicle.boat.AbstractBoatAccessor", + "world.entity.vehicle.minecart.MinecartFurnaceAccessor", "world.food.FoodDataAccessor", "world.inventory.AbstractContainerMenuAccessor", "world.inventory.AbstractCraftingMenuAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java index df9f20c0230..da8e6203e2b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractArrowData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.PickupRule; -import org.spongepowered.common.accessor.world.entity.projectile.AbstractArrowAccessor; +import org.spongepowered.common.accessor.world.entity.projectile.arrow.AbstractArrowAccessor; import org.spongepowered.common.bridge.world.entity.projectile.AbstractArrowBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractChestedHorseData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractChestedHorseData.java index 58958516445..ee091a26e54 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractChestedHorseData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractChestedHorseData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.animal.equine.AbstractChestedHorse; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java index 4576e7471f5..96b72955d2f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractHorseData.java @@ -25,9 +25,9 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.world.entity.EntityReference; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.animal.horse.AbstractHorseAccessor; +import org.spongepowered.common.accessor.world.entity.animal.equine.AbstractHorseAccessor; import org.spongepowered.common.bridge.world.entity.animal.horse.AbstractHorseBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java index da6a08db815..64d14454958 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractMinecartData.java @@ -26,12 +26,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.tags.BlockTags; -import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.persistence.DataContentUpdater; -import org.spongepowered.common.accessor.entity.vehicle.AbstractMinecartAccessor; +import org.spongepowered.common.accessor.entity.vehicle.minecart.AbstractMinecartAccessor; import org.spongepowered.common.bridge.world.entity.vehicle.AbstractMinecartBridge; import org.spongepowered.common.data.ByteToBooleanContentUpdater; import org.spongepowered.common.data.SpongeDataManager; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractVillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractVillagerData.java index 52735629ee3..2befbf97419 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AbstractVillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AbstractVillagerData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java index d10b56dbd69..f16ecd6df2e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ArrowData.java @@ -25,13 +25,13 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.projectile.Arrow; +import net.minecraft.world.entity.projectile.arrow.Arrow; import net.minecraft.world.item.alchemy.PotionContents; import org.apache.commons.lang3.stream.Streams; import org.jetbrains.annotations.NotNull; import org.spongepowered.api.data.Keys; import org.spongepowered.api.effect.potion.PotionEffect; -import org.spongepowered.common.accessor.world.entity.projectile.ArrowAccessor; +import org.spongepowered.common.accessor.world.entity.projectile.arrow.ArrowAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import java.util.List; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java index f5146dd7d27..df9d50fb6a9 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/BoatData.java @@ -24,12 +24,12 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.vehicle.AbstractBoat; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.Boat; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.persistence.DataContentUpdater; -import org.spongepowered.common.accessor.world.entity.vehicle.AbstractBoatAccessor; +import org.spongepowered.common.accessor.world.entity.vehicle.boat.AbstractBoatAccessor; import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; import org.spongepowered.common.data.ByteToBooleanContentUpdater; import org.spongepowered.common.data.SpongeDataManager; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java index b8b0442bc8d..cac638ca49b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java @@ -25,12 +25,12 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.Holder; -import net.minecraft.world.entity.animal.Cat; -import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.feline.Cat; +import net.minecraft.world.entity.animal.feline.CatVariant; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.CatType; import org.spongepowered.api.data.type.DyeColor; -import org.spongepowered.common.accessor.world.entity.animal.CatAccessor; +import org.spongepowered.common.accessor.world.entity.animal.feline.CatAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.MissingImplementationException; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java index ddfe38d8e2f..5289fbef991 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.registries.Registries; -import net.minecraft.world.entity.animal.Chicken; +import net.minecraft.world.entity.animal.chicken.Chicken; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ChickenVariant; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (ChickenVariant) (Object) h.getVariant().value()) .set((h, v) -> { final var holder = h.level().registryAccess().lookupOrThrow(Registries.CHICKEN_VARIANT) - .wrapAsHolder((net.minecraft.world.entity.animal.ChickenVariant) (Object) v); + .wrapAsHolder((net.minecraft.world.entity.animal.chicken.ChickenVariant) (Object) v); h.setVariant(holder); }); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CommandBlockMinecartData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CommandBlockMinecartData.java index ee00c87f8a6..1065855f7e8 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CommandBlockMinecartData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CommandBlockMinecartData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import org.spongepowered.api.data.Keys; import org.spongepowered.common.accessor.world.level.BaseCommandBlockAccessor; import org.spongepowered.common.adventure.SpongeAdventure; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java index a86cfcaf9d4..017f734d8b9 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CowData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.registries.Registries; -import net.minecraft.world.entity.animal.Cow; +import net.minecraft.world.entity.animal.cow.Cow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.CowVariant; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -43,7 +43,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (CowVariant) (Object) h.getVariant().value()) .set((h, v) -> { final var holder = h.level().registryAccess().lookupOrThrow(Registries.COW_VARIANT) - .wrapAsHolder((net.minecraft.world.entity.animal.CowVariant) (Object) v); + .wrapAsHolder((net.minecraft.world.entity.animal.cow.CowVariant) (Object) v); h.setVariant(holder); }); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/DamagingProjectileData.java b/src/main/java/org/spongepowered/common/data/provider/entity/DamagingProjectileData.java index 637e43bf59b..3ee14260859 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/DamagingProjectileData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/DamagingProjectileData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/DolphinData.java b/src/main/java/org/spongepowered/common/data/provider/entity/DolphinData.java index be838cdebb3..4a5aa9d00a2 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/DolphinData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/DolphinData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Dolphin; +import net.minecraft.world.entity.animal.dolphin.Dolphin; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java index 50ba45c0ba3..050aa8e4cc6 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EvokerData.java @@ -26,7 +26,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.living.animal.Sheep; -import org.spongepowered.common.accessor.world.entity.monster.EvokerAccessor; +import org.spongepowered.common.accessor.world.entity.monster.illager.EvokerAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class EvokerData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java index 1325ffea14b..163203e22ed 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FoxData.java @@ -25,10 +25,10 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.world.entity.EntityReference; -import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.fox.Fox; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.FoxType; -import org.spongepowered.common.accessor.world.entity.animal.FoxAccessor; +import org.spongepowered.common.accessor.world.entity.animal.fox.FoxAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import java.util.Optional; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/FurnaceMinecartData.java b/src/main/java/org/spongepowered/common/data/provider/entity/FurnaceMinecartData.java index c0b85677851..dc257ecd559 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/FurnaceMinecartData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/FurnaceMinecartData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.vehicle.MinecartFurnaceAccessor; +import org.spongepowered.common.accessor.world.entity.vehicle.minecart.MinecartFurnaceAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class FurnaceMinecartData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/HorseData.java b/src/main/java/org/spongepowered/common/data/provider/entity/HorseData.java index 2f40374ac79..38a8585dadb 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/HorseData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/HorseData.java @@ -25,13 +25,13 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.MappedRegistry; -import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.animal.equine.Horse; import org.spongepowered.api.Sponge; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.HorseColor; import org.spongepowered.api.data.type.HorseStyle; import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.common.accessor.world.entity.animal.horse.HorseAccessor; +import org.spongepowered.common.accessor.world.entity.animal.equine.HorseAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class HorseData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/IronGolemData.java b/src/main/java/org/spongepowered/common/data/provider/entity/IronGolemData.java index 53441f770ff..83f3a585789 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/IronGolemData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/IronGolemData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.animal.golem.IronGolem; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java b/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java index 9ef0758d1ca..21245664a2d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/LlamaData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.animal.equine.Llama; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.LlamaType; -import org.spongepowered.common.accessor.world.entity.animal.horse.LlamaAccessor; +import org.spongepowered.common.accessor.world.entity.animal.equine.LlamaAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class LlamaData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java index e340e1f6774..e9cb7e00fa0 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/MooshroomData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.animal.cow.MushroomCow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.MooshroomType; -import org.spongepowered.common.accessor.world.entity.animal.MooshroomAccessor; +import org.spongepowered.common.accessor.world.entity.animal.cow.MooshroomAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class MooshroomData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/OcelotData.java b/src/main/java/org/spongepowered/common/data/provider/entity/OcelotData.java index 636404e2d3a..361b5167a1f 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/OcelotData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/OcelotData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.animal.OcelotAccessor; +import org.spongepowered.common.accessor.world.entity.animal.feline.OcelotAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class OcelotData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java index 33b1260e63a..e8e1fce95e8 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PaintingData.java @@ -29,15 +29,15 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerPlayerConnection; -import net.minecraft.world.entity.decoration.Painting; -import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.decoration.painting.Painting; +import net.minecraft.world.entity.decoration.painting.PaintingVariant; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ArtType; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.level.ChunkMapAccessor; import org.spongepowered.common.accessor.server.level.ChunkMap_TrackedEntityAccessor; import org.spongepowered.common.accessor.world.entity.decoration.HangingEntityAccessor; -import org.spongepowered.common.accessor.world.entity.decoration.PaintingAccessor; +import org.spongepowered.common.accessor.world.entity.decoration.painting.PaintingAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class PaintingData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PandaData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PandaData.java index 108618c2361..ebc827147ff 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PandaData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PandaData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.panda.Panda; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.PandaGene; -import org.spongepowered.common.accessor.world.entity.animal.PandaAccessor; +import org.spongepowered.common.accessor.world.entity.animal.panda.PandaAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.SpongeTicks; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java index b3b80751a6d..7c88008a879 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ParrotData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Parrot; +import net.minecraft.world.entity.animal.parrot.Parrot; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ParrotType; -import org.spongepowered.common.accessor.world.entity.animal.ParrotAccessor; +import org.spongepowered.common.accessor.world.entity.animal.parrot.ParrotAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class ParrotData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java index 539849f5758..c95735b4a19 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java @@ -26,13 +26,13 @@ import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.animal.Pig; -import net.minecraft.world.entity.animal.PigVariant; +import net.minecraft.world.entity.animal.pig.Pig; +import net.minecraft.world.entity.animal.pig.PigVariant; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.PigType; -import org.spongepowered.common.accessor.world.entity.animal.PigAccessor; +import org.spongepowered.common.accessor.world.entity.animal.pig.PigAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class PigData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PillagerData.java index 63165c7b34d..8976d5740be 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PillagerData.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.monster.Pillager; +import net.minecraft.world.entity.monster.illager.Pillager; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.PillagerAccessor; +import org.spongepowered.common.accessor.world.entity.monster.illager.PillagerAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class PillagerData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PolarBearData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PolarBearData.java index 3bdbffef841..095dc447729 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PolarBearData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PolarBearData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.PolarBear; +import net.minecraft.world.entity.animal.polarbear.PolarBear; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java index b800abdf95d..f0f35429966 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PotionData.java @@ -26,7 +26,7 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.projectile.AbstractThrownPotion; +import net.minecraft.world.entity.projectile.throwableitemprojectile.AbstractThrownPotion; import net.minecraft.world.item.alchemy.PotionContents; import org.apache.commons.lang3.stream.Streams; import org.spongepowered.api.data.Keys; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java index a637ed6ce87..2fa89155b3b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PufferfishData.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.fish.Pufferfish; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.animal.PufferfishAccessor; +import org.spongepowered.common.accessor.world.entity.animal.fish.PufferfishAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class PufferfishData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java b/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java index ddf8e108a5d..54ee3619aca 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/RabbitData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.rabbit.Rabbit; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.RabbitType; -import org.spongepowered.common.accessor.world.entity.animal.RabbitAccessor; +import org.spongepowered.common.accessor.world.entity.animal.rabbit.RabbitAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class RabbitData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java index bbb56f00e43..2e55974f395 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SalmonData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.component.DataComponents; -import net.minecraft.world.entity.animal.Salmon; +import net.minecraft.world.entity.animal.fish.Salmon; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SpellcastingIllagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SpellcastingIllagerData.java index 6cad9021fe5..8f515a26359 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/SpellcastingIllagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SpellcastingIllagerData.java @@ -24,10 +24,10 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.SpellType; -import org.spongepowered.common.accessor.world.entity.monster.SpellcasterIllagerAccessor; +import org.spongepowered.common.accessor.world.entity.monster.illager.SpellcasterIllagerAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class SpellcastingIllagerData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SpiderData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SpiderData.java index c66df4b8cf4..871ae19ed64 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/SpiderData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SpiderData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.monster.Spider; +import net.minecraft.world.entity.monster.spider.Spider; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ThrowableItemProjectileData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ThrowableItemProjectileData.java index 605b675f489..6e140cd74b6 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ThrowableItemProjectileData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ThrowableItemProjectileData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.projectile.ThrowableItemProjectile; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrowableItemProjectile; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.item.util.ItemStackUtil; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TraderLlamaData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TraderLlamaData.java index 79bfc39773f..05b2b1c43b5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TraderLlamaData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TraderLlamaData.java @@ -28,7 +28,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.util.Ticks; import org.spongepowered.common.accessor.world.entity.MobAccessor; -import org.spongepowered.common.accessor.world.entity.animal.horse.TraderLlamaAccessor; +import org.spongepowered.common.accessor.world.entity.animal.equine.TraderLlamaAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.SpongeTicks; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java index 204556b1a10..5ec5bf46e69 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TropicalFishData.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.fish.TropicalFish; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; import org.spongepowered.api.data.type.TropicalFishShape; -import org.spongepowered.common.accessor.world.entity.animal.TropicalFishAccessor; +import org.spongepowered.common.accessor.world.entity.animal.fish.TropicalFishAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class TropicalFishData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java b/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java index 8a9f62cca76..8a969650f69 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/TurtleData.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.animal.Turtle; +import net.minecraft.world.entity.animal.turtle.Turtle; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.animal.TurtleAccessor; +import org.spongepowered.common.accessor.world.entity.animal.turtle.TurtleAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.VecHelper; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java index cc7a7f11909..071ac8731bc 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java @@ -25,9 +25,9 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.registries.Registries; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.entity.npc.WanderingTrader; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.entity.npc.villager.VillagerProfession; +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.item.trading.MerchantOffers; import org.spongepowered.api.data.Keys; @@ -35,7 +35,7 @@ import org.spongepowered.api.data.type.VillagerType; import org.spongepowered.api.item.merchant.TradeOffer; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.world.entity.npc.AbstractVillagerAccessor; +import org.spongepowered.common.accessor.world.entity.npc.villager.AbstractVillagerAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.SpongeTicks; @@ -80,7 +80,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (VillagerType) (Object) h.getVillagerData().type()) .set((h, v) -> { final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE) - .wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); + .wrapAsHolder((net.minecraft.world.entity.npc.villager.VillagerType) (Object) v); h.setVillagerData(h.getVillagerData().withType(villagerType)); }) .create(Keys.IS_UNHAPPY) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VindicatorData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VindicatorData.java index 4c442dfaa6b..7ad33e0f335 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VindicatorData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VindicatorData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.VindicatorAccessor; +import org.spongepowered.common.accessor.world.entity.monster.illager.VindicatorAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class VindicatorData { diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieData.java index 713841f069c..1b4d42c074e 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.monster.zombie.Zombie; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java index 990da40d732..6315e33ca84 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java @@ -25,8 +25,8 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.registries.Registries; -import net.minecraft.world.entity.monster.ZombieVillager; -import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.monster.zombie.ZombieVillager; +import net.minecraft.world.entity.npc.villager.VillagerProfession; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ProfessionType; import org.spongepowered.api.data.type.VillagerType; @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.VILLAGER_TYPE) .get(h -> (VillagerType) (Object) h.getVillagerData().type()) .set((h, v) -> { - final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE).wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); + final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE).wrapAsHolder((net.minecraft.world.entity.npc.villager.VillagerType) (Object) v); h.setVillagerData(h.getVillagerData().withType(villagerType)); }); } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java index 5f188d08b21..292afe3a555 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombifiedPiglinData.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.provider.entity; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.ZombifiedPiglinAccessor; +import org.spongepowered.common.accessor.world.entity.monster.zombie.ZombifiedPiglinAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; import java.util.SplittableRandom; diff --git a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java index e25b188ab68..8d5fa86f272 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/biome/BiomeData.java @@ -115,12 +115,12 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.BACKGROUND_MUSIC) .get(h -> { final var value = h.getAttributes().applyModifier(EnvironmentAttributes.BACKGROUND_MUSIC, EnvironmentAttributes.BACKGROUND_MUSIC.defaultValue()); - return (SoundConfig.BackgroundMusic) (Object) value; + return (SoundConfig.BackgroundMusic) (Object) value.defaultMusic().orElse(null); }) .create(Keys.AMBIENT_ADDITIONAL_SOUND) .get(h -> { final var value = h.getAttributes().applyModifier(EnvironmentAttributes.AMBIENT_SOUNDS, EnvironmentAttributes.AMBIENT_SOUNDS.defaultValue()); - return (SoundConfig.Additional) (Object) value; + return (SoundConfig.Additional) (Object) value.additions().stream().findFirst().orElse(null); }) .create(Keys.AMBIENT_MOOD) .get(h -> h.getAttributes().applyModifier(EnvironmentAttributes.AMBIENT_SOUNDS, AmbientSounds.EMPTY).mood().map(SoundConfig.Mood.class::cast).orElse(null)) diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java index 823a3e268d8..fe9da7ba032 100644 --- a/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/data/type/SpongeArtTypeBuilder.java @@ -25,7 +25,7 @@ package org.spongepowered.common.data.type; import net.minecraft.resources.Identifier; -import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.decoration.painting.PaintingVariant; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.type.ArtType; diff --git a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/horse/SpongeRunAroundLikeCrazyAIBuilder.java b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/horse/SpongeRunAroundLikeCrazyAIBuilder.java index c4e1bcd75af..a024c9fd3fa 100644 --- a/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/horse/SpongeRunAroundLikeCrazyAIBuilder.java +++ b/src/main/java/org/spongepowered/common/entity/ai/goal/builtin/creature/horse/SpongeRunAroundLikeCrazyAIBuilder.java @@ -60,6 +60,6 @@ public RunAroundLikeCrazyGoal.Builder reset() { @Override public RunAroundLikeCrazyGoal build(HorseLike owner) { Objects.requireNonNull(owner); - return (RunAroundLikeCrazyGoal) new net.minecraft.world.entity.ai.goal.RunAroundLikeCrazyGoal((net.minecraft.world.entity.animal.horse.Horse) owner, this.speed); + return (RunAroundLikeCrazyGoal) new net.minecraft.world.entity.ai.goal.RunAroundLikeCrazyGoal((net.minecraft.world.entity.animal.equine.Horse) owner, this.speed); } } diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index e0922d877b2..1e562c7e0d6 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -66,7 +66,7 @@ import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; import net.minecraft.world.entity.monster.RangedAttackMob; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.Arrow; +import net.minecraft.world.entity.projectile.arrow.Arrow; import net.minecraft.world.item.ArrowItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; diff --git a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java index ac10e3be464..653feb40438 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java @@ -28,18 +28,18 @@ import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.animal.equine.Llama; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; import net.minecraft.world.entity.projectile.ThrowableProjectile; -import net.minecraft.world.entity.projectile.ThrownEgg; -import net.minecraft.world.entity.projectile.ThrownEnderpearl; -import net.minecraft.world.entity.projectile.ThrownExperienceBottle; -import net.minecraft.world.entity.projectile.ThrownLingeringPotion; -import net.minecraft.world.entity.projectile.ThrownSplashPotion; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEgg; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearl; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownExperienceBottle; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownLingeringPotion; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownSplashPotion; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.entity.DispenserBlockEntity; @@ -179,7 +179,7 @@ static

Optional

doLaunch(final World extent, final P p @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final var arrow = new net.minecraft.world.entity.projectile.Arrow(source.level(), source, new ItemStack(this.item), source.getWeaponItem()); + final var arrow = new net.minecraft.world.entity.projectile.arrow.Arrow(source.level(), source, new ItemStack(this.item), source.getWeaponItem()); arrow.shoot(source.getXRot(), source.getYRot(), 0.0F, 3.0F, 0); return ProjectileUtil.doLaunch(loc.world(), (Arrow) arrow); } @@ -189,7 +189,7 @@ protected Optional createProjectile(final LivingEntity source, final Serv @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final var arrow = new net.minecraft.world.entity.projectile.SpectralArrow(source.level(), source, new ItemStack(this.item), source.getWeaponItem()); + final var arrow = new net.minecraft.world.entity.projectile.arrow.SpectralArrow(source.level(), source, new ItemStack(this.item), source.getWeaponItem()); arrow.shoot(source.getXRot(), source.getYRot(), 0.0F, 3.0F, 0); return ProjectileUtil.doLaunch(loc.world(), (SpectralArrow) arrow); } @@ -209,7 +209,7 @@ protected Optional createProjectile(final LivingEntity source, final Server @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { final net.minecraft.world.phys.Vec3 lookVec = source.getViewVector(1); - final var fireball = new net.minecraft.world.entity.projectile.SmallFireball(source.level(), source, lookVec.scale(4)); + final var fireball = new net.minecraft.world.entity.projectile.hurtingprojectile.SmallFireball(source.level(), source, lookVec.scale(4)); fireball.setPos(fireball.getX(), fireball.getY() + source.getEyeHeight(), fireball.getZ()); return ProjectileUtil.doLaunch(loc.world(), (SmallFireball) fireball); } @@ -227,7 +227,7 @@ protected Optional createProjectile(final LivingEntity source, f @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { - final net.minecraft.world.entity.projectile.Snowball snowball = new net.minecraft.world.entity.projectile.Snowball( + final var snowball = new net.minecraft.world.entity.projectile.throwableitemprojectile.Snowball( source.level(), source, new ItemStack(Items.SNOWBALL)); snowball.shoot(source.getXRot(), source.getYRot(), 0.0F, 1.5F, 0); return ProjectileUtil.doLaunch(loc.world(), (Snowball) snowball); @@ -285,7 +285,7 @@ public Optional createProjectile(final ProjectileSource sourc @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { final net.minecraft.world.phys.Vec3 lookVec = source.getViewVector(1); - final var skull = new net.minecraft.world.entity.projectile.WitherSkull(source.level(), source, lookVec.scale(4)); + final var skull = new net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull(source.level(), source, lookVec.scale(4)); skull.setPos(skull.getX(), skull.getY() + source.getEyeHeight(), skull.getZ()); return ProjectileUtil.doLaunch(loc.world(), (WitherSkull) skull); } @@ -350,7 +350,7 @@ public Optional createProjectile(final ProjectileSource source, @Override protected Optional createProjectile(final LivingEntity source, final ServerLocation loc) { final net.minecraft.world.phys.Vec3 lookVec = source.getViewVector(1); - final var fireball = new net.minecraft.world.entity.projectile.DragonFireball(source.level(), source, lookVec.scale(4)); + final var fireball = new net.minecraft.world.entity.projectile.hurtingprojectile.DragonFireball(source.level(), source, lookVec.scale(4)); fireball.setPos(fireball.getX(), fireball.getY() + source.getEyeHeight(), fireball.getZ()); return ProjectileUtil.doLaunch(loc.world(), (DragonFireball) fireball); } diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index fde99c753bf..4808d06264a 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -31,10 +31,10 @@ import net.minecraft.world.MenuProvider; import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.WanderingTrader; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 9013c2e40b7..c3c1ffe64fd 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -39,7 +39,7 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.animal.equine.AbstractChestedHorse; import net.minecraft.world.entity.animal.sheep.Sheep; import net.minecraft.world.entity.animal.wolf.Wolf; import net.minecraft.world.entity.player.Inventory; @@ -61,7 +61,7 @@ import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.inventory.transaction.SlotTransaction; -import org.spongepowered.common.accessor.entity.passive.AbstractChestedHorseEntityAccessor; +import org.spongepowered.common.accessor.entity.animal.equine.AbstractChestedHorseEntityAccessor; import org.spongepowered.common.accessor.network.protocol.game.ServerboundMovePlayerPacketAccessor; import org.spongepowered.common.accessor.world.entity.EntityAccessor; import org.spongepowered.common.accessor.world.entity.animal.sheep.SheepAccessor; diff --git a/src/main/java/org/spongepowered/common/hooks/EntityHooks.java b/src/main/java/org/spongepowered/common/hooks/EntityHooks.java index 471609a73b9..8b600f5147f 100644 --- a/src/main/java/org/spongepowered/common/hooks/EntityHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/EntityHooks.java @@ -25,7 +25,7 @@ package org.spongepowered.common.hooks; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.boss.EnderDragonPart; +import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; public interface EntityHooks { diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java index 00455d01cda..479c408fa4b 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java @@ -26,8 +26,8 @@ import net.minecraft.world.Container; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.animal.equine.AbstractHorse; +import net.minecraft.world.entity.npc.villager.Villager; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; diff --git a/src/main/java/org/spongepowered/common/inventory/lens/impl/LensRegistrar.java b/src/main/java/org/spongepowered/common/inventory/lens/impl/LensRegistrar.java index 6a9b485b44f..e3822ac0ea5 100644 --- a/src/main/java/org/spongepowered/common/inventory/lens/impl/LensRegistrar.java +++ b/src/main/java/org/spongepowered/common/inventory/lens/impl/LensRegistrar.java @@ -27,10 +27,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.world.CompoundContainer; -import net.minecraft.world.entity.npc.AbstractVillager; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.WanderingTrader; -import net.minecraft.world.entity.vehicle.MinecartChest; +import net.minecraft.world.entity.npc.villager.AbstractVillager; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader; +import net.minecraft.world.entity.vehicle.minecart.MinecartChest; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.CraftingContainer; diff --git a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java index 916b7f1dfee..1f84b336cef 100644 --- a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java +++ b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java @@ -27,7 +27,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.VillagerTrades; +import net.minecraft.world.entity.npc.villager.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; import org.spongepowered.api.item.merchant.TradeOffer; import org.spongepowered.api.item.merchant.TradeOfferGenerator; diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 59bb0878af7..d794771f31e 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -40,22 +40,22 @@ import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.animal.Fox; -import net.minecraft.world.entity.animal.MushroomCow; -import net.minecraft.world.entity.animal.Panda; -import net.minecraft.world.entity.animal.Parrot; -import net.minecraft.world.entity.animal.Rabbit; -import net.minecraft.world.entity.animal.Salmon; -import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.fox.Fox; +import net.minecraft.world.entity.animal.cow.MushroomCow; +import net.minecraft.world.entity.animal.panda.Panda; +import net.minecraft.world.entity.animal.parrot.Parrot; +import net.minecraft.world.entity.animal.rabbit.Rabbit; +import net.minecraft.world.entity.animal.fish.Salmon; +import net.minecraft.world.entity.animal.fish.TropicalFish; import net.minecraft.world.entity.animal.axolotl.Axolotl; -import net.minecraft.world.entity.animal.horse.Llama; -import net.minecraft.world.entity.animal.horse.Markings; -import net.minecraft.world.entity.animal.horse.Variant; +import net.minecraft.world.entity.animal.equine.Llama; +import net.minecraft.world.entity.animal.equine.Markings; +import net.minecraft.world.entity.animal.equine.Variant; import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; import net.minecraft.world.entity.monster.Phantom; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import net.minecraft.world.entity.player.ChatVisiblity; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import net.minecraft.world.entity.raid.Raid; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemDisplayContext; diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 4d34b4b0199..1374024d73b 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -45,7 +45,7 @@ import net.minecraft.util.Util; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; -import net.minecraft.world.entity.npc.WanderingTraderSpawner; +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.Level; diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index ab0f0901043..fcfa8e442b0 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -19,4 +19,5 @@ accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$A accessible class net/minecraft/world/entity/monster/SpellcasterIllager$IllagerSpell accessible class net/minecraft/world/level/biome/Biome$ClimateSettings accessible class net/minecraft/core/MappedRegistry$TagSet -accessible class net/minecraft/world/level/BaseCommandBlock$CloseableCommandBlockSource \ No newline at end of file +accessible class net/minecraft/world/level/BaseCommandBlock$CloseableCommandBlockSource +accessible class net/minecraft/world/entity/monster/illager/SpellcasterIllager$IllagerSpell diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/SaddleableMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/SaddleableMixin_API.java index 02a39854d39..78599dd577f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/SaddleableMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/SaddleableMixin_API.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity; import net.minecraft.world.entity.ItemSteerable; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.asm.mixin.Mixin; // TODO - the interface is gone, but the premise of being able to use the saddle diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/BeeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/bee/BeeMixin_API.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/BeeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/bee/BeeMixin_API.java index 6240a3fb372..1ba919e52be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/BeeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/bee/BeeMixin_API.java @@ -22,12 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.bee; import org.spongepowered.api.entity.living.animal.Bee; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; -@Mixin(net.minecraft.world.entity.animal.Bee.class) +@Mixin(net.minecraft.world.entity.animal.bee.Bee.class) public abstract class BeeMixin_API extends AnimalMixin_API implements Bee { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java index 6bd2c701383..a4d4a4ddfb2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/camel/CamelMixin_API.java @@ -26,7 +26,7 @@ import net.minecraft.world.entity.animal.camel.Camel; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse.AbstractHorseMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine.AbstractHorseMixin_API; @Mixin(Camel.class) public abstract class CamelMixin_API extends AbstractHorseMixin_API implements org.spongepowered.api.entity.living.animal.camel.Camel { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenMixin_API.java index f118e88bf8c..6c6d746ded8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.chicken; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Chicken; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Chicken.class) +@Mixin(net.minecraft.world.entity.animal.chicken.Chicken.class) public abstract class ChickenMixin_API extends AnimalMixin_API implements Chicken { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenVariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenVariantMixin_API.java index deded3ad5d8..22f67fd08dd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ChickenVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/chicken/ChickenVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.chicken; -import net.minecraft.world.entity.animal.ChickenVariant; +import net.minecraft.world.entity.animal.chicken.ChickenVariant; import org.spongepowered.asm.mixin.Mixin; @Mixin(ChickenVariant.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractCowMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/AbstractCowMixin_API.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractCowMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/AbstractCowMixin_API.java index fe2a7abd0a9..5177b50a11e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractCowMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/AbstractCowMixin_API.java @@ -22,12 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.cow; import org.spongepowered.api.entity.living.animal.cow.Cow; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; -@Mixin(net.minecraft.world.entity.animal.AbstractCow.class) +@Mixin(net.minecraft.world.entity.animal.cow.AbstractCow.class) public abstract class AbstractCowMixin_API extends AnimalMixin_API implements Cow { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/CowVariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/CowVariantMixin_API.java index 3b1c66dadec..bd48197db3a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CowVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/CowVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.cow; -import net.minecraft.world.entity.animal.CowVariant; +import net.minecraft.world.entity.animal.cow.CowVariant; import org.spongepowered.asm.mixin.Mixin; @Mixin(CowVariant.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCowMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCowMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCowMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCowMixin_API.java index 5eb015f2ca3..7acf88dae03 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCowMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCowMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.cow; -import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.animal.cow.MushroomCow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.cow.Mooshroom; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCow_MushroomTypeMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCow_MushroomTypeMixin_API.java index d9c14c85fb8..7cc2ed7cd13 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/MushroomCow_MushroomTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/cow/MushroomCow_MushroomTypeMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.cow; -import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.animal.cow.MushroomCow; import org.spongepowered.api.data.type.MooshroomType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/dolphin/DolphinMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/dolphin/DolphinMixin_API.java index 2cd310baace..913c2e43aad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/DolphinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/dolphin/DolphinMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.dolphin; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.aquatic.Dolphin; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AgeableWaterCreatureMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Dolphin.class) +@Mixin(net.minecraft.world.entity.animal.dolphin.Dolphin.class) public abstract class DolphinMixin_API extends AgeableWaterCreatureMixin_API implements Dolphin { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractChestedHorseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractChestedHorseMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractChestedHorseMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractChestedHorseMixin_API.java index bcfa475021b..d01a3c75354 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractChestedHorseMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractChestedHorseMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; -import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; +import net.minecraft.world.entity.animal.equine.AbstractChestedHorse; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.horse.PackHorse; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractHorseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractHorseMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractHorseMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractHorseMixin_API.java index 40361de0a52..928067e27ac 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/AbstractHorseMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/AbstractHorseMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.horse.HorseLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/DonkeyMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/DonkeyMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/DonkeyMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/DonkeyMixin_API.java index 91ea7ac9fde..dcc5844e28c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/DonkeyMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/DonkeyMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.entity.living.animal.horse.Donkey; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.Donkey.class) +@Mixin(net.minecraft.world.entity.animal.equine.Donkey.class) public abstract class DonkeyMixin_API extends AbstractChestedHorseMixin_API implements Donkey { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/HorseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/HorseMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/HorseMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/HorseMixin_API.java index a2c8b02512b..a0f8c98e931 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/HorseMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/HorseMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.horse.Horse.class) +@Mixin(net.minecraft.world.entity.animal.equine.Horse.class) public abstract class HorseMixin_API extends AbstractHorseMixin_API implements Horse { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LLama_VariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LLama_VariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LLama_VariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LLama_VariantMixin_API.java index 4eecb60c0db..358d10d77d1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LLama_VariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LLama_VariantMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.type.LlamaType; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.Llama.Variant.class) +@Mixin(net.minecraft.world.entity.animal.equine.Llama.Variant.class) public abstract class LLama_VariantMixin_API implements LlamaType { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LlamaMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LlamaMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LlamaMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LlamaMixin_API.java index 8d4a0ad8d70..23043e38db9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/LlamaMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/LlamaMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.horse.Llama.class) +@Mixin(net.minecraft.world.entity.animal.equine.Llama.class) public abstract class LlamaMixin_API extends AbstractChestedHorseMixin_API implements Llama { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MarkingsMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MarkingsMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MarkingsMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MarkingsMixin_API.java index 94b206d3e46..34d0c42a4d4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MarkingsMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MarkingsMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.type.HorseStyle; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.Markings.class) +@Mixin(net.minecraft.world.entity.animal.equine.Markings.class) public abstract class MarkingsMixin_API implements HorseStyle { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MuleMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MuleMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MuleMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MuleMixin_API.java index 1e353d79fa3..a9b64f76717 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/MuleMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/MuleMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.entity.living.animal.horse.Mule; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.Mule.class) +@Mixin(net.minecraft.world.entity.animal.equine.Mule.class) public abstract class MuleMixin_API extends AbstractChestedHorseMixin_API implements Mule { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/SkeletonHorseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/SkeletonHorseMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/SkeletonHorseMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/SkeletonHorseMixin_API.java index 200470d74e1..ae45c84d937 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/SkeletonHorseMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/SkeletonHorseMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.entity.living.animal.horse.SkeletonHorse; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.SkeletonHorse.class) +@Mixin(net.minecraft.world.entity.animal.equine.SkeletonHorse.class) public abstract class SkeletonHorseMixin_API extends AbstractHorseMixin_API implements SkeletonHorse { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/TraderLlamaMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/TraderLlamaMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/TraderLlamaMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/TraderLlamaMixin_API.java index a9b6f1326bd..bfe88eb7699 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/TraderLlamaMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/TraderLlamaMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.horse.TraderLlama.class) +@Mixin(net.minecraft.world.entity.animal.equine.TraderLlama.class) public abstract class TraderLlamaMixin_API extends LlamaMixin_API implements TraderLlama { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/VariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/VariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/VariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/VariantMixin_API.java index 5b2000ff06b..485c8aad0cd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/VariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/VariantMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.data.type.HorseColor; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.Variant.class) +@Mixin(net.minecraft.world.entity.animal.equine.Variant.class) public abstract class VariantMixin_API implements HorseColor { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/ZombieHorseMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/ZombieHorseMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/ZombieHorseMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/ZombieHorseMixin_API.java index f0a45b55f61..a0d97e58088 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/horse/ZombieHorseMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/equine/ZombieHorseMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.horse; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.equine; import org.spongepowered.api.entity.living.animal.horse.ZombieHorse; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.horse.ZombieHorse.class) +@Mixin(net.minecraft.world.entity.animal.equine.ZombieHorse.class) public abstract class ZombieHorseMixin_API extends AbstractHorseMixin_API implements ZombieHorse { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatMixin_API.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatMixin_API.java index d2b9f0e2f6e..49a7468a23f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.feline; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -32,7 +32,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Cat.class) +@Mixin(net.minecraft.world.entity.animal.feline.Cat.class) public abstract class CatMixin_API extends TamableAnimalMixin_API implements Cat { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatVariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatVariantMixin_API.java index 35500e6c8f6..cc34f8928c5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CatVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/CatVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.feline; -import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.feline.CatVariant; import org.spongepowered.api.data.type.CatType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/OcelotMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/OcelotMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/OcelotMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/OcelotMixin_API.java index ec8c142d6d5..67ee26ea5b9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/OcelotMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/feline/OcelotMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.feline; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Ocelot; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Ocelot.class) +@Mixin(net.minecraft.world.entity.animal.feline.Ocelot.class) public abstract class OcelotMixin_API extends AnimalMixin_API implements Ocelot { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractFishMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractFishMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractFishMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractFishMixin_API.java index be40d35ffc3..dd07e93ece7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractFishMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractFishMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; -import net.minecraft.world.entity.animal.AbstractFish; +import net.minecraft.world.entity.animal.fish.AbstractFish; import org.spongepowered.api.entity.living.aquatic.fish.Fish; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractSchoolingFishMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractSchoolingFishMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractSchoolingFishMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractSchoolingFishMixin_API.java index bbb9cfd9779..93a63da464e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractSchoolingFishMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/AbstractSchoolingFishMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; -import net.minecraft.world.entity.animal.AbstractSchoolingFish; +import net.minecraft.world.entity.animal.fish.AbstractSchoolingFish; import org.spongepowered.api.entity.living.aquatic.fish.school.SchoolingFish; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CodMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/CodMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CodMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/CodMixin_API.java index 5861ec74078..543e8b13f6c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/CodMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/CodMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; import org.spongepowered.api.entity.living.aquatic.fish.school.Cod; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.Cod.class) +@Mixin(net.minecraft.world.entity.animal.fish.Cod.class) public abstract class CodMixin_API extends AbstractSchoolingFishMixin_API implements Cod { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PufferfishMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/PufferfishMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PufferfishMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/PufferfishMixin_API.java index 08db79bbddb..584d634143c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PufferfishMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/PufferfishMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Pufferfish.class) +@Mixin(net.minecraft.world.entity.animal.fish.Pufferfish.class) public abstract class PufferfishMixin_API extends AbstractFishMixin_API implements Pufferfish { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonMixin_API.java index 77c0cbd43b2..a42d21c43bc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; import org.spongepowered.api.entity.living.aquatic.fish.school.Salmon; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.Salmon.class) +@Mixin(net.minecraft.world.entity.animal.fish.Salmon.class) public abstract class SalmonMixin_API extends AbstractSchoolingFishMixin_API implements Salmon { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonVariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonVariantMixin_API.java index 6830b15c2c1..605c6e1b15f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SalmonVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/SalmonVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; -import net.minecraft.world.entity.animal.Salmon; +import net.minecraft.world.entity.animal.fish.Salmon; import org.spongepowered.api.data.type.SalmonSize; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFishMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFishMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFishMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFishMixin_API.java index c899e8468dc..eaba0d4a2d7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFishMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFishMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.TropicalFish.class) +@Mixin(net.minecraft.world.entity.animal.fish.TropicalFish.class) public abstract class TropicalFishMixin_API extends AbstractSchoolingFishMixin_API implements TropicalFish { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFish_PatternMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFish_PatternMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFish_PatternMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFish_PatternMixin_API.java index f4fe5383e8c..1eddb7e0c7e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TropicalFish_PatternMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/TropicalFish_PatternMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; -import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.fish.TropicalFish; import org.spongepowered.api.data.type.TropicalFishShape; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WaterAnimalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/WaterAnimalMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WaterAnimalMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/WaterAnimalMixin_API.java index 8ae63dc801e..bff1d7b0200 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/WaterAnimalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fish/WaterAnimalMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish; -import net.minecraft.world.entity.animal.WaterAnimal; +import net.minecraft.world.entity.animal.fish.WaterAnimal; import org.spongepowered.api.entity.living.aquatic.Aquatic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/FoxMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/FoxMixin_API.java index 8cff309148a..b3bcea4ad09 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FoxMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/FoxMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fox; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; @@ -35,12 +35,13 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; import java.util.UUID; import java.util.stream.Stream; -@Mixin(net.minecraft.world.entity.animal.Fox.class) +@Mixin(net.minecraft.world.entity.animal.fox.Fox.class) @Implements(@Interface(iface = Fox.class, prefix = "fox$", remap = Remap.NONE)) public abstract class FoxMixin_API extends AnimalMixin_API implements Fox { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/Fox_VariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/Fox_VariantMixin_API.java index b7af53b114c..9b44a0350a4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Fox_VariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/fox/Fox_VariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fox; -import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.fox.Fox; import org.spongepowered.api.data.type.FoxType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/FrogVariantMixin_API.java similarity index 99% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/FrogVariantMixin_API.java index 6de70dbb983..91b73533871 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FrogVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/FrogVariantMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.frog; import net.minecraft.world.entity.animal.frog.FrogVariant; import org.spongepowered.api.data.type.FrogType; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/TadpoleMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/TadpoleMixin_API.java index aee39cf5fc7..36bbe9578c0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/TadpoleMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/frog/TadpoleMixin_API.java @@ -27,7 +27,7 @@ import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.frog.Tadpole; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AbstractFishMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.fish.AbstractFishMixin_API; import java.util.Set; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractGolemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/AbstractGolemMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractGolemMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/AbstractGolemMixin_API.java index bc1a53beaa9..58bb6ad99fe 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/AbstractGolemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/AbstractGolemMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem; -import net.minecraft.world.entity.animal.AbstractGolem; +import net.minecraft.world.entity.animal.golem.AbstractGolem; import org.spongepowered.api.entity.living.golem.Golem; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.mixin.api.minecraft.world.entity.PathfinderMobMixin_API; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java new file mode 100644 index 00000000000..daaf5c310c1 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java @@ -0,0 +1,34 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem; + +import org.spongepowered.api.entity.living.golem.CopperGolem; +import org.spongepowered.api.entity.living.golem.SnowGolem; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(net.minecraft.world.entity.animal.golem.CopperGolem.class) +public abstract class CopperGolemMixin_API extends AbstractGolemMixin_API implements CopperGolem { + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/IronGolemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/IronGolemMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/IronGolemMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/IronGolemMixin_API.java index d6917022ae5..6c98ba3f6e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/IronGolemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/IronGolemMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.IronGolem.class) +@Mixin(net.minecraft.world.entity.animal.golem.IronGolem.class) public abstract class IronGolemMixin_API extends AbstractGolemMixin_API implements IronGolem { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SnowGolemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/SnowGolemMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SnowGolemMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/SnowGolemMixin_API.java index e8c23f3e482..6c3f2ed4d08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SnowGolemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/SnowGolemMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem; import org.spongepowered.api.entity.living.golem.SnowGolem; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.SnowGolem.class) +@Mixin(net.minecraft.world.entity.animal.golem.SnowGolem.class) public abstract class SnowGolemMixin_API extends AbstractGolemMixin_API implements SnowGolem { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PandaMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/PandaMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PandaMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/PandaMixin_API.java index 1c801518f22..8ed5f345a23 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PandaMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/PandaMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.panda; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Panda; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Panda.class) +@Mixin(net.minecraft.world.entity.animal.panda.Panda.class) public abstract class PandaMixin_API extends AnimalMixin_API implements Panda { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Panda_GeneMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/Panda_GeneMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Panda_GeneMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/Panda_GeneMixin_API.java index b4648c09241..b200fa35273 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Panda_GeneMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/panda/Panda_GeneMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.panda; -import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.panda.Panda; import org.spongepowered.api.data.type.PandaGene; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ParrotMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ParrotMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ParrotMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ParrotMixin_API.java index 4b11b38bb91..71d2039381f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ParrotMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ParrotMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.parrot; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Parrot.class) +@Mixin(net.minecraft.world.entity.animal.parrot.Parrot.class) public abstract class ParrotMixin_API extends ShoulderRidingEntityMixin_API implements Parrot { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Parrot_VariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/Parrot_VariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Parrot_VariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/Parrot_VariantMixin_API.java index b9b6f5798a9..4e83cb7e5a3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Parrot_VariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/Parrot_VariantMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.parrot; import org.spongepowered.api.data.type.ParrotType; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.Parrot.Variant.class) +@Mixin(net.minecraft.world.entity.animal.parrot.Parrot.Variant.class) public abstract class Parrot_VariantMixin_API implements ParrotType { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ShoulderRidingEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ShoulderRidingEntityMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ShoulderRidingEntityMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ShoulderRidingEntityMixin_API.java index 44e88b5417b..50a696ee04d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/ShoulderRidingEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/parrot/ShoulderRidingEntityMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.parrot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.mixin.api.minecraft.world.entity.TamableAnimalMixin_API; -@Mixin(net.minecraft.world.entity.animal.ShoulderRidingEntity.class) +@Mixin(net.minecraft.world.entity.animal.parrot.ShoulderRidingEntity.class) public abstract class ShoulderRidingEntityMixin_API extends TamableAnimalMixin_API { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigMixin_API.java index 99a9bb2709b..a77790bf21d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.pig; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Pig; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Pig.class) +@Mixin(net.minecraft.world.entity.animal.pig.Pig.class) public abstract class PigMixin_API extends AnimalMixin_API implements Pig { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigVariantMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigVariantMixin_API.java index cd55ac4eed2..b374b70822d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PigVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/pig/PigVariantMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.pig; -import net.minecraft.world.entity.animal.PigVariant; +import net.minecraft.world.entity.animal.pig.PigVariant; import org.spongepowered.api.data.type.PigType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PolarBearMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/polarbear/PolarBearMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PolarBearMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/polarbear/PolarBearMixin_API.java index ffc308a242b..60bdbd05d19 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/PolarBearMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/polarbear/PolarBearMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.polarbear; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.PolarBear; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.PolarBear.class) +@Mixin(net.minecraft.world.entity.animal.polarbear.PolarBear.class) public abstract class PolarBearMixin_API extends AnimalMixin_API implements PolarBear { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/RabbitMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/RabbitMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/RabbitMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/RabbitMixin_API.java index a4a60b1fef3..23262a67025 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/RabbitMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/RabbitMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.rabbit; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Rabbit; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Rabbit.class) +@Mixin(net.minecraft.world.entity.animal.rabbit.Rabbit.class) public abstract class RabbitMixin_API extends AnimalMixin_API implements Rabbit { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Rabbit_VariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/Rabbit_VariantMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Rabbit_VariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/Rabbit_VariantMixin_API.java index 424366ea007..94a1fb9e31e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/Rabbit_VariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/rabbit/Rabbit_VariantMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.rabbit; import org.spongepowered.api.data.type.RabbitType; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.animal.Rabbit.Variant.class) +@Mixin(net.minecraft.world.entity.animal.rabbit.Rabbit.Variant.class) public abstract class Rabbit_VariantMixin_API implements RabbitType { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/GlowSquidMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/GlowSquidMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/GlowSquidMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/GlowSquidMixin_API.java index de783fb269b..08daa57f927 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/GlowSquidMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/GlowSquidMixin_API.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.squid; import org.spongepowered.api.entity.living.aquatic.GlowSquid; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.GlowSquid.class) +@Mixin(net.minecraft.world.entity.animal.squid.GlowSquid.class) public abstract class GlowSquidMixin_API implements GlowSquid { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/SquidMixin_API.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/SquidMixin_API.java index 91950d3f8bd..7f20da49d1e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/SquidMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/squid/SquidMixin_API.java @@ -22,12 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.squid; import org.spongepowered.api.entity.living.aquatic.Squid; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AgeableWaterCreatureMixin_API; -@Mixin(net.minecraft.world.entity.animal.Squid.class) +@Mixin(net.minecraft.world.entity.animal.squid.Squid.class) public abstract class SquidMixin_API extends AgeableWaterCreatureMixin_API implements Squid { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TurtleMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/turtle/TurtleMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TurtleMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/turtle/TurtleMixin_API.java index af8c0ac2d78..b1790c8a505 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/TurtleMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/turtle/TurtleMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.turtle; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.animal.Turtle; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AnimalMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.animal.Turtle.class) +@Mixin(net.minecraft.world.entity.animal.turtle.Turtle.class) public abstract class TurtleMixin_API extends AnimalMixin_API implements Turtle { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonMixin_API.java index 1d5ea3ce658..593c5647d80 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonMixin_API.java @@ -43,7 +43,7 @@ public abstract class EnderDragonMixin_API extends MobMixin_API implements EnderDragon { // @formatter:off - @Shadow @Final private net.minecraft.world.entity.boss.EnderDragonPart[] subEntities; + @Shadow @Final private net.minecraft.world.entity.boss.enderdragon.EnderDragonPart[] subEntities; @Shadow @Final private EnderDragonPhaseManager phaseManager; // @formatter:on @@ -51,7 +51,7 @@ public abstract class EnderDragonMixin_API extends MobMixin_API implements Ender public Set parts() { Builder builder = ImmutableSet.builder(); - for (net.minecraft.world.entity.boss.EnderDragonPart part : this.subEntities) { + for (net.minecraft.world.entity.boss.enderdragon.EnderDragonPart part : this.subEntities) { builder.add((EnderDragonPart) part); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/EnderDragonPartMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonPartMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/EnderDragonPartMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonPartMixin_API.java index 2018ad2420b..75068e50e3c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/EnderDragonPartMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/boss/enderdragon/EnderDragonPartMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.boss; +package org.spongepowered.common.mixin.api.minecraft.world.entity.boss.enderdragon; import org.spongepowered.api.entity.living.monster.boss.dragon.EnderDragon; import org.spongepowered.api.entity.living.monster.boss.dragon.EnderDragonPart; @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.mixin.api.minecraft.world.entity.EntityMixin_API; -@Mixin(net.minecraft.world.entity.boss.EnderDragonPart.class) +@Mixin(net.minecraft.world.entity.boss.enderdragon.EnderDragonPart.class) public abstract class EnderDragonPartMixin_API extends EntityMixin_API implements EnderDragonPart { // @formatter:off diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingMixin_API.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingMixin_API.java index 6182867cd8c..d3da6aea61a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.decoration; +package org.spongepowered.common.mixin.api.minecraft.world.entity.decoration.painting; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.hanging.Painting; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.decoration.HangingEntityMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.decoration.Painting.class) +@Mixin(net.minecraft.world.entity.decoration.painting.Painting.class) public abstract class PaintingMixin_API extends HangingEntityMixin_API implements Painting { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingVariantMixin_API.java similarity index 87% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingVariantMixin_API.java index fcad5395cb3..21d95cde7a4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/PaintingVariantMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/decoration/painting/PaintingVariantMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.decoration; +package org.spongepowered.common.mixin.api.minecraft.world.entity.decoration.painting; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.type.ArtType; @@ -32,11 +32,11 @@ import java.util.Optional; -@Mixin(net.minecraft.world.entity.decoration.PaintingVariant.class) +@Mixin(net.minecraft.world.entity.decoration.painting.PaintingVariant.class) public abstract class PaintingVariantMixin_API implements ArtType { @Override public Optional toDataPack(final RegistryHolder registryHolder) { - return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.entity.decoration.PaintingVariant.DIRECT_CODEC, (net.minecraft.world.entity.decoration.PaintingVariant) (Object) this); + return DataPackUtil.toDataContainer(registryHolder, net.minecraft.world.entity.decoration.painting.PaintingVariant.DIRECT_CODEC, (net.minecraft.world.entity.decoration.painting.PaintingVariant) (Object) this); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ShulkerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ShulkerMixin_API.java index 3a0ed7b26d7..28a25f70e15 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ShulkerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ShulkerMixin_API.java @@ -32,7 +32,7 @@ import org.spongepowered.api.entity.projectile.Projectile; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.entity.projectile.ProjectileUtil; -import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.AbstractGolemMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem.AbstractGolemMixin_API; import java.util.Objects; import java.util.Optional; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BreezeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/breeze/BreezeMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BreezeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/breeze/BreezeMixin_API.java index dc84063fb15..0edbfbb5754 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BreezeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/breeze/BreezeMixin_API.java @@ -22,10 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.breeze; import org.spongepowered.api.entity.living.monster.breeze.Breeze; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.monster.MonsterMixin_API; @Mixin(net.minecraft.world.entity.monster.breeze.Breeze.class) public abstract class BreezeMixin_API extends MonsterMixin_API implements Breeze { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HoglinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/hoglin/HoglinMixin_API.java similarity index 98% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HoglinMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/hoglin/HoglinMixin_API.java index 566a80e54ca..d1af4d6b6de 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HoglinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/hoglin/HoglinMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.hoglin; import org.spongepowered.api.entity.living.animal.Hoglin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractIllagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/AbstractIllagerMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractIllagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/AbstractIllagerMixin_API.java index 8843ee358c6..c9ce5d9216f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractIllagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/AbstractIllagerMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; -import net.minecraft.world.entity.monster.AbstractIllager; +import net.minecraft.world.entity.monster.illager.AbstractIllager; import org.spongepowered.api.entity.living.monster.raider.illager.Illager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.mixin.api.minecraft.world.entity.raid.RaiderMixin_API; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/EvokerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/EvokerMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/EvokerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/EvokerMixin_API.java index bfa2e906e67..08f90069f81 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/EvokerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/EvokerMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Evoker.class) +@Mixin(net.minecraft.world.entity.monster.illager.Evoker.class) public abstract class EvokerMixin_API extends SpellcasterIllagerMixin_API implements Evoker { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/IllusionerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/IllusionerMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/IllusionerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/IllusionerMixin_API.java index d3543f85819..b24b6f7f2a2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/IllusionerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/IllusionerMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; import org.spongepowered.api.entity.living.monster.raider.illager.spellcaster.Illusioner; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Illusioner.class) +@Mixin(net.minecraft.world.entity.monster.illager.Illusioner.class) public abstract class IllusionerMixin_API extends SpellcasterIllagerMixin_API implements Illusioner { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PillagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/PillagerMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PillagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/PillagerMixin_API.java index 64e7ef99122..0fc56689a09 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PillagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/PillagerMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Pillager.class) +@Mixin(net.minecraft.world.entity.monster.illager.Pillager.class) public abstract class PillagerMixin_API extends AbstractIllagerMixin_API implements Pillager { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllagerMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllagerMixin_API.java index 76a27df8baf..e421c14e7be 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllagerMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.monster.raider.illager.spellcaster.Spellcaster; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllager_IllagerSpellMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllager_IllagerSpellMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllager_IllagerSpellMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllager_IllagerSpellMixin_API.java index e7b900dbfc9..74477199c0e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpellcasterIllager_IllagerSpellMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/SpellcasterIllager_IllagerSpellMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; -import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.illager.SpellcasterIllager; import org.spongepowered.api.data.type.SpellType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/VindicatorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/VindicatorMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/VindicatorMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/VindicatorMixin_API.java index 2053431df08..f5f5cdff131 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/VindicatorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/illager/VindicatorMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.illager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Vindicator.class) +@Mixin(net.minecraft.world.entity.monster.illager.Vindicator.class) public abstract class VindicatorMixin_API extends AbstractIllagerMixin_API implements Vindicator { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractPiglinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/AbstractPiglinMixin_API.java similarity index 98% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractPiglinMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/AbstractPiglinMixin_API.java index a06f5e83730..d4d7686e79b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractPiglinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/AbstractPiglinMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.piglin; import net.minecraft.world.entity.monster.piglin.AbstractPiglin; import org.spongepowered.api.entity.living.monster.piglin.PiglinLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinBruteMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinBruteMixin_API.java similarity index 98% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinBruteMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinBruteMixin_API.java index ff57494d1e7..90869eb2712 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinBruteMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinBruteMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.piglin; import org.spongepowered.api.entity.living.monster.piglin.PiglinBrute; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinMixin_API.java similarity index 98% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinMixin_API.java index 07d859aa8cf..6447ac82a16 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/PiglinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/piglin/PiglinMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.piglin; import org.spongepowered.api.entity.living.monster.piglin.Piglin; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractSkeletonMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/AbstractSkeletonMixin_API.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractSkeletonMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/AbstractSkeletonMixin_API.java index da02f7d8a40..dd8833642cd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/AbstractSkeletonMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/AbstractSkeletonMixin_API.java @@ -22,11 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; -import net.minecraft.world.entity.monster.AbstractSkeleton; +import net.minecraft.world.entity.monster.skeleton.AbstractSkeleton; import org.spongepowered.api.entity.living.monster.skeleton.SkeletonLike; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.monster.MonsterMixin_API; @Mixin(AbstractSkeleton.class) public abstract class AbstractSkeletonMixin_API extends MonsterMixin_API implements SkeletonLike { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BoggedMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/BoggedMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BoggedMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/BoggedMixin_API.java index 6dc064db04e..2cb15655d58 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/BoggedMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/BoggedMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; import org.spongepowered.api.entity.living.monster.skeleton.Bogged; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Bogged.class) +@Mixin(net.minecraft.world.entity.monster.skeleton.Bogged.class) public abstract class BoggedMixin_API extends AbstractSkeletonMixin_API implements Bogged { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/ParchedMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/ParchedMixin_API.java index c9f2db7934f..f201b9abd60 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ParchedMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/ParchedMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; import org.spongepowered.api.entity.living.monster.skeleton.Parched; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Parched.class) +@Mixin(net.minecraft.world.entity.monster.skeleton.Parched.class) public abstract class ParchedMixin_API extends AbstractSkeletonMixin_API implements Parched { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SkeletonMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/SkeletonMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SkeletonMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/SkeletonMixin_API.java index 5256da67b7e..10a4b5cff05 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SkeletonMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/SkeletonMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; import org.spongepowered.api.entity.living.monster.skeleton.Skeleton; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Skeleton.class) +@Mixin(net.minecraft.world.entity.monster.skeleton.Skeleton.class) public abstract class SkeletonMixin_API extends AbstractSkeletonMixin_API implements Skeleton { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/StrayMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/StrayMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/StrayMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/StrayMixin_API.java index 598393f3d6e..a9753f77498 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/StrayMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/StrayMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; import org.spongepowered.api.entity.living.monster.skeleton.Stray; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Stray.class) +@Mixin(net.minecraft.world.entity.monster.skeleton.Stray.class) public abstract class StrayMixin_API extends AbstractSkeletonMixin_API implements Stray { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/WitherSkeletonMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/WitherSkeletonMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/WitherSkeletonMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/WitherSkeletonMixin_API.java index 0b2370c82f4..d094112c222 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/WitherSkeletonMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/skeleton/WitherSkeletonMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.skeleton; import org.spongepowered.api.entity.living.monster.skeleton.WitherSkeleton; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.WitherSkeleton.class) +@Mixin(net.minecraft.world.entity.monster.skeleton.WitherSkeleton.class) public abstract class WitherSkeletonMixin_API extends AbstractSkeletonMixin_API implements WitherSkeleton { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/CaveSpiderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/CaveSpiderMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/CaveSpiderMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/CaveSpiderMixin_API.java index d4642c10802..f6d75889526 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/CaveSpiderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/CaveSpiderMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.spider; import org.spongepowered.api.entity.living.monster.spider.CaveSpider; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.CaveSpider.class) +@Mixin(net.minecraft.world.entity.monster.spider.CaveSpider.class) public abstract class CaveSpiderMixin_API extends SpiderMixin_API implements CaveSpider { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpiderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/SpiderMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpiderMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/SpiderMixin_API.java index dee3c008865..c2c2009a9d1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SpiderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/spider/SpiderMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.spider; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.monster.spider.Spider; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.monster.MonsterMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Spider.class) +@Mixin(net.minecraft.world.entity.monster.spider.Spider.class) public abstract class SpiderMixin_API extends MonsterMixin_API implements Spider { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/DrownedMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/DrownedMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/DrownedMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/DrownedMixin_API.java index 1df42a64f8a..b016c59527a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/DrownedMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/DrownedMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.zombie; import org.spongepowered.api.entity.living.monster.zombie.Drowned; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Drowned.class) +@Mixin(net.minecraft.world.entity.monster.zombie.Drowned.class) public abstract class DrownedMixin_API extends ZombieMixin_API implements Drowned { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HuskMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/HuskMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HuskMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/HuskMixin_API.java index 977efde3f47..fe5303be2c4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/HuskMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/HuskMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.zombie; import org.spongepowered.api.entity.living.monster.zombie.Husk; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.Husk.class) +@Mixin(net.minecraft.world.entity.monster.zombie.Husk.class) public abstract class HuskMixin_API extends ZombieMixin_API implements Husk { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieMixin_API.java index f2bda1f4acb..bf5b20f310b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.zombie; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.monster.zombie.Zombie; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.monster.MonsterMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Zombie.class) +@Mixin(net.minecraft.world.entity.monster.zombie.Zombie.class) public abstract class ZombieMixin_API extends MonsterMixin_API implements Zombie { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieVillagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieVillagerMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieVillagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieVillagerMixin_API.java index c649140cf59..41061c9d42b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombieVillagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombieVillagerMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.zombie; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.ZombieVillager.class) +@Mixin(net.minecraft.world.entity.monster.zombie.ZombieVillager.class) public abstract class ZombieVillagerMixin_API extends ZombieMixin_API implements ZombieVillager { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombifiedPiglinMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombifiedPiglinMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombifiedPiglinMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombifiedPiglinMixin_API.java index a86f41dfb40..09d78f74d03 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/ZombifiedPiglinMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/zombie/ZombifiedPiglinMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.zombie; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.ZombifiedPiglin.class) +@Mixin(net.minecraft.world.entity.monster.zombie.ZombifiedPiglin.class) public abstract class ZombifiedPiglinMixin_API extends ZombieMixin_API implements ZombifiedPiglin { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/AbstractVillagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/AbstractVillagerMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/AbstractVillagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/AbstractVillagerMixin_API.java index e60b8d0166d..d0ea92835ad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/AbstractVillagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/AbstractVillagerMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.trader.VillagerLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerMixin_API.java index 1b3603129df..c2fdcddd70c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.npc.Villager.class) +@Mixin(net.minecraft.world.entity.npc.villager.Villager.class) public abstract class VillagerMixin_API extends AbstractVillagerMixin_API implements Villager { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerProfessionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerProfessionMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerProfessionMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerProfessionMixin_API.java index 2f6d3d6700e..bcf1e8769d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerProfessionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerProfessionMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; -import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.villager.VillagerProfession; import org.spongepowered.api.data.type.ProfessionType; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java index aa40f796fab..5776537988f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTrades_ItemListingMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.VillagerTrades; +import net.minecraft.world.entity.npc.villager.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.item.merchant.TradeOffer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTypeMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTypeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTypeMixin_API.java index bbe9082a9a4..0c87bd0aa47 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/VillagerTypeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTypeMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; -import net.minecraft.world.entity.npc.VillagerType; +import net.minecraft.world.entity.npc.villager.VillagerType; import org.spongepowered.asm.mixin.Mixin; @Mixin(VillagerType.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/WanderingTraderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/wanderingtrader/WanderingTraderMixin_API.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/WanderingTraderMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/wanderingtrader/WanderingTraderMixin_API.java index f9e31164eae..11a4667f181 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/WanderingTraderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/wanderingtrader/WanderingTraderMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc; +package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.wanderingtrader; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.trader.WanderingTrader; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager.AbstractVillagerMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.npc.WanderingTrader.class) +@Mixin(net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader.class) public abstract class WanderingTraderMixin_API extends AbstractVillagerMixin_API implements WanderingTrader { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrowMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrowMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrowMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrowMixin_API.java index 14702b4832c..677e9cd3641 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrowMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrowMixin_API.java @@ -22,13 +22,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.arrow.ArrowLike; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.ProjectileMixin_API; import java.util.Set; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrow_PickupMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrow_PickupMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrow_PickupMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrow_PickupMixin_API.java index 2b6317f72bc..af2ee6cfd1f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractArrow_PickupMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/AbstractArrow_PickupMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import org.spongepowered.api.data.type.PickupRule; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ArrowMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ArrowMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ArrowMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ArrowMixin_API.java index af7f6e134e5..aacaed6b0ec 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ArrowMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ArrowMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.arrow; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.projectile.Arrow.class) +@Mixin(net.minecraft.world.entity.projectile.arrow.Arrow.class) public abstract class ArrowMixin_API extends AbstractArrowMixin_API implements Arrow { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SpectralArrowMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/SpectralArrowMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SpectralArrowMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/SpectralArrowMixin_API.java index f7b1de3429b..54817227838 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SpectralArrowMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/SpectralArrowMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.arrow; import org.spongepowered.api.entity.projectile.arrow.SpectralArrow; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.projectile.SpectralArrow.class) +@Mixin(net.minecraft.world.entity.projectile.arrow.SpectralArrow.class) public abstract class SpectralArrowMixin_API extends AbstractArrowMixin_API implements SpectralArrow { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownTridentMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ThrownTridentMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownTridentMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ThrownTridentMixin_API.java index 4dcadc05ee9..41509d0537f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownTridentMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/arrow/ThrownTridentMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.ThrownTrident; +import net.minecraft.world.entity.projectile.arrow.ThrownTrident; import org.spongepowered.api.entity.projectile.arrow.Trident; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractHurtingProjectileMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin_API.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractHurtingProjectileMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin_API.java index e709112d51e..4b96313a9e8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/AbstractHurtingProjectileMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin_API.java @@ -22,13 +22,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; -import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.AcceleratingProjectile; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.ProjectileMixin_API; import java.util.Set; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/DragonFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/DragonFireballMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/DragonFireballMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/DragonFireballMixin_API.java index 49758fd8b01..a38feff5816 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/DragonFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/DragonFireballMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; import org.spongepowered.api.entity.projectile.explosive.fireball.DragonFireball; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.projectile.DragonFireball.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.DragonFireball.class) public abstract class DragonFireballMixin_API extends AbstractHurtingProjectileMixin_API implements DragonFireball { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/FireballMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireballMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/FireballMixin_API.java index 3ee190cad57..1c958da47f4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/FireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/FireballMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; -import net.minecraft.world.entity.projectile.Fireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.Fireball; import org.spongepowered.api.entity.projectile.IgnitingProjectile; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/LargeFireballMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/LargeFireballMixin_API.java index 52af501a93a..f8a822382b0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/LargeFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/LargeFireballMixin_API.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; import net.minecraft.world.level.Level; import net.minecraft.world.level.gamerules.GameRules; import org.spongepowered.api.data.Keys; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SmallFireballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/SmallFireballMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SmallFireballMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/SmallFireballMixin_API.java index c7b55172d1d..8bffdf58b1b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SmallFireballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/SmallFireballMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -31,7 +31,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.projectile.SmallFireball.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.SmallFireball.class) public abstract class SmallFireballMixin_API extends FireballMixin_API implements SmallFireball { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/WitherSkullMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/WitherSkullMixin_API.java index 72742b09d19..ed258a11ad1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/WitherSkullMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/WitherSkullMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile; import net.minecraft.world.level.Level; import org.spongepowered.api.data.Keys; @@ -33,7 +33,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.projectile.WitherSkull.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull.class) public abstract class WitherSkullMixin_API extends AbstractHurtingProjectileMixin_API implements WitherSkull { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/AbstractWindChargeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/AbstractWindChargeMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/AbstractWindChargeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/AbstractWindChargeMixin_API.java index 863d312b601..72f44feb2e5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/AbstractWindChargeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/AbstractWindChargeMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.windcharge; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile.windcharge; -import net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge; +import net.minecraft.world.entity.projectile.hurtingprojectile.windcharge.AbstractWindCharge; import net.minecraft.world.phys.Vec3; import org.spongepowered.api.entity.explosive.Explosive; import org.spongepowered.api.entity.projectile.windcharge.WindChargeLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/BreezeWindChargeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/BreezeWindChargeMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/BreezeWindChargeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/BreezeWindChargeMixin_API.java index f5313aff01b..5f42a87470d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/BreezeWindChargeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/BreezeWindChargeMixin_API.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.windcharge; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile.windcharge; import org.spongepowered.api.entity.projectile.windcharge.BreezeWindCharge; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.windcharge.BreezeWindCharge.class) public abstract class BreezeWindChargeMixin_API extends AbstractWindChargeMixin_API implements BreezeWindCharge { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/WindChargeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/WindChargeMixin_API.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/WindChargeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/WindChargeMixin_API.java index 5988ba9f4d0..2f85850c616 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/windcharge/WindChargeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/hurtingprojectile/windcharge/WindChargeMixin_API.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.windcharge; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.hurtingprojectile.windcharge; import org.spongepowered.api.entity.projectile.windcharge.WindCharge; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.projectile.windcharge.WindCharge.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.windcharge.WindCharge.class) public abstract class WindChargeMixin_API extends AbstractWindChargeMixin_API implements WindCharge { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SnowballMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/SnowballMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SnowballMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/SnowballMixin_API.java index 48f40eef4aa..ff855ac10e6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/SnowballMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/SnowballMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; import org.spongepowered.api.entity.projectile.Snowball; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.projectile.Snowball.class) +@Mixin(net.minecraft.world.entity.projectile.throwableitemprojectile.Snowball.class) public abstract class SnowballMixin_API extends ThrowableItemProjectileMixin_API implements Snowball { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrowableItemProjectileMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrowableItemProjectileMixin_API.java similarity index 88% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrowableItemProjectileMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrowableItemProjectileMixin_API.java index 4c837849ac9..f7715097f66 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrowableItemProjectileMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrowableItemProjectileMixin_API.java @@ -22,16 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.ThrowableItemProjectile; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.ThrowableProjectileMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.projectile.ThrowableItemProjectile.class) +@Mixin(net.minecraft.world.entity.projectile.throwableitemprojectile.ThrowableItemProjectile.class) public abstract class ThrowableItemProjectileMixin_API extends ThrowableProjectileMixin_API implements ThrowableItemProjectile { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEggMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEggMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEggMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEggMixin_API.java index c0d3cf6129f..dc134e7f5a2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEggMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEggMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; -import net.minecraft.world.entity.projectile.ThrownEgg; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEgg; import org.spongepowered.api.entity.projectile.Egg; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEnderpearlMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEnderpearlMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin_API.java index 534361f9473..d500aec68d8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownEnderpearlMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; -import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearl; import org.spongepowered.api.entity.projectile.EnderPearl; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownExperienceBottleMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownExperienceBottleMixin_API.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownExperienceBottleMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownExperienceBottleMixin_API.java index 1ec7c1b777e..c44afc19677 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownExperienceBottleMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownExperienceBottleMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; -import net.minecraft.world.entity.projectile.ThrownExperienceBottle; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownExperienceBottle; import org.spongepowered.api.entity.projectile.ExperienceBottle; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownPotionMixin_API.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownPotionMixin_API.java index 96450dea666..fb503acbad3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/ThrownPotionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/projectile/throwableitemprojectile/ThrownPotionMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile; +package org.spongepowered.common.mixin.api.minecraft.world.entity.projectile.throwableitemprojectile; -import net.minecraft.world.entity.projectile.AbstractThrownPotion; +import net.minecraft.world.entity.projectile.throwableitemprojectile.AbstractThrownPotion; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.projectile.Potion; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractBoatMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractBoatMixin_API.java index a3c3c926942..aef5b5d68ff 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractBoatMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractBoatMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.boat; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; @@ -34,7 +34,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.vehicle.AbstractBoat.class) +@Mixin(net.minecraft.world.entity.vehicle.boat.AbstractBoat.class) @Implements(@Interface(iface = Boat.class, prefix = "apiBoat$")) public abstract class AbstractBoatMixin_API extends EntityMixin_API implements Boat { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractChestBoatMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractChestBoatMixin_API.java index ee842169990..d8c51298e93 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractChestBoatMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/boat/AbstractChestBoatMixin_API.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.boat; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.vehicle.ChestBoat; @@ -30,7 +30,7 @@ import java.util.Set; -@Mixin(net.minecraft.world.entity.vehicle.AbstractChestBoat.class) +@Mixin(net.minecraft.world.entity.vehicle.boat.AbstractChestBoat.class) public abstract class AbstractChestBoatMixin_API extends AbstractBoatMixin_API implements ChestBoat { @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartContainerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartContainerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_API.java index be06c2e6cb9..b112b1914ad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartContainerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_API.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import org.spongepowered.api.entity.vehicle.minecart.carrier.CarrierMinecart; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartMixin_API.java index b4f4074fb83..9a2207db953 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/AbstractMinecartMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/AbstractMinecartMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.vehicle.minecart.MinecartLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartChestMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartChestMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartChestMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartChestMixin_API.java index b930cd56408..2bf826b2468 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartChestMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartChestMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartChest; +import net.minecraft.world.entity.vehicle.minecart.MinecartChest; import org.spongepowered.api.entity.vehicle.minecart.carrier.ChestMinecart; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartCommandBlockMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartCommandBlockMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartCommandBlockMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartCommandBlockMixin_API.java index a53afd2da02..52e3f4c9fb1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartCommandBlockMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartCommandBlockMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import net.minecraft.world.level.BaseCommandBlock; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartFurnaceMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartFurnaceMixin_API.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartFurnaceMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartFurnaceMixin_API.java index ddb17dd9cc3..b384d470155 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartFurnaceMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartFurnaceMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.entity.vehicle.minecart.MinecartFurnace; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.vehicle.minecart.FurnaceMinecart; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartHopperMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartHopperMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartHopperMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartHopperMixin_API.java index 0fcceb8049a..4f5e4b3389a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartHopperMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartHopperMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartHopper; +import net.minecraft.world.entity.vehicle.minecart.MinecartHopper; import org.spongepowered.api.entity.vehicle.minecart.carrier.HopperMinecart; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartMixin_API.java index aa186ec4187..db76e281ef2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; import org.spongepowered.api.entity.vehicle.minecart.Minecart; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.vehicle.Minecart.class) +@Mixin(net.minecraft.world.entity.vehicle.minecart.Minecart.class) public abstract class MinecartMixin_API extends AbstractMinecartMixin_API implements Minecart { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartSpawnerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartSpawnerMixin_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartSpawnerMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartSpawnerMixin_API.java index 5c9f7acbdcf..62026b7cc23 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartSpawnerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartSpawnerMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartSpawner; +import net.minecraft.world.entity.vehicle.minecart.MinecartSpawner; import org.spongepowered.api.entity.vehicle.minecart.SpawnerMinecart; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartTNTMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartTNTMixin_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartTNTMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartTNTMixin_API.java index 5ed1652b6e3..effee95c015 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/MinecartTNTMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/vehicle/minecart/MinecartTNTMixin_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle; +package org.spongepowered.common.mixin.api.minecraft.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.MinecartTNT; +import net.minecraft.world.entity.vehicle.minecart.MinecartTNT; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.vehicle.minecart.TNTMinecart; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/service/permission/SubjectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/service/permission/SubjectMixin_API.java index e50c4b7698e..5cfd85d9854 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/service/permission/SubjectMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/service/permission/SubjectMixin_API.java @@ -26,7 +26,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.rcon.RconConsoleSource; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import net.minecraft.world.level.block.entity.CommandBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.service.server.permission.BridgeSubject; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 3aab053803f..c45e077e024 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -60,9 +60,9 @@ import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.HangingEntity; -import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.decoration.painting.Painting; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearl; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.CustomSpawner; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 9590730b9f1..904ddf9309d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -61,7 +61,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Relative; -import net.minecraft.world.entity.animal.AbstractFish; +import net.minecraft.world.entity.animal.fish.AbstractFish; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 0fc1f133681..e44213cb7bf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -211,7 +211,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack cancellable = true, slice = @Slice( // TODO - confirm we are injecting at the right spot given the subtle changes - from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;hasClientLoaded()Z"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;hasClientLoaded()Z"), to = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z"))) private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) { final boolean fireMoveEvent = packetIn.hasPosition(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/service/permission/SubjectMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/service/permission/SubjectMixin.java index cf03857795d..111c2e8f0bb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/service/permission/SubjectMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/service/permission/SubjectMixin.java @@ -26,7 +26,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.rcon.RconConsoleSource; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import net.minecraft.world.level.block.entity.CommandBlockEntity; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.service.permission.Subject; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMaxAirMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMaxAirMixin.java index 2a8f7da99c2..8fc76c652fb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMaxAirMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMaxAirMixin.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.Dolphin; +import net.minecraft.world.entity.animal.dolphin.Dolphin; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/GrieferBridgeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/GrieferBridgeMixin.java index 023be957be2..45d6df44d5c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/GrieferBridgeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/GrieferBridgeMixin.java @@ -25,9 +25,9 @@ package org.spongepowered.common.mixin.core.world.entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.projectile.LargeFireball; -import net.minecraft.world.entity.projectile.SmallFireball; -import net.minecraft.world.entity.projectile.WitherSkull; +import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.SmallFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull; import org.spongepowered.api.data.Keys; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.bridge.data.SpongeDataHolderBridge; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java index 93b201f05d6..18883133a52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/behavior/HarvestFarmlandMixin.java @@ -26,7 +26,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.ai.behavior.HarvestFarmland; -import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.villager.Villager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -42,7 +42,7 @@ public abstract class HarvestFarmlandMixin { * would fail in forge environments. This changes the injection to a predictable * place where we still can forcibly call things but still cancel as needed. */ - @Inject(method = "canStillUse(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)Z", at = @At(value = "HEAD"), cancellable = true) + @Inject(method = "canStillUse(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/villager/Villager;J)Z", at = @At(value = "HEAD"), cancellable = true) private void onCanGrief(ServerLevel level, Villager owner, long $$2, CallbackInfoReturnable cir) { if (!((GrieferBridge) owner).bridge$canGrief()) { cir.setReturnValue(false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/RunAroundLikeCrazyGoalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/RunAroundLikeCrazyGoalMixin.java index 46eab5028f0..beef75b6dc5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/RunAroundLikeCrazyGoalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/RunAroundLikeCrazyGoalMixin.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.core.world.entity.ai.goal; import net.minecraft.world.entity.ai.goal.RunAroundLikeCrazyGoal; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.api.entity.living.animal.horse.HorseLike; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.SpongeEventFactory; @@ -51,7 +51,7 @@ public abstract class RunAroundLikeCrazyGoalMixin extends GoalMixin { method = "tick", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/animal/horse/AbstractHorse;tameWithName(Lnet/minecraft/world/entity/player/Player;)Z" + target = "Lnet/minecraft/world/entity/animal/equine/AbstractHorse;tameWithName(Lnet/minecraft/world/entity/player/Player;)Z" ), cancellable = true ) @@ -68,7 +68,7 @@ public abstract class RunAroundLikeCrazyGoalMixin extends GoalMixin { method = "tick", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/entity/animal/horse/AbstractHorse;ejectPassengers()V" + target = "Lnet/minecraft/world/entity/animal/equine/AbstractHorse;ejectPassengers()V" ), cancellable = true ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/equine/AbstractHorseMixin.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/equine/AbstractHorseMixin.java index c223d6299b1..95ee43bfccc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/equine/AbstractHorseMixin.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal.horse; +package org.spongepowered.common.mixin.core.world.entity.animal.equine; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Cat_CatRelaxOnOwnerGoalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/Cat_CatRelaxOnOwnerGoalMixin.java similarity index 86% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Cat_CatRelaxOnOwnerGoalMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/Cat_CatRelaxOnOwnerGoalMixin.java index f4181d3b388..8d45ca231e6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Cat_CatRelaxOnOwnerGoalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/Cat_CatRelaxOnOwnerGoalMixin.java @@ -22,22 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.feline; -import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.animal.feline.Cat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(targets = "net/minecraft/world/entity/animal/Cat$CatRelaxOnOwnerGoal") +@Mixin(targets = "net/minecraft/world/entity/animal/feline/Cat$CatRelaxOnOwnerGoal") public abstract class Cat_CatRelaxOnOwnerGoalMixin { private boolean impl$teleportResult; @Redirect(method = "giveMorningGift()V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Cat;randomTeleport(DDDZ)Z")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/feline/Cat;randomTeleport(DDDZ)Z")) private boolean impl$storeTeleportResult(Cat entity, double x, double y, double z, boolean changeState) { this.impl$teleportResult = entity.randomTeleport(x, y, z, changeState); return this.impl$teleportResult; @@ -45,7 +45,7 @@ public abstract class Cat_CatRelaxOnOwnerGoalMixin { @Inject(method = "giveMorningGift()V", at = @At(value = "INVOKE_ASSIGN", - target = "Lnet/minecraft/world/entity/animal/Cat;randomTeleport(DDDZ)Z", + target = "Lnet/minecraft/world/entity/animal/feline/Cat;randomTeleport(DDDZ)Z", shift = At.Shift.AFTER), cancellable = true) private void impl$makeCatsRespectTeleportResult(final CallbackInfo ci) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/OcelotMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/OcelotMixin.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/OcelotMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/OcelotMixin.java index 6ac10940bc5..ed1788b7a36 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/OcelotMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/feline/OcelotMixin.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.feline; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; @@ -38,7 +38,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.AgableMobMixin; -@Mixin(net.minecraft.world.entity.animal.Ocelot.class) +@Mixin(net.minecraft.world.entity.animal.feline.Ocelot.class) public abstract class OcelotMixin extends AgableMobMixin { @Redirect(method = "mobInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java index 69bdc94b064..7cd65a66812 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/PufferfishMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.fish; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; @@ -30,7 +30,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.fish.Pufferfish; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/ParrotMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/parrot/ParrotMixin.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/ParrotMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/parrot/ParrotMixin.java index ba87ad79146..38dd761cfa7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/ParrotMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/parrot/ParrotMixin.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.parrot; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; @@ -38,7 +38,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.mixin.core.world.entity.AgableMobMixin; -@Mixin(net.minecraft.world.entity.animal.Parrot.class) +@Mixin(net.minecraft.world.entity.animal.parrot.Parrot.class) public abstract class ParrotMixin extends AgableMobMixin { @Redirect(method = "mobInteract", diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Rabbit_RaidGardenGoalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/rabbit/Rabbit_RaidGardenGoalMixin.java similarity index 92% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Rabbit_RaidGardenGoalMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/rabbit/Rabbit_RaidGardenGoalMixin.java index de97d0704e0..8f8cbe8ff08 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/Rabbit_RaidGardenGoalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/rabbit/Rabbit_RaidGardenGoalMixin.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.animal; +package org.spongepowered.common.mixin.core.world.entity.animal.rabbit; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; -import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.rabbit.Rabbit; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -35,7 +35,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.world.entity.GrieferBridge; -@Mixin(targets = "net/minecraft/world/entity/animal/Rabbit$RaidGardenGoal") +@Mixin(targets = "net/minecraft/world/entity/animal/rabbit/Rabbit$RaidGardenGoal") public abstract class Rabbit_RaidGardenGoalMixin extends MoveToBlockGoal { // @formatter:off diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/zombie/ZombifiedPiglinMixin.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/zombie/ZombifiedPiglinMixin.java index b2e7acfcc76..4f617112c41 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/ZombifiedPiglinMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/monster/zombie/ZombifiedPiglinMixin.java @@ -22,13 +22,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.monster; +package org.spongepowered.common.mixin.core.world.entity.monster.zombie; import net.minecraft.world.entity.NeutralMob; -import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.monster.zombie.ZombifiedPiglin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.bridge.world.entity.AggressiveEntityBridge; +import org.spongepowered.common.mixin.core.world.entity.monster.MonsterMixin; @Mixin(ZombifiedPiglin.class) public abstract class ZombifiedPiglinMixin extends MonsterMixin implements AggressiveEntityBridge { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/AbstractVillagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/AbstractVillagerMixin.java similarity index 91% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/AbstractVillagerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/AbstractVillagerMixin.java index 9bd38e94a91..ecfd4220a5a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/AbstractVillagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/AbstractVillagerMixin.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.npc; +package org.spongepowered.common.mixin.core.world.entity.npc.villager; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.mixin.core.world.entity.AgableMobMixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/VillagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/VillagerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java index e34c6aeeabe..eb5d8f41915 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/VillagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.npc; +package org.spongepowered.common.mixin.core.world.entity.npc.villager; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.villager.Villager; import org.slf4j.Logger; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockSnapshot; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/wanderingtrader/WanderingTraderMixin.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/wanderingtrader/WanderingTraderMixin.java index 251de521ef6..c8afe7fcfbf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/WanderingTraderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/wanderingtrader/WanderingTraderMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.npc; +package org.spongepowered.common.mixin.core.world.entity.npc.wanderingtrader; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.npc.WanderingTraderSpawner; +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java index 54790720d92..0cbb1ce6fc6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java @@ -22,13 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.arrow; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -45,6 +45,7 @@ import org.spongepowered.common.bridge.world.entity.projectile.AbstractArrowBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; +import org.spongepowered.common.mixin.core.world.entity.projectile.ProjectileMixin; @Mixin(AbstractArrow.class) public abstract class AbstractArrowMixin extends ProjectileMixin implements AbstractArrowBridge { @@ -149,7 +150,7 @@ private void onProjectileHit(final EntityHitResult hitResult, final CallbackInfo @Inject( method = "tickDespawn", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;discard()V") + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/arrow/AbstractArrow;discard()V") ) private void impl$throwExpireArrow(final CallbackInfo ci) { this.impl$callExpireEntityEvent(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/ThrownTridentMixin.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/ThrownTridentMixin.java index d5abc0c2954..c5b4589a0c3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/ThrownTridentMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.arrow; import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.entity.projectile.ThrownTrident; +import net.minecraft.world.entity.projectile.arrow.ThrownTrident; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; @@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; +import org.spongepowered.common.mixin.core.world.entity.projectile.ProjectileMixin; @Mixin(ThrownTrident.class) public abstract class ThrownTridentMixin extends ProjectileMixin { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java similarity index 86% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java index b909d0e1e36..dd91edf01b5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.hurtingprojectile; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.entity.projectile.ProjectileDeflection; import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; @@ -33,11 +33,12 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; +import org.spongepowered.common.mixin.core.world.entity.projectile.ProjectileMixin; @Mixin(AbstractHurtingProjectile.class) public abstract class AbstractHurtingProjectileMixin extends ProjectileMixin { - @Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractHurtingProjectile;hitTargetOrDeflectSelf(Lnet/minecraft/world/phys/HitResult;)Lnet/minecraft/world/entity/projectile/ProjectileDeflection;")) + @Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectile;hitTargetOrDeflectSelf(Lnet/minecraft/world/phys/HitResult;)Lnet/minecraft/world/entity/projectile/ProjectileDeflection;")) private ProjectileDeflection impl$callCollideImpactEvent(AbstractHurtingProjectile projectile, HitResult result) { if (result.getType() == HitResult.Type.MISS || ((LevelBridge) this.shadow$level()).bridge$isFake()) { return this.shadow$hitTargetOrDeflectSelf(result); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/LargeFireballMixin.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/LargeFireballMixin.java index 711996a198f..0ea2b682b46 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/LargeFireballMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/LargeFireballMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.hurtingprojectile; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SmallFireballMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/SmallFireballMixin.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SmallFireballMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/SmallFireballMixin.java index c63e625c155..2c5a7ac1cde 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SmallFireballMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/SmallFireballMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.hurtingprojectile; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.entity.projectile.hurtingprojectile.SmallFireball; import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/WitherSkullMixin.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/WitherSkullMixin.java index 5a93b6709a6..b65f0b5b3a7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/WitherSkullMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/WitherSkullMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.hurtingprojectile; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.WitherSkull; +import net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; @@ -43,7 +43,7 @@ import java.util.Optional; -@Mixin(net.minecraft.world.entity.projectile.WitherSkull.class) +@Mixin(net.minecraft.world.entity.projectile.hurtingprojectile.WitherSkull.class) public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin implements WitherSkullBridge, ExplosiveBridge { private float impl$explosionRadius = Constants.Entity.WitherSkull.DEFAULT_EXPLOSION_RADIUS; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/SnowballMixin.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/SnowballMixin.java index 00ec313c112..b07e81e60cc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/SnowballMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/SnowballMixin.java @@ -22,14 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.throwableitemprojectile; import org.spongepowered.api.entity.projectile.Snowball; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.common.mixin.core.world.entity.projectile.ThrowableProjectileMixin; -@Mixin(net.minecraft.world.entity.projectile.Snowball.class) +@Mixin(net.minecraft.world.entity.projectile.throwableitemprojectile.Snowball.class) public abstract class SnowballMixin extends ThrowableProjectileMixin implements Snowball { // TODO Key not implemented diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEggMixin.java similarity index 90% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEggMixin.java index 40bebdc1d5b..592656ff2b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEggMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEggMixin.java @@ -22,12 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.throwableitemprojectile; -import net.minecraft.world.entity.projectile.ThrownEgg; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEgg; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.common.mixin.core.world.entity.projectile.ThrowableProjectileMixin; @Mixin(ThrownEgg.class) public abstract class ThrownEggMixin extends ThrowableProjectileMixin { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin.java similarity index 93% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin.java index 9bd4d1b0e25..07b38137601 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/throwableitemprojectile/ThrownEnderpearlMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.projectile; +package org.spongepowered.common.mixin.core.world.entity.projectile.throwableitemprojectile; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearl; import net.minecraft.world.level.portal.TeleportTransition; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; @@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.mixin.core.world.entity.projectile.ThrowableProjectileMixin; @Mixin(ThrownEnderpearl.class) public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin.java similarity index 98% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin.java index 26b135e677a..c5d72fe7604 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractBoatMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.boat; -import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import org.spongepowered.api.data.Keys; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartContainerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartContainerMixin.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartContainerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartContainerMixin.java index 5cee1271dad..8d40d43a1f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartContainerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartContainerMixin.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import org.spongepowered.asm.mixin.Mixin; @Mixin(AbstractMinecartContainer.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartMixin.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartMixin.java index 9844796031e..a2be1bcb455 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/AbstractMinecartMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; import net.minecraft.world.phys.Vec3; import org.spongepowered.api.data.Keys; import org.spongepowered.asm.mixin.Mixin; @@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.common.bridge.data.SpongeDataHolderBridge; import org.spongepowered.common.bridge.world.entity.vehicle.AbstractMinecartBridge; +import org.spongepowered.common.mixin.core.world.entity.vehicle.VehicleEntityMixin; import org.spongepowered.common.util.Constants; import org.spongepowered.math.vector.Vector3d; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlockMixin.java similarity index 97% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlockMixin.java index 70ac4854a67..5f4a6ab62d2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlockMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import net.minecraft.world.level.BaseCommandBlock; import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.PermissionService; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlock_MinecartCommandBaseMixin.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlock_MinecartCommandBaseMixin.java index 6eb7efd46ae..25e5e41a1d4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartCommandBlock_MinecartCommandBaseMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartCommandBlock_MinecartCommandBaseMixin.java @@ -22,14 +22,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.Subject; @@ -40,7 +40,7 @@ import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.mixin.core.world.BaseCommandBlockMixin; -@Mixin(targets = "net.minecraft.world.entity.vehicle.MinecartCommandBlock$MinecartCommandBase") +@Mixin(targets = "net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock$MinecartCommandBase") public abstract class MinecartCommandBlock_MinecartCommandBaseMixin extends BaseCommandBlockMixin implements SubjectProxy { // @formatter:off diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartFurnaceMixin.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartFurnaceMixin.java index 69ce2149a1a..10f0b276bec 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartFurnaceMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartFurnaceMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.entity.vehicle.minecart.MinecartFurnace; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartTNTMixin.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartTNTMixin.java index b6fd2c3435d..158f2490746 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/MinecartTNTMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/MinecartTNTMixin.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.vehicle.MinecartTNT; +import net.minecraft.world.entity.vehicle.minecart.MinecartTNT; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.world.server.ServerWorld; @@ -147,7 +147,7 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin implements } @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/entity/vehicle/MinecartTNT;explode(Lnet/minecraft/world/damagesource/DamageSource;D)V")) + target = "Lnet/minecraft/world/entity/vehicle/minecart/MinecartTNT;explode(Lnet/minecraft/world/damagesource/DamageSource;D)V")) private void attackImpl$postOnAttackEntityFrom(final ServerLevel level, final DamageSource source, final float damage, final CallbackInfoReturnable cir) { if (SpongeDamageTracker.callDamageEvents((org.spongepowered.api.entity.Entity) this, source, damage) == null) { cir.setReturnValue(true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/OldMinecartBehaviourMixin.java similarity index 88% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/OldMinecartBehaviourMixin.java index c08dbd2504b..88d6dd7e0cc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/OldMinecartBehaviourMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/vehicle/minecart/OldMinecartBehaviourMixin.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.entity.vehicle; +package org.spongepowered.common.mixin.core.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.entity.vehicle.OldMinecartBehavior; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.OldMinecartBehavior; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -34,7 +34,7 @@ @Mixin(OldMinecartBehavior.class) public abstract class OldMinecartBehaviourMixin { - @Redirect(method = "getSlowdownFactor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/AbstractMinecart;isVehicle()Z")) + @Redirect(method = "getSlowdownFactor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/minecart/AbstractMinecart;isVehicle()Z")) private boolean impl$applyDragIfEmpty(final AbstractMinecart minecart) { return !((AbstractMinecartBridge) minecart).bridge$getSlowWhenEmpty() || minecart.isVehicle(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/AbstractArrowEntityMixin_EntityActivation.java b/src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/arrow/AbstractArrowEntityMixin_EntityActivation.java similarity index 95% rename from src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/AbstractArrowEntityMixin_EntityActivation.java rename to src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/arrow/AbstractArrowEntityMixin_EntityActivation.java index c0bdbb05971..602bccdb92a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/AbstractArrowEntityMixin_EntityActivation.java +++ b/src/mixins/java/org/spongepowered/common/mixin/entityactivation/entity/projectile/arrow/AbstractArrowEntityMixin_EntityActivation.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.entityactivation.entity.projectile; +package org.spongepowered.common.mixin.entityactivation.entity.projectile.arrow; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.arrow.AbstractArrow; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.mixin.entityactivation.entity.EntityMixin_EntityActivation; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java index 5d5e2f794fa..aa64527414e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java @@ -26,10 +26,10 @@ import net.minecraft.world.CompoundContainer; import net.minecraft.world.Container; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.npc.ClientSideMerchant; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.PlayerEnderChestContainer; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/horse/AbstractHorseMixin_Carrier_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/equine/AbstractHorseMixin_Carrier_Inventory_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/horse/AbstractHorseMixin_Carrier_Inventory_API.java rename to src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/equine/AbstractHorseMixin_Carrier_Inventory_API.java index 3e0ab03763a..5088f481a98 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/horse/AbstractHorseMixin_Carrier_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/animal/equine/AbstractHorseMixin_Carrier_Inventory_API.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.inventory.api.world.entity.animal.horse; +package org.spongepowered.common.mixin.inventory.api.world.entity.animal.equine; import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import org.spongepowered.api.item.inventory.Carrier; import org.spongepowered.api.item.inventory.type.CarriedInventory; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/PillagerMixin_Carrier_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/illager/PillagerMixin_Carrier_Inventory_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/PillagerMixin_Carrier_Inventory_API.java rename to src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/illager/PillagerMixin_Carrier_Inventory_API.java index 7b3da8a4f4c..b631114f78e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/PillagerMixin_Carrier_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/monster/illager/PillagerMixin_Carrier_Inventory_API.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.inventory.api.world.entity.monster; +package org.spongepowered.common.mixin.inventory.api.world.entity.monster.illager; import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.monster.Pillager; +import net.minecraft.world.entity.monster.illager.Pillager; import org.spongepowered.api.item.inventory.Carrier; import org.spongepowered.api.item.inventory.type.CarriedInventory; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/AbstractVillagerMixin_Carrier_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/villager/AbstractVillagerMixin_Carrier_Inventory_API.java similarity index 96% rename from src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/AbstractVillagerMixin_Carrier_Inventory_API.java rename to src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/villager/AbstractVillagerMixin_Carrier_Inventory_API.java index 31ebb802dae..9a80f099b20 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/AbstractVillagerMixin_Carrier_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/npc/villager/AbstractVillagerMixin_Carrier_Inventory_API.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.inventory.api.world.entity.npc; +package org.spongepowered.common.mixin.inventory.api.world.entity.npc.villager; import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import org.spongepowered.api.item.inventory.Carrier; import org.spongepowered.api.item.inventory.type.CarriedInventory; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carried_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carried_Inventory_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carried_Inventory_API.java rename to src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carried_Inventory_API.java index 66aea21b821..59686c3b50d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carried_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carried_Inventory_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.inventory.api.world.entity.vehicle; +package org.spongepowered.common.mixin.inventory.api.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import org.spongepowered.api.entity.vehicle.minecart.carrier.CarrierMinecart; import org.spongepowered.api.item.inventory.type.CarriedInventory; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carrier_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carrier_Inventory_API.java similarity index 94% rename from src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carrier_Inventory_API.java rename to src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carrier_Inventory_API.java index c770d7e904c..dace7bfd2e5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/AbstractMinecartContainerMixin_Carrier_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/vehicle/minecart/AbstractMinecartContainerMixin_Carrier_Inventory_API.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.inventory.api.world.entity.vehicle; +package org.spongepowered.common.mixin.inventory.api.world.entity.vehicle.minecart; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import org.spongepowered.api.entity.vehicle.minecart.carrier.CarrierMinecart; import org.spongepowered.api.item.inventory.Carrier; import org.spongepowered.api.item.inventory.type.CarriedInventory; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index e785812bec4..5b2270743fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -40,7 +40,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -214,7 +214,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory method = "openHorseInventory", at = @At( value = "NEW", - target = "(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/animal/horse/AbstractHorse;I)Lnet/minecraft/world/inventory/HorseInventoryMenu;" + target = "(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/animal/equine/AbstractHorse;I)Lnet/minecraft/world/inventory/HorseInventoryMenu;" ) ) private HorseInventoryMenu impl$transactHorseInventoryMenuCreationWithEffect( diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java index 259d84bbe9d..bca9ba50105 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java @@ -30,7 +30,7 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MerchantContainer; import net.minecraft.world.inventory.ResultContainer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java index 69fa5771b1e..0a94588bee9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java @@ -26,9 +26,9 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.CompoundContainer; -import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.npc.ClientSideMerchant; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.PlayerEnderChestContainer; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java index 22771af4874..2e53bbb1954 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java @@ -27,8 +27,8 @@ import net.minecraft.world.CompoundContainer; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; -import net.minecraft.world.entity.vehicle.ChestBoat; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; +import net.minecraft.world.entity.vehicle.boat.ChestBoat; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MerchantContainer; import net.minecraft.world.inventory.ResultContainer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/HorseInventoryMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/HorseInventoryMenuMixin_TrackedMenuBridge_Inventory.java index 4566094a93a..c82724ff7a6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/HorseInventoryMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/HorseInventoryMenuMixin_TrackedMenuBridge_Inventory.java @@ -25,7 +25,7 @@ package org.spongepowered.common.mixin.inventory.impl.world.inventory; import net.minecraft.world.Container; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.HorseInventoryMenu; diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index 6efeb3485e2..67761185c8a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -36,19 +36,19 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ambient.AmbientCreature; import net.minecraft.world.entity.animal.Animal; -import net.minecraft.world.entity.animal.WaterAnimal; +import net.minecraft.world.entity.animal.fish.WaterAnimal; import net.minecraft.world.entity.animal.sheep.Sheep; -import net.minecraft.world.entity.boss.EnderDragonPart; +import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.wither.WitherBoss; -import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.decoration.painting.Painting; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.monster.Enemy; -import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.villager.Villager; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.entity.projectile.ThrowableProjectile; import net.minecraft.world.level.chunk.LevelChunk; diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 2772f46d459..5b7cd2e650e 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -108,7 +108,6 @@ "minecraft.world.entity.EntityTypeMixin_API", "minecraft.world.entity.ExperienceOrbMixin_API", "minecraft.world.entity.FlyingAnimalMixin_API", - "minecraft.world.entity.GlowSquidMixin_API", "minecraft.world.entity.HumanoidArmMixin_API", "minecraft.world.entity.InteractionMixin_API", "minecraft.world.entity.LeashableMixin_API", @@ -144,47 +143,43 @@ "minecraft.world.entity.ai.goal.target.TargetGoalMixin_API", "minecraft.world.entity.ambient.AmbientCreatureMixin_API", "minecraft.world.entity.ambient.BatMixin_API", - "minecraft.world.entity.animal.AbstractCowMixin_API", - "minecraft.world.entity.animal.AbstractFishMixin_API", - "minecraft.world.entity.animal.AbstractGolemMixin_API", - "minecraft.world.entity.animal.AbstractSchoolingFishMixin_API", + "minecraft.world.entity.animal.cow.AbstractCowMixin_API", + "minecraft.world.entity.animal.fish.AbstractFishMixin_API", + "minecraft.world.entity.animal.fish.AbstractSchoolingFishMixin_API", "minecraft.world.entity.animal.AgeableWaterCreatureMixin_API", "minecraft.world.entity.animal.AnimalMixin_API", - "minecraft.world.entity.animal.BeeMixin_API", - "minecraft.world.entity.animal.CatMixin_API", - "minecraft.world.entity.animal.CatVariantMixin_API", - "minecraft.world.entity.animal.ChickenMixin_API", - "minecraft.world.entity.animal.ChickenVariantMixin_API", - "minecraft.world.entity.animal.CodMixin_API", - "minecraft.world.entity.animal.CowVariantMixin_API", - "minecraft.world.entity.animal.DolphinMixin_API", + "minecraft.world.entity.animal.bee.BeeMixin_API", + "minecraft.world.entity.animal.feline.CatMixin_API", + "minecraft.world.entity.animal.feline.CatVariantMixin_API", + "minecraft.world.entity.animal.chicken.ChickenMixin_API", + "minecraft.world.entity.animal.chicken.ChickenVariantMixin_API", + "minecraft.world.entity.animal.fish.CodMixin_API", + "minecraft.world.entity.animal.cow.CowVariantMixin_API", + "minecraft.world.entity.animal.dolphin.DolphinMixin_API", "minecraft.world.entity.animal.FlyingAnimalMixin_API", - "minecraft.world.entity.animal.Fox_VariantMixin_API", - "minecraft.world.entity.animal.FoxMixin_API", - "minecraft.world.entity.animal.FrogVariantMixin_API", - "minecraft.world.entity.animal.IronGolemMixin_API", - "minecraft.world.entity.animal.MushroomCow_MushroomTypeMixin_API", - "minecraft.world.entity.animal.MushroomCowMixin_API", - "minecraft.world.entity.animal.OcelotMixin_API", - "minecraft.world.entity.animal.Panda_GeneMixin_API", - "minecraft.world.entity.animal.PandaMixin_API", - "minecraft.world.entity.animal.Parrot_VariantMixin_API", - "minecraft.world.entity.animal.ParrotMixin_API", - "minecraft.world.entity.animal.PigMixin_API", - "minecraft.world.entity.animal.PigVariantMixin_API", - "minecraft.world.entity.animal.PolarBearMixin_API", - "minecraft.world.entity.animal.PufferfishMixin_API", - "minecraft.world.entity.animal.Rabbit_VariantMixin_API", - "minecraft.world.entity.animal.RabbitMixin_API", - "minecraft.world.entity.animal.SalmonMixin_API", - "minecraft.world.entity.animal.SalmonVariantMixin_API", - "minecraft.world.entity.animal.ShoulderRidingEntityMixin_API", - "minecraft.world.entity.animal.SnowGolemMixin_API", - "minecraft.world.entity.animal.SquidMixin_API", - "minecraft.world.entity.animal.TropicalFish_PatternMixin_API", - "minecraft.world.entity.animal.TropicalFishMixin_API", - "minecraft.world.entity.animal.TurtleMixin_API", - "minecraft.world.entity.animal.WaterAnimalMixin_API", + "minecraft.world.entity.animal.fox.Fox_VariantMixin_API", + "minecraft.world.entity.animal.fox.FoxMixin_API", + "minecraft.world.entity.animal.frog.FrogVariantMixin_API", + "minecraft.world.entity.animal.cow.MushroomCow_MushroomTypeMixin_API", + "minecraft.world.entity.animal.cow.MushroomCowMixin_API", + "minecraft.world.entity.animal.feline.OcelotMixin_API", + "minecraft.world.entity.animal.panda.Panda_GeneMixin_API", + "minecraft.world.entity.animal.panda.PandaMixin_API", + "minecraft.world.entity.animal.parrot.Parrot_VariantMixin_API", + "minecraft.world.entity.animal.parrot.ParrotMixin_API", + "minecraft.world.entity.animal.pig.PigMixin_API", + "minecraft.world.entity.animal.pig.PigVariantMixin_API", + "minecraft.world.entity.animal.polarbear.PolarBearMixin_API", + "minecraft.world.entity.animal.fish.PufferfishMixin_API", + "minecraft.world.entity.animal.rabbit.Rabbit_VariantMixin_API", + "minecraft.world.entity.animal.rabbit.RabbitMixin_API", + "minecraft.world.entity.animal.fish.SalmonMixin_API", + "minecraft.world.entity.animal.fish.SalmonVariantMixin_API", + "minecraft.world.entity.animal.parrot.ShoulderRidingEntityMixin_API", + "minecraft.world.entity.animal.fish.TropicalFish_PatternMixin_API", + "minecraft.world.entity.animal.fish.TropicalFishMixin_API", + "minecraft.world.entity.animal.turtle.TurtleMixin_API", + "minecraft.world.entity.animal.fish.WaterAnimalMixin_API", "minecraft.world.entity.animal.allay.AllayMixin_API", "minecraft.world.entity.animal.armadillo.ArmadilloMixin_API", "minecraft.world.entity.animal.axolotl.AxolotlMixin_API", @@ -194,27 +189,33 @@ "minecraft.world.entity.animal.frog.FrogMixin_API", "minecraft.world.entity.animal.frog.TadpoleMixin_API", "minecraft.world.entity.animal.goat.GoatMixin_API", - "minecraft.world.entity.animal.horse.AbstractChestedHorseMixin_API", - "minecraft.world.entity.animal.horse.AbstractHorseMixin_API", - "minecraft.world.entity.animal.horse.DonkeyMixin_API", - "minecraft.world.entity.animal.horse.HorseMixin_API", - "minecraft.world.entity.animal.horse.LLama_VariantMixin_API", - "minecraft.world.entity.animal.horse.LlamaMixin_API", - "minecraft.world.entity.animal.horse.MarkingsMixin_API", - "minecraft.world.entity.animal.horse.MuleMixin_API", - "minecraft.world.entity.animal.horse.SkeletonHorseMixin_API", - "minecraft.world.entity.animal.horse.TraderLlamaMixin_API", - "minecraft.world.entity.animal.horse.VariantMixin_API", - "minecraft.world.entity.animal.horse.ZombieHorseMixin_API", + "minecraft.world.entity.animal.golem.AbstractGolemMixin_API", + "minecraft.world.entity.animal.golem.CopperGolemMixin_API", + "minecraft.world.entity.animal.golem.IronGolemMixin_API", + "minecraft.world.entity.animal.golem.SnowGolemMixin_API", + "minecraft.world.entity.animal.equine.AbstractChestedHorseMixin_API", + "minecraft.world.entity.animal.equine.AbstractHorseMixin_API", + "minecraft.world.entity.animal.equine.DonkeyMixin_API", + "minecraft.world.entity.animal.equine.HorseMixin_API", + "minecraft.world.entity.animal.equine.LLama_VariantMixin_API", + "minecraft.world.entity.animal.equine.LlamaMixin_API", + "minecraft.world.entity.animal.equine.MarkingsMixin_API", + "minecraft.world.entity.animal.equine.MuleMixin_API", + "minecraft.world.entity.animal.equine.SkeletonHorseMixin_API", + "minecraft.world.entity.animal.equine.TraderLlamaMixin_API", + "minecraft.world.entity.animal.equine.VariantMixin_API", + "minecraft.world.entity.animal.equine.ZombieHorseMixin_API", "minecraft.world.entity.animal.nautilus.AbstractNautilusMixin_API", "minecraft.world.entity.animal.nautilus.NautilusMixin_API", "minecraft.world.entity.animal.nautilus.ZombieNautilusMixin_API", "minecraft.world.entity.animal.sheep.SheepMixin_API", "minecraft.world.entity.animal.sniffer.SnifferMixin_API", + "minecraft.world.entity.animal.squid.GlowSquidMixin_API", + "minecraft.world.entity.animal.squid.SquidMixin_API", "minecraft.world.entity.animal.wolf.WolfMixin_API", "minecraft.world.entity.animal.wolf.WolfSoundVariantMixin_API", "minecraft.world.entity.animal.wolf.WolfVariantMixin_API", - "minecraft.world.entity.boss.EnderDragonPartMixin_API", + "minecraft.world.entity.boss.enderdragon.EnderDragonPartMixin_API", "minecraft.world.entity.boss.enderdragon.EndCrystalMixin_API", "minecraft.world.entity.boss.enderdragon.EnderDragonMixin_API", "minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstanceMixin_API", @@ -226,112 +227,112 @@ "minecraft.world.entity.decoration.HangingEntityMixin_API", "minecraft.world.entity.decoration.ItemFrameMixin_API", "minecraft.world.entity.decoration.LeashFenceKnotEntityMixin_API", - "minecraft.world.entity.decoration.PaintingMixin_API", - "minecraft.world.entity.decoration.PaintingVariantMixin_API", + "minecraft.world.entity.decoration.painting.PaintingMixin_API", + "minecraft.world.entity.decoration.painting.PaintingVariantMixin_API", "minecraft.world.entity.item.FallingBlockEntityMixin_API", "minecraft.world.entity.item.ItemEntityMixin_API", "minecraft.world.entity.item.PrimedTntMixin_API", - "minecraft.world.entity.monster.AbstractIllagerMixin_API", - "minecraft.world.entity.monster.AbstractPiglinMixin_API", - "minecraft.world.entity.monster.AbstractSkeletonMixin_API", "minecraft.world.entity.monster.BlazeMixin_API", - "minecraft.world.entity.monster.BoggedMixin_API", - "minecraft.world.entity.monster.BreezeMixin_API", - "minecraft.world.entity.monster.CaveSpiderMixin_API", "minecraft.world.entity.monster.CreeperMixin_API", - "minecraft.world.entity.monster.DrownedMixin_API", "minecraft.world.entity.monster.ElderGuardianMixin_API", "minecraft.world.entity.monster.EnderManMixin_API", "minecraft.world.entity.monster.EndermiteMixin_API", "minecraft.world.entity.monster.EnemyMixin_API", - "minecraft.world.entity.monster.EvokerMixin_API", "minecraft.world.entity.monster.GhastMixin_API", "minecraft.world.entity.monster.GiantMixin_API", "minecraft.world.entity.monster.GuardianMixin_API", - "minecraft.world.entity.monster.HoglinMixin_API", - "minecraft.world.entity.monster.HuskMixin_API", - "minecraft.world.entity.monster.IllusionerMixin_API", "minecraft.world.entity.monster.MagmaCubeMixin_API", "minecraft.world.entity.monster.MonsterMixin_API", - "minecraft.world.entity.monster.ParchedMixin_API", "minecraft.world.entity.monster.PatrollingMonsterMixin_API", "minecraft.world.entity.monster.Phantom_AttackPhaseMixin_API", "minecraft.world.entity.monster.PhantomMixin_API", - "minecraft.world.entity.monster.PiglinBruteMixin_API", - "minecraft.world.entity.monster.PiglinMixin_API", - "minecraft.world.entity.monster.PillagerMixin_API", "minecraft.world.entity.monster.RangedAttackMobMixin_API", "minecraft.world.entity.monster.RavagerMixin_API", "minecraft.world.entity.monster.ShulkerMixin_API", "minecraft.world.entity.monster.SilverfishMixin_API", - "minecraft.world.entity.monster.SkeletonMixin_API", "minecraft.world.entity.monster.SlimeMixin_API", - "minecraft.world.entity.monster.SpellcasterIllager_IllagerSpellMixin_API", - "minecraft.world.entity.monster.SpellcasterIllagerMixin_API", - "minecraft.world.entity.monster.SpiderMixin_API", - "minecraft.world.entity.monster.StrayMixin_API", "minecraft.world.entity.monster.StriderMixin_API", "minecraft.world.entity.monster.VexMixin_API", - "minecraft.world.entity.monster.VindicatorMixin_API", "minecraft.world.entity.monster.WitchMixin_API", - "minecraft.world.entity.monster.WitherSkeletonMixin_API", "minecraft.world.entity.monster.ZoglinMixin_API", - "minecraft.world.entity.monster.ZombieMixin_API", - "minecraft.world.entity.monster.ZombieVillagerMixin_API", - "minecraft.world.entity.monster.ZombifiedPiglinMixin_API", + "minecraft.world.entity.monster.breeze.BreezeMixin_API", + "minecraft.world.entity.monster.hoglin.HoglinMixin_API", + "minecraft.world.entity.monster.illager.AbstractIllagerMixin_API", + "minecraft.world.entity.monster.illager.EvokerMixin_API", + "minecraft.world.entity.monster.illager.IllusionerMixin_API", + "minecraft.world.entity.monster.illager.PillagerMixin_API", + "minecraft.world.entity.monster.illager.SpellcasterIllager_IllagerSpellMixin_API", + "minecraft.world.entity.monster.illager.SpellcasterIllagerMixin_API", + "minecraft.world.entity.monster.illager.VindicatorMixin_API", + "minecraft.world.entity.monster.piglin.AbstractPiglinMixin_API", + "minecraft.world.entity.monster.piglin.PiglinBruteMixin_API", + "minecraft.world.entity.monster.piglin.PiglinMixin_API", + "minecraft.world.entity.monster.skeleton.AbstractSkeletonMixin_API", + "minecraft.world.entity.monster.skeleton.BoggedMixin_API", + "minecraft.world.entity.monster.skeleton.ParchedMixin_API", + "minecraft.world.entity.monster.skeleton.SkeletonMixin_API", + "minecraft.world.entity.monster.skeleton.StrayMixin_API", + "minecraft.world.entity.monster.skeleton.WitherSkeletonMixin_API", + "minecraft.world.entity.monster.spider.CaveSpiderMixin_API", + "minecraft.world.entity.monster.spider.SpiderMixin_API", "minecraft.world.entity.monster.warden.WardenMixin_API", - "minecraft.world.entity.npc.AbstractVillagerMixin_API", - "minecraft.world.entity.npc.VillagerMixin_API", - "minecraft.world.entity.npc.VillagerProfessionMixin_API", - "minecraft.world.entity.npc.VillagerTrades_ItemListingMixin_API", - "minecraft.world.entity.npc.VillagerTypeMixin_API", - "minecraft.world.entity.npc.WanderingTraderMixin_API", + "minecraft.world.entity.monster.zombie.DrownedMixin_API", + "minecraft.world.entity.monster.zombie.HuskMixin_API", + "minecraft.world.entity.monster.zombie.ZombieMixin_API", + "minecraft.world.entity.monster.zombie.ZombieVillagerMixin_API", + "minecraft.world.entity.monster.zombie.ZombifiedPiglinMixin_API", + "minecraft.world.entity.npc.villager.AbstractVillagerMixin_API", + "minecraft.world.entity.npc.villager.VillagerMixin_API", + "minecraft.world.entity.npc.villager.VillagerProfessionMixin_API", + "minecraft.world.entity.npc.villager.VillagerTrades_ItemListingMixin_API", + "minecraft.world.entity.npc.villager.VillagerTypeMixin_API", + "minecraft.world.entity.npc.wanderingtrader.WanderingTraderMixin_API", "minecraft.world.entity.player.ChatVisiblityMixin_API", "minecraft.world.entity.player.PlayerMixin_API", - "minecraft.world.entity.projectile.AbstractArrow_PickupMixin_API", - "minecraft.world.entity.projectile.AbstractArrowMixin_API", - "minecraft.world.entity.projectile.AbstractHurtingProjectileMixin_API", - "minecraft.world.entity.projectile.ArrowMixin_API", - "minecraft.world.entity.projectile.DragonFireballMixin_API", "minecraft.world.entity.projectile.EvokerFangsMixin_API", "minecraft.world.entity.projectile.EyeOfEnderMixin_API", - "minecraft.world.entity.projectile.FireballMixin_API", "minecraft.world.entity.projectile.FireworkRocketEntityMixin_API", "minecraft.world.entity.projectile.FishingHookMixin_API", "minecraft.world.entity.projectile.ItemSupplierMixin_API", - "minecraft.world.entity.projectile.LargeFireballMixin_API", "minecraft.world.entity.projectile.LlamaSpitMixin_API", "minecraft.world.entity.projectile.ProjectileMixin_API", "minecraft.world.entity.projectile.ShulkerBulletMixin_API", - "minecraft.world.entity.projectile.SmallFireballMixin_API", - "minecraft.world.entity.projectile.SnowballMixin_API", - "minecraft.world.entity.projectile.SpectralArrowMixin_API", - "minecraft.world.entity.projectile.ThrowableItemProjectileMixin_API", "minecraft.world.entity.projectile.ThrowableProjectileMixin_API", - "minecraft.world.entity.projectile.ThrownEggMixin_API", - "minecraft.world.entity.projectile.ThrownEnderpearlMixin_API", - "minecraft.world.entity.projectile.ThrownExperienceBottleMixin_API", - "minecraft.world.entity.projectile.ThrownPotionMixin_API", - "minecraft.world.entity.projectile.ThrownTridentMixin_API", - "minecraft.world.entity.projectile.WitherSkullMixin_API", - "minecraft.world.entity.projectile.windcharge.AbstractWindChargeMixin_API", - "minecraft.world.entity.projectile.windcharge.BreezeWindChargeMixin_API", - "minecraft.world.entity.projectile.windcharge.WindChargeMixin_API", + "minecraft.world.entity.projectile.arrow.AbstractArrow_PickupMixin_API", + "minecraft.world.entity.projectile.arrow.AbstractArrowMixin_API", + "minecraft.world.entity.projectile.arrow.ArrowMixin_API", + "minecraft.world.entity.projectile.arrow.SpectralArrowMixin_API", + "minecraft.world.entity.projectile.arrow.ThrownTridentMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectileMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.DragonFireballMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.FireballMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.LargeFireballMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.SmallFireballMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.WitherSkullMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.windcharge.AbstractWindChargeMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.windcharge.BreezeWindChargeMixin_API", + "minecraft.world.entity.projectile.hurtingprojectile.windcharge.WindChargeMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.SnowballMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.ThrowableItemProjectileMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.ThrownEggMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearlMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.ThrownExperienceBottleMixin_API", + "minecraft.world.entity.projectile.throwableitemprojectile.ThrownPotionMixin_API", "minecraft.world.entity.raid.Raid_RaidStatusMixin_API", "minecraft.world.entity.raid.RaiderMixin_API", "minecraft.world.entity.raid.RaidMixin_API", - "minecraft.world.entity.vehicle.AbstractBoatMixin_API", - "minecraft.world.entity.vehicle.AbstractChestBoatMixin_API", - "minecraft.world.entity.vehicle.AbstractMinecartContainerMixin_API", - "minecraft.world.entity.vehicle.AbstractMinecartMixin_API", - "minecraft.world.entity.vehicle.MinecartChestMixin_API", - "minecraft.world.entity.vehicle.MinecartCommandBlockMixin_API", - "minecraft.world.entity.vehicle.MinecartFurnaceMixin_API", - "minecraft.world.entity.vehicle.MinecartHopperMixin_API", - "minecraft.world.entity.vehicle.MinecartMixin_API", - "minecraft.world.entity.vehicle.MinecartSpawnerMixin_API", - "minecraft.world.entity.vehicle.MinecartTNTMixin_API", "minecraft.world.entity.vehicle.VehicleEntityMixin_API", + "minecraft.world.entity.vehicle.boat.AbstractBoatMixin_API", + "minecraft.world.entity.vehicle.boat.AbstractChestBoatMixin_API", + "minecraft.world.entity.vehicle.minecart.AbstractMinecartContainerMixin_API", + "minecraft.world.entity.vehicle.minecart.AbstractMinecartMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartChestMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartCommandBlockMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartFurnaceMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartHopperMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartSpawnerMixin_API", + "minecraft.world.entity.vehicle.minecart.MinecartTNTMixin_API", "minecraft.world.item.ArmorMaterialMixin_API", "minecraft.world.item.DyeColorMixin_API", "minecraft.world.item.FireworkExplosion_ShapeMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 89f424f51e9..ce7a1f480d1 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -143,12 +143,12 @@ "world.entity.ai.sensing.NearestLivingEntitySensorMixin", "world.entity.ai.sensing.SensorMixin", "world.entity.animal.AnimalMixin", - "world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin", - "world.entity.animal.OcelotMixin", - "world.entity.animal.ParrotMixin", - "world.entity.animal.PufferfishMixin", - "world.entity.animal.Rabbit_RaidGardenGoalMixin", - "world.entity.animal.horse.AbstractHorseMixin", + "world.entity.animal.feline.Cat_CatRelaxOnOwnerGoalMixin", + "world.entity.animal.feline.OcelotMixin", + "world.entity.animal.parrot.ParrotMixin", + "world.entity.animal.fish.PufferfishMixin", + "world.entity.animal.rabbit.Rabbit_RaidGardenGoalMixin", + "world.entity.animal.equine.AbstractHorseMixin", "world.entity.animal.wolf.WolfMixin", "world.entity.boss.enderdragon.EndCrystalMixin", "world.entity.decoration.ArmorStandMixin", @@ -168,37 +168,37 @@ "world.entity.monster.ShulkerMixin", "world.entity.monster.Silverfish_SilverfishMergeWithStoneGoalMixin", "world.entity.monster.Silverfish_SilverfishWakeUpFriendsGoalMixin", - "world.entity.monster.ZombifiedPiglinMixin", - "world.entity.npc.AbstractVillagerMixin", - "world.entity.npc.VillagerMixin", - "world.entity.npc.WanderingTraderMixin", + "world.entity.monster.zombie.ZombifiedPiglinMixin", + "world.entity.npc.villager.AbstractVillagerMixin", + "world.entity.npc.villager.VillagerMixin", + "world.entity.npc.wanderingtrader.WanderingTraderMixin", "world.entity.player.PlayerMixin", "world.entity.player.PlayerMixin_Attack", - "world.entity.projectile.AbstractArrowMixin", - "world.entity.projectile.AbstractHurtingProjectileMixin", + "world.entity.projectile.arrow.AbstractArrowMixin", + "world.entity.projectile.hurtingprojectile.AbstractHurtingProjectileMixin", "world.entity.projectile.EyeOfEnderMixin", "world.entity.projectile.FireworkRocketEntityMixin", "world.entity.projectile.FishingHookMixin", - "world.entity.projectile.LargeFireballMixin", + "world.entity.projectile.hurtingprojectile.LargeFireballMixin", "world.entity.projectile.LlamaSpitMixin", "world.entity.projectile.ProjectileMixin", "world.entity.projectile.ProjectileUtilMixin", "world.entity.projectile.ShulkerBulletMixin", - "world.entity.projectile.SmallFireballMixin", - "world.entity.projectile.SnowballMixin", + "world.entity.projectile.hurtingprojectile.SmallFireballMixin", + "world.entity.projectile.throwableitemprojectile.SnowballMixin", "world.entity.projectile.ThrowableProjectileMixin", - "world.entity.projectile.ThrownEggMixin", - "world.entity.projectile.ThrownEnderpearlMixin", - "world.entity.projectile.ThrownTridentMixin", - "world.entity.projectile.WitherSkullMixin", - "world.entity.vehicle.AbstractBoatMixin", - "world.entity.vehicle.AbstractMinecartContainerMixin", - "world.entity.vehicle.AbstractMinecartMixin", - "world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin", - "world.entity.vehicle.MinecartCommandBlockMixin", - "world.entity.vehicle.MinecartFurnaceMixin", - "world.entity.vehicle.MinecartTNTMixin", - "world.entity.vehicle.OldMinecartBehaviourMixin", + "world.entity.projectile.throwableitemprojectile.ThrownEggMixin", + "world.entity.projectile.throwableitemprojectile.ThrownEnderpearlMixin", + "world.entity.projectile.arrow.ThrownTridentMixin", + "world.entity.projectile.hurtingprojectile.WitherSkullMixin", + "world.entity.vehicle.boat.AbstractBoatMixin", + "world.entity.vehicle.minecart.AbstractMinecartContainerMixin", + "world.entity.vehicle.minecart.AbstractMinecartMixin", + "world.entity.vehicle.minecart.MinecartCommandBlock_MinecartCommandBaseMixin", + "world.entity.vehicle.minecart.MinecartCommandBlockMixin", + "world.entity.vehicle.minecart.MinecartFurnaceMixin", + "world.entity.vehicle.minecart.MinecartTNTMixin", + "world.entity.vehicle.minecart.OldMinecartBehaviourMixin", "world.entity.vehicle.VehicleEntityMixin", "world.food.FoodDataMixin", "world.inventory.StonecutterMenuMixin", diff --git a/src/mixins/resources/mixins.sponge.entityactivation.json b/src/mixins/resources/mixins.sponge.entityactivation.json index 79fd4a3428c..7e0303e48d3 100644 --- a/src/mixins/resources/mixins.sponge.entityactivation.json +++ b/src/mixins/resources/mixins.sponge.entityactivation.json @@ -8,7 +8,7 @@ "entity.LivingEntityMixin_Activation", "entity.item.FireworkRocketEntityMixin_EntityActivation", "entity.item.ItemEntityMixin_EntityActivation", - "entity.projectile.AbstractArrowEntityMixin_EntityActivation", + "entity.projectile.arrow.AbstractArrowEntityMixin_EntityActivation", "world.server.ServerLevelMixin_EntityActivation" ] } diff --git a/src/mixins/resources/mixins.sponge.inventory.json b/src/mixins/resources/mixins.sponge.inventory.json index 6ea796e028c..27918fbc51a 100644 --- a/src/mixins/resources/mixins.sponge.inventory.json +++ b/src/mixins/resources/mixins.sponge.inventory.json @@ -20,14 +20,14 @@ "api.world.entity.EquipmentSlot_TypeMixin_Inventory_API", "api.world.entity.EquipmentSlotGroupMixin_Inventory_API", "api.world.entity.EquipmentSlotMixin_Inventory_API", - "api.world.entity.animal.horse.AbstractHorseMixin_Carrier_Inventory_API", - "api.world.entity.monster.PillagerMixin_Carrier_Inventory_API", - "api.world.entity.npc.AbstractVillagerMixin_Carrier_Inventory_API", + "api.world.entity.animal.equine.AbstractHorseMixin_Carrier_Inventory_API", + "api.world.entity.monster.illager.PillagerMixin_Carrier_Inventory_API", + "api.world.entity.npc.villager.AbstractVillagerMixin_Carrier_Inventory_API", "api.world.entity.player.InventoryMixin_Carried_Inventory_API", "api.world.entity.player.InventoryMixin_Inventory_API", "api.world.entity.player.PlayerMixin_Inventory_API", - "api.world.entity.vehicle.AbstractMinecartContainerMixin_Carried_Inventory_API", - "api.world.entity.vehicle.AbstractMinecartContainerMixin_Carrier_Inventory_API", + "api.world.entity.vehicle.minecart.AbstractMinecartContainerMixin_Carried_Inventory_API", + "api.world.entity.vehicle.minecart.AbstractMinecartContainerMixin_Carrier_Inventory_API", "api.world.inventory.AnvilMenuMixin_BlockCarrier_Inventory_API", "api.world.inventory.ArmorSlot_Inventory_API", "api.world.inventory.BrewingStandMenu_PotionSlotMixin_Inventory_API", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/golem/SnowGolemMixin_Vanilla.java similarity index 96% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java rename to vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/golem/SnowGolemMixin_Vanilla.java index 95b2c7ea3d0..23198ebae2e 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/SnowGolemMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/animal/golem/SnowGolemMixin_Vanilla.java @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.mixin.core.world.entity.animal; +package org.spongepowered.vanilla.mixin.core.world.entity.animal.golem; -import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.entity.animal.golem.SnowGolem; import net.minecraft.world.level.gamerules.GameRule; import net.minecraft.world.level.gamerules.GameRules; import org.spongepowered.asm.mixin.Mixin; diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Vanilla.java similarity index 96% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java rename to vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Vanilla.java index 693141a973a..fddc1321515 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/AbstractBoatMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Vanilla.java @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.mixin.core.world.entity.vehicle; +package org.spongepowered.vanilla.mixin.core.world.entity.vehicle.boat; -import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import org.spongepowered.asm.mixin.Mixin; diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 6c6e9c2c14b..887d035d10a 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -35,10 +35,10 @@ "world.entity.LivingEntityMixin_Vanilla", "world.entity.LivingEntityMixin_Vanilla_Damage", "world.entity.ai.attributes.DefaultAttributesMixin", - "world.entity.animal.SnowGolemMixin_Vanilla", + "world.entity.animal.golem.SnowGolemMixin_Vanilla", "world.entity.item.ItemEntityMixin_Vanilla", "world.entity.player.PlayerMixin_Vanilla_Damage", - "world.entity.vehicle.AbstractBoatMixin_Vanilla", + "world.entity.vehicle.boat.AbstractBoatMixin_Vanilla", "world.level.ServerExplosionMixin_Vanilla", "world.level.block.FireBlockMixin_Vanilla", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", From a50bebcd30b1fa36b680a085566e80f9c00dc524 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 10 Dec 2025 00:43:13 -0800 Subject: [PATCH 425/586] feat(minecraft): update to 1.21.11-pre2 Notable Changes: - Minor package class shuffles - Updated verification metadata See https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_2 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 6 ++++++ .../common/entity/projectile/ProjectileUtil.java | 2 +- .../registry/loader/VanillaRegistryLoader.java | 14 +++++++------- .../entity/animal/golem/CopperGolemMixin_API.java | 1 - .../AbstractHurtingProjectileMixin.java | 2 +- .../api/TraitMixin_Viewable_Inventory_API.java | 2 +- .../impl/TraitMixin_ViewableBridge_Inventory.java | 2 +- .../TraitMixin_TrackedMenuBridge_Inventory.java | 2 +- .../entityactivation/EntityActivationRange.java | 4 ++-- 10 files changed, 21 insertions(+), 16 deletions(-) diff --git a/gradle.properties b/gradle.properties index b5c947e420d..5041998aa68 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=1.21.11-pre1 +minecraftVersion=1.21.11-pre2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 94cd74e12d1..8a3e0c5c8f2 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1812,12 +1812,18 @@ + + + + + + diff --git a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java index 653feb40438..83883aaf397 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/ProjectileUtil.java @@ -33,8 +33,8 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; import net.minecraft.world.entity.projectile.ThrowableProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEgg; import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownEnderpearl; import net.minecraft.world.entity.projectile.throwableitemprojectile.ThrownExperienceBottle; diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index d794771f31e..aa2f8449fbd 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -40,17 +40,17 @@ import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.animal.fox.Fox; -import net.minecraft.world.entity.animal.cow.MushroomCow; -import net.minecraft.world.entity.animal.panda.Panda; -import net.minecraft.world.entity.animal.parrot.Parrot; -import net.minecraft.world.entity.animal.rabbit.Rabbit; -import net.minecraft.world.entity.animal.fish.Salmon; -import net.minecraft.world.entity.animal.fish.TropicalFish; import net.minecraft.world.entity.animal.axolotl.Axolotl; +import net.minecraft.world.entity.animal.cow.MushroomCow; import net.minecraft.world.entity.animal.equine.Llama; import net.minecraft.world.entity.animal.equine.Markings; import net.minecraft.world.entity.animal.equine.Variant; +import net.minecraft.world.entity.animal.fish.Salmon; +import net.minecraft.world.entity.animal.fish.TropicalFish; +import net.minecraft.world.entity.animal.fox.Fox; +import net.minecraft.world.entity.animal.panda.Panda; +import net.minecraft.world.entity.animal.parrot.Parrot; +import net.minecraft.world.entity.animal.rabbit.Rabbit; import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; import net.minecraft.world.entity.monster.Phantom; import net.minecraft.world.entity.monster.illager.SpellcasterIllager; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java index daaf5c310c1..e759e96fcf0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/golem/CopperGolemMixin_API.java @@ -25,7 +25,6 @@ package org.spongepowered.common.mixin.api.minecraft.world.entity.animal.golem; import org.spongepowered.api.entity.living.golem.CopperGolem; -import org.spongepowered.api.entity.living.golem.SnowGolem; import org.spongepowered.asm.mixin.Mixin; @Mixin(net.minecraft.world.entity.animal.golem.CopperGolem.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java index dd91edf01b5..d1354b772d2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/hurtingprojectile/AbstractHurtingProjectileMixin.java @@ -25,8 +25,8 @@ package org.spongepowered.common.mixin.core.world.entity.projectile.hurtingprojectile; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.entity.projectile.ProjectileDeflection; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java index aa64527414e..a1b2efe37c7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_Viewable_Inventory_API.java @@ -26,8 +26,8 @@ import net.minecraft.world.CompoundContainer; import net.minecraft.world.Container; -import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.npc.ClientSideMerchant; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.PlayerEnderChestContainer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java index 0a94588bee9..743832b4643 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_ViewableBridge_Inventory.java @@ -26,8 +26,8 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.CompoundContainer; -import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.npc.ClientSideMerchant; +import net.minecraft.world.entity.npc.villager.AbstractVillager; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.PlayerEnderChestContainer; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java index 2e53bbb1954..6a27e19b411 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/TraitMixin_TrackedMenuBridge_Inventory.java @@ -27,8 +27,8 @@ import net.minecraft.world.CompoundContainer; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.entity.vehicle.boat.ChestBoat; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MerchantContainer; import net.minecraft.world.inventory.ResultContainer; diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index 67761185c8a..381d1dd41ed 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -38,9 +38,9 @@ import net.minecraft.world.entity.animal.Animal; import net.minecraft.world.entity.animal.fish.WaterAnimal; import net.minecraft.world.entity.animal.sheep.Sheep; -import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; import net.minecraft.world.entity.boss.wither.WitherBoss; import net.minecraft.world.entity.decoration.painting.Painting; import net.minecraft.world.entity.item.FallingBlockEntity; @@ -48,9 +48,9 @@ import net.minecraft.world.entity.monster.Enemy; import net.minecraft.world.entity.npc.villager.Villager; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.entity.projectile.ThrowableProjectile; +import net.minecraft.world.entity.projectile.hurtingprojectile.AbstractHurtingProjectile; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.entity.EntitySection; import net.minecraft.world.level.entity.EntitySectionStorage; From db788f75293b2aeac3238b6f7c6443c77621167f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 10 Dec 2025 01:08:55 -0800 Subject: [PATCH 426/586] feat(minecraft): update to 1.21.11 Notable Changes: - Updated to the stable release of 1.21.11 See https://minecraft.wiki/w/Java_Edition_1.21.11 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++++++ .../common/mixin/core/client/MinecraftMixin.java | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5041998aa68..32043ccde3d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=1.21.11-pre2 +minecraftVersion=1.21.11 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 8a3e0c5c8f2..3c0e3f57ae9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -33,6 +33,14 @@ + + + + + + + + diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index 1dfa562ce15..e2cc02207db 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -105,7 +105,7 @@ public MinecraftMixin(String param0) { Launch.instance().lifecycle().callStoppingEngineEvent(this); } - @Redirect(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;Z)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;singleplayerServer:Lnet/minecraft/client/server/IntegratedServer;", opcode = + @Redirect(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;ZZ)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;singleplayerServer:Lnet/minecraft/client/server/IntegratedServer;", opcode = Opcodes.PUTFIELD)) private void impl$storeTemporaryServerRef(Minecraft minecraft, IntegratedServer server) { ((MinecraftBridge) minecraft).bridge$setTemporaryIntegratedServer(this.singleplayerServer); From 3068e03506393e69ae6c19b497f425d6552f2c86 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 10 Dec 2025 13:27:45 +0100 Subject: [PATCH 427/586] Avoid recursion as much as possible when searching for a spawn (#4258) Fix MC-304426 and #4253 --- .../server/level/PlayerSpawnFinderMixin.java | 139 ++++++++++++++++++ src/mixins/resources/mixins.sponge.core.json | 3 +- 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java new file mode 100644 index 00000000000..da503e41a34 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java @@ -0,0 +1,139 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.server.level; + +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.PlayerSpawnFinder; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.TicketType; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.CollisionGetter; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +@Mixin(PlayerSpawnFinder.class) +public abstract class PlayerSpawnFinderMixin { + + @Shadow @Final private CompletableFuture finishedFuture; + @Shadow @Final private ServerLevel level; + @Shadow @Final private BlockPos spawnSuggestion; + @Shadow @Final private int radius; + @Shadow @Final private int candidateCount; + @Shadow private int nextCandidateIndex; + @Shadow @Final private int offset; + @Shadow @Final private int coprime; + + @Shadow private static Vec3 fixupSpawnHeight(CollisionGetter level, BlockPos pos) { return null; } + @Shadow @Nullable protected static BlockPos getOverworldRespawnPos(ServerLevel level, int x, int z) { return null; } + @Shadow private static boolean noCollisionNoLiquid(CollisionGetter level, BlockPos pos) { return false; } + + /** + * A mix of loop and recursion. + * Loop is preferred when possible. + * + * @author Yeregorix + * @reason Fix MC-304426. + */ + @Overwrite + private void scheduleNext() { + int i; + while ((i = this.nextCandidateIndex++) < this.candidateCount) { + if (this.finishedFuture.isDone()) { + return; + } + + final int candidate = (this.offset + this.coprime * i) % this.candidateCount; + final int relX = candidate % (this.radius * 2 + 1); + final int relZ = candidate / (this.radius * 2 + 1); + final int x = this.spawnSuggestion.getX() + relX - this.radius; + final int z = this.spawnSuggestion.getZ() + relZ - this.radius; + + if (this.scheduleCandidate(x, z, i, () -> { + final BlockPos pos = getOverworldRespawnPos(this.level, x, z); + return pos != null && noCollisionNoLiquid(this.level, pos) ? Optional.of(Vec3.atBottomCenterOf(pos)) : Optional.empty(); + })) { + return; + } + } + + if (this.finishedFuture.isDone()) { + return; + } + + scheduleCandidate(this.spawnSuggestion.getX(), this.spawnSuggestion.getZ(), i, () -> Optional.of(fixupSpawnHeight(this.level, this.spawnSuggestion))); + } + + private boolean scheduleCandidate(final int x, final int z, final int index, final Supplier> supplier) { + final int chunkX = SectionPos.blockToSectionCoord(x); + final int chunkZ = SectionPos.blockToSectionCoord(z); + final CompletableFuture future = this.level.getChunkSource().addTicketAndLoadWithRadius(TicketType.SPAWN_SEARCH, new ChunkPos(chunkX, chunkZ), 0); + final MinecraftServer server = this.level.getServer(); + + // We exit either the loop or the recursion, depending on what happens first. + final AtomicBoolean exit = new AtomicBoolean(true); + + future.whenCompleteAsync((chunk, error) -> { + if (error == null) { + try { + Optional result = supplier.get(); + if (result.isPresent()) { + this.finishedFuture.complete(result.get()); + } else if (!exit.getAndSet(false)) { + this.scheduleNext(); + } + } catch (Exception exception) { + error = exception; + } + } + + if (error != null) { + CrashReport report = CrashReport.forThrowable(error, "Searching for spawn"); + CrashReportCategory category = report.addCategory("Spawn Lookup"); + category.setDetail("Origin", this.spawnSuggestion::toString); + category.setDetail("Radius", () -> Integer.toString(this.radius)); + category.setDetail("Candidate", () -> "[" + x + "," + z + "]"); + category.setDetail("Progress", () -> index + " out of " + this.candidateCount); + this.finishedFuture.completeExceptionally(new ReportedException(report)); + } + }, server); + + return exit.getAndSet(false); + } +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 7481d2c397e..f90170ea8bf 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -76,6 +76,7 @@ "server.level.ChunkMapMixin", "server.level.DistanceManagerMixin", "server.level.GenerationChunkHolderMixin", + "server.level.PlayerSpawnFinderMixin", "server.level.ServerBossEventMixin", "server.level.ServerChunkCacheMixin", "server.level.ServerEntityMixin", @@ -130,7 +131,6 @@ "world.entity.LightningBoltMixin", "world.entity.LivingEntityMixin", "world.entity.LivingEntityMixin_Damage", - "world.entity.decoration.MannequinMixin", "world.entity.MobMixin", "world.entity.MobMixin_Attack", "world.entity.PortalProcessorMixin", @@ -156,6 +156,7 @@ "world.entity.decoration.BlockAttachedEntityMixin", "world.entity.decoration.HangingEntityMixin", "world.entity.decoration.ItemFrameMixin", + "world.entity.decoration.MannequinMixin", "world.entity.item.ItemEntityMixin", "world.entity.item.PrimedTntMixin", "world.entity.monster.Blaze_BlazeAttackGoalMixin", From cf63e894402c7771b7963912e917324a8627b4f7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 10 Dec 2025 13:35:01 -0800 Subject: [PATCH 428/586] feat(forge): update to 1.21.11 See https://minecraft.wiki/w/Java_Edition_1.21.11 See https://maven.minecraftforge.net/net/minecraftforge/forge/1.21.11-61.0.1/forge-1.21.11-61.0.1-changelog.txt --- .../bootstrap/dev/DevClasspath.java | 14 +- forge/gradle.properties | 2 +- .../registries/ForgeRegistryMixin_Forge.java | 2 +- .../ReloadableServerResourcesMixin_Forge.java | 11 +- .../vehicle/{ => boat}/BoatMixin_Forge.java | 4 +- ...AbstractFurnaceBlockEntityMixin_Forge.java | 8 +- .../resources/mixins.spongeforge.core.json | 2 +- gradle/verification-metadata.xml | 178 ++++++++++++++++++ .../entity/player/PlayerMixin_Attack.java | 53 ++++-- 9 files changed, 249 insertions(+), 25 deletions(-) rename forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/{ => boat}/BoatMixin_Forge.java (95%) diff --git a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java index fb7b3ddf7db..708594f063a 100644 --- a/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java +++ b/bootstrap/src/main/java/org/spongepowered/bootstrap/dev/DevClasspath.java @@ -58,6 +58,7 @@ public static List resolve() { final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false); + boolean skipMixinExtras = false; for (final String str : cp) { final Path path = Paths.get(str); if (!Files.exists(path)) { @@ -96,6 +97,9 @@ public static List resolve() { } break; case "", "vanilla", "forge", "neoforge": + if ("forge".equals(projectName)) { + skipMixinExtras = true; + } final WeightedPath weightedPath = new WeightedPath(projectName.isEmpty() ? 1 : 2, path); switch (sourceSet.name()) { case "applaunchConfig": @@ -132,6 +136,14 @@ public static List resolve() { } continue; } + // We need to skip mixinextras-common in Forge's UserDev mode as this will cause duplicate module + // errors with JPMS. + if (fileName.startsWith("mixinextras-common") && skipMixinExtras) { + if (Bootstrap.DEBUG) { + System.out.println("Ignored: " + path); + } + continue; + } if (bootNames.contains(fileName) || fileName.startsWith("org.jacoco.core-") || fileName.startsWith("mockito-") || fileName.startsWith("objenesis-")) { if (Bootstrap.DEBUG) { @@ -158,7 +170,7 @@ public static List resolve() { final List classpath = new ArrayList<>(); for (final Path lib : bootLibs) { - classpath.add(new Path[] { lib }); + classpath.add(new Path[]{lib}); } for (final List sourceSets : bootUnions.values()) { diff --git a/forge/gradle.properties b/forge/gradle.properties index 6759ac977d5..1ca22cd4a56 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=60.0.1 +forgeVersion=61.0.1 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java index d00213424b6..7d447c466e1 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/registries/ForgeRegistryMixin_Forge.java @@ -58,7 +58,7 @@ public abstract class ForgeRegistryMixin_Forge { @Inject(method = "add(ILnet/minecraft/resources/Identifier;Ljava/lang/Object;Ljava/lang/String;)I", at = @At("TAIL")) public void forge$writeToParent(final int id, final Identifier key, final V value, final String owner, final CallbackInfoReturnable cir) { final ResourceKey root = (ResourceKey) (Object) this.key.registry(); - final ResourceKey location = (ResourceKey) (Object) this.key.location(); + final var location = (ResourceKey) (Object) this.key.identifier(); if (!this.forge$warnedIfNoParent && this.forge$parents.isEmpty()) { // We only care about minecraft namespaced registries, as that is what we've got parents for. diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java index 2d4516bc38d..e98b5000234 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java @@ -33,6 +33,7 @@ import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.flag.FeatureFlagSet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -44,9 +45,13 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Forge { - @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) - private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", + target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;" + )) + private static ReloadableServerResources impl$onCreateResources( + final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, + final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/boat/BoatMixin_Forge.java similarity index 95% rename from forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java rename to forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/boat/BoatMixin_Forge.java index e52b4a69c3c..8af584df124 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/boat/BoatMixin_Forge.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.mixin.core.world.entity.vehicle; +package org.spongepowered.forge.mixin.core.world.entity.vehicle.boat; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index aa0bd75b07c..38d46dea6d9 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -99,13 +99,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF final Cause cause = PhaseTracker.getInstance().currentCause(); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.getFirst()); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -122,7 +122,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -174,7 +174,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(PhaseTracker.getInstance().currentCause(), entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 62a1c2a8d60..5a88ce6b7cf 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -25,7 +25,7 @@ "world.entity.LivingEntityMixin_Forge_Damage", "world.entity.item.ItemEntityMixin_Forge", "world.entity.player.PlayerMixin_Forge_Damage", - "world.entity.vehicle.BoatMixin_Forge", + "world.entity.vehicle.boat.BoatMixin_Forge", "world.level.ServerExplosionMixin_Forge", "world.level.block.FireBlockMixin_Forge", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Forge" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3c0e3f57ae9..f98dda046ec 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -40,6 +40,9 @@ + + + @@ -1309,6 +1312,9 @@ + + + @@ -4390,6 +4396,14 @@ + + + + + + + + @@ -4409,6 +4423,14 @@ + + + + + + + + @@ -4428,6 +4450,14 @@ + + + + + + + + @@ -4826,6 +4856,14 @@ + + + + + + + + @@ -4992,6 +5030,14 @@ + + + + + + + + @@ -5158,6 +5204,14 @@ + + + + + + + + @@ -5410,6 +5464,14 @@ + + + + + + + + @@ -5509,6 +5571,14 @@ + + + + + + + + @@ -5675,6 +5745,14 @@ + + + + + + + + @@ -5849,6 +5927,14 @@ + + + + + + + + @@ -6048,6 +6134,14 @@ + + + + + + + + @@ -6099,6 +6193,14 @@ + + + + + + + + @@ -6280,6 +6382,14 @@ + + + + + + + + @@ -6473,6 +6583,11 @@ + + + + + @@ -6552,6 +6667,20 @@ + + + + + + + + + + + + + + @@ -6560,6 +6689,14 @@ + + + + + + + + @@ -6672,6 +6809,14 @@ + + + + + + + + @@ -6776,6 +6921,14 @@ + + + + + + + + @@ -6904,6 +7057,14 @@ + + + + + + + + @@ -7816,6 +7977,9 @@ + + + @@ -7943,6 +8107,9 @@ + + + @@ -8017,6 +8184,9 @@ + + + @@ -11035,6 +11205,14 @@ + + + + + + + + diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index 620c915aae9..7bd5c3dabf6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -206,8 +206,8 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem } @WrapWithCondition(method = "attack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;playServerSideSound(Lnet/minecraft/sounds/SoundEvent;)V")) + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;playServerSideSound(Lnet/minecraft/sounds/SoundEvent;)V")) private boolean attack$preventSound(Player instance, SoundEvent soundEvent) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null || !tracker.postEvent().isCancelled(); @@ -220,9 +220,17 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem this.attack$trackers.removeLast(); } - @WrapOperation(method = "doSweepAttack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D")) + @WrapOperation(method = { + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;F)V", + // NeoForge changes where this gets invoked in a new method, so we add it as a target + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/phys/AABB;)V" + }, + slice = @Slice(from = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;" + )), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D"), + require = 1 + ) private double sweepAttack$fireEvents(final Player self, final Entity sweepTarget, final Operation operation) { final double distanceSquared = operation.call(self, sweepTarget); if (!(distanceSquared < this.attack$interactionRangeSquared())) { @@ -271,16 +279,27 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return distanceSquared; } - @WrapOperation(method = "doSweepAttack", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) + @WrapOperation(method = { + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;F)V", + // NeoForge changes where this gets invoked in a new method, so we add it as a target + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/phys/AABB;)V" + }, + require = 1, + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")), + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F")) private float sweepAttack$cancelEnchantedDamage(final Player self, final Entity sweepTarget, final float damage, final DamageSource source, final Operation operation) { return damage; // We already did it above } - @WrapOperation(method = "doSweepAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( + @WrapOperation(method = { + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;F)V", + // NeoForge changes where this gets invoked in a new method, so we add it as a target + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/phys/AABB;)V" + }, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;doPostAttackEffects(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)V"))) + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;doPostAttackEffects(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)V")), + require = 1 + ) private void sweepAttack$knockbackModifier( final LivingEntity sweepTarget, double modifier, final double dirX, final double dirZ, final Operation operation) { final SpongeAttackTracker sweepTracker = this.attack$tracker(); @@ -290,8 +309,18 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem operation.call(sweepTarget, modifier, dirX, dirZ); } - @WrapOperation(method = "doSweepAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z"), - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"))) + @WrapOperation(method = { + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;F)V", + // NeoForge changes where this gets invoked in a new method, so we add it as a target + "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/phys/AABB;)V" + }, at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z" + ), + slice = @Slice(from = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;" + )), + require = 1 + ) private boolean sweepAttack$finalDamage( final LivingEntity sweepTarget, final ServerLevel level, final DamageSource source, float damage, final Operation operation) { From bcf1e7638d5d9be4c1daad4cd9dbdf5ac44ec160 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 10 Dec 2025 13:36:09 -0800 Subject: [PATCH 429/586] feat(neoforge): update to 1.21.11 See https://minecraft.wiki/w/Java_Edition_1.21.11 See https://neoforged.net/changelog/ --- neoforge/gradle.properties | 2 +- .../applaunch/plugin/NeoForgePluginPlatform.java | 2 +- .../server/ReloadableServerResourcesMixin_Neo.java | 10 +++++++--- .../entity/animal/{ => golem}/SnowGolemMixin_Neo.java | 4 ++-- .../vehicle/{ => boat}/AbstractBoatMixin_Neo.java | 4 ++-- .../entity/AbstractFurnaceBlockEntityMixin_Neo.java | 8 ++++---- .../src/mixins/resources/mixins.spongeneo.core.json | 4 ++-- 7 files changed, 19 insertions(+), 15 deletions(-) rename neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/{ => golem}/SnowGolemMixin_Neo.java (97%) rename neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/{ => boat}/AbstractBoatMixin_Neo.java (97%) diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 66656a03bc3..48d323c8be4 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.10.16-beta +neoForgeVersion=21.11.0-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java index 4daeaaabd44..3c1204b3ea8 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java @@ -26,7 +26,7 @@ import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; +import net.neoforged.neoforge.common.NeoForgeVersion; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java index 0b0698bfb04..45edb4ffa57 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java @@ -33,6 +33,7 @@ import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.flag.FeatureFlagSet; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -44,9 +45,12 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Neo { - @WrapOperation(method = "lambda$loadResources$3", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;I)Lnet/minecraft/server/ReloadableServerResources;")) - private static ReloadableServerResources impl$onCreateResources(final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final int $$5, final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { + @WrapOperation(method = "lambda$loadResources$3", at = @At(value = "NEW", + target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) + private static ReloadableServerResources impl$onCreateResources( + final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, + final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, + final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/golem/SnowGolemMixin_Neo.java similarity index 97% rename from neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java rename to neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/golem/SnowGolemMixin_Neo.java index 564bae8e0e1..57c40a3356a 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/SnowGolemMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/animal/golem/SnowGolemMixin_Neo.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.mixin.core.world.entity.animal; +package org.spongepowered.neoforge.mixin.core.world.entity.animal.golem; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.entity.animal.golem.SnowGolem; import net.neoforged.neoforge.event.EventHooks; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Neo.java similarity index 97% rename from neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java rename to neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Neo.java index 0be84dc6caf..e42d84f0743 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/AbstractBoatMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/vehicle/boat/AbstractBoatMixin_Neo.java @@ -22,11 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.mixin.core.world.entity.vehicle; +package org.spongepowered.neoforge.mixin.core.world.entity.vehicle.boat; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index fbfa6af4670..d67fc4ca999 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -96,13 +96,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final Cause cause = PhaseTracker.getInstance().currentCause(); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.getFirst()); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location())); + Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); SpongeCommon.post(event); return !event.isCancelled(); } @@ -122,7 +122,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().location())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -182,7 +182,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB } final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().location()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index d6ae4849c84..1f6a819a953 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -31,11 +31,11 @@ "world.entity.EntityMixin_Neo", "world.entity.LivingEntityMixin_Neo", "world.entity.LivingEntityMixin_Neo_Damage", - "world.entity.animal.SnowGolemMixin_Neo", + "world.entity.animal.golem.SnowGolemMixin_Neo", "world.entity.item.ItemEntityMixin_Neo", "world.entity.player.PlayerMixin_Neo_Damage", "world.entity.projectile.FishingHookMixin_Neo", - "world.entity.vehicle.AbstractBoatMixin_Neo", + "world.entity.vehicle.boat.AbstractBoatMixin_Neo", "world.level.ServerExplosionMixin_NeoForge", "world.level.block.FireBlockMixin_Neo", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" From 04aace7781d795a206ada53ed521229268ed201d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 10 Dec 2025 22:42:51 +0100 Subject: [PATCH 430/586] Update NeoForge to 21.10.64 --- .../bootstrap/neoforge/TestServer.java | 9 +- gradle/libs.versions.toml | 4 +- gradle/verification-metadata.xml | 99 ++++++++++++++++--- neoforge/gradle.properties | 2 +- .../plugin/NeoForgePluginPlatform.java | 2 +- 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java index 01b11972f89..0653b6bc680 100644 --- a/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java +++ b/bootstrap/src/neoforge/java/org/spongepowered/bootstrap/neoforge/TestServer.java @@ -25,7 +25,6 @@ package org.spongepowered.bootstrap.neoforge; import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.startup.Entrypoint; import net.neoforged.fml.startup.FatalStartupException; import org.spongepowered.bootstrap.dev.DevClasspath; @@ -38,13 +37,13 @@ public static void main(final String[] args) { DevClasspath.resolve(); // Do not close the loader until tests are done - final FMLLoader loader = Entrypoint.startup(args, true, Dist.DEDICATED_SERVER, true); + final StartupResult startup = Entrypoint.startup(args, true, Dist.DEDICATED_SERVER, true); - final MethodHandle main = Entrypoint.createMainMethodCallable(loader, "net.minecraft.server.Main"); + final MethodHandle main = Entrypoint.createMainMethodCallable(startup, "net.minecraft.server.Main"); try { - main.invokeExact(loader.getProgramArgs().getArguments()); + main.invokeExact(startup.loader().getProgramArgs().getArguments()); } catch (Throwable e) { - throw new FatalStartupException("Failed to invoke main", e); + throw new FatalStartupException("Failed to invoke main", startup.startupArgs(), e); } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8fdb839654e..9fc54c4d3aa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ mixin = "0.8.7" mixinextras = "0.5.0" modlauncher = "10.2.2" securemodules = "2.2.22" -fancymodloader = "10.0.21" +fancymodloader = "10.0.32" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" @@ -75,4 +75,4 @@ indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = " shadow = { id = "com.gradleup.shadow", version = "9.0.2" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } -modDevGradle = { id = "net.neoforged.moddev", version = "2.0.107" } +modDevGradle = { id = "net.neoforged.moddev", version = "2.0.123" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9112c2d8d7d..c0b4551f293 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6184,6 +6184,14 @@ + + + + + + + + @@ -6220,6 +6228,20 @@ + + + + + + + + + + + + + + @@ -6228,6 +6250,14 @@ + + + + + + + + @@ -6244,6 +6274,14 @@ + + + + + + + + @@ -6340,6 +6378,14 @@ + + + + + + + + @@ -6444,6 +6490,14 @@ + + + + + + + + @@ -6572,6 +6626,14 @@ + + + + + + + + @@ -6593,6 +6655,11 @@ + + + + + @@ -7435,14 +7502,6 @@ - - - - - - - - @@ -7451,6 +7510,14 @@ + + + + + + + + @@ -7549,14 +7616,6 @@ - - - - - - - - @@ -7565,6 +7624,14 @@ + + + + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 66656a03bc3..0168b70ea99 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.10.16-beta +neoForgeVersion=21.10.64 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java index 4daeaaabd44..3c1204b3ea8 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java @@ -26,7 +26,7 @@ import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; +import net.neoforged.neoforge.common.NeoForgeVersion; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; From 252f572bf853f4f144d66bb2d5c90594e45c0ad5 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 11 Dec 2025 22:21:59 +0100 Subject: [PATCH 431/586] Fix compatibility with Lithium #4254 --- .../spongepowered/common/mixin/core/nbt/CompoundTagMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java index 613494934ae..316418741e4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/nbt/CompoundTagMixin.java @@ -45,7 +45,7 @@ public abstract class CompoundTagMixin { @Shadow @Final private Map tags; // @formatter:on - @ModifyArg(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V")) + @ModifyArg(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V"), require = 0) private BiConsumer impl$checkForOverflowOnCopy(final BiConsumer putCopy) { return (key, tag) -> { try { From b88b4404e9d9005ecd4ce6fc4efb51e5c30b155d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Dec 2025 19:19:53 -0800 Subject: [PATCH 432/586] feat(gradle): update to Gradle 9.2.1 --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 165 +++++++++++++++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 43764 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 5 +- gradlew.bat | 3 +- mise.toml | 2 + 7 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 mise.toml diff --git a/SpongeAPI b/SpongeAPI index b6d8da6771d..11e7548ef82 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b6d8da6771d215d170d684d027b0c90dac6308ff +Subproject commit 11e7548ef82439a1b85e38c803d5b1ca50317fec diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d3d84d16435..cd0f7727bb5 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6,6 +6,19 @@ + + + + + + + + + + + + + @@ -19,6 +32,10 @@ + + + + @@ -33,6 +50,14 @@ + + + + + + + + @@ -960,6 +985,14 @@ + + + + + + + + @@ -1061,6 +1094,14 @@ + + + + + + + + @@ -1085,6 +1126,14 @@ + + + + + + + + @@ -1101,6 +1150,14 @@ + + + + + + + + @@ -1166,6 +1223,11 @@ + + + + + @@ -1203,11 +1265,24 @@ + + + + + + + + + + + + + @@ -1466,6 +1541,11 @@ + + + + + @@ -1474,11 +1554,24 @@ + + + + + + + + + + + + + @@ -7681,6 +7774,14 @@ + + + + + + + + @@ -8571,6 +8672,9 @@ + + + @@ -9136,6 +9240,14 @@ + + + + + + + + @@ -9176,6 +9288,14 @@ + + + + + + + + @@ -9207,6 +9327,11 @@ + + + + + @@ -10348,6 +10473,14 @@ + + + + + + + + @@ -10404,6 +10537,14 @@ + + + + + + + + @@ -10473,6 +10614,14 @@ + + + + + + + + @@ -10542,6 +10691,14 @@ + + + + + + + + @@ -10582,6 +10739,14 @@ + + + + + + + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb587c669f562ae36f953de2481846..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch delta 37442 zcmX6^V`E)y*G$_Ojn&w;ZQHhOYNtI^y0dB5x*u&jIU21Bhf}7%e`>rSh z1#LY&uAK}92G$A&y5+$IAt4F@2|8jt0LwA}}afFkG#WBw^#$TCX0J^k+I+tvA_2h1Itw`Li1kgyHcDwujll*+Po z$XwsbUNDm$Wt&2Li;oZ)KsqHBet>&OoWy>!E1MRems2?s$vd~r0vYTN=myB^=e|Ep zOPhp4yC7$yh?X{pJgiX}r=I+{B<4TOeoUksBm-D~H<`&WFHZHWL|{HK)gK&-S}>%I ziIqri>?=0OaJ^KsnnmZJiFiG_f?UADlLvkG)=-3Aw~z%^S?4XD<*iL~Me#4^m2$Zj`empiTmN1WnOgbi8v`sM08Y{O`ZL zDN>@uIp~1rj*c9p2a4rsJ73t%3fhNB|EHS9+$2cA79N(jr%Qb1IRH{_$pRXHaK`8dw#}-s*DfXJeoWNogcLPp( zC#5c477mpu8)E~nb*Lev%2hfE^f-7GM%lGk{TaOK^n$z$aidXt)|O&57^|vNL>i(A z#)k1{uik?cea-bP^a_f6K&sH6VAxcnmS1QMy#2JiyY`*r9k9U@c%6$#Db1g4QmPTw zP-deC)iPvGaxE1m;GFQI)sY#;1|iY~Z6?hbnLrJT6FpYiejmw@Q~IHbUGL-xND<2H z)p(|GQFxTZ0Z$`p7!szU_@vn|OEhF%W2}>S`xPL$Q5I20*Q2c#UZ*|-a{ zHzYc6en{$9^L)!5OqfHaa8Tcj#Y=((4}9UN>~bEB#cO1=P7B_!+=f+Q)*C&M+}T{A zC$+v;Z=?Rmh%t98yfbSSdXdE1ik=VA0XEuuTl;a7dqqhIalVtBiDWUu(_dP$jeCeT zg=taDEp4CPa+l{5z;DhDQH6y3?xR^7gTqNT18`DFf(ZXGMz10kuL(@XTIRo_Fi&weHNZ z{f+G(;f9?EH1rb4&On<@5auFNj4=O6plt+z2MsAQ z8k`XP$8pawNz0h;U|{P%{&AcJ)J=l{ibTZ&*eRe2A^E3#m#8U5L%z}D75eMWs?LvQ zEgL^DQ1p!?GLXUCrU=t9~vC@d(;hnKYq zz-NRPA}7GAe!c-G)@#XGGL2KR9#Pk!OP#C^T{%|z?md4$f^_9{Ph=PBs!J8(Tr9Gb zqDXW|?BjJhtGwDEHvYm1Ih5xBA!in0QB8q0A;={r;k1q_HtrI29(e6yr9m|ZS1p`> zw0xGJm>J`~n-4Ss_6bUB*oyI@{1V3ope$jB^p@#E&jhX?_o-ru6SU981 ze)V2H^*$Qu)80DEw0)aq15ULt$3JT0kL+Z3h%PZs68>Feuhj^a;WIF8F0SVWm^;Q? zF~#Eq@?K8P`}4hb-@v;B!!9{S5s__4MAlH1p2A^=x&k&ACPyA4ZKQAeD{#bKkGcWnJ&KdnWOzmd7*3E|K=Jp6|BnUXG#*K^`Fw zoKj0L0wF5~|G`d7z(qj&AMBdI|JPb@h{!++807z8x2}%nPj8A9?d4$A?55*L6-Y{M zXUK{)1o_*6noez=I8?gIK1*hAFLlJ-aK7O)?$HGxNK?lY({-_4^ik$E>|P<9pT;0( zO5uOyGQ~H|b&UV@wrx=JO?Dr$f1X0&3d3KCMt2*{T`gPX5rM7pEOwDm_6jGqN=sf1 z=?Va=;;1lVob8jLkNLM`xq;WsJ~%UHq#`E6{1#{)!e3H)|N2hrwAsh=7E@w{va{Ig z9)TaK$6`yQ+h2{`My4D0MBKs1#ilh=VJ!2}h#DO3B6=G5LMoO9*4jCysFxZB!7mT(pAs+&x3tA+WNE6*L{!uJLW%`O+he16V|(Lf61#p- z+5;bNlZSnyj%Dqaoyi0w?QR*Fk#Ur1kl&mIGa68}#o8sYOeM2va~cKbsjx*jCjs%% z>*9UbKz@piah<FraUf9bX;sb6pnTz6@^OtCl{Xm@FVPZ>AZLr+j` z+FrD-xpS`2$~Op!%w0nxbxz`5@s2qKdnKo~+szzy7VEK&ae-AdEdh0ef6)4EZH*CE z2u>zofc77JU*S)@8*;GBBkoF2Rsi_DGT1@yaEH8)D%3>|3K9fvf%Ld_`nJXrGTW~) zg*MA##_5?aBWzMxmgolOMBDOZS?BoZHsbWQonmqxCYPQUJp+sr&$;kg&PBf`=vTy8 zhfoZeUff7#bEav>zt9W`ClJ^wFQ24^$43&d9V0ii{yJYY)iTAqG0zpjiA*{Oss8tZS-9rG^AyY)Wa|1j~~6Bg#bIlf8RGXZ|*4fzu%?X zvR?7{(l6-$>Jz@e=jB$1Kce7C&Rq9D-~-2+e=Obn^mccoe}h`+X439@L@b#jV*SK{ ze2%A|pEo^H^2SWfxi+fEGW85~80T1ToZC5k$bGTL6zEv(S02%x{e!)y=Y=os5pyNg z&^ajEQY=aW=fD&lf+mfP@J+YWCi-FKJgT7~KUEbzu@^c)8O<)IjHRJX9v6e!R^;vL zKf?7J+_EYE00RR-{f}_t*s_3g1KdSyf5;SgT9D`nLZT&mCJt@8A+*|eR&+*d(?C|F zlOa_+cSJ@bcMBF4I3XKjhqa2%Rhp$G{ep5fyTZf7k(#R9zxmtifV__tfu1F5zo`p) zTSFD$?uo4XoaeiaWtY#p(Ki72Opq8vjb4{;$>ZuyIDRftxo9mN76AYO80`KVIH}Ees*qdW5YMA!`(*T zpVcITlyl$vfU=pG&Ace2Hf8~<9MtD-8TGIplWXoQ%lURZBQC?E55TFaRp!!jL1&huPF?kM)nXq0Y zSkHSGKvPF;8M#%Q^INbzNKOj^Ht0))l}6-h>;<+iJlujO!g4Oz8*9Ax2(HWy6_~($IN;e!=A3uP`^0TeU)dC{b&0=;1 z!JJ~urGMEwU4i57C5x--mNIl=z?o-bQNRYsKx@pW!%qQFPq%t{*vq zeJJvTX06{ea*@9AHC~`5JTcw=L3LZdL`~Hlk_@!wq$s}D=T9%4-iw}?4+w%M7?$;8Cyx``?!aOr=YFU+7<~{;UDH+XL_5(v4_nLN< z)_I+|aujQA+|t^af$2z1k<)Ltr0y;k7|_&Z^eN4y`Qz2UjId8mSsi2`5(?}9P$sGg z0r5}bTxpT2QLyehtu}`>8JBKi=f~g4i%>vE9IOD4TG4@QAu7h4P3dIDYh|B$EgOze zsSS6WwN9^IZ$r%UnN^T;LU};2)XyTeVQTuivote^uqe5hMpA_79W8;9TZqWtVJreT z4BO^Bm7_|xyfhOSm@GiLzrR%pa*2L*kv0O54UUx7Fn*rXRt{*LZw16Vc12XMO9F~D)uL+OW8>IOoiV`6Y;;N{kQCzW0Cs!IhS9sdtxUG`*{jq%{>mF?p z0@OH+uj=)nafI->pI-+}=<5n7Iu>x4v_Y1hIY)5@QW-_H~dmPzJ z)H_p4ln&SI4x@~n+X5Spsr|&rrb#u@3G$D`4LTW#DQ<5Laiy(Bl7Fc2K9L*0|*znNkRynffSJJ zaLio&qPSBb&5zn4KmfCqs{npIO%Xag3T=$j&CzO8;)?whCQ^5QEQ49=g3MNz191T} zxw{4Ax`3ND0+{}Uvi5V~e4yX4;*KWadQGL&>-%b*p?#VrzQfPh7M1De)wWPXkDOE< z<>dw*-_FE{xeksr)(k&G@#03M00EE{1Xe8(!$K@`3Kw3SG{k# z8vPRB(Wuj^NplhePT4~dxYa~+XrGAaduyYUo%dK-flcB0nwH<{aEM^+R>4ER=X_>A z$Y?8i)rKB)Zd^VW`2MtTX6N=Kx3i^b$p2g2tKsdZRY)zQ!B^y|{Xu%vs16u?7FAb~ zBB9CzBU3N4a>TyeCmN#A_Umev6)#nQtavE@X26q2 z_9Oe|_|Q9W>`VMGOr3cnE|TmaPnJp|CK3Z3IMxm)^P6(eCN$3R$pmm=BwS59Iz}uv zh_mtStIzK%Ftx!DCZT z!^$DGi3F5DL<#6Oe5vjJD!7%madOcZX=*A+$Ezwx&snd>!(Yo`)vci$xrURt5u6#O zM})7Znb^#`hFp^l;|VOYbF>5#6*hzoihwWZK-(oJj)DuE8LW8K#K_jM&fmXnd@$DvXp$|uvQ5SWGu3evwGe;}6=DxC~ z%0WCxF#rGyE#~l!R37!(AUsGbsD-yE2a@_oab%Bnib>Y%j^Q;M`Htj!&Tq}e{dzRr zqSqTzA)i=iD}MX4FXRtLUG&tt_(3vVB`18$0%99@E(Lo}=a+Sx!V2#WMyCwc7(a~> z#X&b(F(wB^mc5IxiQzw!@pJn_HS<+QX|WqPet>4O_tcI<=n2Jp^tSeBcUHKD%sf8~ zF70vG3=vopQ<@OR-w~%JMfbl2Y+QN+$OL>4+v#))Rc~ZIV-=^aXz{u-*Ze9;e z`972;UHl970lJr;^8FfV`1@8xK@vbJj?g~%AeT){G5Icv-VJVLv!Q*1S|S9eor z63+tjSKkF$#(#l8`}_Oz1Iec}U)hOf$U9fgcF|3JOtKQtR@{*JVZv=_Q8y1G1CrV_ z;UbSJBv>Mzg_?FXxw$0vI>I0n8v@PELOierQ z%bQydx@H{$rh*{`g$aivh@OJD1Q*hL(-pN2F*Fp8C7a|3%4JKur z8~}a&?K8ZzZEuVXNrdzBa$LPi0+=E&vzKF5XCUd-U_0sm}a_&jn+{ML;Z+ymwj*kl7 zNz~0NC;lg(m@`Nf`j@x^Ygb}mkP}c`#4`%RqkJq@^Ibc|EFPTvmNy!v!*Ir$ou^(z zi3aM3T9O5RGkx?76|+|sYd#MZmVQpn!tzmWH8C608FWl1n)cQ#E$ z^o{Y(q2!V5@-H%J$V7ju?jC$qAY22*^vo;5C#skwW*b9#oMdHemvlkrF)m`)3`0L} z6~e>gHYGkvxv)NoQZ6rN7LV956%gfE(l)!`k!PrBimCAtb-vYzS6INMOhL9RG9t(&o~J9n!|)&CvH1@Mm;M1>8sdLD3k8J)Ku!UN2?-CxAUTgjX{XTn zo0AlMTzG^CLbW_bwNW`q75uPgay8plwqq;#GA6#_PUHnMi~6w#@g%N-TRwOWrvlMG z=h-~R;%NCg7ZGeGa2fu}-hrWQy8{OCxQzIE0j_i_5VJ&zoV1x(%|B6GvO_##gD`@{ z{@oF{yKxW!xRo!}{l$CpXGOvDD5_YZbl$#sTdDere@VfGDuR*aia;ft8Ut1d4jr{! z(C&m`uRV++Oi!RM^w|#;EBK6Z(k(nUL=^H;by(=P7bz2TF|@Z;q9gj_=qb%I-4Mwc$Q2Wa$B|9 z=b$yl$f69Gt8A*=bYds@q+dUP#7&f*S zW1yL4(`L;Cy&uyP;N+hO4oV@J30ZaU6;3z0+*f(8CQ z>^*JS?keN4b1I)v7y>{ABuyn3@jre(q%?~nIvhj+$JeSx=Qr16kQY zE6)A{LPNEPi6=@XO(Ow2pI3zYK^z+%uK2FuCrVq+&|V;r)Cjn!E>!B{Vc+8e)#Xmyg~^hI_pn#+Ufw|~`h3XRP&l3)ZoX%&RTB}Iw( zip3J`t!lNMH_x2d5YQ^!?ibq{!*WnzLFo&*hgKo*la)~f+EPtEVH`88kfMlj ztlEh!kI-^CPhjku@SUpV;Sjgz7*5g%Drwy?D#wYDV>0~Sz$)O%Io)vcRKkAZt$GA& z(!6kXr9gY$dwUyCQYxZocyk-AATmUlRah(uuRy8{^H3)fz^-E-E^_P+ixsRafhZdg zCQKaM#-4zQjW7N1ovOnRZ&)|fjyT&Hl=u2*&P}CI2MvO!PW2t(8&x~Veo4hD5~F0K zd`FiqYKM1TTm!t)%J#a#L@F9HYVlQMrxH4RNKe%GktRtg{B=ixSFgBK(5Gk&+b-8* zq_lagx-ypCOv}C`sJVxHcP__+WYNa6dEByg*huh)1W2ei{8e_&6V4dm=fes1%H+f! z;LiYTq)L)Z&X-+ifSFTBoWqL2nPRWL50OmpYIYhQu5u=H$h#YprdCZDx(yKKmbow@ zt_CBIu8C=mRip@TC)KBYM$6mBF2Rg+{?7;NNZZ>i|5pX3{#ONt=!^lHQnZHuECfs2 zo^WGA@+0@>KeQJTE*??8ND%i}UPM4a5dywo1Y?}-XjZjS{khq#EYDe7EcMUNxw+k7 zw1zpmI|x%3)6mv@aYKMLe2JaTog27Myb}0(jb(IjiRd!-w#;i^Y3vB^GWGK7ROVu z?&0ibE;~*)!LN_WCG14BoBm0_6u$8ly$M54&fh&6KfyQdK#etU2tPMMJz|(gKow1? z=ty-pg!Ygxa7T^>Nr%jT*c;jKtNKRRS|D}1r1l!Q7=C#m%#kc(*q0tKD`f5)SG|CT z3=1)zHl{du?gV)Gy|({TrPVP%-QGl2q&TGveN;gP3f_dG7$^Voghu%;PK^gT6@6mQ zUBG_#XTM|^oYg@AV1P9uPw(B^P62Dz*{}4FGfF@ZP zD~4I7G)!PTYy&L?rNa~=m+9ny>2=t@E1Wejmzy- zi?Mn|#uVNpt1>!31>LkcguaE&vTousNf~3TL$7k>wwJ4Vy?{rbu9&(bV~#iW^K)x! zt3IR=lKp9V(KQ?1J-t+ZUKNXM5~*)48bu2;#B5&6l;Gs_99y#7nCO!cd(g^yAwajs9RF$_-|skMcGTm*bild?wpt#1@WH=LTLF)B4WUW79mE}> z!}{ZA24(;aQ6j=FSQ0a6Lf}w1vjHaX`7W+*xjQpUa`oI?G(YD!qDVvEQvbx{vpF5_EqhcTGPfyJ@@8$}7Mov@^N4un=9?j=llt}$ zzMcwylO`K#(!FcMKHE^)gI>Ee!YZ9X7J`ncX2}MS#xc4v+CxeoDkap;kkhhIo# zA>4oiWsYGL{l+Kjv6CsSYDmvEeTt%ZQbQkdq@!B!ZHe%Uv%YwwyYEL#?%5@ZEv>54tD#iB`QII+H>YWoMg!R>C!+2TBTtsGhQ z!^%SvbO+$ZbPMl6B=Wz&w9Q-wYenN)6Ruk?XWj?GQD}GfYm8Q-b_VyRT1G%<+|07* z#z7Qz(qMT4AL1n2hFoYyc*XWPzCHO~PA`vO1a}Kl$3hzS3cGT?!je>Cz1ac6_?pA~ zjK}%aXk$G(`!3Zs{9w9*<}{b5XRvejJQKy$fZMaVB*V&^G>-Os25*&bKF)pw7$;sZ zbK91Nwg`S(p^``bdBtW3bSo73LVcvQKy&bp2y!LoxsI5SP>vzukN$xtI;s1CdB&YO zs85Lh#wG@8ddf3!Ft9mjFi;_zB0xt2M-A=sCyXrCce}Z{IdxJwnLyoe-2unS@5)wE zdF+j87z`rLD3IhVPUd~qspIsiUwxl}T}?Jb4d&&3cfE%MH?z6B!9#xJFmkdf8DU&L zPZ#6O)1OaM3;@3`k^n0-tQ=l{Uy4sNM~Tr37e1UUICJM-Nk$X2$cmDc3P8RDoOlXo z>)@9LtvrDTI!(svVY*+XYHg4Umsq_gspf0&2iu@MDS#tO)|Sf8q_mQg*Oj9w{OJ{xHY|B;F{RkX_kZK}Z+Huo zSff$(#+3}?OY-DBUJ--Y1B~U%$qKJZt;qGhi35oJ01JhQzb_)|swoq`<$_y9Ck{6{ z%yNfH!i^yo%Rv>DPi{b$LObHPO%unM*vi`{m9n2kP1_REE8@WGnrnj1jfNgb;{|a?Jviy}~N=2J5vH zFTCqWVAt@@M}g^zuhjGwvud`{p9E4F9tP^k z-Cn%iLTPpDbfcmEhLCj2#-lMd4Kq{RkzobK!6D)%DqVD_e&KbW7eI7jQ%kt@zzjRB)p*2oKD7J=BREc*SoSoH z_6NQ?fw^bQ3}B%&(7K{$q?Qe327xF3kn4Lq-ZLS^$R=cGy`{UEV;O5CO+zKNw+j0Q z-b_X-jpsK4H<5xbI1Z@>d&#?q(7mj!HL3Hyx;(z9`G<|t=Hr7!spI8cMea_&Xcn`F zQq*Bi%+H@c%yiN2$P%G&4)U4l;kYF47D=MX`xuy}ZUA%`QfdEu-BV`sxlxl2mk=-J zm2hh912wx~g_XCg@Y77_`~HE-?L4=y9anG-H>4G6dsLR}O(^!JE>5Ns5hhKGR~ zo!T16FC6M&F$-qZA#3jsERGF01}6{^cDYeT3tD-pEN>w0T@8VeOH|||fHI`kQ&nua zZ+@&MA3);!Z~;D!9ykb<8lrX-P;NNm1*$#i_zL{?SKdXbpG6_{w1h<*<|ot3cb)UF z7HNsSfAJ&IcK?8+tu4n;63C5l<~W0N@(%K-RUKyjg`lcbY4npWa8<>hL0cC0)1)`NlM1EV zj+bX*Nzn+rq1m27^S$Tp@)dltilf0G(5kJ^1v2@6p{@eP=SM}*1&;~9#${d{jSnYN zlIf^8#K?Ua1{?Su_ZRWOCJYf6nEx>q zXY5S|go#sSNzpjo^0{hlx7hCRdqoU@&^5ubwcD%~a9Z-bQ7p2v7=_`U`i*KT#SqyV z`==qr)J~`ct!_tJv34AwMt2gqlYd4rrge6s8KG5*xrDM+DF!jz*SE2;L3}v&_wBE| zKrD=+o<5IME-^x(Dl~R6QU19w^_iIGX6Ex*W0R&wPKF_TvieeLU<=k@P=3nj3?iAs za9^A(F-wx$n&@VlL1QhtS}!~xr~ zmvF~$Y38~WU3Qdq&MWTU@Jl@NygoxwYqrxB659R=dYmAP8aU(z3_I26@6(Plf8jqk$=f1 zlpk!s&HNb-vn5nz2lZW(-`^1hI;OAADW5X6dQ6NAW6fV12MyT-V(2tRLraGk;|L;@ zEGBJ5Mj%&h-(>kGwsvJJ%1oGYZ6Z`1M6Gz%70K1HvMv_@<4&}~_y+Mt0?6h1ez@WK z_I5ukush17*vurxm_n^HW8eB$X?#z!~>!3#?01=G_b z!q@Uc_oWZiU#(ZU5%y%#Bz{kT-?uvGn71+z$Bq&C8+q#kwWYDA95HX=AcNOU(GmBsVS~qjwA@$%cMxuayqGV*WIx%}Git%fH}J=;B>d9(%Rkh` zW4y*_!!Bhb#cg*0?l=GNAwa4Zx_ZtB?QpaZ6<&^1I}XI|Ot|V9(vaeaV-^CTPJJiy z_3ghosr4R#0OemGrseP+;)_8t(IAs|FGk)$IfXx0WA@v+5 zNbEOG+^r|;FFy0C%=fC?e~G;vOlJPQB-;wQgn4!|SFtG?Hk{yMxgtIjm zOO}l`J*+$>D`)O$>-mccuycD=&1-B1%nn1g@qwSfz%zTX6{~=Jy!EW8CzE@ww#J7< zkEKLL%JV@Va2Q`uP%R`gN^Wbz>}{DVeS(I^+ep0h=#MEsE}$C}ywtw$dX08Fkw-N* z!a$zfus&)9mxb+n=GK4P4!WMYfn#_0C4}i0()>`U<8AZuWA}!J<_gwV{B08<*bXDK zWw=HUBSiCU@*C1O6ZobK^(uk?9&PfOh$!oyqD1~bMae@*7ND&6FR6;gM-n>thY)t~ z8gVJLKu_Iyp9iV1vp+j)|IxXevP(3G=g<$=u0IF|@~>!UppN+PpCcMVuu8bym!g^u}vves#PwQPOv?)_<7{9{m@eQ8^=||smzq1 zChZ?VJB{8D-=N5K) ziK%|Y#IHsCgP3dV&h&w-bgG}Q-=mIBJz z^gHVwb+#J3wqqJ$&_D=J?gkv-8v-U!Vu9%v)ap;Ig5~dsA6;;m_hJ)9LOaHyO`|TC z^|Oa}Yum1vQ7u`Znk==ys~N#&^fxkFvQ(;i=vR^^dcS2^H6X6Owr5)M&&84)MGV)- zZG(^1`K>G#2I)4Yq&&c3GkrV1-^-0NSn8BGnCYM*`uzHN7w2b`lG?);tDhG@wbiLI z(Wt$SsNiT7Qp}*qEmr=R$K2P5x`DfU<#g!zTkr7e`+x^V{e%$#SB6DPK>7b#+4-E3 z&)UBiAO82^IsiV0f3ajg8U86Ok-ZSo8GJPNgL|r>P$?t`NmU_9%>qGI(Bn(T)aI6z zhg~G)E73dTuV3+$FW=rN2VTB^C(Xc{%zWPJ*!=k1Kj#1w+0b}#bbIu6Mb1s&x8RA0 zGvSNzsiTh?J3y1Q0u^M{?!>x~PcvsFC_F?zwi=-E^8<2}uUauRw3HQ-)7DHlap583 zLeIs!ALqq#;C3vMaHYoCSyEQ9Ghy0HkIhnd3O@@!DbsJ5yKDuiSceb$to)6f)lX9B zWmqIYS@X}a6_I*>f71pd&UKKQ3w^r6e7h);}z+X1Rseme(2-mdI-4 zq(mk+TLOq#(b#jbZ2D9}8|9zn;N&)}iG^h#i`X=Tc7=`~96m-*bMf|T+a{%+tNMD~ zMo3FTlS`eYzHamY^3{Qt0AoEF;tNVq2#9>|(9WqZS)G=sPIC9Un%Ym@Ei^k@NzTyB zyHt)MX>G1+spXW4B70o_-b)2Rgw5Win%jTn8?#8fGyBN`*Y`I}1<>>c^*>6^UDVBh z0>qpFat{BgZIC|ox9%WLQlKEXeN)I9c`Q*;@4$?(NCK{`${^*4G8y+OUJZxVb=%u6 zq1xdb4wSs^4%l!`LIzT!^14dG3&r~n`G#v+#W`4{_PLI0-usCTg6WBQ%`aCjKkTQSybb^_`mN_WK{tXe|3c&#JiN4-ct-X>Ck|GO z^$mo<=-K*ly)7D^QSAGB7Z(?c2pm;|Ylq=#8Nrp^Llsu^oJ&t(@K_7fHB2GNI_R3I zoSdo@x>*i?T=0LFB>uQ*dw=#}ff)oV=sY_qG}JoZt{+7eTMrz(s;8?=QbjX|?H>T% zpK?3vfzbUxRPjF4z(`gR_uyx*!NVLqEv;=N^CIH_qn<}Q9dLM1Of$G8X%rh!C`#M# zJ{*PXi+wN5Tv!6{0;1sh#p#7XLNP&qpyw=UnrqmlU>Z9XV+*9{6hov&S$&Ent{xnz zgcm$wnrA2*28=68ozFLs^oGKAUIJ8FPKHZ3wJhZGLq`cw(K28zL((_I`@;7-thpvj z;Gs)Us-|uyEqHfoE+-5R|B5x1-is~W2c_Pdd|5gDoAE0+r}Ca!aiWsh$&|`4alVch zT+tL4Zm6W;!?v{QBeBn7MR}#)OpT_wRApz-wuk#z#OxdbqF^#>+Jk~73IGN9(IB*< z+6VllEYoarEE%j=gYp_*w|O+aS3*_aA;*`=rNxz~tm>6|f1r`EgZ(mhV0UuXhjLZ@ zuL@1lDhntl`C%g5B}u|Lo=#DRP^0h%CXSlBEwZE-r3j#@^*!aaO7VMGXUB+R-zuw^2bY)3xT>Ar>2-6<#w{X(xe2*QXRws{a_zG z3a=BJP%qUFa6fs4Xe!OB%GY1lKRL-cu8Zt1`c?*A)mL3j$C!)nsT-vajWNDVluwKhwb?1v~o?)z-U;qYd< zqq7xcYL|=^oP+sGIq&4Z|FcoGsaz6d{>>;T|8IbcN{Ik;{%d!i!0$RKVzAWE`ZMTm zI+m5;+KR|!9)w8rLqkw3wqfo@?K&3CgiLoLzBjWLY}y5+LlkoV+*2+35<1ekqIQ;J z-{Y+7tXFfu$LC*!9zt^LEnC}(68+Pt4P9h;b%LcyvQ7hzP2t%;tq!g79XsX_tHret z&){758-S=xFQaPD;-FGQhJW`IAKpxu3^&FbYg0^|oQ#Z&qMGSzQ3lkj?ART=aR&KS zj?O70Aq`o$S{k7bWf-d}5tR|Dyfo^M%SMclZc}tpDjUtVz44A_^ywg8o2Y|~gTaFM z(e|qhlXl*99+J(}a}zQF2Hb7t)@x~qM|iw(UqCVi-Y$iWZwx%L!{)tMATbrl0VXcr z%^Anwj*f?GFp2~FmxEU9VH{%v4qMj=Dli_|uRtiYL|7;a$e58a6QB;P&bqN^Ij(AD z)=|n>Gv#y;rTDt##u7~?NitIJpoEEop02^P`Yvu}s3y{>Hj?=(c2BeClvCu|h#1Y4 z8NfO*Aulk=sLN}cK<~=23ofsoP|Tv2MrJ2QJ(?JLQ|d%cxY(bk=8cwRV)+x2TyL9A zFLQTAzjiWP*LeytNf>6TP$M)J4nDha>o(EM0wVi@3>{MYree+5i4(B=hNV*04u-sTMf32#Ox*zVWIp6Sf(ZRTL6T(|0GcqK zx@zd34lJN&Zait0;?Qr}x%q*viRn~!y{twy^K_;}u8Ar6gMXP_SiCMLeENMH{sgG% zDk|wB2?>fhRZ?13x(Y|oQa41xQI}CtQ(wIWMM6XzZ*hR+6YHMl{a=r|T(0RoeVp#QR>C|4pV7Z`XWv;jxAq*0g&Z2IX|V1 zi(B#LpT2zYwi%ev_SO!JGwP-H(~PrlV?pgUHN;eCg|)`Eu2(1Tw@bXPD9DqMZ%T07 zYGP*h$fECeYNZ07sv%e0a$5D~FT?y}pMI51M6b$i@{nDKjpB-M#hA51W=Gp1&c0Q3 zY&Gi(Y9~qQY@Z%+s@zdl1#n}@%WIK)4a!X@&n#%>@1BUR-@!haZ(`piEl(O#Lnp{g zvB>s!2IQAGy)F^T_Z5I)7&G-tExOWhh6){)*u;@>VrwpIwqn<<1#zO6LLd#D!c)j* zD%U2NBBZXj*(AtdDu6C2Z>0i(snh-Aiql9Ld^LvH!NMcwyM@&afWLQyQv+J}GXdg| zxm2qZ$!;2i0jv@;q)Tipv{^@QW;g>8Xagez*jMg%b%g5SjZRr|?Ct7(=r392%lnC2 zYMOWfK`xeb5e|#>5cmT$ybyHrJtq;AmSpqy!~=9O^$6LM<=z?hj$PsCgZ5_oOgFj^ z2zcYous)bj`NmhefR{S@a6)+`gLCY)PsB2sm66&9%_C3Bb=)3uS8(JW-Z~o#qta+ZL({y>ti(OS zf;^L(wV#n3tpeA<^OJ^UStdx1#C4_*P6&nIy?y&sx}4avV#DTdyCb~1I0lZ|%b?Z& zk}{dM{XGHBqD{kb(2Ou=d8_uOd>11era6+6E{Ne)+iy71*4A&vt4_d2_X3X8#VvA} z>X7^uOi6|R1Nc!Z2x0dbe|}`*h5XO@P044WE|pbb#SE-GGD6c( z8ASh^J%&(i6pjaX$?}czY}%%bo^7gZbBjwKr>D^qPpye+cnZnyhn~q#4;d~|i$fr{2ck3c{~y}K1{5X=^j6_#YOvcazJYUMj|)!8jtC3SIOyb9PxLj z@A{igCn(aDo;-T|Ed4FjhNknxliS!mF?$(h=)&YeyxL?(^-*S0IepHkTXd=$vaee! z{uiOw$Z!tm0>_@^q_)?LP*sFm=f!hxSntd&)K`R=FUb&RVptez{m`431OwUM8g@nC zm+f@givgvD7NDi;nUb}mt}cB!Z|%%0>&XHh&3U;=M!cMYxuW8d4w{=>dLnTWB0G?4 zSxQNUCC(3sI`Wdov1+MsE=W9C8d1(j>&eNl9+52p?E9(~^e z6yJHmyd8UKawp1h_Uc3nk(1*SA5@iUCUo|0`?s=Xs$D*nhWOYUaC=qo$TG3}uPqmhDit zieQL4M$(LboP*N~^g%lx5H(XCF5K)!4+Yd~P1AGg<=aQWTF!g~-*s%-sD}RV7pyYMNovcnSOQ>|*vFN>Agd8o0CXq?TK7}d#+ZQhvFE?g zIKP3pDgMH=IyK;>|c8K1>S{u}9ry>D} zHS}FhF>Rc479J{bOs|k>)hYL4;!BpbN2bu8P(#rzBMXA{3c1) zFY|yC?0`Zvp;W7w-;~Q9OBqgMnMtbS`+p>zV{oQjvxVb{?M!Ujwr$(C^CX$rwrx8T z+qP}nXWsApxT~wW_OD%aSM6Ti>uS7Iig(Z)a`dN{wlb4lXeJHJHkt&$X1(!m>rD8( zt~Vey83W~pM$6wA;_!LaW5AE7j%R*h0Oxw}@Px-H5vW!jj)3o?S%pEb><(z^Y76$45CfLyHnTAG=56F)j`<`-wQ| zO4w5{-JNFm81s!NJlPd|lr>khu4zq!vpqL>ic_E>4JV!Y?a z`Iac9B#Y3+Axn<~K)lKE?PFL(c@H8z+8Y2NPq(>&fG_Y;|n!3l{w(-O2lR}|>4OcGZC54ViSB@{m(mC_6yXuweO zIAG(V1^`ufo6C!{=9j%8Uncx=(*%#|H}?P32S!^6u2m=?pkw6! zH&vh}zH*}_s(4`}&XhtVI;ar=6cKq-LALzzG!zv+bCf|)WEiJ@!d1* zA3-gnDe9i!wy;kxI?&$ZFUAJpKnDH!U8^j#XN8SO$0$z;O7xBig zOiY_qVugyeEBH<|R^R&wN;Ad;cv1&^ov0jk0!5p>hAuKx$9hrh)(BRz110s}YJU(Z z+y+!Mn-084>aeLsT#}l2ne?f#M2jZ3Ca;Eyo`rJP4LPI=c}l>K5sox6a$tWu|Ln$9 zk;G~S6kjb*tJQuL^lSju*6mu~yX-0#{`oYQk;|F@%pGGQYsA2|3-_D7vUo6u71s3N z=s$8^2^~4IRIv@cmu4y2!<ZRwjN#LUhIGy)wO&Be{lZk`&{%XV&(*3~WOWOFL@IO}{B z)mzrSTd6DN)mxV(ML*8hG6|Ao5`b9!$8GQF7vGbO)PEZB?WnOxlT>@o*)@*+X8W@% z+LhQLAT0g#-@8eKi@JiENbN5@$FW8$`%X#$e7GK(1#fVLq)w^>)Rkl1V)Pa2z-*Q~*<@pID} z(2O}3Bqdi;zJenjy`C0-TCuh5*M%ind1&S|TtCB7=mfAZ>7k`f)97(QSV)Rr3Q3EX zDlcMAc1=ISm86CvGN_+xuvAf@Yql(!lpw>BeOZnP*1RD^kex42B4eKF;i!^QPAA&~ z@SVXf%=qDp^7(Q;vpIg|U#KCX#0`EHrnzhX`1pzqw>c zHm36wx~pVN97<_-y0gU!TSKh-Xyq;N++!55R;u)=1Tt^z5<7-5^2Ty$ZQyB%M7nB8 zqz+JJGt`JBgR3>}sb~!!ve}RJj--tPsD+KEI{eP~5LA@~N~tOWs%_*7)T;9|I|n4( z2f`-Oe;Yu4D{E4S=#|Xf8rYKR<}W~N4ISe4)XrPgCAHYZ{$7R=7=*4{neR~25*Bn& z9-LC?pt^x`YF|poS+;PqYhVhGDKVLss%T=YUHq+?Tw|ydOdJS`u=KAU0U}lhh@#9r z4l{OOxmhBx&XHxGTQu4x;)>176!9+7KrYUyWm;4svGbxftY`^53QRqTImL@@?D4Yl zO2Wh^$7E1O>w$JBn8{BfBBjd+7F$PVX$K`5;mwM52Cca<)3&n^DP?s9j#*z>)DIy+ z-_P=Ck-I%JzlocMOVC7kgpEW4M8qNAARsAG-gzNo%bLz`=g+vfV2!cr(_C%b_a*wd zQdYN#3&80{9BSPnl7LD;^>wjb`%l^K1R$C~w$y%4Z@^V+^16jpQ)cK1p*Wl7LPYDx zi-WP(M~)i^R|X~Wh&527ghIPLJ@;aj1`i+7$6e;*NR1Ydr1c0AV@|pPgvqQ*Sh*sS z#iC;d2Ftfq)}wv}<+FOxE|^G?CB_U}3D2P_om>#AWTroF_8 zYgw#2tUd#VJ!)6C5N~*`2APiMv7_w

WNp5~7YD4``2J+2^JLXSDAn1#GQa=Wm~d2R({ zo63@NZ(FrJihQ9_^uk{wU5VSIS%+H(kcQgDKY>6>gbwAJ$%XB-?=Ouo$MLDV2g7VW5&SW870b@!rgWBdQKt`zM07NLOKQp@?CQMZO|HcU$9EA* z->CPr3Vl_okGT}K`MjU<&vtNB)pwSA{El?B2M;YWFt88v(*UK8Ts#p?snMhU`{W09 z1m74uWQW|)p5bV~wi^mL>B5FHo*oORQ^rwD$jctPfj+8eybIwzYXmcE#Fkx zD6{ee4_e_MmM^+SP#&s^wt~j)S#dVYWjdw zA-bFr`}0RsUzkOzS~=ROGiTu`rs(c}s1X$0wUkA)XWdqvw&wtlejT0s%>Dpyod_a(owhK3$j-yt`FYiO8p`$LWb% z_y@R>D?Bm4L4n|tYDY)P@BBWko$iR8>q{+ZdOj>!qA*g{mf4&4k$WyWyXeO_gHtW( zU4~_u@ciaR(FYL-Fnb0*m(eErkRuQPhl&OOVTyZ{e>4}|rys?)oY;Pxl`e?)4ETmH z&KDQZnyg$A{>l3lWcE$j4A1&JILYD_nri#d4I&3H!jzfcV#4W-69y`x8vd@m`2!!WORtD*v)GwkwKyjP|Z5`>7Y9On%F3{OYDcg91!JG!(G zIaUI=|J~LL5q%;XM=OeY2a@jti&?}N0xd3YW;2j3J%Yjp2F{s@!T9@t#Q4zRkBTm= zZ;HDMI9l@W^h9dU@@Z$R!jZ$AqV&KM*q1-Xkv$Y`cs0iYP^gi>A`_v3p{bD^ZQ1H! zpK(?ZFGb$GKH#6RzENZS=@H$_j|^r|^>tR3WC2RyShvH6OwLZRkW4`AEdkiN3-Q#P1 z=*yj7_J9x2ltKK1keYfb$1azm%kvuG6LX9_nfYn-TCU31vPRLRnUQcSjZ^ODv>5LUx$J`!l4J^@`&gh zLBMK+7^x{1I?g+kU5}}nJSQkO><^ff!dpX&&PPO7k`gTqy*^8U0nQ zpdycJ)|i@z5sv6Ni)L`w392E$COm{Gu{JZzH|`l z&_+G<=yYky9O+!d{FO-FEqS7id9c_Q$>f7%jJid$OX@za?b02-6MGi!w5+VD&Tr>jA-dJQ2MJ~r;?%;fU3~qz?d_LtLT659>X;n1NTrNe`*q1e z8l8Zc>P$^0r#xiopNnu8>iSJ!4DEEa-Aq}hX3Y5NZ{usP<*^fG#PR}I@qRt{gvtj) zRdz2a1?9v?rFvP3)Ow=qmY@A}>7Fj=ys4>!;FOfma1y%|@6fl97ycYbf>V5m| zMwLm5wR-Wu#ot>h`r;z@*HjcHSck#2>Fqok)oOWwD7W+#Y1L?C`bs+!+s*Pbm@)1? zCj!5ba0cYQc@7WfBk~!ro_fiOb4~rcu8stCd?!JZ7=f3}-t8I>sj_NBk|!GU6f)P1 z5$rz}gw$w%Y@~Jwxv09qLdf;_1IDijQu>L#uo(_&HwT@}XiGwmEfbuhMnmGX7;%j@ z71Dy%o&VtJH~tLm8T{v6k-`7?+VwT_lQvt$4??UuTr|ew6ITPk>{kS8{5Q16{KR(> zzgW@bP0|Hf4f$#W;mQ>jw^5wpdXi**G_i0!4BuGHs*b51ehphBfsAK*hxlgw6W7z~ zTaNk+!|DYF^p$nEjS*aDrMa|9gUoh4<*WR!%3Y{700b$%x<+RxB!1zAfBR z#xAW{SQWJ>L1mJ~Tf}V@+F_`?&1ERR?ZMX`;12Iqv zdWcbf7)&*wNVIs3|M*^)Qr)a~Cn^1HkNHJABq{@O9OJR{b&$87|7AmLv~Uuw2SB4T zNWw%meUAwfryJVYrpUdYW2fV=uDyH2R4kUryI#z48=`m7|?b?2XrH$kwRG zV5N%`;e2&$y~B80j!PL58XPMv?yH}zIZH}w7VA(x)@cn0kON{Z7#FtC!8%GH1HKL* zqsY=(xQDVWs%3$jRwxCtrIMe(+0la)DjI+#nKC%6a0NlM)J@{DUai^LP;~;+Fn90~*mXvc%=gWPWbUN4V|Pya2t-?`l`>uQ?GvPnWYtdd(~?r9#TI z)XmX)ic@0`+Jao7zsDyerjhee$AW7SMsXLRLtR}ZL4)*BqI9KVTQwBbryxmJGR=N% zn6KBj_{;^CKx3EuI+b4`lM3HWq>+M%i;Mu2zlkpmW$$O)8>g>xX35_}V z@1Q;_W6%VS6fOn{vV*yxvsg&}OF`4b`;&xpKxO=+J6UxbzmaR&6(W~?|G--d(+YsH z>4|K9_)hV@C2}J-@^+ihBea%l$i8C~bTlcR7?Z#a3Ug80QFS3Byfss@JrMPVNHs-i z5X15{HkqzKGW1SOswml8S2H7__?~8JY~FNFAtl8l)vWwE>D^`tNcW9_&`-$saEn{Q zbuXoYhV^+N<$SiG;`4>=bLD(%ZwruK%=?8pJrDdr&myrBjPTpyihRH`L}sN>1r472 zudc0}eG{#;qx}+=)R8)~1}~Y~%dxsw{XJJb@^d$^|2BJ0K0Dm(2Ex z8Ly_7KL6I1JU(U-Lhzp&|Cu%U7e1L>6X*`#>(H}CnbOy+8PaWeW?uMtK~{h?XzA+# z-_l1IVqyv0Jcd8D!pt*V_Q*R%<72Y&A!r8l5zm=2g6Wx0N)A-Vd&u?3xBH=A^lEMg zp)|h+Ezkt;dlj74wG&>7y}a2OImj7ioF7^IC&(Bl$hqm(;f&R8^BhaTc)a7;I zyx_ZSTkiLZ4UmODtX154sVU&>O_@b^7Wu|=y9C0i=?^JLg@{ns*a>zKMt^sL@HWQB zS*+%}b;>v0^R)0O&DRBL@)3CRTH7rvJ|7*JZq1Tb`>}Fk)u#7e)QoBkCjyM*1S_SL zLZV4CNCO))Mj+6gr6A%d4i^k}dhnzkVyOt(A@wf>dWMEe{{>o-=i;O(=VVK6hCiXkC%zTs)@~%nNLfA{5 z9OhQ-U!J+lzY)dNJUfGORy$uC0zI^P^esFW+G1ON!$IQ0s1$vkILM3{kuPfwQn5 zbkf~3@HS`PHER1l2pUpGK;3H<)q(EUUw3~5A&B~2XSAx@d9lO&$HWxhTM%t zn;fSsoWmN2Hm|sokdOAx+}JF$O4B%dAdkFv7W_Y?5U;MG?{C8Z!EVaUz)_q-ZGm~! zr5SRNFCXgNf$GvX+(16oz&$2E^OPMFz3Oe^-`))~x^@>jt2I&b$1g6UMbC32xf_Z# zQWIeP1kAlR6Zcz!)loNCyWRtR$oP8vDM#{VZ{LD`Kz@fh)uwOxPH;Tg=^YdkU-Mlm zKJdNmgJ+K`!Y!Eqa8*P8D;9)6L>1}>|7&M(>GxeS4NsLS3U?K7X%N0Cbs`FIu>6J3 zR|Z;+QWA)4Xe-jvw~4*HoKm%Y=is0uubkDRrS60Z#h__4adTYo1n9@?A0|<6xQE-Y%F$8bsa$^cdh;B11@~n(MbM9r=HNnp zX?J%<^E=a}2oS8DoA(yxa^m0rnkgoqgQ;L3@0%%adv)McRHnA-e%iS4jydNZ)2*MZ z%Hx1wT&0&J?N*8W#tlPeF*;XZ=tD59zX zqO*7}ZlE*2T1GSSsIo54$WRmKpwiD?&GJ1`z`+EFrzu?F+oQ1QI2|{23Z=K0K`5{k8PF;j!FZDI#C!4| zb8$xZPCVl9c>UDT-b)_og*gV9WvS$Ujeb!TNp)^~mmI}hr5aawj+wC&&y(1} z1>P+H?}%^KXxC(y5Z_AMKTyJ4mn0v1d*;@bN66;Jk#p(?*PD&I`^3rAHHsB(4*BLy z$}Rbpdqk;LX~>~-XNNMMdwKRfma09vyb`Jbw~Q7m*fVM}TUk?_Msa1Rh0`^TN$4qY z(K`P94OgC(*rHO3 ztf0@RC*U#s`HCNy#TkTP)E@Mee)tTLi~Hr4Z7q{+nL_tgr`=I0!8bSs2I5EVA=DyP zA%stat9@7iMVIZylxpY&@d?hkm%ThI@R_s-@jkbxM`l6uw16Y(@E%RdVmh@*iX09Q z$qg?TC?RZz`U?X{QP12pqf&AHvvl`E%?XlMvZ$TSl#jk=sAp5G-IlC9|NeohXIJHI z=+lmu%M^HmKJ14Vp+`w7WK`Gxp&L7udXOri(ESYZ4{hPtU|^I#6|@;e zp~z!xk(oubYzX)zvLPaPRF1iLL&QO0kWwz!&D>lTk9u%#!Sy zF|2n_m7C9Wgp^T}RqS*m%`(6kYsU4-GEtxA6I0BxQJ-qS#65l1ZH6pTt|&% zYke}30RtDrl9Is|h2bBs)Xf%ml6KPewGafA!9AFxJ?k)pTSgU?Ub6-n!ndlmyPWTs>{nLM5vLthmdgR#%7R<}znKvBk7^l?W&07j8I#2HcZu5M(N)@x&_*+@+fmsV-qIgfuH4_t`8Q6D#>_k|ej+{57jD69)>@NsYHtX9 zl`J@<+j;~CgagA~h2zc@kI4bAc?u=xg6z!yfs~Njv9FD3&ee3dF%g1o-q|hVrQ^A7 z{onLfY{$A<0=7;6u@t~%k7)Z&Z$i>!;o0-?&(cUzc@B*sotR3IZod>GlrX4vx(jGS zoPlUrHcc|-;lwOTZ?Ol;0H!(cv&B%052mpUUPwKyp(zt8Bc0_Fk!sx>b!(-)Q>m<5 zIvj^eNmGUElQy+_tD9+}pbj0nt$2Y4E{y7+fYo2|=648)({F&DdPM8h&^ua8HcNG6 zu|$uxphUo3lK%Rp+P9J$PeI+uyTj61i#!iQansV4n70q$tR<(jq9rL_O1i8?`7X+;O^ zhYnDTG|LQ}NOu5#UZA%=(gY6BSZ;wK7Vd0@drcvxam|Ii4YS965%DYfUE6Zh@Y?Nn z#mrDMolCnWVD<+zw1YEmk<^xx^jM)?7eGt97WHp|g2(?Nd`^{iy#dVM3!C-G?p%KC?f> zx_=I(?<4@*G5=sfoQ3qc;a?*2Y%tI8YMJll8*+C{;CHl}^g7+L_NdKV)EgVtrB|vELl^4n5sw3P>`Xf@qSwCp>QzYqnGOVCI zW<^YDwOyQ3LLFs>LeZI+#XI}%z@HE^GHIj{qQ>i*`v^`C-(`6jvY+YKd5KJRR6?Xb zM81HTXXq=+u$~BSzwjPKR`!Lg{Uqc4o8LGjNAq+~FB-z~9=Zdtq(7ka5Uam_G^^g; zn8?@zuRmG??VVTlVl)~?5`X$8l0Be)iY;cY9NZgTZbcc%I+DDU=6(h$fpr2Du^Sd7 zhqkh@l<%Sqoc=!3kPjvJxs;>XeyMd#bQ1xrON}}zD0-+4JXPg>Y@C&X2{OhN()isX z=;DD(IS4DH#wz@}jbv1Zgxv1Wmr61O4~pNkDA|t`^nIO|Xm~}+*OdBNW#YFhxbi?M zLU=gKi+In_i%ZahaYnSc_|64R)@4$+zUDTW?bC6Yj^b%6&X@uWzP@NY#E}RtOp?odZsDh!qo)RcB}WW+6f2|RtB?a4{T-4gaYn`kho8?cb=_z#B zOYOe$wN8&IWP9Llgl}83EqOsyM9vJ4oZ=5u^eGL}I|Ar-5 zI(R}=m#RNg2PlO(Y!P9cIGh0pYV;HNwg?%XW^@3U0!|xDG4aR0f;yO2JYf-C-MjjkK*8xPwFnrRNxLO!rC#e0`+mD(?Th%AKT+N1GnZR3?Nso?W+Oztq|6KnpIo( zR^v2rbg-f)XQkAGK?wc2dOkAp*16wZC=eNikJ%mm2z?(ELVG(T_*^O4Y)FsBz5|qg zBSSx`0K6bu=O_QtJH7TZbT4+fKMJ0!Gltb3I+$~qz#1!{;*?-{-)&s4k4I?VNsMv? zg=Vm*vKU#og>Z0$dJh3QU(h)D5E;dr7UQs>gJAL@PbgDU6`0^%Mj_!vTF1kM=a6_L z;6iV|&O<|QPZ9AZ_DYeML&=5B23I5H95qZO(66l{&}o^xDsoFi2VQ;Q0Tq7Fb(%xI zjiv9Lws#Mqttx{Q)~wdlzV;C@nTW8NUv2+$0*O)SarhPpfr09@w?}Be^v`eZ=Mdr?NZE7bg zIa^Wrl{hY{(qm>@C#yL;lR>2H{g5!EeI?(g0p7>8Lc%{Wn2M2->_sWF+5Dt^f-FH) zR*T_CjhA|ua}t1JeiN6utz^#Ts6L+xXL_@TRsl@flabBaI;$y4>>nORW*P<`#F60f z2s^5qa>Y`)(WsJPQ_kiVZT&oszToUVZt=x*#dbJht1aLA>{#1qs|E8PmBMK{u+$HY zaGY1YHq4jZ#H_#I+kK8&y9DAY0XxHlaQOWL*nDFF5_y0q29TdoLgC#Bn~5NsHefjO zx>%?rIpR9K?1H^BtHKaT*1Viy<#XsKJh+|GnuS}hCnz|3#Q|(TW!{Rt!gIza*gU_2 zoY`0AbIpM63m^Qu85LS=2$fa$$Qx#C42sw4?ip*HyxrE1XUl(Kpc^R~2GytM#_wPF z1l|z@{1*jx=vn9#ZcBXuvuy%>xer}=jsbx^r{0nWAmBf>JwgW{;UAS>4`3^C96sm2 zQ?{%XU-)%Q48jAZQyHC;ob`JJ+Vwcpf83vbt{_5jz@r)>vEPmI=xwE1$@qFH!sJl;Jwaiut8tifpXW z0iYS@sYa_TD)N@m(`kBzifmIWVZ&<;ndGOFiDOp3#m3G9`VHY(Hn{@`sjdlogo9Pv zrW9yvd*!Jdk1^p|p;h8~Q|y|eY?G4h!X_SY==a(b-Agnr-dIJ5mLaCbZ1eZdwsKV2`o70Xqg4VjF z8AmXLn`;qRyDJ@%dSIHrCm2@nM|gVvynTZSeFM{u)Q-Ua{J+;$T{=B+2o?ya0rP() zkBS%1KifYjBWlQxMzfZ@s~)WU)#i!)*Ra`5V}J6avo zzF>r1;c)W`BBEbT({B&i{DhuA9=@OoBZ0ljweE8s4)!Jv;*JYju76UrUH_0sC8wlI z8PQ8+{J-_zzNPpnkPY0u1x3@nm9)9IA`=jzN1`kb$8-LqRoyaBW%)VT%B9t4ura@} zpR%toBqBCMSgFgDGGo+L-`=%$o3ZGMKSBT|l`1&`=2FB0RYgMfC`_E0@##&xkQ4<# z-jK2C`pianh(u$gVeqByoL^yr|9Z&OhHfAdTf4FTUZ8=U!i(Xfy#<_3gJ zk7{8tF*?6rIHe!8np(N&4^eR=YG{2~-{R|aB2!e==yEzRs0tyO{xZhIAAzKTmr5J0 z)C|}Y_9Inkqr9JibsR!fPtMw-;rK0c&o#3}1pQmU^XvT`d;!OIQspDf8v??@&_MAO z?7y1RWv7|R>Yt19VgJA;mjNw2Q5W{VS6hP1&|U|V;+ zv5T@R+$t=#9$B`n3wZvS?rJa{39*}?=g0a|S1_T>Hm$Ihl-#c`L|SVwE1*Pcs`@F!p*+Qytfw z3P+-~KEs^~p7W5S9)zPjxSwFR-}V9bh}@|75SLn`A**7f?S?AK!Dqei&||qTOyjM= zpv?+?v&~L*wTm==JeYF-B>@S5hD$Ft((0KWJrAT~iY(ME6s1jE>Ku;L%Fn~-e1Ax( zHf@CV1gGtk<*soxZT_@a+1}fDY^sjakK?zFi8&V)tW12klpi0u3IxG&=E-Gkj>?NX zG2Yyx`}0KfCBmiM5Ottbo8zL@TD7I6msqN!+POBm;l)^M+9}q%n#>AV7;)IE$%e5D zb@)jZ+peoce~fQIn0*0d&9ZmQHH&@HNXfyOHuC-u6wGOP{$r>mG$B-^(3N-fgV2R$ z1v}?dfuNj*{%cH}x*s)<08kCB9CrSCLDZ(4*tu-K*`_#q`WM3mw}Y25+cHhpCrw&% z1%53m_!HmAXVDtzfL}9Zkd8&MT8TtJM-nMWN$eB{by_=GR|m zBaMA|%urprjMzL|+_-yuTBMMfN5-k$5N)HLn?3~+EYMP{prW8KgLWBCQUqmHc23CY z32)`1z$3zV4rYzcTm>>+ZEwxbvw>~6E|IAbITe^Pt*MN-y2t?_?kLq*JWPkSg;Qkr z?wGD~!xXhJLnrTd33kp0qboD@|1N1c+~ioF#^_0?+5ZwaPFRbecBv*9s&l))>R*(u zc3l+q4Ycdh^Aex(FSmeAT}3_*QM3M&!RRVImD!TP_RwN>s7lKZ%qC7Q+{(3-O%6@) z7-f}t9u_}S_6`N0wKXSSlwI&a$p&7B`iV*#%7RGLn{y+Sf}e3tg=z11;oU+ka689n z+7k~-76J{_TIWM8VH$P|rI7Rn^Q1k1*Ci_Fm-#pqV_PH;@)Z5$xpqP3`kn?XXg=P%PUV<2n<)350bBGrjD1kgwGM zYMlu|if=O<=yev3_ijqN1;PTgSfoM2t3!q5GQ4JM)KcOPca&oGK%YQZ-zGBc8_Q>x zWe&40|0F#Cw1iV^4RK3s*2A>g?dwfwECf<_g3`pvDXseNpVkdw6#~>k(NJ%+hRQb} zp2imZUj%o-X)n#V*QOFVdEtoB3%FqwN`!@Lv$}ms0RG6X$ZNCc>+*=i)-`@LmXT(| z>Est7IWB80uQb1`%5e@~R41l;Ar2_bDt4Kd1^GHaTyB+KqAj!q#Om9nz=O4fRHD}h3-`?lAN zmTnmL&Io}~`dRu0x?EIL{ncQYOP(Qa`NG##Gu4$N+lPvG=|`+%-yrL$E7C`0L$9br zTkbCa6Aof_DqN=D^4LO8U=o7E6Rfsbi^+w~%D`hKO@1)h5Ydm|a94cFRHjwTBnIJm z7(|)La`UnF1LdRo!~J0sl&cJPP31sGj=C*v=&E=D7W-xW^s-NGIzD3r=Mvt6&FATP z$oiD9F*cEDS<*%xdITBUIto?4Yv7DigXAV)iY)t@t08^7E5u48?3$>QZZQbfUa^@- z#rXgeB5|aBV=2BMT^PGAk~DH5kF;}0u6s3Red0HT8H!b9u%>!U1`93<=fZ+#)A}lz z$+hLwOOY){k(rh&20V6(VWn}4ZXL3&UBu;~%^BM`Gp!SbISo0EDosyKmiq(jJEs z7dK09*B9E?POdmtwbqYVM1JmME`(!OxRpV^q#a8zJ9$cG!6lRlXSGMPXR6Kz8_PJy zHF(_c9V8nnpPeUiQ*nI95EZOCyR`%`eb}l=i|*#KWrLb!b|p>d71NkgaAI2%8%WgH zQI-9sBu6jRD%}3?2=dUwA*}}&Dby3GFko%os=4TH_Vl}mhzSt8kx9QGJu2+^6?8>6 z8GUs&{toRMyrwTI+97a}t>7$_&+k7RcFIeUWcW@cesBHAYLW&1;TZGwB^nLTm(5s+ zaxnYk%21caiN^{sh3a?|AJacu1*AG2~dzLmCZfu67JN_mUsa@D9=u9eh_EJ?)*LLz-P^D+? ztl8tUpKo1l-U(4Z=2plD0Br(>72OPP0s9rtv5&alZxlB|bI_6$P7$LaXOS*3Nbg_k zR2{8kao^zd0ep=?3`b<5*D9cowOMmWf_gFEKwq5%0ePSDn1+4g*+Mr?Kc+DuXFZ%C zKatzQPnaTXdn{;q(5QcGH^m5}Rv7b~ay5c1n|eJ+F5J9q@?Xa;+*SYqeSTQ{k%XrB z4OZK3+e;Jc>nAK`{q(3FdSI(xy#=+6{(STV=l=D$tmPa8=!IDC{;g$1DIi<06QH6^ zqNz<&b7pK<=uZWNBq`y;oZ#+#%UvbA5oBpPRftV~67)oDiv@P65uPMZIL|jbzs9Ku znu&fguyBu2D=T7oUt9p9y8-8oQ=oswuoF2VCCggGbbcdO4v{vtlA;BuA0VSL)`WYW zw1+NooBvE=ldwjn#A%Q(6O-=_EmdlYb(99p`=ef=7N?VSSfvLC5xNW(8-Z@X+Rs1$ zvFVN%*mE144dp0Gz(!IS1Rh};^fx+k;v(KziFF8+5p@uZ&tCxqU5HP&p4&-(+ZTd+ zpKy|j*!%-U85Op{mIQn{HhS3bkH=~X6`+0@){EM}368fghh#wO$6^O~P;^hlce%YE5~5(WReZ~sA$kzh*l06|hj00S^E9MHOQEbfNY9_C z4Dl^H7PdJq<73TQUHn!Q4m04v=J3ldZyy>-2cLxx`$Jf-|GOVzU?06hg9dH(I7k#a z9haK@BkYHkxL?u&PYj6^z31%d6C5y+fwO+$eoCxGX{`=8^L1`H_|zU$bbF|7{Aqja zK`RO~Ts*b<6^2o&+weZ@ps3re<920KXA*>mY{?i1#=UhAZJlB@x!J)?Fq{WZcuPqT zL)eObbm7v2h0bXwtOZ6?+s)Q9_RK^uo6OQC>nzla%U@{=426Mg2M zpnNsxm?r^<0=vIueO%~%st5+kEHz^RpkomNnC%G|{C3@gf&lfPtMbn~YvgwBmE zT)l26ww?~1cA-Pqblo9C$h_RzAfYBa`K)2Fcj6F`TlGoc71NLhN`V@=dypYa-euHqZ)QXAPIHCm5}|VATvP-JY> zn;Fj7oU-TSH<}WZy-h^byXj-GKtIM^!^E|W?GwKc++Enr!Xf=atZe_*V>sDQf%w{u z{UGr+Q#Q?lyx|Y%D!(X#SIc{b&)o@r>9j}UO@mj(rgI9O6lvX?A?9DYechINnOrUa z*j?KDV}2qZ!Ttp<&B@$i4im2*G}VxjsTYWaH&c0?x{^4up1jK_4$i$R?Aw7bTo2wI z7o8Us_^+>H&+;Kpjl6KWz%eLDyLe-6zg8LU%LCN=E_rIy4%z%bp1iHX5)F+x=zRdggW`uxK^`2F3u~LD8=}x0?zoK zuZS@Kv>ib|uy#Xlf&L&1YZVaAm_4lF8?PBvYooe*><}N87BglYWIYwW} z4#)|LykTjayS_}$OPOFkW&JsB7_1YX|!-nEo*UlQ%qe z2LrNpMalb>A&*3_gr7$mK=$WyMt)AI z{P6|KzRMlHiBDF#a`ye&)FxHSvhKuL zL!ufpwMaF>woWxdeQL#dU8DLdK3OeI<>cILw}gEwNk#LDF2t0Xg3UQwTS3GA6%@8ztctcdP7Q9L zH|~-8$z8DvDX0gr>w##@`{lf3?ZVCGz}LgL?3m)`K-Ns2;gv!3JER^^2=~J#$}jRt z(2M;I%8z^f!u=|km3-!#%Ib$2&H4a6^EmJMTg*QQzkQ$&-f7Ymy3A`2jqk+cW?&wP zWcw_v#AF#aELn7x6HhabMhJ10qCZ9>Jc%5>z0_@Yk(A@9N<$Bwx)Qp2dth5E9!XG4 zxiF06FVP+fRL`MyrW6Grs!GH^A3V-4QIS+j*&mBx@JAW9H`#(dGDd99vx$Zdpk+fH zNquy~N*|G<+(f9?F?9!$KV9!G2n{SobTnW_gK_c5h9%!L z1YLJr@0uJjF1IRTR;ke-hrJ%iM{Zz?qO(Jp(zWr>xkMZfs(;FeKmk*A55!tc0$xg7wB*ni2^$j<+Qe1!d|_xL6Otd?59 zxy4WrQ3|K2fez9IM@2l4mPuj=8vK)E#jqE+elyH9M3}@lX*#3UVFMA{bV6Iid6p`j zm_?;|i+9)GoU}$dvubv=GRN-3Y`6U5RZG|Uh7|O6>V_S~%_}(}=bHn;4MlFa_GBq1YtB3?E)+;QQy!FZ1R z>cu3+=vOUMl=<8P_YgftI7n}SoKtga$Xs)ue#l|wWZv=feS^*mVhuScEHpo2x5~!( z=(jDysi?24DGNDyO_?H|aAqB`hMWgAgu#Q>vbk4a&gfr7FeX<4u)DS6MxZURvxa_T zEZtKiM-1)jM!@}Bm1}3SK@uceQ@v2@AUlCZRHu`;D2x=86#006eznxFj2L>pLC6qd zG8G9b%+qAk$8Z5&Vh8cp5avs@*H<6RYl&GFi9&)Q>gGb=Zpa?)-Lzs)Q*mB*+y^A{N5v4_m#O zGsciyne(!fYz9DM}yhd{D7%X*MeZ^3fU2EDn_9ufQEZ90ss(alQ@PG#KMRb@;gpoh~cLghg zcdfcQ2Wo{rq@zeDfzn>_z&VpQ+x)xAm61Z?kLme2S+-EfoR-M1FQk`T=`=#!V&PW~ zw{s#3%29<_GzQp(%y`*SZzh2URI#(lxgC~w3!t(7i5bk?kD&0EIC+S~Q8%L$F2=Kd zahc!5Z@{UkCh`ud5KL7qv;c#sG*O)khGO_cOJ-u*~hw(lY`@r4)E} zZg}^&JYbm?T(RPT&weN;fTs`n`D9_wQT&bW&?c1Hw>G#gfm8g%SI_@Qh2VG^n%e&s zVQBq7sj!X#Au(42GVyl|0RWT{ahUwMwmHHVgtSzxL$`{zN)-%=2P#77X5rF>-IlGB zWWx*bgP=Q@yzkF{3aawlAC$D%n^b$U!-tD6P$027@?F!e?%13|)TKZhnh~Wb6a5Mv z>ZU%W6SmR&v@~v}pqy7GQT(!`#eRBb`VnT9oc9KaK-frupG(YWK*+!zrMd1SJHIye zKyNAL??%#03+clq*|eHbPrpb{77i>CK^f||O)$c|r#SlT0&81|Uc>7I21iUBXnb6B z@b+8yiN|^G@sbc7&}leYfZJlXz@vn-W0{|^86_Lh#nhz_$|Z&0T^n>M^3H(n^f z$#(YhA!JQjv;MfibW7CVATD{sZpwl3C@t+b4HtE48rI_WvwmN2HofR7-T%A4@pgbV z@jv0y>VNClLt=#i@CsydLei8;N<$@rj6p#f5g9`CEfU~3dB`*+dbcJ{39vF|!|ei^ zR_eaD;!Ozet1EoLEmfxYJ`YnmD=E7Qj}=?;U$uA0X=GH$TuvMk~6Et*6ZVGg<>B2Tl+ zdkr#GRGfNzAp=;e>3dw+&1JYg#MUgQj?3Eu!ud@2R@=Rz8!q%N9^JNivy{vt7gQGp zm)bkH9JV%qrW`%`a?mm5sR@TNx}M#{lSuR4m;+%BT$L*|tzn6nTWohJ&Y7p3Jfld) z6SPW*+}4(CB`=>7e;{OsN|0khe(fH&Ef$1m$+`~s7A&D+a~G|U2?s7eHc22}mZBqe z7i<@tDzQAcIpwA5)?(L%;Ho!L)_{M6UzYi){j>vMy2+RRgfmbb?Jr>=E+vD5uksK9 z9fJ!dIz3aCH74uZuNDlXM8gnFIg5~^2*~Y}fM1L`U<*<5!yI^SS@b{eGTv?zwaCoOABE&qHJz3F50^!cMY|-nmM!0>IrPce=&H zArqom&j-z0s*4Ep_3h7ISC|x5;sg*p0ZkAePGyCIwM5P70R@YBu8#iY($O-hatq<7 z^-&H6;)4y12uHcr`J^en&y_qIBR7xTTm$<)_m1;-Yd6!kvv0TrX1f?0Ug0IvDsTuV zDEsCbQ`}>K;?ZJ=)1nJCWNX}J@#d6@VNN@dvS9QH?63coK@&_5i4+{(Ci|5}$&RT6 z=sVm-eR!Y9l$1ZNC%NW-nM=ziPq{ZM*kYceZavh#SxL1LkpyGg9PR9GwSMQ$Gd`QH ze<;Zl*80%>LNN46k@|PS9l5X$?#T8Mh`}}{tj5*c49h&}C516g3{KpL+7fKJ7k)WR zSU6`P>QEe-OL73eRyqHgmE%9|{%oi1&b#9(R^;xUYfhSd(V5E?Ll$hcETYA-#t>jU z3LOSfWtV|BwCnQ^#cOe7KSlZB-d#sdlD-xV+`7Ybe|^2<>Y0K_G{=pe`L_K!3%;+_ z8ysZiYOr!?0YOsiQS$nNeTNp<6h2QU=3SZf{7K@u;~VCZKr;5}p8rN#R^z6JKNJ1= zh(}?};%P7TtV*K=snD3qfP3R59K8;I5MW=D{Wh|M{{w$+hnw;%iDp}onbnK$LHHVE zxUdSoJ4_CiA~>8qG{_kBT&V+^*Tw2=A%{=DoS~N3c)9evE>nU=M9S8MDRlgXoVVjS z*3$0R(RaPT!(BIH44V=(C^NnrSsB7k0-tstVqGo#lqXNIu6Eo_P~PzvsLo*mwt>S~ zY6@Q?36+s4lWC25oYN$-LYHa68W+Lmj$jFQVxSim)5IS>T@MM8J zdFPG{C3*Rl#J*STzvlsbD^Y|Y$`H_>DlO-Z96Z(Q+ z;Sz3eOuNs-yt3Zoiyh*bc%5AcHtB_Z2rub_e@|>&tC>RoBQwC%-0G|(5!UZ24p?ds zqi?QbY|K4tbKARN`xC{b_#Hy=&B_CIp$}b#1KfQA72^>Fp-b|hU{rp3U!=(GJi;TC zq0(5fYkN#f=T}BzPeOFy^#KkWDJje#dZwTA4BfElr*x+$&KUpIu~=U0F|{Rbh(Wj$ zv_(I4iaFTF3K41ft@6hTtH})6TSYFYsjbS8A!4r7bT!n9m#%KcG=%k|wDiI6=5$-D z1|Qq%RjmbTc}d=*(?rU+Z%_pFn&r_+LQX82Zm$+DD(NU~QIZigFBv&n($ z)aUDrKDR{t_%zYhOSZ*ck;4AKtoB?0=`b+YMxL1rlBfIW{$g$G1L*TXRQ`Qm2Il@R zs{0sSjk$%`MOJ6oAVKQ0szP#h$6XdpzSXadeBqEY}Lj%2Ui$At^{G>1@WFDE2#RWDcp)Z zDZd8qr!W$6V^K3wxEO1*8Qs7p=eVUi5+S&7@*PKjo6tzvkF{Dd134~TckK?^vZmlC zj^mV1b-}+s;@xjHbf<%6Hs#RVUFIAFks5MGh zP!L|>T{8|=7EQr|xh8AXP&Y8;EM4vaj3)nF(rV?K)DOHr$#+zR%}G|}`v|8h*^@7A zv7ymMW%S{7n}8YtQu!MG=$YY>sJCPmK9b)EAoFf4(ztx>cbO;$j=^UYyO#(qMeEHxO?(6*h zZLX>Zs~<&;I}M=rH$^=fza z>q*D-E;498Ii`*68}U=EbNVubprq18)D=RFITx26Sbj*3_O`TC@RK%adcTMf&Qn&r zK>R*Eed%nujs-OBSPsG{p$-!u_K>p5m;Y-hejM!+Dw-MGyJEf=^f^e zF5{yoI3*C*A57}VM4uRY)N;Tf^pb?f5i$Yk{)N<~eO3u8dJ8%+1L%$iBV5Yrdo%8+ zxap%sOc^wf8l4>$ue)cfn~j!qwztCss@A21$4z!aX^*5Ro1A#+}&i4BEeRO_DJj1!`!ppS@xKbXVfmn}oQ{^$G zlln1PZ4g=}{;Hq};!5l}=v{H(r55i6(|d`CaU-wLfYOL7fqA{*7n$vd=`WyDha6dw zE;VpMIEh`FDe{w66G}twH7ahE>l0q_?8m$fBfztDI$SMTk}T{^z4@H0#>OaV@ciB6 zYV7^4%Cafdyq>V;8znts`Jc=DjS3T1Gvcpw@N@w$_bpYdyg8ox^KvYETXpl1dw|%Va+yL{x!q_QKrx?_xZ|=_Vc#aTo{w=T1e=8=ibs6|8eHZ+yAuFd`Le z8TxOLsh(srypYrCO&3EYo!3%+lt;^7AFN=(kL&W=&mVeARJFIK*U@q;ZoEI?_4pjV z)481?r#e4adM?&n?1*(hizG`mJ9ojlwy68x!t&^N;zqKg#a#CkeoNhdKWWpGT~D<{P3_vquYB44KElrEUzn zseP$Oj-T$%(YqCuAy52n-x??+le|j4VuWoL?~0!1@~$#;E4#B6JdE>KeZEz*X;!}g zt!oHWRYAPeK780TcX*yzZOBaC_24b5W`xRt3&rKj;+U4@Esb-<=kqst2hUr5bX*-4 zU~DGmD@c`JG9J9!Hk2#z{f*h(7H3YIkjjTv;go3bZr?>x&4#`8=E5pI(k`jg4Pp4LmD5;5iJY3OIsw|t# zGO}9AodVbfw3i89l}lsaWhcT)hd&7Eg<0a`)5G3PhM+F1lh1hQ_#@jTf*!oTv{A*L z&m32Mwg_9IJMgRk?F`E}i~c8bqp<_Sg=LeqCu>WWc(#VE9X}kIowd!(mt5_pXtn8D zKUvh(kaUiZWy;~U+h><&$l}E3VFsOX=LGfX3n~u_=nEh3nGb6r}|m6!)i6^6uh2PL5ZyOZLn;8HYZ7Xgu`(UuD~Om>`n~y8~?_a^(d*P$q2t z0Cd%^9%>HrYS2`keI(mabqHF&SjNE7r|U82JwL|-|8BjUk(y+qmL(_-#H+VLJD zJ$;8GaHGo!k-lyzZ&9PoQqPqlioXIlmy^sssajEXTfzD3@Vx*pRFmJdFN9vd3L38-q3}`yOHlvZ? zY|A!xj4JPx9acQoreW(0?||OF;!K-*EY?D0(G3+0@R@oY=hRh1(!txL#=O&bd7r?3 z{gZ_+ikCWcJT5*ox|YfCbjbVoq_=^;p{RdkJ*Kx+!ek=96GW=oSr)T+S+6345d_lW z06wHzvN)4kt)75DpfW(_sRnHG+)*bH%COOcvdM!e9#g+R5KiEH8Vr!(6au2sAh264 zdgw^XAK?JSh*X>gOoC8BNSc^{w%ScKD+=_Q(t|uf0|f);(u`qsm&pny6aj#e5UxVA zU+*AAKrOft#b$- z0i(wDQGiBD3#rjS2{Ke@7Ow>RBi-t+whod9)Ss!te+SGk|9vu=6hT0Zg4|Ap;M9N= z%6ZMDY|=Dk5s*8SFaUop2H%T_`1=s8RY3qmMU|@cJClG?cXb-AKGY7y4?Izmr#8cH zFMA4khK8Kd08p8h@EtF89HmN!DS#{ua9SG#6lk8J7P#jM{da*fx;qpPAeW^J-?PRA zflktBkqv%PEWlNLVXEezK5D`=wEaK7Xl6hlTaaPbbxSRqmpC z2tlLMX7!7fgYT^e1c5|oD5B^8OCw0Y|6H_ojD~6r{6#SXH~j^uCGSnif4=dxJv|NQOr9MBFZ! t8b!T+8K~W6KrV-uzBy@k&+aI4S7+~z1OiFW=mWbWLH{s(Q46{`RM delta 35599 zcmXt;V|-nG^Yzo1jhhoUwr$(CZ5t;%vDLV-Z8x@UyRrTBzW$%*{eHD)X8qQD*YqBM z-!FpK+I|N{kHhydqKG{OzJ$I1f!s95Y7Cz-Jv8B4s)L+kl@0pru5$C4=2}*XWvE7S zpkKIDbBjU^=$xex2;-3*TsKjl; zZQqNKd^<774daff>xtuB*-V&lkbno*L7n_B7Y3`)?*QITl4}o+U`kC+7NtV^Ir+v@x+1=}mn_DjBZ(YF4wDEpcdfXP4v) z*mwfrG2tnjMqwaTizY*fW+>?hy9n%J?a;|*x)r!b zel8a$wKVp9^myi3SPfl6)1S&pzngrTOiwoec7K2|Mv;M@e0-*992&Vf+(T@vqcZA> zFxmQDGUkr*?l%(m(}VW9YoU-K`Pe-bfy_94D{$KKzv=9qcu>TutWxl{Xh*{fx@#5L z&5z;EHP&8q=+=t`XLgF1+xnUcX+jwEqVhZXkR_w`QqtSfrAIM3*4DobAMUO=9d zcD;;;FRAt~8;zm%E6N6scwrspDZkV+mFnQp5c}7C)6UsF==_?x>7o^d1cLVlf#Cs0 zjW`h6d5sUlyp{{1k}-;H4o!HwAe)*@(v&iH%~U%ANJyznVn$!=JH}{NB5R|2)F4v2 zZ5uWY(-p&$9tu6|Es9>|Qc(Lu08sry~p zenSb@&7|TWDbT>$Q3DM16iM~~kV{uFA=2Kjwb1yQ(kXK6g0woM@7PU;as~ixdJvj3 z&6qRpf!XeiXQ1qav^?J$iEEdNeg*Hmpr;*KvZn?Bo`*()7tfCrNDj6+c~(wtvSAtL z1QP7pXa8DL;=r6h!{v|z*U}%3q zGAkLJ4&{Re)d#Wb(@X74eJGhjjJUBzEAj}tObO+%*bN8_?|JGoVF2610~Wd)!-rp= zDIy!DrSgRN1J~b^pxRTg{f#e2v1BoN_NIoydU^!D)u}>x#6dBeVy||C_wo--)2ja! zx)S(bGuoO~%h`j2fi)xrq8k7&L=6MuMLaKW8AxW(Q!d^P)Z0(NHp2FUegjj&fYC(s?}mzg}(-{(!?H z=ElbAtMdcc>@N_kaAiPh9MT}nXQbu*1YF5^WLu#(Y0sdrpsWsF)+(T$(M6b?0Bh>m z27=hAC1>$8ZZYm~DINWk4niDk1$D{0_xznD$;ROkFI}jsE>(zgkw^!OaAI!_++~3uw`y0 zVJXjuGlqyX2_TqiG;kcoCgiNTzz@^!S=~O2?76x>N97>yG?{wGgV-PV4%0FZwH)fD zw0D@;2$4gBn0@1K55bSY_rq$0Gd{SIxQROYe$55{~Ck4buZxw$6j64YDEFEdJ z;Cvc*g39!R*fxwu!k-fMXvVBwg~f?B4S3vGoV#u#mEUX6K(o#`9*!Il>%WWv=ioDj zjHIo029^OaYdN*V)&Z==Oa=S=1d1Y6b2KI+L&Qs&{&J-nokwsJDk@g@OW5N31O-|G zlWv8U6SLN6aOU?3a+uBN6eActMh7%|4#}T1_=+G~#4{P+%jY4-rv1z!NVxjd++Qp7 zcqWC<&5l9m2HISAtltymnr^rMOnxt$8O@-wMc)TJMQ$^_9Yq%;c?29u)mLJ6BS-Z7 zuib1aVbXPygnrlpZ4~AWG5qxf;hQM2Zv3$^v2AJ4XSjZG{Lvx)?Ig`C%X-zGRy8+1 z=l+}Nl|}ZxK|l~4ljP=ha)8i`SI+`cXbfw)^1^59IO{HJ+~;-wxP$>r+$nf>@$T58 zUSW}VIW0s_nL^c1Nv^EjL=7qF4P;`Is)9!95lYocVcF0JVj z5t?Zbky7h<>L+5t93s9JzDL2o9!F1v7({5tVnQH*h(6iv3=U^fmLYi*th#qdEPla0 zDO&oIRGcCG7o6cFhpi53!Gg`lO5p z<>s~8EEra&BJs!gpqqd1U_gVLJArOS2JC0HXVOIwJ01j{>DF9aIH)9v7v=E_nZm26 zF|3Gy?SV@z@|xR?(U2$aq+eA$r>QonwI3C6ZnKiRlp@F5X7P@oyqbh0O%m@(Qi!@* z8si%kecx83bfmGKH)fgPB=L~Jvdev)5FqeP-SRhv>`w|4ykl(dmRdAuKcyi6{e|iM z#=Ary1-8D#bUc!TL&t4M>zC@D6}C!i-wZQQ4kCBT5-g`eOKf-RP)x-z}SR)c(N$b3jzM<0`+6J*!8(E#fQiOLSuet4lBrT~ z&36eE!r%TPK%+;VAvCwy9U0deBBkGpj<-g}m?REMjOvyz(G8)QliJ;Hx_cz_m3y~> z%WSfXN-WycQmqvZ;5n`GPv4BC35ktYL-+=2GCQA?NS*eWq;E_uJpvgkr@G)Kd%*rT zKTwk22k0Td!1Q4L^IUDDWJx(CWWa3oQx9}AtS>%Rvo%*y?WOuoM4{huN#Z~1nma9Z zP!kFd$(sCvTV+`k<^xA%v(g(?p`QG<2RAh!J!V^?#++UbV0ygo31{{Rcerx)DQ@^# zq;Mr`7Z}ph-!^=5w?8)Nw!dBum%-TgzYrM+`PyqP9%p`M@DIq*Ef7c}hXRT78dD}u zL1$;F*pu2g6m648)!bR%!_+7;2#!ugO6h$O?bn;Bx?Y&) zn${y9MZEfd2C`I&bIek3u(Xf1Rb^r)#yYO&bx3Y4wHGzfmER=HB;YWD4Cltyt^8x` z9YN!CJm}*q<>uF#YcnRB>Ol624DBr53pKm2^|ZfCRZ0yU6ajCEg%$0(!U0Bil|z_+ zk61=hDdgM1X+&uK1O0u2zk^=7AwVHICGR!sRsG4ZG6V zc_NbNRBcw0zFNbhTHy8^8(fvBvVrxLJa!s<5rCbEmKUo%gf7`9*n0v0v2=}YpV=0{ zn1;T@L2bU&RGQ=xpLb;5UgFLlTjRH$;@U2%DCz+sz4hH(G1nZ?{`LwgX?cyQC0CCb z6BG|}iC193R0HvCp45r?%9a&1Z>Gy|GI8iw=@}*0I?gOxHIPaqwF;x1!8+by&_UO1 z-`m2(2FV?bqA*d7YFk5fj8VJDjGR3m={6B5xo{Ue&H8jL)L|B-Y5wq{C&9vLZFLCG z8)}NgHFHuKWX1;3yCTogx!`o6Au_eY+WatoQKZ6c0HQe~V!erS>zRnDMoFuKn^|z? z9l<6emHcQ4N>nv)r!@+Rj7l7>&6{(i#2V#{uKOwOgquDAYTyLF`W-pCx{ zn>QfL3K-A*YNtC?V9ZQEY|_LTq&ApvuJyWpBn85c=-fSHg)cc@Qxb2RWbl0CmBTFP z*ihFSH`mmz1YD(VLUD<`)8?Qn=9IwG3#45WGYNfd4amkjA-DQ1p(&L7`Y)eB#@`tpSD1Hr|R)Ph@*Da9Bw$L_zMgCIBqlq-@IQ=wAN6SP~hhox!`x3*;x_Q5y=;5 zT`a{~&)Pa0q<_k39POgGaJrK6*`6mIstxxSc=!a!kbYwiQGxlcDraD1#aFxs33dk8Nr*$b zG`|%*#Eiimqn1>1=%lS1V_f-FlP{v%1Q@SSAb^=8e5R`TC*8dxSr{dj%(){#w=%z` zi6HN-u4ac@+@kLxUwK)1hZJ0mP@V@qQF&IWOY^jw=`E1-?lhg2?J{%7P48EJ90#7H zYSfAkB$65j1q6PfFAhi18iY!#7v8C=&x1#)4I-<$0x`=>Vx*`F4Gu&SXENg|2vJ)5+B|Ehy=OQTMK8Rbja!X6nl3t0F zNg?2M5(4E1I2wc888$Z-+5%=NX9rA!P=ga3JT~>p8e3%6>5?3YDS^F)&$T^Y`8V=5 zPA&=~&CTWM_*I4JIqOaM1Zz30x;1noR|pc@@^mG|ZQ8BPmP6{4>j`3)L7*WxfRv*{=?vM=hUOqo zk#S0qJJH7wZHTnL5UYZ5!=7N257txCDCYUe)++1?`|^web;N-s`dr~|oqA4jUXiiD z7=C{K*B@Gur9%gupx^$j=?CfanGT-08hG?oW9ooKce=rK(yS7P)* zJL*(R2dygB>lnhC#EUKvDK~i^q;S9FBiQ`dNW%9cFNYeWMh$Tu9%LP%+% z=)eGhv1fOP!_-PSd7qpouiPi+t;eTa!XB__qrly}(NXQ!f{f$WZb$gD=<=&lDK&;Q znBqach7(Kox}UIVeP|n)rW=RV#lS0gziqnJYVL-9It|iA2$6=DK=W6em(furKii;I zX1~K8m3mt64ZZ4^Idx9ZDJ+rP@Xvci$uwis90CGDc^fFFQvY%o6WAIo8D*>*IT=P- z%%TKlQU*=pA{}$*ofSQ(9xz(ojw;|Umgh6J}bA7P<*BCW+25KsbNB=|G8 z?|1bE8s$8~vZ*=tS*PASKAp-}0XIYvE$nj!*<$tCJn4QXI^I zM`r%-OiK1AOM(qpf_#=}0^q&!d8B;viEczsyF#b+;PP~E#-c`*Ka?M$+}=nMFG)-y z9o}?NA9bEgj#Uw}^6ft6{DV1(;tgwvKO$q}rikKoG|?Y~P@Qb8$t$?cf+;^y*PQXh(hYT7Z}DNr%8Uo!N!(Si6r z4K^jfq?9A1#nLIQ+%{^k#!L%ZY6ptE4=_v`tlqSmjvuMb#i${aVRStuyCvX+IuXKz z#GSW8?01GZ*-fQWeA$BXNpq3P$Xa=X93q9i~s6P`*aRUiPY zaf`iCL8Bi_+UDfH@Q8CvGc~=S&+CYow*T2!21@f4s>xgt-P)0cx=U9_#dkYL3$|tb zG5BB07eQi^to-YEX{i4;2M9_DV6Qwb6AFG({0vxN>JNFm_A??OS{-FfF-4+pX!**J zrDdFscit4Z!OI=>T}ouC{Dr_?xUw*RFv3tk*iUbf=bd9Oha)fZ%ge7%h=A{vjL$B9 z9|b;`1G>8T@xR7u%D%NpViY&*K;A$-T$w z9Z$x%Uu?A^EC(6V9(<<4zG^1(Z!}L_<*~Tra=BW4+dp2u0$Va-^yTGQcj%ng+2F;@DRMY7*Qq%xzJiWD zNZ9uQo$CZSk`?ac{T~00jMP9f0i3Tr2fdnSjw`A@{9)H60LWL)uC0`2o=;P1uvI@_ zR3}4*;M*^pQu40fgeb;Zps%4*7q-AURPyQB08&p*uUHHbS0Q>TWN*e2f_kr0^cpZ* z3QN=H%Iw~%$N6l+k{?^)L$$Y%_A-$3H92BP`zPS8ZZZyX^w#aNVOgX}fP?WnW9F29 z-@EaYn*qw7fk&h5oMpxWBA#e?#PktD zX26m3p%kVpwm5XlC-p~p-nywIzzH+dA-lAnQ6R7JHUR`hYwiT&fgSm^)$^Bo4vjkI z?JEzN+cSO;jUW+@7uJ#sF_RJ&x}@}` zpErki_vC1F#LcNsW|9{#}G7f=roDaI2ICVrS7#cZ#z0KY!GAOnz|`*toL9~<5F zC3JQ3Vn6H*TtA8#WY^LnkLON)vN0)dejENKfxi+nxNGD4@s zVrvEp6bVDinItjR@u~yh$@(FZigkzWl(~1=MLJ#)v$Kv*gd&745|O=1Tjl%qPte3J zh0=w*G_2FFm?(iuxW{*l2!zx-LZL!spA}B}f!G$y%KrF7QmgN+SKPgZZCjr;%cGn7 z9ynNt<>Ec#9lzo^cFldxJaVA6eXYZKvt}j4dy?03?+Z`+uE=b}d!)D)nB4XPhK3A# zp<X-ppUpEj+wo3VX=27o?w1;c=&Qo&fb~4(ij=ZYT!>AnpFz1 zBb|}Z{;@PHJa9zikE>7Br%{#QzewOt7vn}y^acOl$iJrlg0D(S_@_|;s5Ag{QYIYS zfAl>(qHVK_7U6AnV>5r~|LA+6;T|&KpD^YrIx$>QtLFw55A&&X7MG{b*N=UQ0IvyV zUw%$crO#50wk8U29fO4`yRK55JOdX#f(|3Y=R7(}`cMi_Qp&b|lKwT+C4JQ=5eegqxAkR7Q_XQ@wA{cC`-yR6f4_#HByBAhE90YZl7x51q za;Aj5SdC2JE^w0|yDr6rBjc=bh}9J*LOkKU&~1Rxd83`6Bd3j)>`T$9z*DN9)&6l0 z+MWq9TPa>#{)41h4)S7exxAwp#&LhW!646)Y_5zi5{z>CeAp zw}uuoskR&$7^9}AgD!#LKMct+&?u>DOMAw?hz3psg@O8R8Ldeb|5M0LR3>bbNNeTq z&?b^}mHzX6`}BU1{^QVkv-aW~x)`-&td>JP|l-%95&f5EDLEX$4k0G`WWj5JMAa-*~`AYlG4ied3J)tPG%i_lR znWIhZ!5HKT=XuQR8*3`H-Nj@gzlr+?HygeZxbyp(i`=Soa_kLe1-E%sO|pKpKBh`E zEv%6JIW5zxtFwzUg;QgqPe#Zg6#5l533Lram48M+MLG?yI+M66U7XuSgL-35VsxI< zLwA=F2+RC8cOT&&Xs<|~nx250RH;qd74-LY=FH8UG8+OF53?jCiJ)_VR!Whpy+G;i zqEZ_QaW2#7v22n&@{Vb~(r6pwpm7V?JeFD=L^=1x7JY46PiBZd`&*ZkjzcE>6oOW( zwWn&GyHvmFvE?VmzkC*&Adf(zc*`DCA@oOJSl;jSJg-b-D40IZ@FQ4a&k|H5OC#9q zf`#+%8SKoH85os80Ffwq-F{SWbGqlC;jWBxLJyjtr&*jKRJ@p<(SCD>PN1cMiztKb zYW|U5>Q%Rn)_%zu-AT5{yAYuMj+w$85$K{Vdez^m#;zoV+#JCd9m;sUQoa~NaE)R> z6yXBI;_Q>Mq;W@brlzEpO`qRWj5pm14Rmq1sXW9#u)o`VFW*89PK>~4CvCGTx1tWY z{9={=V1?>h2&^8)pYF2qJf!Ph5+*h%nZ+8S$|7Q>-Y8h#WxTf^G9TZd3h!VuvNDE| z9y-emPiz3hCnH||d7+lEyK)i|B2g#`n_tm!-RC zBoyc!$5#%CjANhN_909WnWV%KRTU2#QAV->1Cn*iA!Ze@m?8JBxE?rgFN5rUd1g=s ziN67=5|^tB^>h)Fd5AS@qoatxMn+D_ul)68%n4<{z0OF)n?9sjqjro?Rv343>|I&uU2%?xC}DxF zpT^2I0Uu0M0j5@|YtjZFj}NZ^@xsx2cPsaaT!>jyC+t}bPE94bkEz>hi@}A_+AGD%ji8KKH zp%Vw4zioPd_i-O1jGZbaO`viaOwP!P(|(Hc_z&UrtKdn^g*QHXWQ{2qmQ9gya^&{B zblmymGR18fjlJsN2;4Lv$D1L8fBpBS=8??2)&0{q6WIUGE}qLt{|VZ=+3 z?o`wAx1u1asPsA>&iWjVH`uy1WJaT8GEQmO=!87?g(>-zY`bBb=?hqQKqpvBtGeAE z+7ucF-R^+2?(m0gEK3yEOi>q~>o{xw9X|Q4=W?rxNXZzap)bisqp@eE3?fM_ZnnlkbZLd`BGiSoC8vDpx0}OJ6_C zpva5c{iTPt-%1n5oKrgHNUR2t%GWQup}LvfsI6@Xpyk>)Ol{E$^XOyVKxYiYy6~&+ z2|~IJ%PFAe33X1$A7$D=Yx&E0R*<|KInpiG&)jK)STfXMn$tSGgPYr0vI78_O2RTD zy4_Rl7DgKZAu%Cmw&V1(E(MjC;VewEFe$Miz#odii|o6^T->Y_ge8Z>P;a22p)Tz} z0lQ8T54IAnyt8w+RUn{HFC~4HvzfK+)B+D^%?{S7`p9O<8*4c;zqQ($*# zL6JyD_mtQv<{ov(>yi%&!3K?gktLA3s}E(Z=(Yj>{4+uu?1o9`P*S=nPEdDtd*$bn zeZ-Th)bp^TH&bxje0sy3p!1-aCqOd8c=K=?-AA*XCgOY*vDQ>uA=9KzlU&kX>2b5| z14z=if}XL?;;iA=oO-Rix!N9DG>;LY==3EX;e^%hLO@v`4DFp@;umy}J}5-Y`Z zaR5s(l-wC{_eXR1OOQ4DlhH-q5N;58jyUkFNZ6#{QgfufD}L&3A%GuSP(Qpw=BX*l zTmm{wNWv-Q(pq-*Qs(|^XE?r9e*^~&OVUmahei*X4RW)BQ+}Gy`z;xH5wpUp@o#59!*sVAyW)wEs?HYcgdJjd8-QACdJ&(xXR211}+YSu! zK&}%Ei1EaCyq6%|5~Q7cLuPayBIFskU79Zt=m~p%Kp@5)<$$Ktl~{k znH)yrT?dQ}+65n^kaQC`dlr+1W^)9hgGIjsA^1j52nabAdQpAs?ymf57(sB$X+pt7 zMRoEKmGUO$5~ldm#@%he)@?*$oR?`c*uXJ6bxpCfwfH~k=KGAz%*+_n1^qTw_+nUE zi6gAmF8UUnTC4q)f6jvOMrTG?zw>OuD7S@q1->M(LU9GgJgPD{+x5BF9Gd8KyoVqe zm2fY9V>Ty59gN2I(}cvN0?=Y7J#KvV((u`8A88gCs7>qN4xAm#Z^@3O)9@+6m zBVVOJ!MC;DUPeZ{?Y9Cz>;U6#qP6(krN`9El*eP%$JN6)5RCTsDC5RjyBct>(d$~W z5Z_`Iu6-&C-Bd~-vMsj0G1U}bs1>7bM;aJkH>^f?60wtjLpr8)d8--0RYJIgwpAm> zCE;Ub#jnXJ)?NQe-^~+l08?xLbR-=C&?si-TH>7A~ z27w(;qeKg^PDlJuyp^YYr(6^+=6&oiy>)Qh?4a|S>faZqmzRVv1AQRBa6g&kfPkOV z7h%LR&_meekse|MF4+_VKE}mu7fW+(r75cldB`hU#?aJ=;)P3z-CL%VlM`Dt`H_5> ze~0v;k1|&j#3(0=)O$qRhaDYDOfk%M1qmLw#P}GQMj4O1$h%D$gJ~Cer7`>So=kB0 z=ymp50wp1o7=2?zxcZIeZhpq`NdxN^7Kj}%A9X&d>b(ifo@Ab-?}MswSk;|jA|PBi=6c0YaRE6a~%@zNVF^d^z!Sp_lIjRALTJM?2r zP;Z~}5n&=EAJ+B-@9$>W9bJ zw9+$1d$6QCPCA;0>3^=hdmgwi`N75LKAGj~#LP+NzU9ug>I`DOEB1Q5k0{#D*cq=Z z7mmC5#W#j_POjHcDi~oQ9srU1A!WU>t7k8f`-V??4r6N_!v8e!UDJn5ZB89U84 zb>r-gpzH&U*P3Eub`a~%w6}lk{P^$4|u1IeOvGREdVi=1fRM=D3-u! znUa$vc2dXq4p#YWJnYCOx)Cj_Jtmd9(Z%Gdy*R9~Wc}%LkV( z9US&g!yx{T=R%3d0+sasBe^7@gZ0#~gICB)X+fLShNMVr-G;KVj5s)~ep&JkEf5V2 znX9YafES`q_#A2Ch#K-w%6(cWHp@NIq)|SXDZZx(->;iPngFCqMqhs34Ld(XZ(Y3j zOBkI%0A!3{p%gi03-h8;;^XKp2;(Me<1qd>50J!Lf)y^IWBgcpzO)p{vCSGOQ4ezuZF!rXS}>{;>BxC;Nq3eP_o#H7k&Wdzxk z7zxlWizryR?#?f*RTfj$Va}*H3EtHbKPsB2O6bbR^PMieQ0O~%{SE6^pAVjkTMTCm>*Y>?GJ>Bq`4 zZ$WwLUtynJ$b=f@zxvfc<4miuKFb48dgV2ra!*Wgp^3g98>hCc$TCwqX`M+4@eov7 zP9}b|3alIef)9b2Q^A(<(p~ocMmasiC;JBkA!Waf!LCHt+`RgW?w0x>D^JR_@j$H> zY=ZXk2>9X+>@36Tb-%l3!19phJ7^Gnq1`5i$(~?;3VUCC>~2{r`@rZq(sd5HaYP`XwdVGb4V`~IW3I==4uZ06v2J} zo^>&)G4rgvGN#CqIxS`K7u1t&I{3JwG|{}u5|)uZ=-w45%b*ocvH^rU4lK8$$!BSBqRPb1ifwC@op zhfdH=X7i>@drLTYv)m%texaXBCmL!HQBlFOQT}cDvRLc0`^!-m1`+yDa$9_2BGN~t zo7U4wt~NL3CDD#wCVe(Ei?#6%S@~OM<&|v<{WSxBp|GRl4m*rc1F|W|^cwwt5_#5o z&ma4*N(BE`B}oZIppwJ9I>zVa+(MO;j5IE#YW!jWEu5SPLP%vGk~%0EZK+I1EP=cZ z_if1Od}Vh{J^`ikdZ<6g(+GKeKPO>H*=}wKJ*oMN^+Fe-AQNmd)%V{pb{z8@`*s80 zAMR?vQm?uCJ&*}1HLlX_?Cs#T+0*1IOr|o`XU;na;x_&O86LoO6m{Vht`%p@)56Fq zXez51FGG)>+KRW~NIUmc=OZfg?XuTMQeSMvgOlra(r&;1-g^YQm>ym=tcFJm6gthL_zdC@&MwMm-mTtG3F=Pz8p zcfM|_&yfC}f|Oa7$G-&|1%~h}I@`teSG^nky5djv9y%%a=&EoW*>Yb2&P?~n~Tq;yFpKr@(9gz#=s3)7K-)j%D<#ZjCW*7?@!j2cL+9}xJ>=3JdKU{Nik2NW60Mhp;uZDiZ_QdtpW>o|_trA?1N zdaFBd?^B74^nm>l9FlS~{~FV2ru1j>T9S}1G@IRysL-l}s-3P-Mi(Pa0w(`PQrgzW zA=nUctUf6X^oxnE7sbt#J2jQpEMg`0pe-xD&dOrA887EdKY8kWbF?!Jwb=q^!^IR# z4bd*sHxoE)yE{1M%!Vj;S$!TstENmbjX^K6zk$ksm9B1^b1aT+JtVt+KZLD)U$1MK zlBbMZRj&A(8uquo7)n!9sW^#e`N(yqx)w%?@|BREQbnAjgg=Eh(gm`&=sxc zG_%0jVMPPuC@|=eAB|WzCQMg-uf>d=Xj@6~kwS=zy9Af>6Ju&nj1x1CwEGKGLh(E! z*2nLI;M8anJ=gtc;8`3=T8_=|KaaC=9#|= z3ysm!1jfWt81r2rKAnX8f95|(=>CRxfv5amV)BN2dVKURF+qj;|B1AZ$!lg-}n`8^8FpmIW|dc{wmy!JM_GCKXvc>Ex&D< zOba|S2DovKJ09%x<_tk#LP)#*vH{jb7Dt{KiusADDikk-7?-vGkUe9PcMYa!HFnm< zQ=Tw%4VMU;be*fT#8E{fuc?t743;9pR1J*|l*?QaU$!gk5;utjGGn?I~sM5(VpxXZ`j5>+Qd&nCyjE+;?pbcd5?Dt*^zs0u>VyT>o@f6umGzP+LF0;Hd4NTfxCXZMhnzyCc}8V^PTC58~hxdcD+z{8%@Vr52fnVmQV zXPSpuYwMyTYWy%Bv8vn{f=O}h8{6G}u6DmR{j z$LJKaGi_9mx8*bgG;#aIlz@69HJZC#;AiD`q**$a)uSX=$`eEqo~yk1F#gV?nB~RV zI)KOun^!+g(4ju97*~J2a6R9@$Z#*iEINz}TT?x|CR%cmUpEL-AJUPkKT%7DppsaB zaSvpCdN6mZ)oG{24HtjYH|Y6|8t{I%%vWl9t$5^i!!+Lf>P<*L3_Kew6=n;TX&4=M zuD@drAYIOv|65_9$vys*vOXBW3!5OYw_$y}&tHk^gIk+w+k9V3cI#5D8z$|%Y!Zw` zU|ZNVuvJ4kw-JWL1&%X1k_>BZ^5C0vqyoRT8Dfr_LIYS*V~B5q+S^i}XP~8d66(tr zbKJKk^wlKp)&^vJ0pkiE4RQO+LnoYWt-`R@>*iq?ejrrY@#_X43~KQ77bUL;Tl3mE zCi1g)v)Lgj*_SDGY(LLXCCasH|O70!c5mQxt~jN)>#P^Y|jhkoo!Y4?Sjx&PLx$UopX+V+sc%EdX_5+~** z?YSEKp^C(VVO_zrI(L|C{7aX7SxS;|f!@~bDn2ic8Uik7vBc|N+PY@rkJz`LQ51bh z)tSJ(8E;l345UK6=TE{#o6y?qvzNDu6xL-;A4kBD?`6gwTrrL|%<`^?cQ~Tq{DY!R zxqeLk`-GK41*SY_z9>7mdm}2?6Y8NhJ$TB<4^vN*yrrH^lwee5T}#I+%`NqD>hX0!7p=$ON?dF2*WvJ#9r_+<{mBc7b;DM!S#^v78R^gdp*y6 zo`IqMJ&OVr!#z>EwcnThJlWtrSi$Sx+d?`<$^A_-%uzvyq0C{IQBQjW43~f20QQ?* zO(hjoHo%e%i$rBF4F`u7+c$$8d@!vN9!+&ttwmXaA`qE`g)jXWdFmud`mclRW|2dH zo3seNWE3A!+j>q0WMkHo89EGpu1_I%{|rrI_^&?VQj`;!^(O(WKJKQh36 z#LZHP4hnueSwhXmGO$lgPHUcSRklRgwPBu2qS47)dSv-=+mTR0QP}5yYsH$?;q4LeqGXcVjZo#gafX<8q1)W$@pT@HekrM zA~-s8!!wVC5>vhi+UHMmq_cWvQH8ztBPi0i)!W#9|lQJRJ%3FO2O?3 zs+C;WYCpdaOcy5b-ZeO>91#8s$xV3cKvlI;`XNGg5|U6MCD_*`J7A_uFZo=t3e$^nq+Kj-rwy zzk9N0w2-9Q%ENS;-Em~8P2|+2$x`Jlf4t>Y1J|4op`5U!9EI> zU#d&-Psw#7Qf_YpyDRYBKpsj&P4-1iG>~q{#j(yfKV`RMB_8S8$n(OqP0uvb@oU=U z(gACQ!9_FdkAHSQH`L=g-V#~ub}mAu;1_3byA0Vb0$NW?+5h9|oPsm!x@et_ZQHhO z+j!%S-7z}J8{4*R+qSKat&W}3|94KEi@jFWthKIo?W$d4j`@tDwQt+Cqi?x20{B#L zJ!7Rlf)wk)VhYziRVAObZ@s)j@UQgBil1)`qJMk;(_i+A4@4l%VL(7=QUB`?RA~zV z|2NP~x9yv!t)i@MszD92iGVE=I0RnYCx%c`OfJZ=xV?F`@Hug5kHB&#_JK759!>cL z0!;ebVi~m`$i(J6v*mo#?tZ-aJZt!)%0y;&`^>8GN%BV4M%cgF;apS6aJhOeR!@o2 z9vj=&674>MKY``1nc+ytGL;Q-sc#j~;i(8~v4W5%go$jB;ONxewo2zBmPd2h_w0B1 z2@A?|as5af=qN&15+3&yqRg;fdAZCrU3KFrh?!2`XkK&Cn(h5vZ9qb*FT z3cV4m7Wf^FZspT@W=JKl%{qGs=9NbejhZ*9OP%C7F$s=Xzq_@W=B!lZ9%3OmKN3b-`A6dm=yh~bB!%VJi6hK2M8oWB zePblN(?>tJ#YyL18L=M{J4CF25%65USEe+tN0h~*JF2PdJ-1gzCW|?t-TvQ3^pm%| z{!>W*6LPAR-;&n<2{{e_SI9X9@Brbw@y(irES^{z6R+qplNgK5WOO^N8ekaWT69%2 zv^JYEo7fS|-t*+$sKytzv+MXaImW(O@_XIZJr4rcL=I0*h_KUfU+U|BQJ} z@`@#|t5%`SBSk5MmRs}g*@SFnPHa4CYZd_PEv)pd8x{yOJnPz@8C>lfDN7AH>FSh! z{Oqr%uqng*hTR5BRM4uLtxO-a855a9@k$46Zxd3F%hW}j(^GN?G=U|r^3K1M@siBs zrd;}?$SB=Kx)Qu;8S-dLBpOA=o8rnrP01vuSSiuf$TL=^M|Sj4kOAVp$uoub>0N5> zrX7CcX1Lv*ycT(`pmsF+WecdVNd>MG>Vt><=>oU$=tE_+1&YfpsVR%F$tm*}M#;X| zTKPud%eLIqSdq# zx@Ha@id+_9|DpZno}FV*K$i>fR5Rys@(};mGk<1;z zkIIrg%v)ah$yBgjguF z?cYaO1QP1nSqc}me0a?bi~tzAhCv-QrQo1^4BjdBRUm018`}7YG->3eJG$uOsd*nH zJUahRZledNDG`CXtBM+7We03a=%5X?!Jn->9NyY;#}6Bj!S;PHjskd-507c~70+sX~ z&?5!aHDHAq6iJPID@o<1=5!0pwX26D`Ax^4yT@!lEYAiMN01W;{Qe>nzN z#iN#KY04{8L{j$!KJ|{kuk3LmdL)zg%TD!<>>UPc6;sGnh`8r67rO4$^0VduW6#PR z2h+=6*W-^EPi7sNR&uxWiZ&(=X^1Rh?GV1#D!?_t(w2k;S_0r;eAZFc2|)RXSC=^BG^R&nCheEvvu~{~dytLH!ARF#||wSi(e_ ziLr*^JD=bmgatM0pQ_5(BR^aAK=B4!285^`Tfux-->Q?%x5!@*=dB^yo=0K|yyNYD zaP?9=J;xhJ<+D&bX$2nx=F4y_Fa)#DECFVmzjW+-#b)8`dm}-O9qH1VJ$!zw+whzR zP@nuNeG=CkGTf3As*~G7im!mf&IbeC8y)_d+b=B+TaO|7TvT! z%`ZO^!~9-2x=%1x+%x;aIV_JeVAR~L7;?a|u1m!6sq|**_y2hy< zWk$srgt3!FV5*s>x?7_ZHF`wPhhCS7Bxjl}(^_OjpL3dlyFEASte9w+Jl$9@=x-{f z+gtA%dd`_*5LT^nJq9NZE;{cWdLES_SQEc86L{nz<`BqHWqU7O9qGkJV9IBL-i#bh z;V?ned_hH)rrAi?-Utc9I63V25-cq(4=WYZ2?i~bi9D8bD61D{4%qXXyWWT<=KzPQz zwz*h;vAaT`Phem#Vl$fA=33xrj~wkBxXkU`DPV$m$p*j5Uy2R_EOt0%AmwZcxO`y4 z*nz|gtjZC*JPJbyTQ?Kg`=B91xG@4?(i04t;|RRS!ee(u(r8PvBqCBu+e%-eJ|zp{@O@yUi_Gw)cQ-9{QK3KJ5*rL`->qMYvOM~5X_{MJiEpAV$c5i4hZ%p7iCv=4Z}?v+S8(!?%T+1rdqWNy#Mc9S|fYF$72;fz5>XB?Bz z2=~2RvkdAm$rIsX5CR7ME5xHqMdWc2>cmk3b)tTKCHDJ@hUqi?pxiwvjknC?R?u=bXra||nznZWAS-?7&{i}64i=F8V zu6%KhCL=lQ(!_Q0bVv(EPubn#2gN2`6&?OkY(jkVuiC-cTP^j3*GgtlfHS-kIE@Ho8>Kc&gGSlt2AZOXi0Oj+Go? zW-cCjMq?c|a6^$xpr4YI#7l(8kkHgojwXa{_Ggp0<5}gKDL(xj>W4R#A6=(>Nlhu7 z;+ieEmv#nUDBs#k$GL6NAL*+d<02o^R1s=WOWknEOVaBpP4=QVfx$^U1-DEZU%_R- zkqYJIycER?YBVf}QoYHM%jGJwMo?(=XPd8R;ZKIegvNl0sCH3Kwm}qWnuTfGqG7?) zFaPhdyPH=fdAu(oUs|@3M2MAaQQd{HbFGMrj>B71x4yHL5bW(Lx5wHKuH^3lrqn6C zPAFr}q?uka4b#L9LGl7%CI~Qjw(J9l1k)JF28r}2i%LSk&%hI5prR?LGjK?X)pOuM zfx{Man1a5>l76a2juG4&RoaRh5?+*t5bi*?f*xb++Dz}MVHGpRm_zOq!VT(cpo{Bh z#Xyl{5)shgu))#Ju9Sh)nt+LJF*TqCMaNBArm9?ch_>4AKcE#BrUjtxQKttc4pFl* zWJO^6lFx^m+fBr@#blxcK4E(3(Cg>Pp2*2{Eg64zD33MNK8TIeuW8Q7VU?>U2bG&5 zo`*oQZn`ZpRbFb~x9I^$;KTkF@zM#t_4UVOP+aB^WqtC~P%p!}z|+YY*N2G8Wi2_K ztr2fHbq-=ZsTTbs9vES=&PM=OEvMnyWvt_Hg9(|BUM9AJCKqra3UeL>3goz;5TrZG z;g5XSsFeih3ZEnS<|Q*h5xeEBRm(*Ix=to4uoQ9^@#JV{gCiv5d5>n2Q|q-Uav`i% zfiCT|!4&W^HECfIwJyQXVYF6gYNMv-@)1lH9j;RLl^n|I&PKYEHNrqreZ3q2FBqMc zsTLM;eE6Fux3yTRmXDSYiPkBoIH?;O8$rV2dlXI)#XR#EjnnQ{7LIZZ3w0;kK5 z1-FtB5N{;!Q81~dAQ)o0ccrCsKXbD>KP&BFV)*m4maT%_$UoTiw4mX(#1=q3l_EOF zhoThb3Pe#X>~XLs3UXl3jWNLW$wne5(6J~D3`M+~nq@&l{xSF*Hx2*p5|(0#m**Bh zhKe}g(Oi$vjwt6i6`8J1S`GDcU^_&)kDdi?oW4$B68w!#k`|e5-;2nU4q#o|Hpl~K z^A2GH6~SPhZ*z*Hn7J`OUO`7d?|a&8>4KLs+j{Yt8Lh`_{|DG61Nhr89FQJ>FUEJ)FAtTlvB^D>&Cc<2e!OBWxuD>VK9E**NrpUpk<{C+gig`9{PwTS%-;vD!gmTpn^rJa+*t>~LKt~_({ zdDqV`kX>3EqEBW)*!Q(s^$A%o)XSsv#}?IZ8RWAC0dVDHVDtIrozp`V7Xxzkj;Sh4 z%tIye+3*|H_GIv(u+s{~5BT#(r&QU`EMH85;%`9=P+a0c*rF#o&$nU63e={d8&ZdR zF^CQ0SU=#Mwlded{=vh~r5hgY*9(<5g&g19QlaqfQWBS(FQ+VT2@yL^gUk8UorjKo%eH@-b#R@0Udd@CcVmFgoGvyi4EJm6E?9g1w1I3g<`)VfToctQtfBs zod$>{2DYd9-_G$HaJ5T(ljh%9*B~c_dMfFY_gg@;%gOrz85=c=@M@nf>e<#xD0p-o)g|o9`+2(4HoXXOQMS2d-|9$L;~lfn_)(K3S_$K3&F1OhRVgThzXS zQ+B}L-dijq+1wZG8j*7W(u}(=+i|&~f;)mE+l`kqjhcFSq@rx-7`3i~J3JEtCiubd zKl^WJb@qJb?Z>n|1q#Zk34Gb3?l?SGV)$}!Pqf(qLNk*Eh4@5A{%GE1Hd$&QNXxmq z^z|vTE z!a0fUkIhn$%@NY6_A6DIHq1Fu(!HiQcm&Uq%TnwWvh38+#(Yv!yrqT~Y1SlE{;UDk zS%BLIBufoNJY09wQ5|Z15Q@-{Luc>K%Fm(3lZ1(s24tLo=SGAqlXArV!9Y>1koZY= z@tM;>6O=!xIx#8@dKaJ02L2^IU~q!1L?`jr>kOC=f$R33WYqq#n29=I&k_-IUu1^UYC zUhLOhrsfvx44jLuc3$UKAACfXVHh&41O^%&y}GB6ee!I4qBBSo1&+|Ybo%88a#H?< zF5mogdWL2ak2nwUndNWt2@>#qW%ns%Wa8NqoC`So5#stmr)0F%Dp7qegCPneCK0#m zrVv;7Y-6X|;GmtZo|Q|UuUTa8{c=2klCE~II>RNwa$n9Z**;L!Z~=lNFMC?4q~5at zP+gavqh#dnRgKgEoRrl=<9UP=a+USEDAC;B3lsu^XR1}TgAq~58Uj(R(ZBChCrg8N zs*bK=c>S8IaT8mhlc$YxI+cJJuJ8vhMT(Q$LbGxxxl0UHmozG`70N2QXqLW@c}g2r zr4qSKHmGi(eQa=jZa?-C-D+`@pRzIr90j;zFnMw)$9wiWg5jrZ6jd;IL)s&>I#Mtf zonU2sW}vdEjx37XoTofDyaW$EYCJkBw<5Qt!nZ27DyvTb?rUE5E)Kw!oXqX)YZ3l` zgsT+3 zy^tIBkDM1W1=)vr-G}4^0!jf}>`^l(3a6es{st!osxU`Mg0co)e#dix?5R1$o)7rb z7Ri{uC^TeqiE|&QHDrLLWdN@POx~0^&lnH}rz+y!!ju_z_W7Suc>23*GIIEVO-u15 za0IQ&eU5nghcA%J+y(_^ick#h6HNm=u?8nqMaeV75ZRCF7hOr3JgchNjlt*HT54mS zez;jI)-HsFk=f7l)+f-_j)Kyu+`V$CyoLpnS+&Y&lGn{OM@_mj7zK|tku;a*MF=$n zF70#@(=~%l^BnS8Z98(AdPu5~oe_X-oAPNNtme*}62#~GCY>Eo-NV*J%~zWxnqJ|} zLm?3@?Dc%6aQttm|7onF8X#g67$6`MH2*2;qmC><1aDmpjPE~1)4zRu-Yq-b-DK>veN2$6 z=#1V4O0r>AJZVAwuDGZSbZeT8z>YB+^;Y3CUGUh7N|PKY8aE)@gL}&8j}A9wSGl@j zA%$t|>0r8y#Pt!3G;`tNVuEF~FKGTtvHmGAE*%7k+8yG6Qg2RgJ1oy;KRm$RF&;%F zjTOyg#a&|@&SYv|(W4%WJjZ)!%5PcIL|W1Zgy$o)haZhr9EOu5N4@`(SflD#=xSUbaJfZ8;=Lz#o}+Fvt^GoSL#{; z)nJ&&ss%K;aZ*t*wC7Sr<7e3I#`R_21r%$O(^})QW?N|v1Zs7yhv_ZSg}cnFwqM(- zJf%=QmpB=@wWMHVBbCFP2yi1_Z7L82K981JexSYDbi~M{O&PL5Y;kne!Z&hIm!VSU z&8dBqEYVxy0YeV6b1s4cJVDV0N*e#U?E~d=R}L>ns!Dld`s;Cz3nh)t%f=8xov)jU zFksRhA)0Z|wYx?4H=@gUb^;!pP>;pH;B1Pdo#B6y{4ku(heO)VRFNRXG-k2ki^+1R ziVpL!vH^5Q|tEqN4 z#l3xT7ieBfN=MMJ%wAyHk6Xn66or~8=G!sRjyK)nkK8v3qA`=brb+iPkWzUC zOTsc}IdLc<1L9)Dq@Uu2{i2ioH?Hc$oyS((K8CmC;87HqJsCQ#J3bEbzV0KBch0K5 z2oLiLCWO|4r*@2taT85Akak3SGXsZ;uVx@M;;)3B0wMu#?Jlk?Y(?$WvANW!R$UeL z>OL>%Xd3y~8Cd(0u{c?R*4sOWJNFHVVf6E!@6OAC%e?f#Nla5V4X%y!7+&Gew6r!E>dtWD zg16gd(%)(>{9!05z&m8m%w;b?L+NN#X8v*s$;I-Zi{g6winbvu7}ffjR6{eP$*&ny zh}a_@Y8`3cf;~rm66H3xY1u!h7)r29F^p63j%%t9O(9bCp^m4!Elo1%uesK1!MXDo zBsBS)=N~Toqa>TbxrrM_LyB`_Ol>%8!G;Nu3~sEb6%p%-KnO=iFGXM zvwKr(P8Rf!i2WR9uc>Cofd(CpgI!DSDZ_zDT;J$FQFJHka=;;{FWnxVUNmF`S_6uc zv7;b@`^5NKGe^m5y+yp%_r>aCqBhEO#S)iOkHEq@A|QF@mAF_GFER$OAYmpQqjj7m zwC^gd(3*V=Sk!vkBFS-{Z5u3ifJVjnkE!8jV>jAwoy;c1_hw$gII4oD&7(Zra|9Mnr{$n#$Zr`kUe!Ixh_5#P#1Wh8F!bdp8_0;{bl24p+N z21)ED{p?{MSVZ?EbSXT}8gqk28>fu0=&j`Iz#PRko?@@F?feMQfoimj4E6jt z6FtW0G=j!415Z1Nc-!AWBYxf2%$2WphL5EXfrx=_$_Br>G|`jqT4$SOzNNnI*9_rsV9_+=zTa zYG{q7Kp_Dk7NHW@x4VZi9sgp_1MED3nUctbnRihU2P8nFa9@pLZts#4vh;gRpN1-?G7iz$})ta%J`x4RV!5)QB(1 z-rBJA`w6Ei(3>`sud!@S`>tO^3^#NmFIj8F0IdzPqj)rz_bO>0D*yp90#_$Q`MukOYh8nVF z>K-q%!qs3}B;A|L4@^RwR+O;}=R}!otdDUNHxuXW*?L0A#M{)R6^JA-gA?Um1R#-@ zfow@TKNA+@96*m@vMT}7WN`-- z2bRh2Emd1q$mN^S;aVy|eA0r^RN+hN0(YxKvd}F5Ak6yx{<-~mN=|a2%B%|Qx&jG$ zVZ~9MwjvmY^98zb%!EHw<@ZM|SJdHzxWIRKyUHsg(p$9yP-7pgd2^3h^eeuV8NvcD zBGj?okU*I3J{98QJhAAakI%prJQeC=16lC>mveom4%6yn9Mv@eo^WFJ9K;v67eBdg{;1xqSYXkuG4M=^2C>Bg zgh@IT&c|#(!Z-X0MFsixa_HUPueFYDmk})|CV(~H4W0A1YC+r9;xY?4Wr;YAnS!kR zW(4?Xes^hr4@IEsscW20uZN#wwpbn42Kq)=#Knu=I6y_yz%b+;0 zKtBof{*2zxim1=@O`{>t1bA9Fz(s$qRuCT`oONz;z8U@RFT*wowsT^rz%g9KP&XBI z)P3R|jnql8^JWKS9)EX|nOt#g_|I7(0~*yt_xr?j?2^s1#6--U+Lyl>Sb+(1sL_7G@xb#Pl9G78ijyP zRSG-p+fd~`x?_Bs>_X*mbAka=i=0;@cFF@uz1BkazGpoVGE+n0vsn&@OHgzuIxA9+GSh%{`xftn|Mvwmm2AUoqFIo7A&p z>c+X7PBHcYdexoqV`^Y8zczYLW-&)FKQ&S6+gj)~-D0u3}p~ zBE-WXQ;~ZKlol%V9}o<8lrmp%1$rqK|0>3TG~$A^Q$UDJ4M*B#2M9$Cv8=vvQaj@? z`m=RXCzEh6Us(CIfxNRr(5juBfIZB^_4j`s8%3BnlEEW55Rh+-|L3v6O5AaTPTZ-* z1DeHe{x1R~QunlQr&WL-_E;Q*&+^CEjBAjSc^=+ zthbj=Y#PcWu#x3&T-mmhvnvN4m*iuOFR8UlIa`zx+S;?(;0oPe)vVC3#XOvE zsp40pjg@hmHcO4%=~QuXws7JaM0)+>XNcx`r@JT!OUWkoIsFtBVs9uO?`30E7=NLv zpDtRF`}4}&tBo=Us>ano<->3=C*-iB9EZU&;cIv>Dl_DpSPCXd;d|XXDyj>l-R5wS zT$zXqKU*|Rouuz&P%C_=)m-=Q+n+ED{JuR;7B)6}obV4EXN@T1rZ%>PCoAKnHsP-| z2M3pg>-(X;Qd4Wl-24@Fw!vne>-PhIt&J}D z-^&os;RCh#=YTo+_bAIHHYZ^xHu^CEVLb3gU46wsz}o^46ADaE>sFI2{kf$HP-w(j z@Ch3fPzumhrHsZ?Qu_k*VAjmsuo5g+WjDsGVp^&3&7W)exeP7#l@?ftpe!p5U&< zj4^8-sn}-4sNwq!@vU6}$s_x1LLEW(<=G`cpzjmkR$7#mr9d>CZ*aFp? zh%*B(H8BJPo%=YSE*EG&Py>>HD3wN~kMGf0jF#DEv92-e0LoJLociW)nC)wPW&*9r zqmM(3rt=~~TNVdr$!5R`l}(k>#Q1gqD9%MxdSg>mUUW0~ z`{W|Berc}432clb;Cwkz@gkC$0arF4{ z8M|cf8s*{F3+CI7>L4Hyio?BY)bZiN5^-`f7Wyt|GZx$mqFQxKDLTLnNaXciu9LsK zgk40;;6O}N4WsIZ`*P7jOw$zAyV9SXq1Wtru~Ho{Vr@`&IkzoyCO>$7I5;72wtj1>5m69#t|HLGbb&$d><^omVmuu9`6V%P6P-wpk6n zfG6tKm^+_k%h&d+J8(%P+nexmnZH#o*3QQ1w~(EdB~+(F`rZQ&k29(6a-8^z-fA79 zx*48$8JK4#lHQ{RQFRtXxwVkjlFO*ZDh{ril>ywn^WzZYX(^Iho** zv!uM{A2Kol`s zk{yGRH3KgDGYuDe_iAQ=+~y8@Xpv`fKJWo7iwNHfbRVaji4$Dz5%TQn0WsyXKVn6L z>zV<(9o{0?oz^ACe}S8d#czp}ZKTtPchyT-NEZNXgsyM=@ow)GD=H*^bEF>A(NBQ1 z5IgrHW{+qXS!{UdlQZZYvzC!AKw(EoXr{wkSlQbOiJ|^Ztm}@Z2xYb6w1ZbqZ8{f*&l zoMmkc$=2F-oF0y?u`f5^XRRSYmV|v}I1jQj&gUy9#ie@v2M!yWG@Vz;fzm10<0uOW z+-*)zkAr6I5?{70(?nFmmM7FQs4=&ri=_s-Uj+=(pNw_X1~RP}`lJuKG3K}MU^Cnl zQdTE~%MLcO>(Hp6B>*<2a+=^m)e$O>!pTBR+Roc96uHA^Si#(waZ==V+JCkt!jy}1 zsy?p6JjEmj*TQEh+X>!23AdP5t3W0Jei;!eC>$iT**9CtySnJ}N^t0fR{Ly#fQSGc zg`y*z5p4z`7CG*Ctyz2mR$tF7u!^2N&n#v0Pfk6Pa42r`#mhv#`tA&rj z-XY$=2k#O^-aOwRAcnU}g;5~xS-_^8rKYF2M^*1>DXLDr$I_@Zw6xGWCbo`N6;d0s z^5(jJTGi@|U9>zfx}=rhqyQavd^Lciz8xW91NWxAW*5Jmy$Cx=L4+oYCoN8SPe+z! zJC4GGN%%8~fWf}W!$1U2v-p+Y`Nu`MzF@dyze3}#10GPJE>BL)kS7x$*h8O4bPp_I zG-+wlK!9+|C52{YyY~hG*KavxFtT5qJ_h+(r|vJNOCFD}YGprut^Q$PnM?%=hhk7Y zU^eK)JcB{B(lUMYzLfKs7K!qml3;$hX)6E2n{2uy zPfpFMw$0|ww;~UiB~qI9D_JZJx#^Q z2S(F2%+eB{wiU#ITKj#ayy5`=?jC6)&i#Qyg{}t<>8E_LQ;pg`xYg{V9e?4 z$RsqRt&`ur;^*fl2D9O55rWp_*j|A1)M)b&*$#e(5f)uyVFXb%90dnXwE6u@SNqgZ z$4B;E;%)WNc#{A#n)MK{#S5@UVwyAe<)Tgr&m%>z_ZAt@Z(yyJZTm@)MXsqqXmTX* zSpak1xw5xsx-21=D1+YyXreCAsY>sqKf`MMQ6R05bvCs?h7i7bpU<0!rvn(D~%l@=BWb zC`=44f2MctO|f`}ME<6dgUDHn21QDIp85?#+T;ScPY6O(%s$w|-V`?_S9p7vDG^J0 zjn=Jg#I5JK;bsiFETa4nNW;>&D)r%jfublnL(qs)_3^blEdiX;!A8k^f2`6RYft{_ zhnRHy@>?5q!_NYKuO@$ANcz?j@zknv?-3khX7xDgsi(Sr_V`>zgYD;$h79TUnKl;B z<4mhWx9hrt4~2==F5b_DBV(W=OZA(!c()NW1dtB5`y>kU%xO;}G_b>k9SG~U@5-0i zk1tzu6BF+3cS@ca5X{Fqi62xSkMmvqh{r^4=TNuMX-Wdx1R-`yU?y?np^{-XSVAN^ zlhgM7vx(AyvFfF>%lnkY5iMVdbz#_vY2FTQ5?UYjD(+Rre{)i75;I6$K*4Ly$^JT) zd1w*diFETJclFN5sF^=s+GTGRuUXhQ)qowYS$La76+~$A=S;y2hpHvgY&9r6s@Z&B2T98NWk+3R=E1n;^t-8XnF5C~1D$-*3~zl#Cv4wIL)yYMiC&Mxhq@(`C=A-zH6f@L=6UG&oI&cJ?RM%n%pH@!TFi&w$HMo%Ia=HKi*lkTN_ zMdcUJ$~q#{J16ChR6r2IW-%0Se!*D3-iwLk8R=3ZEfn;4Qtz9Q^WgFd@cw%-t18ts z+*%lKpOcyYT#TyyVbXTf5a+(ULh5r%-7-2C8k_UnPhuGHR}f28OyX@EPMIcyc7cNX zeZ43*I)OLm){B&E=QNCoQMcF4)ifV?qFOgQyB!DE@`C_a5?l>Ua}o*q}+EC5|uN&^; zkp-ahcePTDs~1NpIr{ni@rV1sItoFMLsnIQGbk@pAi0@W%h`HEYofno05bh4NJS>&zER?b&t7s&{% z(RDY*LESctrPnknaDEN`bNXmWncOv4G^*(|yu?9q@y`#EKIKKBT`JA5FRBj^S&6sR z2Fnle#a_Aj@AT|;|3>Jqa;V>Ix;{`Sq)Js_!s+cp$=c);VxG(Z^qht8J~tI$UjmUm z=3{YnQ6(b*0}(pkJUuA4m1Grl#7G3rQf|hfY>E1Ioh{b_>YrLeD+L~jA6JYK;sdMLA@|Q%!`=EjA=koUt*Cdy zwQe z+@Wg1$U|1BC0Ow9M)?^;K*HTmH9Nr6xN>peU(t4GoF?q{al3P@F+)p+_weT9gbpJO zQKT}4bsaxpFZ%-hsWWLooeBB8a4x%@<5KIljaJS7GSkC~B1cc}g9{!2?;;APN!1!$ zOaW2bWjn7Fu*_St!CfB^wOyF)A|$wli9gk`8+^cfrWbYAPg343&K&D;eC)aMzTLbO zpW2VU?jK=L|Z z4}xLeLz;0s%%g#UY|uKfnTW!m$l($w%T<8UZGx9`i5)XBuV+}RZKI@(r#btwJ><%R z++3`(NAlWofEFC%;QSCb5Z29YpzqTK-~hOk0SSYVrMUvgn@)od68gN6H%bU5Qsj<9 zmECyJGama|XqK4CncJz5iqB;Ka2j$vk411qLCfb#<+AOynl4fx6oL*yg^K~}{nk*h zJuhdF* zd%6$c++?+#6A|r^Xjbk1b8G_yJ=Pd2mS7ao>T!oyfo#y#1w)|I67!)aqMi)Zd)Ytk zn{xg>c_XK;1fSGfRuBvZUFRk0NDW^tx~(2i*~_p-#y;RGjhK4=nfA?=w!5=CPhaB* zws7<;#G>=!UtX)Mgy<>%%pROWsrwaEZc@~{cYFt9p9_=vtCWiVF{oX<=2sV8*K^HB za3E;qR_rYnz3SR0VM`Q=y>L&Y0=2F2U-02cqjPk6geSTzqa)UlR6muY%(wq~MY|+-`=@dmpw7VMKDWM>RVuH?1vhi6%MjpcLH%s+|W_ z#pMFelu2|80s`baTs>w!CMANy0mMWF0s~~VvzfYU|8AZ8J({wFwu8X?%^Mq}L9Nh5 z08%z$lQCVW$U#I82$^L#eCJ0j;H|H{3KdVga{IH@v>oPyJc0{H4u!tG_U@|aT!+TbeviFJo@HJpIfOWq_?$I z!QhrEGa~Q%?LTusl4~?Zm>;R;)#Fp^sSbuSt9SZddf>t zTYhtNlkv1Yb-l&?p0l;`2sLE#|K+X#(TeDunaq-c>yI_)3~al`7?j9O?EfL8?I+Z+ zU+e2pOdep@C#HIU_0~G%w-fvvqEg1G^19Gg8x#pOaAzv?2^JwtNEWIP^@Q&{;3IiV zyc$+vx+N6Y`!V#zatT=U@jG!_uEFwu;t{*O)jTH5Gd7Eoa6#b-D!sEy8SGPm3-_-Y z#xJ-5@D_3dhFcHbDpnq>dQlb^D>DtngOI@H{jN*DMh%F)gv>F||P+*x$=d z3g2D=m)p=Yg<4WbjLZ-07ThMlP7UCEYJe7dS8+izy0*KIt`rd?D>!{97WNERRK~|e zODeLO@f(gJZpuM8^p1xAJG1awv|eeuR*5S6kSlyeQGm@)XO)-gqlB;t0#Q}}66_76 za`vKfjS?pEXM*ux*Ks#fIawf*%(x@(ZBuie>a}~Yfs(e_XwRR}g5tk{*d}Aj&73f0 z!|!DZ=p<8)^3jrl3R;90!nXR%6O%c0*8=SY&A{SGaLi)?HpSzrOr?U$H4Tat$MZq(^=wj_W-K8~)|=>DxMhPc1CaNd2)ncn`f z*n}oof;B9M$JQ^vCg+Bb^ijTAwTEq#8e>i_!m_TbK|pALO028L2l^!1 z{X^j)k6PrgH(*Cs8GX4>tw)$Hm!ob`$E|WOUMzT4Ezj%(#1&Q-l0L^7&x^GAN8J{wf2Ea@mR+Y#? zlLJ&U(k&%%aOf;fz@NC5Fk3Uj12xOz={0oDrYx7>9ot1Q0;j`WX>92>8`oWE z8iN1=C%4HV1-n5i#pCRV>9pgtCLL9>+`ngBz*Yxdw>}2E8FkE0_N9oBLB9f4=HxEh ztC&Gm6jD_a6enTj^iP`%EWFOM&A2$4N#zi_n=P0;puv^Scob;VlU08Y1JyKHyXTaI zsV76qCx;5k~ zYFyias8X2u+CCsj7*J$O5jlkL1MGpyJd^oi=!Dp6RLt@f)F<2l`SoY$3CU526#hp( zo#5H7mAm&sKU>X9K_FB6K_p_1>u@RlM?9b4(Jqgc_eMWa=fNUk4?G>?%ajFQ7pzjp zEwtNc|LSfz9HHy2McsACX7upy@IQp7pZ|rzt4_2@-++REfhhmqZ-OI-3;6DiCV~DH zB8V#L!Oq|?haKEvwQw5;fGunC(|jwSF^cfpG)-XK{uj2OpeuY^o%iA!@FFgPj)C5S zA?|yN?|U12=V8HRmB9JFK#Y#PbIw2$C z0g+(OaWUAMHF=(6f!)lWnf|Q7wV|X+{H^4;m6@K}l1CAXJEH*;#blu@#>QGzk%irD znoudUI&s+!5yG;vYT~#M{t==0X<~G~EjGU(-!T^pu5Jtr%Np7*2HoCTW}N{#}RbyDvOnBu>K51gd>X zLWlH!$~yOWsL}?GAJgPgOj=Bf6S?0nFCt_tL$1Tx9d{BUlS_@Z&|q?VZNsn}rkj*P zUe}pyB=Ndsx*$SXYHMm&O-xuNtBXBOKEr9}^O=9<`Ofb-&vP!H^E~G{zn@9pqn4sE zJLBMq8a>IQQq16uOP4FFX7NT3_tgO-GCOYd6I@;?x>dDMU^2&dkvU7 zT|F2dTwIhq*>oUDTkjjKWe2Q4;|HpWyJMbpH=W`tIdvCbw(EJ2yRL;A?Sr*WrTD|7 z!Q6L}o2B-K6_iz$kpo9!)s*nwV-6CUjG_s?WXqg5F}8Yy;Wr!Bc=3O@Sjl-T3HQS3 zWcGj0s0=9lq%$ALAsKrHHatAdFASy1538neIl-9^2nK0{JK(W!ZXdQMeOqe@w)8Z= zpYA{NQ!T+UHK%S*c7@crfJ?vqsu(PJukuW3z`ILa&eMDBze}~{OR^xFbSO1GqVM&= z4vC{i=ZnJQHC_9&tVbt2+cH(bB2$l{Fc0?(vshV@?Tcqy@VxDR;XHZUJ=Dc)&9V|I zWpJggWa7BZV{rIwfrw@QwOWeukcZI^-{R?3Cd3HhmD6L4tp)OeIfZadXKgQvcNC^L z)X$Ff-i1-}i#tJ3lvtKCA0kG4ChABWW7HZGTz7^0lw2n5?WK}C@(YfYVL$ngmPZ}S z<0kb|eD0fOTK!sEI9qd;zm3^@VJhykz1{-+O1_{WBz(l8m3p@f?cL(OG!?RpEh$4bn}NBXooR}278UFWGj-+hEk~a z`D9anC^ue5&=r`aRCvfGufN%5S4Kir4XafnC^7#wK6i*<*pZ_@;X~-iR=Sy=|5rhA z_4Qc^qIb|x59^bAkokq@`a4@3DBkoZizT74Ek0hKlT%cJQtzMN;N0 z%|%>rcF%p?aV3i?w=tDJA|oX-a6GK04SQCsxILrPhg@xV+~wW=VPcT7^u*RFe(sG| zX})O+)VX0_=JkbG7f(!~p>%RU2|@JqbZxU!it-DjCW)+#}uPX zt+{|G%#}Ammq##B+=!beac{@3ZV`)35?5;?AMRsusdrgd_#w{H-f8sRI^tV3K6o)L)dSNXaULi9-sPLXlUf>R zbiKP!{c{Q4=S}@LJnjwMI=JF8~SY2FRRY`wJD~5`(uy(r>q&9&K)4Y$gwzCJ{}tiq1oT~{Js4dpb|w%m zZ-Q_7Oi|@-GKkO#ycpCiqX>&_RTM^?1Hf(+D~(@e^;Rkc*XO|6pg@kiP_*>QPEZ*3 z3D=HR6j2d^%Bt#!>RL`B0H9Sn)r9cxaPB(13D}irKB&D4kCD<^S0)NASLuSnAU3#9 z&}~-ILBY1Va!Acc=oh?>V*u_b6I6Rxdcr^4(pOl4HzJ8mkVv&0rq%!{95ggURMuin zzTOoq<5d+=IL%2JTnjDu8Z6%lO;y`%M7;K)|J2A~Y^>lPRH1`48lcc#{9k)=-WsZ@ z@l+I=Tf@&GQH|JZ3zsWG#ZI%-NcA%6bl3@UZ?AXenaPkW7I%O2(pMz|dY2laS5}C1qkIRGb z7kzS1F%j@3TOa%~rdt`(0e~S&EhZm<95`m+>P;?ukNb6>aUlfyG78iO*I$;jQECdO ORzXA2f%7X@nSTIfr%7r6 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 78cb6e16a49..8a848873f3a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a93670..adff685a034 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index db3a6ac207e..c4bdd3ab8e3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000000..33b2c9b5afc --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] +java = "temurin-25" From f5b4fcaf08a81998c839a37ee51cb4ab68b1b5d9 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Dec 2025 19:20:55 -0800 Subject: [PATCH 433/586] feat(minecraft): update to 26.1-snapshot-1 Lots of changes to RegistryLoader and Villager Trades See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_1 --- gradle.properties | 2 +- settings.gradle.kts | 2 +- .../RegistryDataLoader_LoaderAccessor.java | 2 +- ...ryDataLoader_RegistryLoadTaskAccessor.java | 13 +++ ...sourceManagerRegistryLoadTaskAccessor.java | 11 +++ .../util/BlockableEventLoopAccessor.java | 12 +++ .../resources/mixins.sponge.accessors.json | 37 +++++---- .../advancement/SpongeFilteredTrigger.java | 5 +- .../common/adventure/SpongeAdventure.java | 2 +- .../RegistryDataLoader_LoaderBridge.java | 32 -------- .../data/provider/entity/EntityData.java | 8 +- .../entity/projectile/ShulkerSourceLogic.java | 2 +- .../context/transaction/TransactionSink.java | 4 +- .../inventory/ClickMenuTransaction.java | 6 +- .../tracking/phase/packet/PacketPhase.java | 2 +- .../inventory/custom/SpongeInventoryMenu.java | 10 +-- .../merchant/SpongeTradeOfferBuilder.java | 2 +- .../merchant/TradeOfferGeneratorWrapper.java | 12 +-- .../recipe/ingredient/SpongeItemList.java | 8 +- .../common/item/util/ItemStackUtil.java | 2 +- .../spongepowered/common/util/Constants.java | 16 ++-- .../world/server/SpongeWorldManager.java | 2 +- src/main/resources/common.accesswidener | 1 + .../VillagerTrades_ItemListingMixin_API.java | 54 ------------- .../world/entity/player/PlayerMixin_API.java | 2 +- .../item/trading/VillagerTradeMixin_API.java | 80 +++++++++++++++++++ .../common/mixin/core/block/BlockMixin.java | 18 ++--- .../chat/ComponentSerializationMixin.java | 2 +- .../resources/RegistryDataLoaderMixin.java | 23 ++---- .../RegistryDataLoader_LoaderMixin.java | 50 ------------ .../core/server/MinecraftServerMixin.java | 5 +- .../core/server/PlayerAdvancementsMixin.java | 2 +- .../mixin/core/server/WorldLoaderMixin.java | 37 +++++---- .../core/server/level/ChunkHolderMixin.java | 2 +- .../core/server/level/ChunkMapMixin.java | 2 +- .../core/server/level/ServerLevelMixin.java | 2 +- .../ServerGamePacketListenerImplMixin.java | 4 +- .../mixin/core/tags/TagLoaderMixin.java | 12 +-- .../entity/animal/fish/PufferfishMixin.java | 7 +- .../level/chunk/ChunkStatusTasksMixin.java | 2 +- .../EnchantmentContainerMixin_Inventory.java | 4 +- ...GamePacketListenerImplMixin_Inventory.java | 8 +- .../AbstractContainerMenuMixin_Inventory.java | 22 ++--- ...ractContainerMenuMixin_Menu_Inventory.java | 4 +- .../server/level/ChunkMapMixin_Tracker.java | 2 +- .../level/ChunkStatusTasksMixin_Tracker.java | 4 +- .../level/ServerLevelMixin_Tracker.java | 2 +- .../end/EndDragonFightMixin_Tracker.java | 2 +- src/mixins/resources/mixins.sponge.api.json | 2 +- src/mixins/resources/mixins.sponge.core.json | 1 - .../RegistryDataLoaderMixin_Vanilla.java | 18 +++-- .../server/MinecraftServerMixin_Vanilla.java | 4 +- ...eloadableServerResourcesMixin_Vanilla.java | 2 +- .../core/tags/TagLoaderMixin_Vanilla.java | 4 +- 54 files changed, 274 insertions(+), 302 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java delete mode 100644 src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/trading/VillagerTradeMixin_API.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java diff --git a/gradle.properties b/gradle.properties index 32043ccde3d..5aa5e1d46bc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=1.21.11 +minecraftVersion=26.1-snapshot-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/settings.gradle.kts b/settings.gradle.kts index 0cc5a73822a..61df60b17ed 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { } } plugins { - id("org.spongepowered.gradle.vanilla") version "0.2.2" + id("org.spongepowered.gradle.vanilla") version "0.3.0-SNAPSHOT" id("implementation-structure") } } diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java index 151ea37279a..b9503c3ba0a 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java @@ -29,7 +29,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$Loader") +@Mixin(RegistryDataLoader.RegistryLoadTask.class) public interface RegistryDataLoader_LoaderAccessor { @Accessor("data") RegistryDataLoader.RegistryData accessor$data(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java new file mode 100644 index 00000000000..f3a9f2f2b40 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java @@ -0,0 +1,13 @@ +package org.spongepowered.common.accessor.resources; + +import net.minecraft.core.WritableRegistry; +import net.minecraft.resources.RegistryDataLoader; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(RegistryDataLoader.RegistryLoadTask.class) +public interface RegistryDataLoader_RegistryLoadTaskAccessor { + + @Accessor("registry") WritableRegistry accessor$getRegistry(); + +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java new file mode 100644 index 00000000000..3ed96baad86 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java @@ -0,0 +1,11 @@ +package org.spongepowered.common.accessor.resources; + +import net.minecraft.server.packs.resources.ResourceManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$ResourceManagerRegistryLoadTask") +public interface RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor { + + @Accessor("resourceManager") ResourceManager accessor$getResourceManager(); +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java new file mode 100644 index 00000000000..32058b4c74c --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java @@ -0,0 +1,12 @@ +package org.spongepowered.common.accessor.util; + +import net.minecraft.util.thread.BlockableEventLoop; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(BlockableEventLoop.class) +public interface BlockableEventLoopAccessor { + + @Invoker("pollTask") boolean invoker$pollTask(); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index f2abde481fd..55755f0d9b2 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -17,8 +17,8 @@ "commands.arguments.selector.options.EntitySelectorOptions_OptionAccessor", "commands.arguments.selector.options.EntitySelectorOptionsAccessor", "core.MappedRegistryAccessor", - "entity.animal.frog.FrogAccessor", "entity.animal.equine.AbstractChestedHorseEntityAccessor", + "entity.animal.frog.FrogAccessor", "entity.vehicle.minecart.AbstractMinecartAccessor", "network.ConnectionAccessor", "network.chat.StyleAccessor", @@ -31,6 +31,8 @@ "network.protocol.game.ServerboundMoveVehiclePacketAccessor", "network.protocol.handshake.ClientIntentionPacketAccessor", "resources.RegistryDataLoader_LoaderAccessor", + "resources.RegistryDataLoader_RegistryLoadTaskAccessor", + "resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor", "resources.ResourceKeyAccessor", "server.MinecraftServer_ReloadableResourcesAccessor", "server.MinecraftServerAccessor", @@ -54,6 +56,7 @@ "sounds.SoundEventAccessor", "stats.StatsCounterAccessor", "tags.TagEntryAccessor", + "util.BlockableEventLoopAccessor", "util.datafix.schemas.V100Accessor", "world.CompoundContainerAccessor", "world.DamageSourcesAccessor", @@ -75,23 +78,23 @@ "world.entity.PortalProcessorAccessor", "world.entity.ai.targeting.TargetingConditionsAccessor", "world.entity.animal.AnimalAccessor", - "world.entity.animal.feline.CatAccessor", - "world.entity.animal.fox.FoxAccessor", "world.entity.animal.cow.MooshroomAccessor", + "world.entity.animal.equine.AbstractHorseAccessor", + "world.entity.animal.equine.HorseAccessor", + "world.entity.animal.equine.LlamaAccessor", + "world.entity.animal.equine.TraderLlamaAccessor", + "world.entity.animal.feline.CatAccessor", "world.entity.animal.feline.OcelotAccessor", + "world.entity.animal.fish.PufferfishAccessor", + "world.entity.animal.fish.TropicalFishAccessor", + "world.entity.animal.fox.FoxAccessor", + "world.entity.animal.frog.TadpoleAccessor", "world.entity.animal.panda.PandaAccessor", "world.entity.animal.parrot.ParrotAccessor", "world.entity.animal.pig.PigAccessor", - "world.entity.animal.fish.PufferfishAccessor", "world.entity.animal.rabbit.RabbitAccessor", - "world.entity.animal.fish.TropicalFishAccessor", - "world.entity.animal.turtle.TurtleAccessor", - "world.entity.animal.frog.TadpoleAccessor", - "world.entity.animal.equine.AbstractHorseAccessor", - "world.entity.animal.equine.HorseAccessor", - "world.entity.animal.equine.LlamaAccessor", - "world.entity.animal.equine.TraderLlamaAccessor", "world.entity.animal.sheep.SheepAccessor", + "world.entity.animal.turtle.TurtleAccessor", "world.entity.animal.wolf.WolfAccessor", "world.entity.boss.enderdragon.phases.EnderDragonPhaseAccessor", "world.entity.boss.wither.WitherBossAccessor", @@ -105,26 +108,26 @@ "world.entity.monster.CreeperAccessor", "world.entity.monster.EnderManAccessor", "world.entity.monster.EndermiteAccessor", - "world.entity.monster.illager.EvokerAccessor", "world.entity.monster.GuardianAccessor", "world.entity.monster.PatrollingMonsterAccessor", "world.entity.monster.PhantomAccessor", - "world.entity.monster.illager.PillagerAccessor", "world.entity.monster.RavagerAccessor", "world.entity.monster.SlimeAccessor", - "world.entity.monster.illager.SpellcasterIllagerAccessor", "world.entity.monster.VexAccessor", + "world.entity.monster.illager.EvokerAccessor", + "world.entity.monster.illager.PillagerAccessor", + "world.entity.monster.illager.SpellcasterIllagerAccessor", "world.entity.monster.illager.VindicatorAccessor", "world.entity.monster.zombie.ZombifiedPiglinAccessor", "world.entity.npc.villager.AbstractVillagerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", - "world.entity.projectile.arrow.AbstractArrowAccessor", - "world.entity.projectile.arrow.ArrowAccessor", "world.entity.projectile.EyeOfEnderAccessor", "world.entity.projectile.FireworkRocketEntityAccessor", "world.entity.projectile.FishingHookAccessor", "world.entity.projectile.ShulkerBulletAccessor", + "world.entity.projectile.arrow.AbstractArrowAccessor", + "world.entity.projectile.arrow.ArrowAccessor", "world.entity.raid.RaidAccessor", "world.entity.raid.RaiderAccessor", "world.entity.raid.RaidsAccessor", @@ -134,11 +137,11 @@ "world.inventory.AbstractContainerMenuAccessor", "world.inventory.AbstractCraftingMenuAccessor", "world.inventory.AbstractFurnaceMenuAccessor", + "world.inventory.AbstractMountInventoryMenuAccessor", "world.inventory.BeaconMenuAccessor", "world.inventory.BrewingStandMenuAccessor", "world.inventory.DispenserMenuAccessor", "world.inventory.HopperMenuAccessor", - "world.inventory.AbstractMountInventoryMenuAccessor", "world.inventory.ItemCombinerMenuAccessor", "world.inventory.MerchantMenuAccessor", "world.inventory.ResultSlotAccessor", diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java b/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java index 705d5b3aa87..cf0f5bf883e 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeFilteredTrigger.java @@ -27,7 +27,7 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.advancements.criterion.CriterionValidator; +import net.minecraft.world.level.storage.loot.ValidationContextSource; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.api.advancement.criteria.trigger.FilteredTrigger; @@ -70,8 +70,7 @@ public JsonObject serializeToJson() { } @Override - public void validate(final CriterionValidator var1) { + public void validate(ValidationContextSource validator) { } - } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 40c93f0b8e5..d2b5c0dbf8d 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -520,7 +520,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv final var stack = si.item(); final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); yield HoverEvent.showItem( - SpongeAdventure.asAdventure(stack.getItemHolder().unwrap().map(ResourceKey::identifier, itemRegistry::getKey)), + SpongeAdventure.asAdventure(stack.typeHolder().unwrap().map(ResourceKey::identifier, itemRegistry::getKey)), stack.getCount(), SpongeAdventure.asAdventure(stack.getComponentsPatch()) ); diff --git a/src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java b/src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java deleted file mode 100644 index 296187201d3..00000000000 --- a/src/main/java/org/spongepowered/common/bridge/resources/RegistryDataLoader_LoaderBridge.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.bridge.resources; - -import org.spongepowered.api.registry.RegistryHolder; - -public interface RegistryDataLoader_LoaderBridge { - - RegistryHolder bridge$registryHolder(); -} diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java index 14cbe1bc57c..9ab1a6275fb 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java @@ -216,11 +216,11 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.SCALE) .get(h -> 1d) .create(Keys.SCOREBOARD_TAGS) - .get(Entity::getTags) - .delete(h -> h.getTags().clear()) + .get(Entity::entityTags) + .delete(h -> h.entityTags().clear()) .set((h, v) -> { - h.getTags().clear(); - h.getTags().addAll(v); + h.entityTags().clear(); + h.entityTags().addAll(v); }) .create(Keys.VEHICLE) .get(h -> (org.spongepowered.api.entity.Entity) h.getVehicle()) diff --git a/src/main/java/org/spongepowered/common/entity/projectile/ShulkerSourceLogic.java b/src/main/java/org/spongepowered/common/entity/projectile/ShulkerSourceLogic.java index 35ac80ca2a2..4546363c473 100644 --- a/src/main/java/org/spongepowered/common/entity/projectile/ShulkerSourceLogic.java +++ b/src/main/java/org/spongepowered/common/entity/projectile/ShulkerSourceLogic.java @@ -46,7 +46,7 @@ public

Optional

launch(final ProjectileLogic

logic, new ShulkerBullet(shulker.level(), shulker, (Entity) args[0], shulker.getAttachFace().getAxis()); shulker.level().addFreshEntity(bullet); shulker.playSound(SoundEvents.SHULKER_SHOOT, - 2.0F, (shulker.level().random.nextFloat() - shulker.level().random.nextFloat()) * 0.2F + 1.0F); + 2.0F, (shulker.level().getRandom().nextFloat() - shulker.level().getRandom().nextFloat()) * 0.2F + 1.0F); return Optional.of((P) bullet); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index b25ef160259..2f59f22b1d8 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -30,7 +30,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; @@ -340,7 +340,7 @@ default void logPlayerInventoryChange(final Player player, final PlayerInventory } default EffectTransactor logClickContainer( - final AbstractContainerMenu menu, final int slotNum, final int buttonNum, final ClickType clickType, final Player player + final AbstractContainerMenu menu, final int slotNum, final int buttonNum, final ContainerInput clickType, final Player player ) { @Nullable Slot slot = null; if (buttonNum >= 0) { // Try to get valid slot - might not be present e.g. for drag-events diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java index 25da66c5eb4..46e5f9dfbc9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/ClickMenuTransaction.java @@ -30,7 +30,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Transaction; @@ -53,13 +53,13 @@ public class ClickMenuTransaction extends ContainerBasedTransaction { private final ServerPlayer player; private final int slotNum; private final int buttonNum; - private final ClickType clickType; + private final ContainerInput clickType; private final @Nullable Slot slot; private final ItemStackSnapshot cursor; public ClickMenuTransaction( final Player player, final AbstractContainerMenu menu, final int slotNum, final int buttonNum, - final ClickType clickType, + final ContainerInput clickType, final @Nullable Slot slot, final ItemStackSnapshot cursor ) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java index 7fce29e8d73..caffa2aac64 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java @@ -234,7 +234,7 @@ public PhaseContext populateContext(final Packet packet, final ServerPlaye // Inventory packet specific methods private static BasicInventoryPacketState fromWindowPacket(final ServerboundContainerClickPacket windowPacket) { - final int mode = 0x01 << 9 << windowPacket.clickType().ordinal(); + final int mode = 0x01 << 9 << windowPacket.containerInput().ordinal(); final int packed = windowPacket.buttonNum(); final int unpacked = mode == Constants.Networking.MODE_DRAG ? (0x01 << 6 << (packed >> 2 & 3)) | (0x01 << 3 << (packed & 3)) : (0x01 << (packed & 3)); diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java index 85845e1d45f..77697c42cce 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java @@ -29,7 +29,7 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -232,11 +232,11 @@ public void onClose(final Player player, final Container container) { } public boolean onClick( - final int slotId, final int dragType, final ClickType clickTypeIn, final Player player, final Container container) { + final int slotId, final int dragType, final ContainerInput clickTypeIn, final Player player, final Container container) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(player); final Cause cause = frame.currentCause(); - if (clickTypeIn == ClickType.QUICK_CRAFT) { + if (clickTypeIn == ContainerInput.QUICK_CRAFT) { return this.onClickDrag(cause, slotId, dragType, container); } final Optional slot = container.slot(slotId); @@ -338,7 +338,7 @@ private boolean onClickDrag(final Cause cause, final int slotId, final int dragT } private boolean onClickRight( - final Cause cause, final SlotClickHandler handler, final ClickType clickTypeIn, final Container container, + final Cause cause, final SlotClickHandler handler, final ContainerInput clickTypeIn, final Container container, final int idx, final org.spongepowered.api.item.inventory.Slot slot) { switch (clickTypeIn) { case PICKUP: @@ -354,7 +354,7 @@ private boolean onClickRight( } private Boolean onClickLeft( - final Cause cause, final SlotClickHandler handler, final ClickType clickTypeIn, final Container container, + final Cause cause, final SlotClickHandler handler, final ContainerInput clickTypeIn, final Container container, final int idx, final org.spongepowered.api.item.inventory.Slot slot) { switch (clickTypeIn) { case PICKUP: diff --git a/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java b/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java index 7c8070a5c09..24290f215bc 100644 --- a/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java +++ b/src/main/java/org/spongepowered/common/item/merchant/SpongeTradeOfferBuilder.java @@ -146,7 +146,7 @@ public TradeOffer build() throws IllegalStateException { @NotNull private static ItemCost itemCostOf(final net.minecraft.world.item.ItemStack stack) { - return new ItemCost(stack.getItemHolder(), stack.getCount(), DataComponentExactPredicate.allOf(stack.getComponents()), stack); + return new ItemCost(stack.typeHolder(), stack.getCount(), DataComponentExactPredicate.allOf(stack.getComponents()), stack); } @Override diff --git a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java index 1f84b336cef..6a01d5e3777 100644 --- a/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java +++ b/src/main/java/org/spongepowered/common/item/merchant/TradeOfferGeneratorWrapper.java @@ -24,11 +24,6 @@ */ package org.spongepowered.common.item.merchant; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.villager.VillagerTrades; -import net.minecraft.world.item.trading.MerchantOffer; import org.spongepowered.api.item.merchant.TradeOffer; import org.spongepowered.api.item.merchant.TradeOfferGenerator; import org.spongepowered.api.util.RandomProvider; @@ -36,7 +31,7 @@ import java.util.Objects; import java.util.StringJoiner; -public final class TradeOfferGeneratorWrapper implements VillagerTrades.ItemListing, TradeOfferGenerator { +public final class TradeOfferGeneratorWrapper implements TradeOfferGenerator { private final TradeOfferGenerator generator; @@ -44,11 +39,6 @@ public TradeOfferGeneratorWrapper(final TradeOfferGenerator generator) { this.generator = generator; } - @Override - public MerchantOffer getOffer(final ServerLevel level, final Entity trader, final RandomSource rand) { - return (MerchantOffer) this.generator.apply((org.spongepowered.api.entity.Entity) trader, (RandomProvider.Source) rand); - } - @Override public TradeOffer apply(final org.spongepowered.api.entity.Entity entity, final RandomProvider.Source random) { return this.generator.apply(entity, random); diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java index 2eb5298c845..085c436dfd7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeItemList.java @@ -56,7 +56,7 @@ public SpongeItemList(ItemStack... stacks) { @Override public Stream> stream() { return Arrays.stream(this.stacks) - .map(ItemStack::getItemHolder); + .map(ItemStack::typeHolder); } @Override @@ -78,13 +78,13 @@ public Either, List>> unwrap() { public Optional> getRandomElement(RandomSource source) { return this.stacks.length == 0 ? Optional.empty() : Optional.of(Util.getRandom(this.stacks, source)). - map(ItemStack::getItemHolder); + map(ItemStack::typeHolder); } @Override public Holder get(int var1) { final var stack = this.stacks[var1]; - return stack.getItemHolder(); + return stack.typeHolder(); } @Override @@ -106,7 +106,7 @@ public Optional> unwrapKey() { @Override public @NotNull Iterator> iterator() { return Arrays.stream(this.stacks) - .map(ItemStack::getItemHolder) + .map(ItemStack::typeHolder) .iterator(); } diff --git a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java index 0595ad14ed0..60df08f6f06 100644 --- a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java +++ b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java @@ -57,7 +57,7 @@ public static TransmuteResult toTransmute(final @Nullable ItemStackLike stack) { } return switch ((Object) stack) { case net.minecraft.world.item.ItemStack itemStack: - yield new TransmuteResult(itemStack.getItemHolder(), itemStack.getCount(), itemStack.getComponentsPatch()); + yield new TransmuteResult(itemStack.typeHolder(), itemStack.getCount(), itemStack.getComponentsPatch()); case SpongeItemStackSnapshot snapshot: final var direct = Holder.direct(((Item) stack.type())); yield new TransmuteResult(direct, snapshot.quantity(), snapshot.getComponentsPatch()); diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index d2009d24335..d300c7c8bc6 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -44,7 +44,7 @@ import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.util.Util; import net.minecraft.world.entity.Relative; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; @@ -480,13 +480,13 @@ public static final class Networking { public static final int CLICK_OUTSIDE_WINDOW = 0x01 << 16 << 1; public static final int CLICK_ANYWHERE = Networking.CLICK_INSIDE_WINDOW | Networking.CLICK_OUTSIDE_WINDOW; // Modes flags - public static final int MODE_CLICK = 0x01 << 9 << ClickType.PICKUP.ordinal(); - public static final int MODE_SHIFT_CLICK = 0x01 << 9 << ClickType.QUICK_MOVE.ordinal(); - public static final int MODE_HOTBAR = 0x01 << 9 << ClickType.SWAP.ordinal(); - public static final int MODE_PICKBLOCK = 0x01 << 9 << ClickType.CLONE.ordinal(); - public static final int MODE_DROP = 0x01 << 9 << ClickType.THROW.ordinal(); - public static final int MODE_DRAG = 0x01 << 9 << ClickType.QUICK_CRAFT.ordinal(); - public static final int MODE_DOUBLE_CLICK = 0x01 << 9 << ClickType.PICKUP_ALL.ordinal(); + public static final int MODE_CLICK = 0x01 << 9 << ContainerInput.PICKUP.ordinal(); + public static final int MODE_SHIFT_CLICK = 0x01 << 9 << ContainerInput.QUICK_MOVE.ordinal(); + public static final int MODE_HOTBAR = 0x01 << 9 << ContainerInput.SWAP.ordinal(); + public static final int MODE_PICKBLOCK = 0x01 << 9 << ContainerInput.CLONE.ordinal(); + public static final int MODE_DROP = 0x01 << 9 << ContainerInput.THROW.ordinal(); + public static final int MODE_DRAG = 0x01 << 9 << ContainerInput.QUICK_CRAFT.ordinal(); + public static final int MODE_DOUBLE_CLICK = 0x01 << 9 << ContainerInput.PICKUP_ALL.ordinal(); // Drag mode flags, bitmasked from button and only set if MODE_DRAG public static final int DRAG_MODE_PRIMARY_BUTTON = 0x01 << 6; // << 0 public static final int DRAG_MODE_SECONDARY_BUTTON = 0x01 << 6 << 1; diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 1374024d73b..d0205af8d05 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -948,7 +948,7 @@ private ServerLevel prepareLevel(final ServerLevel level) { } else if (worldData.worldGenOptions().generateBonusChest()) { final BlockPos pos = levelData.getRespawnData().pos(); final ConfiguredFeature bonusChestFeature = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE).getValue(MiscOverworldFeatures.BONUS_CHEST); - bonusChestFeature.place(level, level.getChunkSource().getGenerator(), level.random, pos); + bonusChestFeature.place(level, level.getChunkSource().getGenerator(), level.getRandom(), pos); } levelData.setInitialized(true); if (isDebugGeneration) { diff --git a/src/main/resources/common.accesswidener b/src/main/resources/common.accesswidener index fcfa8e442b0..073554c0c46 100644 --- a/src/main/resources/common.accesswidener +++ b/src/main/resources/common.accesswidener @@ -21,3 +21,4 @@ accessible class net/minecraft/world/level/biome/Biome$ClimateSettings accessible class net/minecraft/core/MappedRegistry$TagSet accessible class net/minecraft/world/level/BaseCommandBlock$CloseableCommandBlockSource accessible class net/minecraft/world/entity/monster/illager/SpellcasterIllager$IllagerSpell +accessible class net/minecraft/resources/RegistryDataLoader$RegistryLoadTask \ No newline at end of file diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java deleted file mode 100644 index 5776537988f..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/npc/villager/VillagerTrades_ItemListingMixin_API.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.npc.villager; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.villager.VillagerTrades; -import net.minecraft.world.item.trading.MerchantOffer; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.item.merchant.TradeOffer; -import org.spongepowered.api.item.merchant.TradeOfferGenerator; -import org.spongepowered.api.util.RandomProvider; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(VillagerTrades.ItemListing.class) -public interface VillagerTrades_ItemListingMixin_API extends TradeOfferGenerator { - - // @formatter:off - @Shadow @Nullable MerchantOffer shadow$getOffer(ServerLevel level, Entity entity, RandomSource random); - // @formatter:on - - @Override - default TradeOffer apply(final org.spongepowered.api.entity.Entity merchant, final RandomProvider.Source random) { - if (merchant.world() instanceof ServerLevel sl) { - return (TradeOffer) this.shadow$getOffer(sl, (Entity) merchant, (RandomSource) random); - } - throw new IllegalStateException("The merchant is not in a server world!"); - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java index 9d0a167240e..a4fc6372810 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/player/PlayerMixin_API.java @@ -141,7 +141,7 @@ public void resetBlockProgress(final int x, final int y, final int z) { @Override public void playSound(final Sound sound, final double x, final double y, final double z) { - ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.playSound(sound, this.shadow$level().random, x, y, z)); + ((ViewerBridge) this).bridge$sendToViewer(ViewerPacketUtil.playSound(sound, this.shadow$level().getRandom(), x, y, z)); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/trading/VillagerTradeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/trading/VillagerTradeMixin_API.java new file mode 100644 index 00000000000..d4a0f7fd82d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/trading/VillagerTradeMixin_API.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.trading; + +import net.minecraft.core.registries.Registries; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.villager.VillagerProfession; +import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.item.trading.TradeSet; +import net.minecraft.world.item.trading.VillagerTrade; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.LootParams; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ProfessionTypes; +import org.spongepowered.api.item.merchant.TradeOffer; +import org.spongepowered.api.item.merchant.TradeOfferGenerator; +import org.spongepowered.api.util.RandomProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.VecHelper; + +import java.util.Optional; + +@Mixin(VillagerTrade.class) +public abstract class VillagerTradeMixin_API implements TradeOfferGenerator { + + // @formatter:off + @Shadow public abstract MerchantOffer shadow$getOffer(final LootContext lootContext); + // @formatter:on + + @Override + public TradeOffer apply(final org.spongepowered.api.entity.Entity merchant, final RandomProvider.Source random) { + if (!(merchant.world() instanceof ServerLevel sl)) { + throw new IllegalStateException("The merchant is not in a server world!"); + } + final var profession = merchant.get(Keys.PROFESSION_TYPE).orElseGet(ProfessionTypes.NITWIT); + final var level = merchant.get(Keys.PROFESSION_LEVEL).orElse(1); + final var trades = ((VillagerProfession) (Object) profession).getTrades(level); + + Optional tradeSetOpt = sl.registryAccess().lookupOrThrow(Registries.TRADE_SET).getOptional(trades); + if (tradeSetOpt.isEmpty()) { + throw new IllegalStateException("The merchant is not in a server world!"); + } + + LootContext lootContext = new LootContext.Builder( + new LootParams.Builder(sl) + .withParameter(LootContextParams.ORIGIN, VecHelper.toVanillaVector3d(merchant.position())) + .withParameter(LootContextParams.THIS_ENTITY, (Entity) merchant) + .create(LootContextParamSets.VILLAGER_TRADE) + ) + .create(tradeSetOpt.get().randomSequence()); + return (TradeOffer) this.shadow$getOffer(lootContext); + } + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java index 97df772ad4f..0c8e49a6022 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java @@ -24,8 +24,10 @@ */ package org.spongepowered.common.mixin.core.block; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -70,13 +72,12 @@ public abstract class BlockMixin implements BlockBridge, TrackableBridge { target = "Lnet/minecraft/world/level/block/Block;popResource(Lnet/minecraft/world/level/Level;Ljava/util/function/Supplier;Lnet/minecraft/world/item/ItemStack;)V" ), cancellable = true, - locals = LocalCapture.CAPTURE_FAILSOFT, require = 0, expect = 0 ) private static void impl$throwConstructPreEvent( - final Level level, final BlockPos pos, final ItemStack stack, final CallbackInfo ci, final double $$3, - final double xPos, final double yPos, final double zPos + final Level level, final BlockPos pos, final ItemStack itemStack, final CallbackInfo ci, + @Local(index = 6) final double x, @Local(index = 8) final double y, @Local(index = 10) final double z ) { if (!ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) { return; @@ -85,7 +86,7 @@ public abstract class BlockMixin implements BlockBridge, TrackableBridge { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(level.getBlockState(pos)); final ConstructEntityEvent.Pre eventPre = SpongeEventFactory.createConstructEntityEventPre( - frame.currentCause(), ServerLocation.of((ServerWorld) level, xPos, yPos, zPos), Vector3d.ZERO, + frame.currentCause(), ServerLocation.of((ServerWorld) level, x, y, z), Vector3d.ZERO, EntityTypes.ITEM.get() ); SpongeCommon.post(eventPre); @@ -101,13 +102,12 @@ public abstract class BlockMixin implements BlockBridge, TrackableBridge { value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;popResource(Lnet/minecraft/world/level/Level;Ljava/util/function/Supplier;Lnet/minecraft/world/item/ItemStack;)V" ), - cancellable = true, - locals = LocalCapture.CAPTURE_FAILSOFT + cancellable = true ) private static void impl$throwConstructPreEvent( final Level level, final BlockPos pos, final Direction direction, final ItemStack stack, final CallbackInfo ci, - final int stepX, final int stepY, final int stepZ, final double itemWidthX, final double itemWidthZ, - final double xPos, final double yPos, final double zPos, final double xMov, final double yMov, final double zMov + final @Local(index = 12) double x, final @Local(index = 14) double y, final @Local(index = 16) double z, + final @Local(index = 18) double xMov, final @Local(index = 20) double yMov, final @Local(index = 22) double zMov ) { if (!ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) { return; @@ -116,7 +116,7 @@ public abstract class BlockMixin implements BlockBridge, TrackableBridge { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(level.getBlockState(pos)); final ConstructEntityEvent.Pre eventPre = SpongeEventFactory.createConstructEntityEventPre( - frame.currentCause(), ServerLocation.of((ServerWorld) level, xPos, yPos, zPos), new Vector3d(xMov, yMov, zMov), + frame.currentCause(), ServerLocation.of((ServerWorld) level, x, y, z), new Vector3d(xMov, yMov, zMov), EntityTypes.ITEM.get() ); SpongeCommon.post(eventPre); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java index 8b71cb7920e..77478a76612 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/network/chat/ComponentSerializationMixin.java @@ -39,7 +39,7 @@ @Mixin(ComponentSerialization.class) public abstract class ComponentSerializationMixin { - @ModifyVariable(method = "lambda$createCodec$5", at = @At(value = "HEAD"), argsOnly = true) + @ModifyVariable(method = "lambda$createCodec$3", at = @At(value = "HEAD"), argsOnly = true) private static Component impl$localizeComponent(final Component input) { final Locale locale = SpongeAdventure.ENCODING_LOCALE.get(); final ServerPlayer player = SpongeAdventure.ENCODING_PLAYER.get(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index f580294ca6b..ba751df790c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -24,22 +24,19 @@ */ package org.spongepowered.common.mixin.core.resources; -import com.mojang.serialization.Decoder; import net.minecraft.core.RegistrationInfo; -import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ChatTypeDecoration; import net.minecraft.resources.Identifier; import net.minecraft.resources.RegistryDataLoader; -import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.packs.resources.ResourceManager; import org.spongepowered.api.adventure.ChatTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_RegistryLoadTaskAccessor; import java.util.Map; @@ -47,19 +44,15 @@ public class RegistryDataLoaderMixin { @SuppressWarnings("unchecked") - @Inject(method = "loadContentsFromManager", at = @At("RETURN")) + @Inject(method = "lambda$load$3", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/WritableRegistry;freeze()Lnet/minecraft/core/Registry;")) private static void impl$afterLoadRegistryContents( - final ResourceManager $$0, - final RegistryOps.RegistryInfoLookup $$1, - final WritableRegistry $$2, - final Decoder $$3, - final Map, Exception> $$4, - final CallbackInfo ci) - { - if (Registries.CHAT_TYPE.equals($$2.key())) { + final Map loadingErrors, final RegistryDataLoader.RegistryLoadTask p, CallbackInfo ci + ) { + final var registry = ((RegistryDataLoader_RegistryLoadTaskAccessor) p).accessor$getRegistry(); + if (Registries.CHAT_TYPE.equals(registry.key())) { final ChatTypeDecoration narration = ChatTypeDecoration.withSender("chat.type.text.narrate"); - $$2.register(ResourceKey.create($$2.key(), (Identifier) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); - $$2.register(ResourceKey.create($$2.key(), (Identifier) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); + registry.register(ResourceKey.create(registry.key(), (Identifier) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); + registry.register(ResourceKey.create(registry.key(), (Identifier) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java deleted file mode 100644 index 0eb5e8828c3..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoader_LoaderMixin.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.resources; - -import net.minecraft.resources.RegistryOps; -import net.minecraft.server.packs.resources.ResourceManager; -import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; - -@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$Loader") -public abstract class RegistryDataLoader_LoaderMixin implements RegistryDataLoader_LoaderBridge { - - private RegistryHolder impl$registryHolder; - - @Inject(method = "loadFromResources", at = @At("HEAD")) - private void impl$onLoadFromResources(final ResourceManager $$0, final RegistryOps.RegistryInfoLookup $$1, final CallbackInfo ci) { - this.impl$registryHolder = (RegistryHolder) $$0; - } - - @Override - public RegistryHolder bridge$registryHolder() { - return this.impl$registryHolder; - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 7985beaa640..acc6bcf86fe 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -34,7 +34,6 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.ChatDecorator; import net.minecraft.network.chat.Component; -import net.minecraft.obfuscate.DontObfuscate; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerFunctionManager; @@ -82,6 +81,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; +import org.spongepowered.common.accessor.util.BlockableEventLoopAccessor; import org.spongepowered.common.adventure.NativeComponentRenderer; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; @@ -274,7 +274,6 @@ private void prepareLevels() { * @author Zidane * @reason Apply our branding */ - @DontObfuscate @Overwrite public String getServerModName() { return "sponge"; @@ -510,7 +509,7 @@ public String toString() { @Inject(method = "pollTaskInternal", at = @At("HEAD"), cancellable = true) private void impl$pollSpongeTasks(final CallbackInfoReturnable cir) { //Pool our tasks first to try to have small impact on timings - if (this.impl$spongeMainThreadExecutor.pollTask()) { + if (((BlockableEventLoopAccessor) this.impl$spongeMainThreadExecutor).invoker$pollTask()) { cir.setReturnValue(true); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/PlayerAdvancementsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/PlayerAdvancementsMixin.java index e6eedbf5f90..dbaa32942f7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/PlayerAdvancementsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/PlayerAdvancementsMixin.java @@ -159,7 +159,7 @@ public abstract class PlayerAdvancementsMixin implements PlayerAdvancementsBridg } } - @Redirect(method = "lambda$award$2", + @Redirect(method = "lambda$award$0", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Z)V")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java index cd3f395554e..9433192c67d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/WorldLoaderMixin.java @@ -43,29 +43,34 @@ import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Supplier; @Mixin(WorldLoader.class) public abstract class WorldLoaderMixin { - @WrapOperation(method = "load", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/WorldLoader$PackConfig;createResourceManager()Lcom/mojang/datafixers/util/Pair;")) - private static Pair impl$onCreateResourceManager(final WorldLoader.PackConfig instance, - final Operation> original, final @Local(argsOnly = true) WorldLoader.InitConfig $$0) { - final Pair pair = original.call(instance); - final CloseableResourceManager resourceManager = pair.getSecond(); - final Lifecycle lifecycle = Launch.instance().lifecycle(); - var permLevel = $$0.functionCompilationPermissions() == PermissionSet.ALL_PERMISSIONS ? PermissionLevel.OWNERS : PermissionLevel.ALL; - if ($$0.functionCompilationPermissions() instanceof LevelBasedPermissionSet lbps) { - permLevel = lbps.level(); - } - lifecycle.establishServerServices(resourceManager, permLevel); - lifecycle.setWorldDataConfiguration(pair.getFirst()); - lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); - return pair; + @WrapOperation(method = "load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", at = @At(value = "INVOKE", + target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", remap = false)) + private static CompletableFuture> impl$onCreateResourceManager( + final Supplier> supplier, final Executor executor, final Operation>> original, + final @Local(argsOnly = true) WorldLoader.InitConfig $$0) { + return original.call(supplier, executor).thenApply(pair -> { + final CloseableResourceManager resourceManager = pair.getSecond(); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + var permLevel = $$0.functionCompilationPermissions() == PermissionSet.ALL_PERMISSIONS ? PermissionLevel.OWNERS : PermissionLevel.ALL; + if ($$0.functionCompilationPermissions() instanceof LevelBasedPermissionSet lbps) { + permLevel = lbps.level(); + } + lifecycle.establishServerServices(resourceManager, permLevel); + lifecycle.setWorldDataConfiguration(pair.getFirst()); + lifecycle.beginEstablishServerRegistries((RegistryHolder) resourceManager); + return pair; + }); } - @ModifyExpressionValue(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$WorldDataSupplier;get(Lnet/minecraft/server/WorldLoader$DataLoadContext;)Lnet/minecraft/server/WorldLoader$DataLoadOutput;")) + @ModifyExpressionValue(method = "lambda$load$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$WorldDataSupplier;get(Lnet/minecraft/server/WorldLoader$DataLoadContext;)Lnet/minecraft/server/WorldLoader$DataLoadOutput;")) private static WorldLoader.DataLoadOutput impl$onBakedDimensionRegistries(final WorldLoader.DataLoadOutput original, final @Local CloseableResourceManager resourceManager) { original.finalDimensions().registries().forEach(r -> ((WritableRegistryBridge) r.value()).bridge$unfreeze()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java index 02072e21807..ab4d063e1e3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkHolderMixin.java @@ -58,7 +58,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolderMixin { /** * After onFullChunkStatusChange */ - @Inject(method = "lambda$scheduleFullChunkPromotion$4", at = @At("TAIL")) + @Inject(method = "lambda$scheduleFullChunkPromotion$0", at = @At("TAIL")) private void impl$onScheduleFullChunkPromotion(final ChunkMap $$0x, final FullChunkStatus $$1x, final CallbackInfo ci) { if ($$1x == FullChunkStatus.ENTITY_TICKING) { this.shadow$getEntityTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).ifSuccess(chunk -> { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java index ba9890194a2..20790c35997 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMapMixin.java @@ -110,7 +110,7 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { return CompletableFuture.completedFuture(null); } - @Redirect(method = "lambda$scheduleUnload$12", + @Redirect(method = "lambda$scheduleUnload$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;unload(Lnet/minecraft/world/level/chunk/LevelChunk;)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;save(Lnet/minecraft/world/level/chunk/ChunkAccess;)Z") diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index c45e077e024..f16fa88b5dd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -527,7 +527,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } } - @WrapOperation(method = "lambda$updatePOIOnBlockStateChange$15", + @WrapOperation(method = "lambda$updatePOIOnBlockStateChange$3", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;add(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;)Lnet/minecraft/world/entity/ai/village/poi/PoiRecord;" diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index e44213cb7bf..f0b3c9b974c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -558,7 +558,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } - @Redirect(method = "lambda$handleChatCommand$8", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performUnsignedChatCommand(Ljava/lang/String;)V")) + @Redirect(method = "lambda$handleChatCommand$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performUnsignedChatCommand(Ljava/lang/String;)V")) public void impl$onPerformChatCommand(final ServerGamePacketListenerImpl instance, final String $$0) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(this.player); @@ -567,7 +567,7 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } - @Redirect(method = "lambda$handleSignedChatCommand$9", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performSignedChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) + @Redirect(method = "lambda$handleSignedChatCommand$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performSignedChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) public void impl$onPerformSignedChatCommand(final ServerGamePacketListenerImpl instance, final ServerboundChatCommandSignedPacket $$0, final LastSeenMessages $$1) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.pushCause(this.player); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java index 51d2af3fda0..9567b486e9c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java @@ -183,11 +183,13 @@ public abstract class TagLoaderMixin implements TagLoaderBridge { } @SuppressWarnings("unchecked") - @WrapOperation(method = "loadTagsForRegistry", at = @At(value = "NEW", target = "Lnet/minecraft/tags/TagLoader;")) - private static TagLoader impl$onLoadTagsForRegistry(final TagLoader.ElementLookup $$0, final String $$1, final Operation> original, - final ResourceManager resourceManager, final WritableRegistry registry) { - final TagLoader loader = original.call($$0, $$1); - ((TagLoaderBridge) loader).bridge$registryKey(registry.key()); + @WrapOperation(method = "loadTagsForRegistry(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/tags/TagLoader$ElementLookup;)Ljava/util/Map;", at = @At(value = "NEW", target = "Lnet/minecraft/tags/TagLoader;")) + private static TagLoader impl$onLoadTagsForRegistry( + final TagLoader.ElementLookup elementLookup, final String directory, final Operation original, + final ResourceManager resourceManager, final net.minecraft.resources.ResourceKey> registryKey, final TagLoader.ElementLookup> lookup + ) { + final TagLoader loader = original.call(elementLookup, directory); + ((TagLoaderBridge) loader).bridge$registryKey(registryKey); return loader; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java index 7cd65a66812..fe8f3ff40f0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java @@ -51,11 +51,10 @@ public class PufferfishMixin { } @WrapOperation(method = "lambda$static$0", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;is(Lnet/minecraft/tags/TagKey;)Z") + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;is(Lnet/minecraft/tags/TagKey;)Z") ) private static boolean impl$considerVanishedEntitiesWithTyeps( - final EntityType entityType, final TagKey> tagKey, final Operation operation, - final LivingEntity entity, final ServerLevel level + final LivingEntity entity, final TagKey> tagKey, final Operation operation ) { if (entity instanceof VanishableBridge vb) { if (vb.bridge$vanishState().untargetable()) { @@ -63,6 +62,6 @@ public class PufferfishMixin { return true; } } - return operation.call(entityType, tagKey); + return operation.call(entity, tagKey); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java index 1f69cbbc2d0..f09cb880962 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/ChunkStatusTasksMixin.java @@ -96,7 +96,7 @@ static CompletableFuture generateBiomes(final WorldGenContext conte } //Sponge end } - @Inject(method = "lambda$full$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;setLoaded(Z)V")) + @Inject(method = "lambda$full$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;setLoaded(Z)V")) private static void impl$onLoad(final CallbackInfoReturnable cir, @Local() final LevelChunk levelChunk) { final Vector3i chunkPos = VecHelper.toVector3i(levelChunk.getPos()); if (ShouldFire.CHUNK_EVENT_BLOCKS_LOAD) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java index f0b824647be..808d416d160 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/inventory/container/EnchantmentContainerMixin_Inventory.java @@ -85,14 +85,14 @@ public abstract class EnchantmentContainerMixin_Inventory { } // enchantItem lambda - @Inject(method = "lambda$clickMenuButton$1", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;onEnchantmentPerformed(Lnet/minecraft/world/item/ItemStack;I)V"), require = 1) + @Inject(method = "lambda$clickMenuButton$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;onEnchantmentPerformed(Lnet/minecraft/world/item/ItemStack;I)V"), require = 1) private void impl$beforeEnchantItem(final CallbackInfo ci) { this.prevItem = ItemStackUtil.snapshotOf(this.enchantSlots.getItem(0)); this.prevLapis = ItemStackUtil.snapshotOf(this.enchantSlots.getItem(1)); } // enchantItem lambda - @Inject(method = "lambda$clickMenuButton$1", cancellable = true, + @Inject(method = "lambda$clickMenuButton$0", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;)V"), require = 1) private void impl$afterEnchantItem(final ItemStack itemstack, final int id, final Player playerIn, final int i, final ItemStack itemstack1, final Level arg5, final BlockPos arg6, final CallbackInfo ci) { final ItemStackSnapshot newItem = ItemStackUtil.snapshotOf(this.enchantSlots.getItem(0)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index f47fd4455c9..41ae443347e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -39,7 +39,7 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.inventory.MerchantMenu; import net.minecraft.world.item.ItemStack; @@ -85,7 +85,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { private void impl$onPickItem(final InventoryMenu menu, final Operation original) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logClickContainer(menu, this.player.getInventory().getSelectedSlot(), 0, ClickType.PICKUP, this.player)) { + try (final EffectTransactor ignored = transactor.logClickContainer(menu, this.player.getInventory().getSelectedSlot(), 0, ContainerInput.PICKUP, this.player)) { original.call(menu); } } @@ -117,13 +117,13 @@ public class ServerGamePacketListenerImplMixin_Inventory { private void impl$onSpectatorClick(final AbstractContainerMenu menu, final ServerboundContainerClickPacket packet) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.slotNum(), packet.buttonNum(), packet.clickType(), + try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.slotNum(), packet.buttonNum(), packet.containerInput(), this.player )) { if (menu instanceof MenuBridge bridge) { final SpongeInventoryMenu spongeMenu = bridge.bridge$getMenu(); if (spongeMenu != null) { - spongeMenu.onClick(packet.slotNum(), packet.buttonNum(), packet.clickType(), this.player, ((Container) menu)); + spongeMenu.onClick(packet.slotNum(), packet.buttonNum(), packet.containerInput(), this.player, ((Container) menu)); } } menu.sendAllDataToRemote(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index 22a981b0e10..b1e98c9658a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -30,7 +30,7 @@ import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.ContainerSynchronizer; import net.minecraft.world.inventory.DataSlot; @@ -82,7 +82,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon @Shadow @Final private NonNullList remoteSlots; @Shadow @Nullable private ContainerSynchronizer synchronizer; - @Shadow protected abstract void shadow$doClick(int param0, int param1, ClickType param2, Player param3); + @Shadow protected abstract void shadow$doClick(int param0, int param1, ContainerInput param2, Player param3); @Shadow protected abstract void shadow$updateDataSlotListeners(int $$0, int $$1); @Shadow protected abstract void shadow$synchronizeDataSlotToRemote(int $$0, int $$1); @Shadow protected abstract void shadow$synchronizeCarriedToRemote(); @@ -113,10 +113,10 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ), slice = @Slice( from = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;SWAP:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;SWAP:Lnet/minecraft/world/inventory/ContainerInput;" ), to = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;CLONE:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;CLONE:Lnet/minecraft/world/inventory/ContainerInput;" ) ) ) @@ -137,14 +137,14 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ), slice = @Slice( from = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;SWAP:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;SWAP:Lnet/minecraft/world/inventory/ContainerInput;" ), to = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;CLONE:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;CLONE:Lnet/minecraft/world/inventory/ContainerInput;" ) ) ) - private ItemStack impl$handleUnviewedSlotSwap2(final ItemStack origin, final int splitOff, int $$0, int index, ClickType $$2, Player $$3) { + private ItemStack impl$handleUnviewedSlotSwap2(final ItemStack origin, final int splitOff, int $$0, int index, ContainerInput $$2, Player $$3) { Inventory inv = $$3.getInventory(); if (!PhaseTracker.getWorldInstance().onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { return origin.split(splitOff); @@ -165,10 +165,10 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ), slice = @Slice( from = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;THROW:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;THROW:Lnet/minecraft/world/inventory/ContainerInput;" ), to = @At(value = "FIELD", - target = "Lnet/minecraft/world/inventory/ClickType;PICKUP_ALL:Lnet/minecraft/world/inventory/ClickType;" + target = "Lnet/minecraft/world/inventory/ContainerInput;PICKUP_ALL:Lnet/minecraft/world/inventory/ContainerInput;" ) ) ) @@ -204,10 +204,10 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon @Redirect( method = "clicked", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;doClick(IILnet/minecraft/world/inventory/ClickType;Lnet/minecraft/world/entity/player/Player;)V")) + target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;doClick(IILnet/minecraft/world/inventory/ContainerInput;Lnet/minecraft/world/entity/player/Player;)V")) private void inventory$wrapDoClickWithTransaction( final AbstractContainerMenu menu, final int slotId, final int dragType, - final ClickType clickType, + final ContainerInput clickType, final Player player ) { if (((LevelBridge) player.level()).bridge$isFake() || player.level().isClientSide()) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractContainerMenuMixin_Menu_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractContainerMenuMixin_Menu_Inventory.java index c6f78c4a7c3..058c2a34d5a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractContainerMenuMixin_Menu_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractContainerMenuMixin_Menu_Inventory.java @@ -28,7 +28,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickAction; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.Nullable; @@ -69,7 +69,7 @@ public abstract class AbstractContainerMenuMixin_Menu_Inventory implements MenuB // Called when clicking in an inventory // InventoryMenu Callback @Inject(method = "doClick", at = @At(value = "HEAD"), cancellable = true) - private void impl$onClick(final int slotId, final int dragType, final ClickType clickTypeIn, final Player player, final CallbackInfo ci) { + private void impl$onClick(final int slotId, final int dragType, final ContainerInput clickTypeIn, final Player player, final CallbackInfo ci) { final SpongeInventoryMenu menu = this.bridge$getMenu(); if (menu != null) { if (!menu.onClick(slotId, dragType, clickTypeIn, player, (org.spongepowered.api.item.inventory.Container) this)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java index ce1863abd8b..2998a1d126e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java @@ -60,7 +60,7 @@ public abstract class ChunkMapMixin_Tracker { return exception; } - @Redirect(method = "lambda$prepareTickingChunk$25", + @Redirect(method = "lambda$prepareTickingChunk$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;startTickingChunk(Lnet/minecraft/world/level/chunk/LevelChunk;)V")) private void tracker$wrapUnpackTicks(final ServerLevel level, final LevelChunk chunk) { final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(level); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java index 7cd68545dd0..242a20fabc4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java @@ -47,7 +47,7 @@ @Mixin(ChunkStatusTasks.class) public abstract class ChunkStatusTasksMixin_Tracker { - @Inject(method = "lambda$full$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V"), slice = @Slice( + @Inject(method = "lambda$full$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;setFullStatus(Ljava/util/function/Supplier;)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;registerAllBlockEntitiesAfterLevelLoad()V") )) @@ -80,7 +80,7 @@ public abstract class ChunkStatusTasksMixin_Tracker { .buildAndSwitch(); } - @Inject(method = "lambda$full$2", + @Inject(method = "lambda$full$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;registerAllBlockEntitiesAfterLevelLoad()V", shift = At.Shift.BY, by = 2), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V")) ) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index d5867c90ef8..b18c9d61811 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -146,7 +146,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @WrapOperation( // This normally would target this.entityTickList.forEach((var2x) -> // but we don't have lambda syntax support yet. - method = "lambda$tick$2", + method = "lambda$tick$0", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;guardEntityTick(Ljava/util/function/Consumer;Lnet/minecraft/world/entity/Entity;)V") diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java index de559780be2..0f5e5193d68 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java @@ -56,7 +56,7 @@ public abstract class EndDragonFightMixin_Tracker { @Shadow protected abstract EnderDragon shadow$createNewDragon(); // @formatter:on - @Redirect(method = "lambda$spawnNewGateway$2", + @Redirect(method = "lambda$spawnNewGateway$1", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/feature/ConfiguredFeature;place(Lnet/minecraft/world/level/WorldGenLevel;Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/util/RandomSource;Lnet/minecraft/core/BlockPos;)Z")) private boolean tracker$switchToFeatureState(final ConfiguredFeature configuredFeature, final WorldGenLevel worldIn, final ChunkGenerator generator, final RandomSource rand, final BlockPos pos diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 5b7cd2e650e..e709ca9aede 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -284,7 +284,7 @@ "minecraft.world.entity.npc.villager.AbstractVillagerMixin_API", "minecraft.world.entity.npc.villager.VillagerMixin_API", "minecraft.world.entity.npc.villager.VillagerProfessionMixin_API", - "minecraft.world.entity.npc.villager.VillagerTrades_ItemListingMixin_API", + "minecraft.world.item.trading.VillagerTradeMixin_API", "minecraft.world.entity.npc.villager.VillagerTypeMixin_API", "minecraft.world.entity.npc.wanderingtrader.WanderingTraderMixin_API", "minecraft.world.entity.player.ChatVisiblityMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 907d8279783..96d69621df3 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -52,7 +52,6 @@ "network.syncher.EntityDataAccessorMixin", "network.syncher.SynchedEntityData_BuilderMixin", "network.syncher.SynchedEntityDataMixin", - "resources.RegistryDataLoader_LoaderMixin", "resources.RegistryDataLoaderMixin", "server.MinecraftServerMixin", "server.PlayerAdvancementsMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java index f60f5dc5c3c..1bedf274bc7 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java @@ -30,13 +30,14 @@ import net.minecraft.resources.RegistryDataLoader; import net.minecraft.util.DependencySorter; import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor; import org.spongepowered.common.bridge.core.WritableRegistryBridge; -import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; @@ -53,19 +54,20 @@ public class RegistryDataLoaderMixin_Vanilla { @SuppressWarnings({"rawtypes", "unchecked"}) - @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", - at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) - private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + @WrapOperation(method = "lambda$load$2(Ljava/util/List;Ljava/util/Map;Ljava/lang/Void;)Lnet/minecraft/core/RegistryAccess$Frozen;", + at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V")) + private static void impl$onLoad(final List> instance, final Consumer consumer, Operation original) { // TODO: Remote layer final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); final Lifecycle lifecycle = Launch.instance().lifecycle(); instance.stream() - .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) - .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + .filter(l -> l instanceof RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor) + .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor)l).accessor$getResourceManager(), Collectors.toSet())) .forEach((k, v) -> { + final var registryHolder = (RegistryHolder) k; ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); - lifecycle.processServerRegistries(k, v.stream() + (List) Stream.concat(registryHolder.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + lifecycle.processServerRegistries(registryHolder, v.stream() .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! .map(l -> (Registry) l.accessor$registry())); v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java index b1f8e74e1f3..88f71ae10ca 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/MinecraftServerMixin_Vanilla.java @@ -59,13 +59,13 @@ public String getServerModName() { Launch.instance().lifecycle().callStoppingEngineEvent(this); } - @ModifyExpressionValue(method = "lambda$reloadResources$29", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$1", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager impl$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$30", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$4", at = @At("TAIL")) public void impl$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java index 2710e82987a..7e78174810a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java @@ -45,7 +45,7 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Vanilla { - @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) + @WrapOperation(method = "lambda$loadResources$0", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) private static ReloadableServerResources impl$onCreateResources( final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java index ccc98e5e9cc..c59dc87a2af 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/tags/TagLoaderMixin_Vanilla.java @@ -52,13 +52,13 @@ public abstract class TagLoaderMixin_Vanilla implements TagLoaderBridge { return this.bridge$acceptTag(instance, lookup, consumer, original::call, $$1, entry); } - @Inject(method = "lambda$build$5", at = @At("HEAD")) + @Inject(method = "lambda$build$1", at = @At("HEAD")) private void vanilla$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } - @Inject(method = "lambda$build$5", at = @At("RETURN")) + @Inject(method = "lambda$build$1", at = @At("RETURN")) private void vanilla$onDoneBuildingTag(final CallbackInfo ci) { this.bridge$buildingTagKey(null); } From 60334d32cf428bd4da5b1b0f3183d241aaf0ff21 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Dec 2025 19:21:37 -0800 Subject: [PATCH 434/586] chore(spotless): fix licenses --- ...ryDataLoader_RegistryLoadTaskAccessor.java | 24 +++++++++++++++++++ ...sourceManagerRegistryLoadTaskAccessor.java | 24 +++++++++++++++++++ .../util/BlockableEventLoopAccessor.java | 24 +++++++++++++++++++ .../common/mixin/core/block/BlockMixin.java | 2 -- .../mixin/core/tags/TagLoaderMixin.java | 1 - .../entity/animal/fish/PufferfishMixin.java | 1 - 6 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java index f3a9f2f2b40..3b927cd1540 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.common.accessor.resources; import net.minecraft.core.WritableRegistry; diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java index 3ed96baad86..57eb8b7ee10 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.common.accessor.resources; import net.minecraft.server.packs.resources.ResourceManager; diff --git a/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java index 32058b4c74c..b550217ac8b 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/util/BlockableEventLoopAccessor.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.common.accessor.util; import net.minecraft.util.thread.BlockableEventLoop; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java index 0c8e49a6022..30b17c6fcc4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BlockMixin.java @@ -27,7 +27,6 @@ import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -41,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.TrackableBridge; import org.spongepowered.common.bridge.block.BlockBridge; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java index 9567b486e9c..6b7897c054d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/tags/TagLoaderMixin.java @@ -29,7 +29,6 @@ import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; -import net.minecraft.core.WritableRegistry; import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.tags.TagEntry; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java index fe8f3ff40f0..5bea2688bf0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/animal/fish/PufferfishMixin.java @@ -26,7 +26,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; From db6559cdc3218854d21a1388dbff44a46618b7e4 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 17 Dec 2025 20:48:09 +0100 Subject: [PATCH 435/586] Fix Mockito error in tests --- SpongeAPI | 2 +- build.gradle.kts | 5 +- forge/build.gradle.kts | 5 +- gradle/libs.versions.toml | 3 - gradle/verification-metadata.xml | 77 +++++++++++++++++++ neoforge/build.gradle.kts | 5 +- .../common/scheduler/SchedulerTest.java | 6 -- .../VolumeTransformationTest.java | 6 -- vanilla/build.gradle.kts | 14 +++- 9 files changed, 91 insertions(+), 32 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 11e7548ef82..809c2467fa2 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 11e7548ef82439a1b85e38c803d5b1ca50317fec +Subproject commit 809c2467fa21d3cf9d97ba2079e4300179db7b79 diff --git a/build.gradle.kts b/build.gradle.kts index eb537a92f4e..99f43a68e33 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -174,10 +174,7 @@ dependencies { testRuntimeOnly(apiLibs.junit.engine) testRuntimeOnly(apiLibs.junit.launcher) - testImplementation(libs.mockito.core) - testImplementation(libs.mockito.junitJupiter) { - exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") - } + testImplementation(apiLibs.mockito) testImplementation(libs.mixin) } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 818801ac27a..1b771665027 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -229,10 +229,7 @@ dependencies { testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) - testImplementation(libs.mockito.core) - testImplementation(libs.mockito.junitJupiter) { - exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") - } + testImplementation(apiLibs.mockito) testRuntimeOnly(libs.jacoco.core) { exclude(group = "org.ow2.asm") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9fc54c4d3aa..180de94a53f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,6 @@ securemodules = "2.2.22" fancymodloader = "10.0.32" jarjar = "0.3.26" guava = "32.1.2-jre" -mockito = "5.11.0" jline = "3.25.1" tinylog = "2.7.0" vineflower = "1.11.1" @@ -52,8 +51,6 @@ javaxInject = { module = "javax.inject:javax.inject", version = "1" } mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" } mixinextras-common = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinextras" } mixinextras-forge = { module = "io.github.llamalad7:mixinextras-forge", version.ref = "mixinextras" } -mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } -mockito-junitJupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "jacoco" } # vanilla diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index cd0f7727bb5..9eb41c7323d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3303,6 +3303,14 @@ + + + + + + + + @@ -3327,6 +3335,14 @@ + + + + + + + + @@ -3342,6 +3358,11 @@ + + + + + @@ -9700,6 +9721,14 @@ + + + + + + + + @@ -9719,6 +9748,14 @@ + + + + + + + + @@ -9738,6 +9775,14 @@ + + + + + + + + @@ -9757,6 +9802,14 @@ + + + + + + + + @@ -9773,6 +9826,14 @@ + + + + + + + + @@ -9792,6 +9853,14 @@ + + + + + + + + @@ -10283,6 +10352,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index d929020ae1e..ec433353cb0 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -220,10 +220,7 @@ dependencies { testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) - testImplementation(libs.mockito.core) - testImplementation(libs.mockito.junitJupiter) { - exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") - } + testImplementation(apiLibs.mockito) testRuntimeOnly(libs.jacoco.core) { exclude(group = "org.ow2.asm") diff --git a/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java b/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java index 1ac7b72f764..f00e8a14038 100644 --- a/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java +++ b/src/test/java/org/spongepowered/common/scheduler/SchedulerTest.java @@ -29,11 +29,7 @@ import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; import org.spongepowered.api.scheduler.Task; @@ -44,8 +40,6 @@ import java.util.concurrent.atomic.AtomicBoolean; -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) public class SchedulerTest { @Test diff --git a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java index 759ba182b96..d5250df6641 100644 --- a/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java +++ b/src/test/java/org/spongepowered/common/util/transformation/VolumeTransformationTest.java @@ -25,13 +25,9 @@ package org.spongepowered.common.util.transformation; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.block.entity.BlockEntityArchetype; @@ -54,8 +50,6 @@ import java.util.Optional; import java.util.stream.Stream; -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) public final class VolumeTransformationTest { private static final Vector3i INVALID_STUB_POSITION = Vector3i.from( diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index de547319b1c..393a34d8af6 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -35,6 +35,8 @@ val gameManagedLibrariesConfig = configurations.register("gameManagedLibraries") val bootShadedLibrariesConfig = configurations.register("bootShadedLibraries") val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") +val testModulesConfig = configurations.register("testModules") + // ModLauncher layers val bootLayerConfig = configurations.register("bootLayer") { extendsFrom(bootLibrariesConfig.get()) @@ -143,6 +145,10 @@ val testSources = sourceSets.named("test") { spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) + + configurations.named(implementationConfigurationName) { + extendsFrom(testModulesConfig.get()) + } } val mixinConfigs = spongeImpl.mixinConfigurations @@ -256,10 +262,8 @@ dependencies { testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) - testImplementation(libs.mockito.core) - testImplementation(libs.mockito.junitJupiter) { - exclude(group = "org.junit.jupiter", module = "junit-jupiter-api") - } + val test = testModulesConfig.name + test(apiLibs.mockito) testRuntimeOnly(libs.jacoco.core) { exclude(group = "org.ow2.asm") @@ -504,6 +508,8 @@ tasks { val runServer = minecraft.runs.server().get() jvmArgs(runServer.allJvmArguments()) + jvmArgs("--module-path=" + testModulesConfig.get().asPath) + jvmArgs("--add-modules=net.bytebuddy.agent,net.bytebuddy") jvmArgs("-Dsponge.test.args=" + runServer.allArguments().joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") From 804dba9f6641313152e2a9bd4d9f681767d17376 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 17 Dec 2025 12:11:20 -0800 Subject: [PATCH 436/586] fix(generator): update Generator for 26.1-snapshot-1 This is primarily updating the generator to use the required threaded executor. --- .../vanilla/generator/GeneratorMain.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index e8f3505e0d1..d52d259bc22 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -59,6 +59,8 @@ import java.nio.file.Path; import java.util.List; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -129,6 +131,8 @@ private static Pair loadVanill // Load resource packs, see WorldStem.load // and call to WorldStem.load in net.minecraft.server.Main // We don't currently try to load any datapacks here + final ExecutorService executor = Executors.newCachedThreadPool(); + final var packRepository = ServerPacksSource.createVanillaTrustedRepository(); MinecraftServer.configurePackRepository(packRepository, WorldDataConfiguration.DEFAULT, /* safeMode = */ false, true); final CloseableResourceManager rm = new MultiPackResourceManager(PackType.SERVER_DATA, packRepository.openAllSelected()); @@ -138,10 +142,10 @@ private static Pair loadVanill List> pendingTags = TagLoader.loadTagsForExistingRegistries(rm, staticRegistries.getLayer(RegistryLayer.STATIC)); final var wga = staticRegistries.getAccessForLoading(RegistryLayer.WORLDGEN); List> tl = TagLoader.buildUpdatedLookups(wga, pendingTags); - RegistryAccess.Frozen wgr = RegistryDataLoader.load(rm, tl, RegistryDataLoader.WORLDGEN_REGISTRIES); + RegistryAccess.Frozen wgr = RegistryDataLoader.load(rm, tl, RegistryDataLoader.WORLDGEN_REGISTRIES, executor).join(); List> cl = Stream.concat(tl.stream(), wgr.listRegistries()).toList(); final LayeredRegistryAccess withWorldGen = staticRegistries.replaceFrom(RegistryLayer.WORLDGEN, wgr); - RegistryAccess.Frozen da = RegistryDataLoader.load(rm, cl, RegistryDataLoader.DIMENSION_REGISTRIES); + RegistryAccess.Frozen da = RegistryDataLoader.load(rm, cl, RegistryDataLoader.DIMENSION_REGISTRIES, executor).join(); final LayeredRegistryAccess withDimensions = withWorldGen.replaceFrom(RegistryLayer.DIMENSIONS, da); TagLoader.loadTagsForExistingRegistries(rm, withDimensions.getLayer(RegistryLayer.WORLDGEN)); @@ -153,12 +157,13 @@ private static Pair loadVanill packRepository.getRequestedFeatureFlags(), CommandSelection.ALL, LevelBasedPermissionSet.ALL_PERMISSIONS, // functionPermissionLevel - Util.backgroundExecutor(), // prepareExecutor + executor, // prepareExecutor Runnable::run // applyExecutor ).whenComplete((result, ex) -> { if (ex != null) { rm.close(); } + executor.shutdown(); }).thenApply(resources -> { resources.updateStaticRegistryTags(); return resources; @@ -170,6 +175,7 @@ private static Pair loadVanill try { resources = resourcesFuture.get(); } catch (final InterruptedException | ExecutionException ex) { + executor.shutdown(); Logger.error(ex, "Failed to load registries/datapacks"); System.exit(1); throw new RuntimeException(); From 76db2a214f16633b57d2716e6435022705bf00b1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 17 Dec 2025 12:16:52 -0800 Subject: [PATCH 437/586] chore(spotless): clean up imports --- .../java/org/spongepowered/vanilla/generator/GeneratorMain.java | 1 - 1 file changed, 1 deletion(-) diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index d52d259bc22..a54e2ea98e0 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -43,7 +43,6 @@ import net.minecraft.server.packs.resources.MultiPackResourceManager; import net.minecraft.server.permissions.LevelBasedPermissionSet; import net.minecraft.tags.TagLoader; -import net.minecraft.util.Util; import net.minecraft.world.level.WorldDataConfiguration; import org.spongepowered.vanilla.generator.item.ItemRegistries; import org.spongepowered.vanilla.generator.world.TagRegistries; From b8bea0e01e18875ebc4918ff3635ae9cbdb00f23 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 17 Dec 2025 12:53:19 -0800 Subject: [PATCH 438/586] chore(ci): update workflows to use Java 25 runtime --- .github/workflows/check-spotless.yaml | 2 +- .github/workflows/common-integration-test.yaml | 2 +- .github/workflows/common-run-build.yaml | 2 +- .github/workflows/deploy.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-spotless.yaml b/.github/workflows/check-spotless.yaml index 5919a3117ef..39d8d6c04d3 100644 --- a/.github/workflows/check-spotless.yaml +++ b/.github/workflows/check-spotless.yaml @@ -10,6 +10,6 @@ jobs: call-check: uses: SpongePowered/.github/.github/workflows/shared-check-spotless.yaml@master with: - runtime_version: 21 + runtime_version: 25 extra_gradle_params: "-Pprojects=vanilla,forge,neoforge,testplugins" secrets: inherit diff --git a/.github/workflows/common-integration-test.yaml b/.github/workflows/common-integration-test.yaml index befe39d8ea2..3becbb81bae 100644 --- a/.github/workflows/common-integration-test.yaml +++ b/.github/workflows/common-integration-test.yaml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-22.04, windows-latest, macos-latest] - java: [ 21 ] + java: [ 25 ] runs-on: "${{ matrix.os }}" steps: - name: Check out repository to use the build.gradle.kts as a hash file diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index 82dc1d45351..b3427aed0c0 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -31,7 +31,7 @@ jobs: uses: SpongePowered/.github/.github/actions/setup-java-env@master if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" with: - runtime_version: 21 + runtime_version: 25 publishing_branch_regex: 'api-\d+' - name: setup / cache minecraft dependencies uses: "actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf" # v4.2.2 diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 99c138c7923..90567c19f33 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -51,7 +51,7 @@ jobs: id: setup uses: SpongePowered/.github/.github/actions/setup-java-env@master with: - runtime_version: 21 + runtime_version: 25 publishing_branch_regex: '' - name: setup / minecraft cache if: "!(matrix.skipUpdateBranch && startsWith(github.ref, 'refs/heads/update/'))" From 435dece2810a38d0125811b9b5be4c278e8dd015 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 17 Dec 2025 13:16:37 -0800 Subject: [PATCH 439/586] refactor(installer): simplify Minecraft jar handling by removing remapping logic Since Minecraft is no longer obfuscated, we can just download the bundle and extract. --- .../vanilla/installer/InstallerMain.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index 3a4cd688cfc..1fb0c45cfb0 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -47,7 +47,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.UncheckedIOException; import java.net.URI; import java.net.URL; import java.net.URLConnection; @@ -116,18 +115,10 @@ private void downloadAndRun() throws Exception { final LibraryManager libraryManager = this.installer.getLibraryManager(); try { if (mcVersion != null) { - final CompletableFuture mappingsFuture = this.downloadMappings(mcVersion); final CompletableFuture originalMcFuture = this.downloadMinecraft(mcVersion); final CompletableFuture extractedFuture = originalMcFuture .thenApplyAsync(this::extractBundle, libraryManager.preparationWorker()); - final CompletableFuture remappedMinecraftJarFuture = mappingsFuture.thenCombineAsync(extractedFuture, (mappings, minecraft) -> { - try { - return this.remapMinecraft(minecraft, mappings); - } catch (final IOException ex) { - throw new UncheckedIOException(ex); - } - }, libraryManager.preparationWorker()); - remappedMinecraftJar = remappedMinecraftJarFuture.get(); + remappedMinecraftJar = extractedFuture.get(); } } catch (final ExecutionException ex) { final /* @Nullable */ Throwable cause = ex.getCause(); From 9fcc02602d66bf6f52596d3afda1216de486f62d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 18 Dec 2025 13:00:28 +0100 Subject: [PATCH 440/586] Remove FART Finally, it smells good. --- SpongeAPI | 2 +- gradle/libs.versions.toml | 2 - vanilla/build.gradle.kts | 5 - .../vanilla/installer/InstallerMain.java | 163 +----------------- 4 files changed, 10 insertions(+), 162 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 809c2467fa2..5d08674ba42 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 809c2467fa21d3cf9d97ba2079e4300179db7b79 +Subproject commit 5d08674ba42258b28592eb51531fba550657c9df diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 180de94a53f..72051fe8e13 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,6 @@ format = { version = "1.1" } [versions] asm = "9.8" log4j = "2.24.1" -forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" mixinextras = "0.5.0" modlauncher = "10.2.2" @@ -54,7 +53,6 @@ mixinextras-forge = { module = "io.github.llamalad7:mixinextras-forge", version. jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "jacoco" } # vanilla -forgeAutoRenamingTool = { module = "net.minecraftforge:ForgeAutoRenamingTool", version.ref = "forgeAutoRenamingTool" } jarjar-fs = { module = "net.minecraftforge:JarJarFileSystems", version.ref = "jarjar" } jline-reader = { module = "org.jline:jline-reader", version.ref = "jline" } jline-terminal = { module = "org.jline:jline-terminal", version.ref = "jline" } diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 393a34d8af6..d688030ab87 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -182,11 +182,6 @@ dependencies { installer(libs.tinylog.api) installer(libs.tinylog.impl) - installer(libs.forgeAutoRenamingTool) { - exclude(group = "net.sf.jopt-simple") - exclude(group = "org.ow2.asm") - } - installer(project(libraryManagerProject.path)) // optional at runtime diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index 1fb0c45cfb0..dbe64be9d6d 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -26,11 +26,6 @@ import com.google.gson.Gson; import com.google.gson.stream.JsonReader; -import net.minecraftforge.fart.api.Renamer; -import net.minecraftforge.fart.api.SignatureStripperConfig; -import net.minecraftforge.fart.api.SourceFixerConfig; -import net.minecraftforge.fart.api.Transformer; -import net.minecraftforge.srgutils.IMappingFile; import org.spongepowered.bootstrap.forge.VanillaBootstrap; import org.spongepowered.libs.LibraryManager; import org.spongepowered.libs.LibraryUtils; @@ -50,15 +45,12 @@ import java.net.URI; import java.net.URL; import java.net.URLConnection; -import java.nio.file.AccessDeniedException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -77,7 +69,6 @@ public final class InstallerMain { private static final String COLLECTION_BOOTSTRAP = "bootstrap"; // boot layer private static final String COLLECTION_MAIN = "main"; // game layer - private static final int MAX_TRIES = 2; private final Installer installer; private final boolean isolated; @@ -104,35 +95,32 @@ public void run() throws Exception { } private void downloadAndRun() throws Exception { - ServerAndLibraries remappedMinecraftJar = null; + ServerAndLibraries extractedMinecraftJar = null; Version mcVersion = null; try { mcVersion = this.downloadMinecraftManifest(); } catch (final IOException ex) { - remappedMinecraftJar = this.recoverFromMinecraftDownloadError(ex); + extractedMinecraftJar = this.recoverFromMinecraftDownloadError(ex); } final LibraryManager libraryManager = this.installer.getLibraryManager(); try { if (mcVersion != null) { - final CompletableFuture originalMcFuture = this.downloadMinecraft(mcVersion); - final CompletableFuture extractedFuture = originalMcFuture - .thenApplyAsync(this::extractBundle, libraryManager.preparationWorker()); - remappedMinecraftJar = extractedFuture.get(); + extractedMinecraftJar = this.downloadMinecraft(mcVersion).thenApplyAsync(this::extractBundle, libraryManager.preparationWorker()).get(); } } catch (final ExecutionException ex) { final /* @Nullable */ Throwable cause = ex.getCause(); - remappedMinecraftJar = this.recoverFromMinecraftDownloadError(cause instanceof Exception ? (Exception) cause : ex); + extractedMinecraftJar = this.recoverFromMinecraftDownloadError(cause instanceof Exception ? (Exception) cause : ex); } - assert remappedMinecraftJar != null; // always assigned or thrown + assert extractedMinecraftJar != null; // always assigned or thrown libraryManager.validate(); // Minecraft itself is on the main layer - libraryManager.addLibrary(InstallerMain.COLLECTION_MAIN, new LibraryManager.Library("minecraft", remappedMinecraftJar.server())); + libraryManager.addLibrary(InstallerMain.COLLECTION_MAIN, new LibraryManager.Library("minecraft", extractedMinecraftJar.server())); // Other libs are on the bootstrap layer - for (final Map.Entry entry : remappedMinecraftJar.libraries().entrySet()) { + for (final Map.Entry entry : extractedMinecraftJar.libraries().entrySet()) { final GroupArtifactVersion artifact = entry.getKey(); final Path path = entry.getValue(); @@ -211,10 +199,9 @@ private static Path newJarInJar(final Path jar) { private ServerAndLibraries recoverFromMinecraftDownloadError(final T ex) throws T { final Path expectedUnpacked = this.expectedMinecraftLocation(Constants.Libraries.MINECRAFT_VERSION_TARGET); - final Path expectedRemapped = this.expectedRemappedLocation(expectedUnpacked); // Re-read bundler metadata (needs original bundled location) - if (Files.exists(expectedRemapped)) { - Logger.warn(ex, "Failed to download and remap Minecraft. An existing jar exists, so we will attempt to use that instead."); + if (Files.exists(expectedUnpacked)) { + Logger.warn(ex, "Failed to download Minecraft. An existing jar exists, so we will attempt to use that instead."); return this.extractBundle(this.expectedBundleLocation(expectedUnpacked)); } else { throw ex; @@ -276,10 +263,6 @@ private Path expectedMinecraftLocation(final String version) { .resolve(Constants.Libraries.MINECRAFT_SERVER_JAR_NAME + ".jar"); } - private Path expectedRemappedLocation(final Path originalLocation) { - return originalLocation.resolveSibling(Constants.Libraries.MINECRAFT_SERVER_JAR_NAME + "-remapped.jar"); - } - private Path expectedBundleLocation(final Path originalLocation) { return originalLocation.resolveSibling(Constants.Libraries.MINECRAFT_SERVER_JAR_NAME + "-bundle.jar"); } @@ -372,137 +355,9 @@ private ServerAndLibraries extractBundle(final Path bundleJar) { } } - private CompletableFuture downloadMappings(final Version version) { - return LibraryUtils.asyncFailableFuture(() -> { - Logger.info("Setting up names for Minecraft {}", Constants.Libraries.MINECRAFT_VERSION_TARGET); - final Path downloadTarget = this.installer.getLibraryManager().getRootDirectory().resolve(Constants.Libraries.MINECRAFT_MAPPINGS_PREFIX) - .resolve(Constants.Libraries.MINECRAFT_VERSION_TARGET) - .resolve(Constants.Libraries.MINECRAFT_MAPPINGS_NAME); - - final Version.Downloads.Download mappings = version.downloads().server_mappings(); - if (mappings == null) { - throw new IOException(String.format("Mappings were not included in version manifest for %s", Constants.Libraries.MINECRAFT_VERSION_TARGET)); - } - - final boolean checkHashes = this.installer.getConfig().checkLibraryHashes(); - if (Files.exists(downloadTarget)) { - if (checkHashes) { - Logger.info("Detected existing mappings, verifying hashes..."); - if (LibraryUtils.validateDigest("SHA-1", mappings.sha1(), downloadTarget)) { - Logger.info("Mappings verified!"); - return downloadTarget; - } else { - Logger.error("Checksum verification failed: Expected {}. Deleting cached server mappings file...", mappings.sha1()); - Files.delete(downloadTarget); - } - } else { - return downloadTarget; - } - } - - if (this.installer.getConfig().autoDownloadLibraries()) { - if (checkHashes) { - LibraryUtils.downloadAndVerifyDigest(TinyLogger.INSTANCE, mappings.url(), downloadTarget, "SHA-1", mappings.sha1()); - } else { - LibraryUtils.download(TinyLogger.INSTANCE, mappings.url(), downloadTarget, false); - } - } else { - throw new IOException(String.format("Mappings were not located at '%s' and downloading them has been turned off.", downloadTarget)); - } - - return downloadTarget; - }, this.installer.getLibraryManager().preparationWorker()); - } - - private ServerAndLibraries remapMinecraft(final ServerAndLibraries minecraft, final Path serverMappings) throws IOException { - Logger.info("Checking if we need to remap Minecraft..."); - final Path outputJar = this.expectedRemappedLocation(minecraft.server()); - final Path tempOutput = outputJar.resolveSibling(Constants.Libraries.MINECRAFT_SERVER_JAR_NAME + "_remapped.jar.tmp"); - - if (Files.exists(outputJar)) { - Logger.info("Remapped Minecraft detected, skipping..."); - return minecraft.server(outputJar); - } - - Logger.info("Remapping Minecraft. This may take a while..."); - final IMappingFile mappings = IMappingFile.load(serverMappings.toFile()).reverse(); - - final Renamer.Builder renamerBuilder = Renamer.builder() - .add(Transformer.parameterAnnotationFixerFactory()) - .add(ctx -> { - final Transformer backing = Transformer.renamerFactory(mappings, false).create(ctx); - return new Transformer() { - @Override - public ClassEntry process(final ClassEntry entry) { - final String name = entry.getName(); - if (name.startsWith("it/unimi") - || name.startsWith("com/google") - || name.startsWith("com/mojang/datafixers") - || name.startsWith("com/mojang/brigadier") - || name.startsWith("org/apache")) { - return entry; - } - return backing.process(entry); - } - - @Override - public ManifestEntry process(final ManifestEntry entry) { - return backing.process(entry); - } - - @Override - public ResourceEntry process(final ResourceEntry entry) { - return backing.process(entry); - } - - @Override - public Collection getExtras() { - return backing.getExtras(); - } - }; - }) - .add(Transformer.recordFixerFactory()) - .add(Transformer.parameterAnnotationFixerFactory()) - .add(Transformer.sourceFixerFactory(SourceFixerConfig.JAVA)) - .add(Transformer.signatureStripperFactory(SignatureStripperConfig.ALL)) - .logger(Logger::debug); // quiet - - try (final Renamer ren = renamerBuilder.build()) { - ren.run(minecraft.server.toFile(), tempOutput.toFile()); - } - - // Restore file - try { - Files.move(tempOutput, outputJar, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); - } catch (final AccessDeniedException ex) { - // Sometimes because of file locking this will fail... Let's just try again and hope for the best - // Thanks Windows! - for (int tries = 0; tries < InstallerMain.MAX_TRIES; ++tries) { - // Pause for a bit - try { - Thread.sleep(5 * tries); - Files.move(tempOutput, outputJar, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); - } catch (final AccessDeniedException ex2) { - if (tries == InstallerMain.MAX_TRIES - 1) { - throw ex; - } - } catch (final InterruptedException exInterrupt) { - Thread.currentThread().interrupt(); - throw ex; - } - } - } - - return minecraft.server(outputJar); - } - record ServerAndLibraries(Path server, Map libraries) { ServerAndLibraries { libraries = Map.copyOf(libraries); } - - public ServerAndLibraries server(final Path server) { - return new ServerAndLibraries(server, this.libraries); - } } } From 7c315e91390482d826713e531eb7bdc121cdcd2b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 18 Dec 2025 21:03:22 +0100 Subject: [PATCH 441/586] Disable spotless on Forge FG 6 does not support Gradle 9 and FG 7 is not out yet. --- .github/workflows/check-spotless.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-spotless.yaml b/.github/workflows/check-spotless.yaml index 39d8d6c04d3..96a95759998 100644 --- a/.github/workflows/check-spotless.yaml +++ b/.github/workflows/check-spotless.yaml @@ -11,5 +11,5 @@ jobs: uses: SpongePowered/.github/.github/workflows/shared-check-spotless.yaml@master with: runtime_version: 25 - extra_gradle_params: "-Pprojects=vanilla,forge,neoforge,testplugins" + extra_gradle_params: "-Pprojects=vanilla,neoforge,testplugins" secrets: inherit From 814832008dad85be8251f21b5b73196ef68d5de2 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 19 Dec 2025 17:59:55 +0100 Subject: [PATCH 442/586] Bump VanillaGradle to 0.3.0 --- gradle/verification-metadata.xml | 88 ++++++++++++++++++++++++++++++-- settings.gradle.kts | 2 +- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9eb41c7323d..cc8d91f40a9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -32,10 +32,6 @@ - - - - @@ -4375,6 +4371,14 @@ + + + + + + + + @@ -7854,6 +7858,11 @@ + + + + + @@ -7902,6 +7911,14 @@ + + + + + + + + @@ -7922,6 +7939,11 @@ + + + + + @@ -7954,6 +7976,14 @@ + + + + + + + + @@ -7986,6 +8016,14 @@ + + + + + + + + @@ -8006,6 +8044,11 @@ + + + + + @@ -9622,6 +9665,14 @@ + + + + + + + + @@ -11356,6 +11407,14 @@ + + + + + + + + @@ -11372,6 +11431,14 @@ + + + + + + + + @@ -11388,6 +11455,14 @@ + + + + + + + + @@ -11408,6 +11483,11 @@ + + + + + diff --git a/settings.gradle.kts b/settings.gradle.kts index 61df60b17ed..1f4d4bdcae3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { } } plugins { - id("org.spongepowered.gradle.vanilla") version "0.3.0-SNAPSHOT" + id("org.spongepowered.gradle.vanilla") version "0.3.0" id("implementation-structure") } } From 63bbbde729f3619a7cba5ed162ebd8b50b59c54e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 4 Jan 2026 19:51:29 +0100 Subject: [PATCH 443/586] Allow plugins to specify mixin configs in manifest on Neo The new Neo loader no longer does that, we bring it back for proper support of cross-platform mixins --- .../metadata/PluginFileConfigurable.java | 18 ++++++- .../metadata/PluginMixinConfigurable.java | 53 +++++++++++++++++++ .../moddiscovery/reader/PluginFileParser.java | 2 +- 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java index 5a97ac24ed4..a9be2b962f1 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java @@ -34,14 +34,17 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.jar.Manifest; // ModFileInfo public final class PluginFileConfigurable implements IConfigurable { private final MetadataContainer container; + private final Manifest manifest; - public PluginFileConfigurable(final MetadataContainer container) { + public PluginFileConfigurable(final MetadataContainer container, final Manifest manifest) { this.container = container; + this.manifest = manifest; } @SuppressWarnings("unchecked") @@ -105,6 +108,19 @@ public List getConfigList(final String... key) { return metadataConfigurables; } + if ("mixins".equals(query)) { + final String mixinConfigs = this.manifest.getMainAttributes().getValue("MixinConfigs"); + if (mixinConfigs == null) { + return Collections.emptyList(); + } + + final List mixinConfigurables = new ArrayList<>(); + for (final String config : mixinConfigs.split(",")) { + mixinConfigurables.add(new PluginMixinConfigurable(config.trim())); + } + return mixinConfigurables; + } + if (key.length != 2) { return Collections.emptyList(); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java new file mode 100644 index 00000000000..e524434e472 --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java @@ -0,0 +1,53 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.loading.metadata; + +import net.neoforged.neoforgespi.language.IConfigurable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public final class PluginMixinConfigurable implements IConfigurable { + private final String config; + + public PluginMixinConfigurable(final String config) { + this.config = config; + } + + @SuppressWarnings("unchecked") + @Override + public Optional getConfigElement(final String... key) { + if (key.length == 1 && "config".equals(key[0])) { + return Optional.of((T) this.config); + } + return Optional.empty(); + } + + @Override + public List getConfigList(final String... key) { + return Collections.emptyList(); + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java index 49db57a80a9..846eb87582c 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java @@ -61,7 +61,7 @@ private static IModFileInfo parsePluginMetadata(final IModFile modFile) throws I container = MetadataParser.read(reader); } - final PluginFileConfigurable config = new PluginFileConfigurable(PluginMetadataFixer.fixPluginIds(container)); + final PluginFileConfigurable config = new PluginFileConfigurable(PluginMetadataFixer.fixPluginIds(container), modFile.getContents().getManifest()); return new ModFileInfo((ModFile) modFile, config, (info) -> {}, List.of()); } catch (final Exception e) { AppLaunch.logger().warn("Could not read metadata for plugin file '{}'", modFile, e); From 7939f917c2f13b907a3434a740504b4d217413a2 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 9 Jan 2026 19:43:28 +0100 Subject: [PATCH 444/586] Update Adventure to 4.26.1 --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 88 +++++++++++++++++++ .../common/adventure/SpongeAdventure.java | 31 +++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 717e4605585..5098d90d768 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 717e4605585983a323fa2860962850f5dd17fb74 +Subproject commit 5098d90d7684cb5228e1813b1c9acdef7a10b2bd diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c0b4551f293..f75f1b8536c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3293,6 +3293,14 @@ + + + + + + + + @@ -3338,6 +3346,14 @@ + + + + + + + + @@ -3395,6 +3411,14 @@ + + + + + + + + @@ -3449,6 +3473,14 @@ + + + + + + + + @@ -3506,6 +3538,14 @@ + + + + + + + + @@ -3560,6 +3600,14 @@ + + + + + + + + @@ -3584,6 +3632,14 @@ + + + + + + + + @@ -3641,6 +3697,14 @@ + + + + + + + + @@ -3698,6 +3762,14 @@ + + + + + + + + @@ -3755,6 +3827,14 @@ + + + + + + + + @@ -3812,6 +3892,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index f6c7eaa7641..8643bedc05d 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.adventure; +import com.mojang.authlib.GameProfile; import com.mojang.brigadier.Message; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; @@ -41,6 +42,7 @@ import net.kyori.adventure.text.EntityNBTComponent; import net.kyori.adventure.text.KeybindComponent; import net.kyori.adventure.text.NBTComponentBuilder; +import net.kyori.adventure.text.ObjectComponent; import net.kyori.adventure.text.ScoreComponent; import net.kyori.adventure.text.SelectorComponent; import net.kyori.adventure.text.StorageNBTComponent; @@ -56,6 +58,8 @@ import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.object.PlayerHeadObjectContents; +import net.kyori.adventure.text.object.SpriteObjectContents; import net.kyori.adventure.text.renderer.ComponentRenderer; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; @@ -77,6 +81,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.contents.KeybindContents; import net.minecraft.network.chat.contents.NbtContents; +import net.minecraft.network.chat.contents.ObjectContents; import net.minecraft.network.chat.contents.PlainTextContents; import net.minecraft.network.chat.contents.ScoreContents; import net.minecraft.network.chat.contents.SelectorContents; @@ -84,6 +89,9 @@ import net.minecraft.network.chat.contents.data.BlockDataSource; import net.minecraft.network.chat.contents.data.EntityDataSource; import net.minecraft.network.chat.contents.data.StorageDataSource; +import net.minecraft.network.chat.contents.objects.AtlasSprite; +import net.minecraft.network.chat.contents.objects.ObjectInfo; +import net.minecraft.network.chat.contents.objects.PlayerSprite; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerBossEvent; @@ -92,6 +100,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ResolvableProfile; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.jetbrains.annotations.NotNull; @@ -315,11 +324,20 @@ private static MutableComponent asVanillaMutable0(final Component component) { net.minecraft.network.chat.Component.nbt(storage.nbtPath(), storage.interpret(), SpongeAdventure.asVanillaOpt(storage.separator()), new StorageDataSource(SpongeAdventure.asVanilla(storage.storage()))); + case ObjectComponent obj -> net.minecraft.network.chat.Component.object(SpongeAdventure.asVanilla(obj.contents())); default -> throw new UnsupportedOperationException("Cannot convert Component of type " + component.getClass()); }; } + private static ObjectInfo asVanilla(final net.kyori.adventure.text.object.ObjectContents obj) { + return switch (obj) { + case SpriteObjectContents sprite -> new AtlasSprite(SpongeAdventure.asVanilla(sprite.atlas()), SpongeAdventure.asVanilla(sprite.sprite())); + case PlayerHeadObjectContents player -> new PlayerSprite(player.id() == null ? ResolvableProfile.createUnresolved(player.name()) : ResolvableProfile.createUnresolved(player.id()), player.hat()); + default -> throw new UnsupportedOperationException("Cannot convert ObjectContents of type " + obj.getClass()); + }; + } + // no caching public static Component asAdventure(final net.minecraft.network.chat.Component component) { if (component instanceof final AdventureTextComponent ac) { @@ -370,11 +388,24 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c .interpret(nbt.isInterpreting()) .separator(SpongeAdventure.asAdventure(nbt.getSeparator())); } + case ObjectContents obj -> Component.object().contents(SpongeAdventure.asAdventure(obj.contents())); default -> throw new UnsupportedOperationException("Cannot convert ComponentContents of type " + contents.getClass()); }; } + private static net.kyori.adventure.text.object.ObjectContents asAdventure(final ObjectInfo info) { + switch (info) { + case AtlasSprite atlas: + return net.kyori.adventure.text.object.ObjectContents.sprite(SpongeAdventure.asAdventure(atlas.atlas()), SpongeAdventure.asAdventure(atlas.sprite())); + case PlayerSprite player: + final GameProfile profile = player.player().partialProfile(); + return net.kyori.adventure.text.object.ObjectContents.playerHead().name(profile.name()).id(profile.id()).hat(player.hat()).build(); + default: + throw new UnsupportedOperationException("Cannot convert ObjectInfo of type " + info.getClass()); + } + } + public static @Nullable Component asAdventure(final Optional component) { return component.map(SpongeAdventure::asAdventure).orElse(null); } From fad8950ffb6d080f1013680d7eac1e9df024fa06 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 9 Jan 2026 23:46:26 +0100 Subject: [PATCH 445/586] chore(release): New recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9db1417b282..7f5e2bc5a2e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.4 -recommendedVersion=0-SNAPSHOT +recommendedVersion=0 org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From d6f3ad8be99964e1ba9e926267c00278ecdd0a4e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 10 Jan 2026 00:04:48 +0100 Subject: [PATCH 446/586] chore: Prepare towards next recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7f5e2bc5a2e..17dcda9d745 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.4 -recommendedVersion=0 +recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From e22865053acc310a44ce71b199db50b8bed119e3 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 10 Jan 2026 09:45:30 +0100 Subject: [PATCH 447/586] chore(release): New recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 93c14ef33fa..c870b6efb60 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.5 -recommendedVersion=0-SNAPSHOT +recommendedVersion=0 org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 04b6a4df703db60f93b2175072f002462ac283c0 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 10 Jan 2026 09:59:22 +0100 Subject: [PATCH 448/586] chore: Prepare towards next recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c870b6efb60..0f8c82b70c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.5 -recommendedVersion=0 +recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 9ac3f73410b942f2d780a0f9412b776fc6916d49 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 10 Jan 2026 11:27:25 +0100 Subject: [PATCH 449/586] chore(release): New recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a3d9a2151fb..61d29cb258a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.8 -recommendedVersion=0-SNAPSHOT +recommendedVersion=0 org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 0180873e27f9621e5d3b4bf8b8d39ea497f79e02 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 10 Jan 2026 12:06:35 +0100 Subject: [PATCH 450/586] chore: Prepare towards next recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 61d29cb258a..069b9e98a8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.8 -recommendedVersion=0 +recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 25278b3c22577a40bff9598954ea25e1e0f4a86c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 11 Jan 2026 23:26:36 +0100 Subject: [PATCH 451/586] chore: update towards 17.1.0-SNAPSHOT --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 5098d90d768..478957cb872 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 5098d90d7684cb5228e1813b1c9acdef7a10b2bd +Subproject commit 478957cb8720f58f285a9c8cc9cd9df67cc1ba64 From ab34e23bc3730ad07415596594bdaf9dcabaea86 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 11 Jan 2026 23:40:22 +0100 Subject: [PATCH 452/586] chore(release): New recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 009b19b0151..42dbe39832d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.10 -recommendedVersion=0-SNAPSHOT +recommendedVersion=0 org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From 3010f39ced48c3bdf21c4d4f0c2e7695227a1e1e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 12 Jan 2026 00:00:56 +0100 Subject: [PATCH 453/586] chore: Prepare towards next recommended version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 42dbe39832d..f0595650efe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json minecraftVersion=1.21.10 -recommendedVersion=0 +recommendedVersion=1-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m From dbbf778fcb2d7abe6cffdb516afebc8ef93106b2 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 14 Jan 2026 14:23:57 +0100 Subject: [PATCH 454/586] Fix DimensionEffectProvider clinit cast error --- .../common/registry/provider/DimensionEffectProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java b/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java index d9bb0869565..1d2c7d189bf 100644 --- a/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java +++ b/src/main/java/org/spongepowered/common/registry/provider/DimensionEffectProvider.java @@ -38,9 +38,9 @@ public final class DimensionEffectProvider { public static DimensionEffectProvider INSTANCE = new DimensionEffectProvider(); - private static final SpongeWorldTypeEffect OVERWORLD = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.OVERWORLD); - private static final SpongeWorldTypeEffect NETHER = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.NETHER); - private static final SpongeWorldTypeEffect END = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.END); + private static final SpongeWorldTypeEffect OVERWORLD = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.OVERWORLD.identifier()); + private static final SpongeWorldTypeEffect NETHER = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.NETHER.identifier()); + private static final SpongeWorldTypeEffect END = new SpongeWorldTypeEffect((ResourceKey) (Object) BuiltinDimensionTypes.END.identifier()); static { DimensionEffectProvider.INSTANCE.register(DimensionType.Skybox.OVERWORLD, OVERWORLD); From 1cd199ef312d4f6130bd6152a712f497b3291879 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 14 Jan 2026 14:25:30 +0100 Subject: [PATCH 455/586] Remove ansi error formatting from log4j2 configs --- vanilla/src/applaunch/resources/log4j2.xml | 5 ++--- vanilla/src/applaunch/resources/log4j2_dev.xml | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/vanilla/src/applaunch/resources/log4j2.xml b/vanilla/src/applaunch/resources/log4j2.xml index 876e95b0b2e..67a69800e10 100644 --- a/vanilla/src/applaunch/resources/log4j2.xml +++ b/vanilla/src/applaunch/resources/log4j2.xml @@ -1,7 +1,6 @@ - StyleMapName=Spock Name=reset,red NameMessageSeparator=red Message=red StackTraceElement.ClassName=red StackTraceElement.ClassMethodSeparator=red,faint StackTraceElement.MethodName=yellow StackTraceElement.NativeMethod=yellow jdk.internal,sun.reflect @@ -9,10 +8,10 @@ + defaultPattern="[%d{HH:mm:ss}] [%t/%highlight{%level}] [%c{1.3}%notEmpty{/%markerSimpleName}]: %highlightError{%msg{nolookups}%n%xEx{filters(${sponge.exceptionFiltered})}}"> + pattern="[%d{HH:mm:ss}] [%t/%highlight{%level}]: %highlightError{%msg{nolookups}%n%xEx{filters(${sponge.exceptionFiltered})}}"/> diff --git a/vanilla/src/applaunch/resources/log4j2_dev.xml b/vanilla/src/applaunch/resources/log4j2_dev.xml index a3cff500bda..b38cd867887 100644 --- a/vanilla/src/applaunch/resources/log4j2_dev.xml +++ b/vanilla/src/applaunch/resources/log4j2_dev.xml @@ -1,7 +1,6 @@ - StyleMapName=Spock Name=reset,red NameMessageSeparator=red Message=red StackTraceElement.ClassName=red StackTraceElement.ClassMethodSeparator=red,faint StackTraceElement.MethodName=yellow StackTraceElement.NativeMethod=yellow @@ -9,10 +8,10 @@ + defaultPattern="[%d{HH:mm:ss}] [%t/%highlight{%level}] [%c{1.3}%notEmpty{/%markerSimpleName}]: %highlightError{%msg{nolookups}%n%xEx{filters(${sponge.exceptionFiltered})}}"> + pattern="[%d{HH:mm:ss}] [%t/%highlight{%level}]: %highlightError{%msg{nolookups}%n%xEx{filters(${sponge.exceptionFiltered})}}"/> From dd709d7b91e12fa817b43786f02939ae79350ccc Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 14 Jan 2026 14:27:46 +0100 Subject: [PATCH 456/586] Verification metadata: trust .pom and .module files --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index bac1ffcd279..709dfa70d43 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit bac1ffcd279fde20eddc6dbbbee0f46a3daf61b4 +Subproject commit 709dfa70d43027c5bef5a203ecef45e8f0e36db7 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2153ea23c80..44285b3f3b9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -21,6 +21,8 @@ + + From 0e4ed55b3872f640cde9d2a0eb55dfb79a07b9a3 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 14 Jan 2026 10:59:29 +0100 Subject: [PATCH 457/586] Update log4j to 2.25.2 --- SpongeAPI | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 709dfa70d43..5686ae7b511 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 709dfa70d43027c5bef5a203ecef45e8f0e36db7 +Subproject commit 5686ae7b5118b1f277afda034e032259c374d3cf diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 09883d63445..5fd2b37997b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ format = { version = "1.1" } # See SpongeAPI's gradle/libs.versions.toml for many dependency declarations that Sponge also uses [versions] asm = "9.8" -log4j = "2.24.1" +log4j = "2.25.2" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" mixinextras = "0.5.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 44285b3f3b9..3ddcf5cbf1f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1051,6 +1051,9 @@ + + + @@ -8319,6 +8322,14 @@ + + + + + + + + From f20192d38a63cf1cabe61077704b618e820c7bbd Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 14 Jan 2026 16:22:35 +0200 Subject: [PATCH 458/586] Fix vanish not sending packets to self --- .../common/data/datasync/VanishedFilteringSynchronizer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java index 4e8b863a9ff..0219107c052 100644 --- a/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java +++ b/src/main/java/org/spongepowered/common/data/datasync/VanishedFilteringSynchronizer.java @@ -54,6 +54,8 @@ public void sendToTrackingPlayersAndSelf(Packet Date: Wed, 14 Jan 2026 16:23:09 +0200 Subject: [PATCH 459/586] Fix overworld world border not updating visually --- .../common/mixin/core/server/MinecraftServerMixin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index a854ee810ec..3e2b3b8141f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -246,9 +246,10 @@ public Subject subject() { } @Redirect(method = "createLevels", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/Registry;entrySet()Ljava/util/Set;")) - private Set impl$onCreateOtherLevels(final Registry stemRegistry) { + private Set, LevelStem>> impl$onCreateOtherLevels(final Registry stemRegistry) { this.worldManager().createNonDefaultLevels(); - return Set.of(); // prevent vanilla code + // prevent vanilla code, except for the overworld as its special cased + return Set.of(Map.entry(LevelStem.OVERWORLD, stemRegistry.getValueOrThrow(LevelStem.OVERWORLD))); } @WrapMethod(method = "setInitialSpawn") From 6fa047b656a33ae62d69120a6f227f1f68e95f90 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 14 Jan 2026 16:24:22 +0200 Subject: [PATCH 460/586] Fix dimension type check on world creation --- .../spongepowered/common/world/server/SpongeWorldManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index c3a9249a9f1..39a9dd227b5 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -887,11 +887,12 @@ private ServerLevel createLevel( final PrimaryLevelData levelData) { final ResourceKey worldKey = (ResourceKey) (Object) registryKey.location(); + final Registry dimensionTypes = this.server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); final List spawners; - if (levelStem.type().is(BuiltinDimensionTypes.OVERWORLD) || levelStem.type().is(BuiltinDimensionTypes.OVERWORLD_CAVES)) { + if (levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD) || levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD_CAVES)) { spawners = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(levelData)); } else { spawners = ImmutableList.of(); From ad2c57443cec6657c1e823a92b82175a973f9279 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 14 Jan 2026 21:54:40 +0200 Subject: [PATCH 461/586] Separate player rotate & move events to match vanilla --- .../ServerGamePacketListenerImplMixin.java | 106 ++++++++---------- 1 file changed, 45 insertions(+), 61 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 90495ff6d64..d86e168a27f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -118,7 +118,6 @@ import org.spongepowered.math.vector.Vector3d; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -208,56 +207,63 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack @Inject(method = "handleMovePlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ServerboundMovePlayerPacket;getYRot(F)F"), - cancellable = true, slice = @Slice( - // TODO - confirm we are injecting at the right spot given the subtle changes from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;hasClientLoaded()Z"), to = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z"))) - private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) { - final boolean fireMoveEvent = packetIn.hasPosition(); - final boolean fireRotationEvent = packetIn.hasRotation(); + private void impl$callRotateEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) { + if (!packetIn.hasRotation()) { + return; + } + + final ServerPlayer player = (ServerPlayer) this.player; + final Vector3d fromRotation = player.rotation(); + + final Vector3d originalToRotation = new Vector3d(packetIn.getXRot(this.player.getXRot()), + packetIn.getYRot(this.player.getYRot()), 0); + + @Nullable Vector3d toRotation = SpongeCommonEventFactory.callRotateEvent( + player, + fromRotation, + originalToRotation); + + if (toRotation == null) { + toRotation = fromRotation; + } - // During login, minecraft sends a packet containing neither the 'moving' or 'rotating' flag set - but only once. - // We don't fire an event to avoid confusing plugins. - if (!fireMoveEvent && !fireRotationEvent) { + if (!toRotation.equals(originalToRotation)) { + this.player.forceSetRotation((float) toRotation.y(), false, (float) toRotation.x(), false); + + ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$yRot((float) toRotation.y()); + ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$xRot((float) toRotation.x()); + ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$hasRot(true); + } + } + + @Inject(method = "handleMovePlayer", + at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ServerboundMovePlayerPacket;getX(D)D"), + cancellable = true, + slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;updateAwaitingTeleport()Z"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isPassenger()Z"))) + private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) { + if (!packetIn.hasPosition()) { return; } final ServerPlayer player = (ServerPlayer) this.player; final Vector3d fromPosition = player.position(); - final Vector3d fromRotation = player.rotation(); final Vector3d originalToPosition = new Vector3d(packetIn.getX(this.player.getX()), packetIn.getY(this.player.getY()), packetIn.getZ(this.player.getZ())); - final Vector3d originalToRotation = new Vector3d(packetIn.getXRot(this.player.getXRot()), - packetIn.getYRot(this.player.getYRot()), 0); // common checks and throws are done here. final @Nullable Vector3d toPosition; - if (fireMoveEvent) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.NATURAL); - toPosition = SpongeCommonEventFactory.callMoveEvent( - player, - fromPosition, - originalToPosition); - } - } else { - toPosition = originalToPosition; - } - - // Rotation result - Vector3d toRotation; - if (fireRotationEvent) { - toRotation = SpongeCommonEventFactory.callRotateEvent( + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.NATURAL); + toPosition = SpongeCommonEventFactory.callMoveEvent( player, - fromRotation, - originalToRotation); - if (toRotation == null) { - toRotation = fromRotation; - } - } else { - toRotation = originalToRotation; + fromPosition, + originalToPosition); } // At this point, we cancel out and let the "confirmed teleport" code run through to update the @@ -266,15 +272,12 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // This will both cancel the movement and notify the client about the new rotation if any. // The position is absolute so the momentum will be reset by the client. // The rotation is relative so the head movement is still smooth. - // The client thinks its current rotation is originalToRotation so the new rotation is relative to that. - // The rotation values can be out of "valid" range so set them directly to the same value the client has. this.player.absSnapTo(fromPosition.x(), fromPosition.y(), fromPosition.z()); - this.player.setXRot((float) originalToRotation.x()); - this.player.setYRot((float) originalToRotation.y()); this.shadow$teleport(new PositionMoveRotation( VecHelper.toVanillaVector3d(fromPosition), Vec3.ZERO, - (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) + 0, + 0 ), Relative.ROTATION ); @@ -287,34 +290,15 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack // Notify the client about the new position and new rotation. // Both are relatives so the client will keep its momentum. // The client thinks its current position is originalToPosition so the new position is relative to that. - // The rotation values can be out of "valid" range so set them directly to the same value the client has. this.player.absSnapTo(originalToPosition.x(), originalToPosition.y(), originalToPosition.z()); - this.player.setXRot((float) originalToRotation.x()); - this.player.setYRot((float) originalToRotation.y()); this.shadow$teleport(new PositionMoveRotation( VecHelper.toVanillaVector3d(toPosition.sub(originalToPosition)), Vec3.ZERO, - (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) + 0, + 0 ), Relative.ALL); ci.cancel(); - } else if (!toRotation.equals(originalToRotation)) { - // Notify the client about the new rotation. - // Both are relatives so the client will keep its momentum. - // The rotation values can be out of "valid" range so set them directly to the same value the client has. - this.player.setXRot((float) originalToRotation.x()); - this.player.setYRot((float) originalToRotation.y()); - this.shadow$teleport(new PositionMoveRotation( - Vec3.ZERO, - Vec3.ZERO, - (float) (toRotation.y() - originalToRotation.y()), (float) (toRotation.x() - originalToRotation.x()) - ), - EnumSet.of(Relative.X, Relative.Y, Relative.Z, Relative.X_ROT, Relative.Y_ROT, Relative.DELTA_X, Relative.DELTA_Y, Relative.DELTA_Z)); - - // Let MC handle the movement but override the rotation. - ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$yRot((float) toRotation.y()); - ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$xRot((float) toRotation.x()); - ((ServerboundMovePlayerPacketAccessor) packetIn).accessor$hasRot(true); } } From db64d33efd2e08260c851047ab61f85a68e1acca Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 16 Jan 2026 20:12:58 +0200 Subject: [PATCH 462/586] Replace brittle ModifyVariable's with Expression in PlayerMixin_Attack --- .../entity/player/PlayerMixin_Attack.java | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index af6d938388c..be4657cb1ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.core.world.entity.player; +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; @@ -50,7 +52,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.world.entity.TrackedAttackBridge; @@ -79,8 +80,9 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return this.attack$trackers.peekLast(); } - @ModifyVariable(method = "attack", at = @At("LOAD"), - slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F", ordinal = 0))) + @Definition(id = "getEnchantedDamage", method = "Lnet/minecraft/world/entity/player/Player;getEnchantedDamage(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F") + @Expression("? = this.getEnchantedDamage(?, @(?), ?) - ?") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION")) private float attack$firePreEvent(final float damage, @Local(argsOnly = true) final Entity target, @Local final DamageSource source, @Local final ItemStack weapon, final @Cancellable CallbackInfo ci) { final SpongeAttackTracker tracker = SpongeAttackTracker.callAttackPreEvent((org.spongepowered.api.entity.Entity) target, source, damage, weapon); if (tracker == null) { @@ -101,36 +103,36 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return value; } - @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") - )) + @Expression("? = @(?) * (0.2 + ? * ? * 0.8)") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION")) private float attack$modifyBeforeBaseCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null ? damage : tracker.startStep(DamageStepTypes.BASE_COOLDOWN, damage, this); } - @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") - )) + @Expression("? = @(? * (0.2 + ? * ? * 0.8))") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION")) private float attack$modifyAfterBaseCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null ? damage : tracker.endStep(DamageStepTypes.BASE_COOLDOWN, damage); } - @ModifyVariable(method = "attack", at = @At("LOAD"), ordinal = 1, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + @Expression("? = @(?) * ?") + @Expression(id = "from", value = "? = ? * (0.2 + ? * ? * 0.8)") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( + from = @At(value = "MIXINEXTRAS:EXPRESSION", id = "from"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V") )) private float attack$modifyBeforeEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); return tracker == null ? damage : tracker.startStep(DamageStepTypes.ENCHANTMENT_COOLDOWN, damage, tracker.weaponSnapshot()); } - @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 1, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAttackStrengthScale(F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;") + @Expression("? = @(? * ?)") + @Expression(id = "from", value = "? = ? * (0.2 + ? * ? * 0.8)") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( + from = @At(value = "MIXINEXTRAS:EXPRESSION", id = "from"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V") )) private float attack$modifyAfterEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -162,8 +164,9 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return (float) step.applyChildrenAfter(damage) - originalDamage; } - @ModifyVariable(method = "attack", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), + @Expression("? = @(?) * 1.5") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") )) private float attack$modifyBeforeCriticalHit(final float damage) { @@ -171,8 +174,9 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return tracker == null ? damage : tracker.startStep(DamageStepTypes.CRITICAL_HIT, damage, this); } - @ModifyVariable(method = "attack", at = @At("STORE"), ordinal = 0, slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSprinting()Z", ordinal = 1), + @Expression("? = @(? * 1.5)") + @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") )) private float attack$modifyAfterCriticalHit(final float damage) { From 44fa83a39961de6e7e4086ffe18c14590c72c124 Mon Sep 17 00:00:00 2001 From: aromaa Date: Fri, 16 Jan 2026 21:29:15 +0200 Subject: [PATCH 463/586] Fix Forge & Neo injections Missed the subtle differences --- .../core/world/entity/player/PlayerMixin_Attack.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index be4657cb1ae..bc766f62fe5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -45,6 +45,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.checkerframework.checker.nullness.qual.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.api.event.entity.AttackEntityEvent; import org.spongepowered.asm.mixin.Final; @@ -121,7 +122,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @Expression(id = "from", value = "? = ? * (0.2 + ? * ? * 0.8)") @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( from = @At(value = "MIXINEXTRAS:EXPRESSION", id = "from"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V") + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;", opcode = Opcodes.GETSTATIC) )) private float attack$modifyBeforeEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -132,7 +133,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem @Expression(id = "from", value = "? = ? * (0.2 + ? * ? * 0.8)") @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( from = @At(value = "MIXINEXTRAS:EXPRESSION", id = "from"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V") + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/EntityTypeTags;REDIRECTABLE_PROJECTILE:Lnet/minecraft/tags/TagKey;", opcode = Opcodes.GETSTATIC) )) private float attack$modifyAfterEnchantmentCooldown(final float damage) { final SpongeAttackTracker tracker = this.attack$tracker(); @@ -164,7 +165,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return (float) step.applyChildrenAfter(damage) - originalDamage; } - @Expression("? = @(?) * 1.5") + @Expression("? = @(?) * ?") @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") @@ -174,7 +175,7 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem return tracker == null ? damage : tracker.startStep(DamageStepTypes.CRITICAL_HIT, damage, this); } - @Expression("? = @(? * 1.5)") + @Expression("? = @(? * ?)") @ModifyExpressionValue(method = "attack", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;getAttackDamageBonus(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;horizontalDistanceSqr()D") From 7ee6c652e026566e1235f0764af0064193185e5a Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 20 Jan 2026 21:54:55 +0100 Subject: [PATCH 464/586] Update badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e76e13f6f01..2dd894ee81b 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) +[![SpongeVanilla 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) +[![SpongeForge 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.10](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.10&queryOpt=%3Aversion%3D1.21.10-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.10-*) +[![SpongeNeo 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) ## Prerequisites From 638270676cab9793361d4047e708a9fe43affbd9 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 20 Jan 2026 22:30:50 +0100 Subject: [PATCH 465/586] Bump Forge and NeoForge versions --- forge/gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 56 ++++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 1ca22cd4a56..13366137a4c 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=61.0.1 +forgeVersion=61.0.6 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5fd2b37997b..3649a369491 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ mixin = "0.8.7" mixinextras = "0.5.0" modlauncher = "10.2.3" securemodules = "2.2.22" -fancymodloader = "10.0.32" +fancymodloader = "10.0.36" jarjar = "0.3.26" guava = "32.1.2-jre" mockito = "5.11.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3ddcf5cbf1f..0fd464a1a90 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4957,6 +4957,11 @@ + + + + + @@ -5131,6 +5136,11 @@ + + + + + @@ -5305,6 +5315,11 @@ + + + + + @@ -5565,6 +5580,11 @@ + + + + + @@ -5672,6 +5692,11 @@ + + + + + @@ -5846,6 +5871,11 @@ + + + + + @@ -6028,6 +6058,11 @@ + + + + + @@ -6810,6 +6845,17 @@ + + + + + + + + + + + @@ -6970,6 +7016,11 @@ + + + + + @@ -7090,6 +7141,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 96389732664..f6da24fbfff 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.11.3-beta +neoForgeVersion=21.11.36-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From bce318c5a28f7ae52feb7c04c490f790134c57b9 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Feb 2026 08:11:43 -0800 Subject: [PATCH 466/586] feature(minecraft): update to 26.1-snapshot-2 Notable changes: ChunkPos is a record --- gradle.properties | 2 +- .../common/event/tracking/PhaseTracker.java | 6 ++--- .../effect/UpdateChunkLightManagerEffect.java | 4 ++-- .../spongepowered/common/util/VecHelper.java | 2 +- .../world/level/chunk/SpongeEmptyChunk.java | 2 +- .../world/level/chunk/SpongeOfflineChunk.java | 2 +- .../world/server/SpongeWorldManager.java | 2 +- .../world/volume/VolumeStreamUtils.java | 22 +++++++++---------- .../server/level/ServerLevelMixin_API.java | 4 ++-- .../level/chunk/ChunkAccessMixin_API.java | 2 +- .../level/chunk/LevelChunkMixin_API.java | 4 ++-- .../structure/StructureMixin_API.java | 2 +- .../world/ticks/LevelTicksMixin_API.java | 4 ++-- .../server/level/DistanceManagerMixin.java | 2 +- .../world/level/chunk/LevelChunkMixin.java | 8 +++---- .../level/chunk/storage/IOWorkerMixin.java | 4 ++-- .../EntityActivationRange.java | 2 +- 17 files changed, 37 insertions(+), 37 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5aa5e1d46bc..55c6546af72 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-1 +minecraftVersion=26.1-snapshot-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index eae4de2cdbf..5751ccd5f6b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -194,7 +194,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world if (useTile) { blockIn = source.getBlockState().getBlock(); } else { - blockIn = (pos.getX() >> 4 == chunk.getPos().x && pos.getZ() >> 4 == chunk.getPos().z) + blockIn = (pos.getX() >> 4 == chunk.getPos().x() && pos.getZ() >> 4 == chunk.getPos().z()) ? chunk.getBlockState(pos).getBlock() : worldServer.getBlockState(pos).getBlock(); } @@ -202,7 +202,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world PhasePrinter.printNullSourceBlockWithTile(pos, blockIn, otherPos, id, useTile, new NullPointerException("Null Source Block For TileEntity Neighbor Notification")); } } else { - blockIn = (pos.getX() >> 4 == chunk.getPos().x && pos.getZ() >> 4 == chunk.getPos().z) + blockIn = (pos.getX() >> 4 == chunk.getPos().x() && pos.getZ() >> 4 == chunk.getPos().z()) ? chunk.getBlockState(pos).getBlock() : worldServer.getBlockState(pos).getBlock(); if (trackerConfig.reportNullSourceBlocksOnNeighborNotifications) { @@ -212,7 +212,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world } } else { - blockIn = (pos.getX() >> 4 == chunk.getPos().x && pos.getZ() >> 4 == chunk.getPos().z) + blockIn = (pos.getX() >> 4 == chunk.getPos().x() && pos.getZ() >> 4 == chunk.getPos().z()) ? chunk.getBlockState(pos).getBlock() : worldServer.getBlockState(pos).getBlock(); if (trackerConfig.reportNullSourceBlocksOnNeighborNotifications) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java index d9542f7b7a4..4117eb9ee03 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateChunkLightManagerEffect.java @@ -67,8 +67,8 @@ public static UpdateChunkLightManagerEffect getInstance() { final var source = pipeline.getServerWorld().getChunkSource(); source.getLightEngine().updateSectionStatus(oldState.pos(), isStillEmpty); final var sectionPos = SectionPos.blockToSectionCoord(blockY); - final var chunkX = chunk.getPos().x; - final var chunkZ = chunk.getPos().z; + final var chunkX = chunk.getPos().x(); + final var chunkZ = chunk.getPos().z(); source.onSectionEmptinessChanged(chunkX, sectionPos, chunkZ, isStillEmpty); } return EffectResult.nullPass(); diff --git a/src/main/java/org/spongepowered/common/util/VecHelper.java b/src/main/java/org/spongepowered/common/util/VecHelper.java index e484d39761d..50c2bbf08e7 100644 --- a/src/main/java/org/spongepowered/common/util/VecHelper.java +++ b/src/main/java/org/spongepowered/common/util/VecHelper.java @@ -153,7 +153,7 @@ public static Vector3i toVector3i(final ChunkPos pos) { if (pos == null) { return null; } - return new Vector3i(pos.x, 0, pos.z); + return new Vector3i(pos.x(), 0, pos.z()); } // === Flow Vector3i --> MC ChunkPos === diff --git a/src/main/java/org/spongepowered/common/world/level/chunk/SpongeEmptyChunk.java b/src/main/java/org/spongepowered/common/world/level/chunk/SpongeEmptyChunk.java index d6efe44e263..f425c3ac256 100644 --- a/src/main/java/org/spongepowered/common/world/level/chunk/SpongeEmptyChunk.java +++ b/src/main/java/org/spongepowered/common/world/level/chunk/SpongeEmptyChunk.java @@ -124,7 +124,7 @@ public Vector3i max() { @Override public Vector3i chunkPosition() { final ChunkPos pos = this.chunk.getPos(); - return new Vector3i(pos.x, 0, pos.z); + return new Vector3i(pos.x(), 0, pos.z()); } @Override diff --git a/src/main/java/org/spongepowered/common/world/level/chunk/SpongeOfflineChunk.java b/src/main/java/org/spongepowered/common/world/level/chunk/SpongeOfflineChunk.java index d5a720b3142..362352822aa 100644 --- a/src/main/java/org/spongepowered/common/world/level/chunk/SpongeOfflineChunk.java +++ b/src/main/java/org/spongepowered/common/world/level/chunk/SpongeOfflineChunk.java @@ -60,7 +60,7 @@ public static OfflineChunk of(final RegionFile regionFile, final ChunkPos pos) { throw new RuntimeException(e); } - return new SpongeOfflineChunk(chunkNbt, pos.x, pos.z); + return new SpongeOfflineChunk(chunkNbt, pos.x(), pos.z()); } @Override diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index d0205af8d05..f0420bbbda6 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -1031,7 +1031,7 @@ private static void updateForcedChunks(final ServerLevel level, final ServerChun while (longIterator.hasNext()) { final long i = longIterator.nextLong(); - final ChunkPos forceChunkPos = new ChunkPos(i); + final ChunkPos forceChunkPos = ChunkPos.unpack(i); serverChunkProvider.updateChunkForced(forceChunkPos, true); } } diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index 25acbf278bd..41c51879d30 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -147,7 +147,7 @@ public static Predicate filterPositions(final Function pos, final ChunkStatus chunkStatus = shouldGenerate ? ChunkStatus.FULL : ChunkStatus.EMPTY; - final @Nullable ChunkAccess ichunk = readerSupplier.get().getChunk(chunkPos.x, chunkPos.z, chunkStatus, shouldGenerate); + final @Nullable ChunkAccess ichunk = readerSupplier.get().getChunk(chunkPos.x(), chunkPos.z(), chunkStatus, shouldGenerate); if (shouldGenerate) { Objects.requireNonNull(ichunk, "Chunk was expected to load fully and generate, but somehow got a null chunk!"); } @@ -224,14 +224,14 @@ public static void validateStreamArgs(final Vector3i min, final Vector3i max, fi ) { if (chunk.getLevel() instanceof ServerLevel) { return ((PersistentEntitySectionManagerAccessor) ((ServerLevelAccessor) chunk.getLevel()).accessor$getEntityManager()).accessor$sectionStorage() - .getExistingSectionsInChunk(chunk.getPos().toLong()) + .getExistingSectionsInChunk(chunk.getPos().pack()) .flatMap(EntitySection::getEntities) .filter(entity -> VecHelper.inBounds(entity.blockPosition(), min, max)) .map(entity -> new AbstractMap.SimpleEntry<>(entity.blockPosition(), entity)); } else if (Sponge.isClientAvailable() && chunk.getLevel() instanceof ClientLevel) { return ((TransientEntitySectionManagerAccessor) ((ClientLevelAccessor) chunk.getLevel()).accessor$getEntityStorage()) .accessor$sectionStorage() - .getExistingSectionsInChunk(chunk.getPos().toLong()) + .getExistingSectionsInChunk(chunk.getPos().pack()) .flatMap(EntitySection::getEntities) .filter(entity -> VecHelper.inBounds(entity.blockPosition(), min, max)) .map(entity -> new AbstractMap.SimpleEntry<>(entity.blockPosition(), entity)); @@ -380,9 +380,9 @@ private static QuadFunction chunkSectionBlockStateGetter() { return ((chunk, chunkSection, pos) -> chunkSection.getBlockState( - pos.getX() - (chunk.getPos().x << 4), + pos.getX() - (chunk.getPos().x() << 4), pos.getY() & 15, - pos.getZ() - (chunk.getPos().z << 4))); + pos.getZ() - (chunk.getPos().z() << 4))); } private static Function>> getElementByPosition( @@ -396,13 +396,13 @@ private static Function>> getElem return chunk -> { final ChunkPos pos = chunk.getPos(); - final int xStart = pos.x == minCursor.chunkX ? minCursor.xOffset : 0; - final int xEnd = pos.x == maxCursor.chunkX ? maxCursor.xOffset : 15; - final int zStart = pos.z == minCursor.chunkZ ? minCursor.zOffset : 0; - final int zEnd = pos.z == maxCursor.chunkZ ? maxCursor.zOffset : 15; + final int xStart = pos.x() == minCursor.chunkX ? minCursor.xOffset : 0; + final int xEnd = pos.x() == maxCursor.chunkX ? maxCursor.xOffset : 15; + final int zStart = pos.z() == minCursor.chunkZ ? minCursor.zOffset : 0; + final int zEnd = pos.z() == maxCursor.chunkZ ? maxCursor.zOffset : 15; - final int chunkMinX = pos.x << 4; - final int chunkMinZ = pos.z << 4; + final int chunkMinX = pos.x() << 4; + final int chunkMinZ = pos.z() << 4; final LevelChunkSection[] sections = chunk.getSections(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 3e743c7b442..ff77c80f070 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -394,7 +394,7 @@ public Stream chunkPositions() { return this.api$chunkPosStream((regionFile, stream) -> // stream.filter(regionFile::doesChunkExist) // filter out non-existent chunks stream.filter(cp -> ((RegionFileBridge) regionFile).bridge$doesChunkExist(cp)) // filter out non-existent chunks - .map(cp -> new Vector3i(cp.x, 0, cp.z)) // map to API type + .map(cp -> new Vector3i(cp.x(), 0, cp.z())) // map to API type ); } @@ -418,6 +418,6 @@ public Stream offlineChunks() { final int ry = Integer.parseInt(split[2]); final ChunkPos min = ChunkPos.minFromRegion(rx, ry); final ChunkPos max = ChunkPos.maxFromRegion(rx, ry); - return new Vector4i(min.x, min.z, max.x, max.z); + return new Vector4i(min.x(), min.z(), max.x(), max.z()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java index f1ea1749899..d9d10bcb485 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/ChunkAccessMixin_API.java @@ -116,7 +116,7 @@ public void setInhabitedTime(final Ticks newInhabitedTime) { @Override public Vector3i chunkPosition() { final ChunkPos chunkPos = this.shadow$getPos(); - return new Vector3i(chunkPos.x, 0, chunkPos.z); + return new Vector3i(chunkPos.x(), 0, chunkPos.z()); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index 1c70a77c8e5..db9845f52eb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -173,7 +173,7 @@ public void setInhabitedTime(final Ticks newInhabitedTime) { @Override public Vector3i chunkPosition() { - return new Vector3i(this.chunkPos.x, 0, this.chunkPos.z); + return new Vector3i(this.chunkPos.x(), 0, this.chunkPos.z()); } @Override @@ -435,7 +435,7 @@ public Optional entity(final UUID uuid) { public Collection entities() { final PersistentEntitySectionManager entityManager = ((ServerLevelAccessor) this.level).accessor$getEntityManager(); final EntitySectionStorage entitySectionStorage = ((PersistentEntitySectionManagerAccessor) entityManager).accessor$sectionStorage(); - return (Collection) entitySectionStorage.getExistingSectionsInChunk(this.chunkPos.toLong()).flatMap(EntitySection::getEntities).toList(); + return (Collection) entitySectionStorage.getExistingSectionsInChunk(this.chunkPos.pack()).flatMap(EntitySection::getEntities).toList(); } @SuppressWarnings({"rawtypes", "unchecked"}) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java index 14e1d805aed..9f7163ca9c8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/StructureMixin_API.java @@ -88,7 +88,7 @@ public boolean place(final ServerWorld world, final Vector3i pos) { chunkSource.randomState(), level.getStructureManager(), level.getSeed(), - new ChunkPos(VecHelper.toBlockPos(pos)), + ChunkPos.containing(VecHelper.toBlockPos(pos)), 0, level, ignored -> true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/ticks/LevelTicksMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/ticks/LevelTicksMixin_API.java index fe317db6684..24ca4fe3f8a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/ticks/LevelTicksMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/ticks/LevelTicksMixin_API.java @@ -85,7 +85,7 @@ public ScheduledUpdate schedule( final var subCount = level.nextSubTickCount(); final var scheduledUpdate = new ScheduledTick<>( target, blockPos, tickDelay.ticks() + gameTime, (TickPriority) (Object) priority, subCount); - if (this.tickCheck.test(ChunkPos.asLong(blockPos))) { + if (this.tickCheck.test(ChunkPos.pack(blockPos))) { this.shadow$schedule(scheduledUpdate); } return (ScheduledUpdate) (Object) scheduledUpdate; @@ -102,7 +102,7 @@ public Collection> scheduledAt(final int x, final i if (!this.alreadyRunThisTick.isEmpty()) { return Collections.emptySet(); } - final long longPos = ChunkPos.asLong(new BlockPos(x, y, z)); + final long longPos = ChunkPos.pack(new BlockPos(x, y, z)); final LevelChunkTicks $$2 = this.allContainers.get(longPos); return $$2.getAll() diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java index f3ea9e10d29..512e317baa7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/DistanceManagerMixin.java @@ -101,7 +101,7 @@ public abstract class DistanceManagerMixin implements DistanceManagerBridge { final int distance = Mth.clamp(Constants.ChunkTicket.MAX_FULL_CHUNK_DISTANCE - distanceLimit, 0, Constants.ChunkTicket.MAX_FULL_CHUNK_TICKET_LEVEL); final TicketType type = (TicketType) (Object) ticketType; final net.minecraft.server.level.Ticket ticketToRequest = new net.minecraft.server.level.Ticket(type, distance); - this.ticketStorage.addTicket(VecHelper.toChunkPos(pos).toLong(), ticketToRequest); + this.ticketStorage.addTicket(VecHelper.toChunkPos(pos).pack(), ticketToRequest); return Optional.of(((TicketBridge) (Object) ticketToRequest).bridge$retrieveAppropriateTicket()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java index 57beb5d15f5..7d68de8b86c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/LevelChunkMixin.java @@ -113,7 +113,7 @@ public LevelChunkMixin(ChunkPos $$0, UpgradeData $$1, LevelHeightAccessor $$2, P private void impl$onConstruct(final Level $$0, final ChunkPos $$1, final UpgradeData $$2, final LevelChunkTicks $$3, final LevelChunkTicks $$4, final long $$5, final LevelChunkSection[] $$6, final LevelChunk.PostLoadProcessor $$7, final BlendingData $$8, final CallbackInfo ci) { - this.impl$cacheKey = ChunkPos.asLong($$1.x, $$1.z); + this.impl$cacheKey = $$1.pack(); } @Override @@ -128,7 +128,7 @@ public LevelChunkMixin(ChunkPos $$0, UpgradeData $$1, LevelHeightAccessor $$2, P @Override public boolean bridge$isQueuedForUnload() { - return ((ChunkMapAccessor) ((ServerChunkCache) this.level.getChunkSource()).chunkMap).accessor$pendingUnloads().containsKey(this.chunkPos.toLong()); + return ((ChunkMapAccessor) ((ServerChunkCache) this.level.getChunkSource()).chunkMap).accessor$pendingUnloads().containsKey(this.chunkPos.pack()); } @Override @@ -355,7 +355,7 @@ public LevelChunkMixin(ChunkPos $$0, UpgradeData $$1, LevelHeightAccessor $$2, P public String toString() { return new StringJoiner(", ", LevelChunkMixin.class.getSimpleName() + "[", "]") .add("World=" + this.level) - .add("Position=" + this.chunkPos.x + ":" + this.chunkPos.z) + .add("Position=" + this.chunkPos.x() + ":" + this.chunkPos.z()) .add("super=" + super.toString()) .toString(); } @@ -369,7 +369,7 @@ public String toString() { public boolean bridge$spawnEntity(final org.spongepowered.api.entity.Entity entity) { final net.minecraft.world.entity.Entity mcEntity = (net.minecraft.world.entity.Entity) entity; final BlockPos blockPos = mcEntity.blockPosition(); - if (this.chunkPos.x == blockPos.getX() >> 4 && this.chunkPos.z == blockPos.getZ() >> 4) { + if (this.chunkPos.x() == blockPos.getX() >> 4 && this.chunkPos.z() == blockPos.getZ() >> 4) { // Calling addEntity on the chunk only adds them to storage, // we need to redirect this to add to the world. // diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java index dae1f194012..80794617996 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/chunk/storage/IOWorkerMixin.java @@ -99,7 +99,7 @@ public abstract class IOWorkerMixin implements IOWorkerBridge { private void impl$onSaved(final ChunkPos param0, final @Coerce Object param1, final CallbackInfo ci) { if (this.impl$type == SpongeIOWorkerType.CHUNK) { if (ShouldFire.CHUNK_EVENT_BLOCKS_SAVE_POST) { - final Vector3i chunkPos = new Vector3i(param0.x, 0, param0.z); + final Vector3i chunkPos = new Vector3i(param0.x(), 0, param0.z()); final ChunkEvent.Blocks.Save.Post postSave = SpongeEventFactory.createChunkEventBlocksSavePost(PhaseTracker.getInstance().currentCause(), chunkPos, (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.identifier()); SpongeCommon.post(postSave); @@ -107,7 +107,7 @@ public abstract class IOWorkerMixin implements IOWorkerBridge { } else if (this.impl$type == SpongeIOWorkerType.ENTITY) { if (ShouldFire.CHUNK_EVENT_ENTITIES_SAVE_POST) { - final Vector3i chunkPos = new Vector3i(param0.x, 0, param0.z); + final Vector3i chunkPos = new Vector3i(param0.x(), 0, param0.z()); final ChunkEvent.Entities.Save.Post postSave = SpongeEventFactory.createChunkEventEntitiesSavePost(PhaseTracker.getInstance().currentCause(), chunkPos, (org.spongepowered.api.ResourceKey) (Object) this.impl$dimension.identifier()); SpongeCommon.post(postSave); diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java index 381d1dd41ed..7d6585433cc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/entityactivation/EntityActivationRange.java @@ -261,7 +261,7 @@ public static void activateEntities(final ServerLevel world) { private static void activateChunkEntities(final ServerPlayer player, final LevelChunk chunk) { final PersistentEntitySectionManager entityManager = ((ServerLevelAccessor) chunk.getLevel()).accessor$getEntityManager(); final EntitySectionStorage entitySectionStorage = ((PersistentEntitySectionManagerAccessor) entityManager).accessor$sectionStorage(); - entitySectionStorage.getExistingSectionsInChunk(chunk.getPos().toLong()).flatMap(EntitySection::getEntities).forEach(entity -> { + entitySectionStorage.getExistingSectionsInChunk(chunk.getPos().pack()).flatMap(EntitySection::getEntities).forEach(entity -> { if (!entity.chunkPosition().equals(chunk.getPos())) { return; } From beb54397519e054b9df2c09dfc41182de5c39c79 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Feb 2026 21:52:19 -0800 Subject: [PATCH 467/586] feat(minecraft): update to 26.1-snapshot-3 Notable changes: - Removed unused accessors and related packet states. - Updated `ItemStackUtil` methods to handle `ItemStackTemplate`. - Adjusted packet mappings for new `ServerboundAttackPacket`. - Updated `RegistryLoadTask` and related mixins. This is most untested, but seeing as it affects both server and client side mixins, it may need some further testing. --- gradle.properties | 2 +- gradle/verification-metadata.xml | 2 +- .../ServerboundInteractPacketAccessor.java | 36 -------- ...eractPacket_InteractionActionAccessor.java | 36 -------- ...t_InteractionAtLocationActionAccessor.java | 36 -------- ...ryDataLoader_RegistryLoadTaskAccessor.java | 37 -------- ...sourceManagerRegistryLoadTaskAccessor.java | 3 +- ...sor.java => RegistryLoadTaskAccessor.java} | 5 +- .../resources/mixins.sponge.accessors.json | 6 +- .../advancement/SpongeAdvancementBuilder.java | 2 +- .../advancement/SpongeDisplayInfoBuilder.java | 4 +- .../common/adventure/SpongeAdventure.java | 9 +- .../provider/block/state/FarmlandData.java | 10 +- .../provider/item/stack/ItemStackData.java | 12 +-- .../effect/particle/SpongeParticleHelper.java | 2 +- .../common/event/tracking/PhasePrinter.java | 5 +- .../common/event/tracking/PhaseTracker.java | 8 +- .../tracking/phase/packet/PacketPhase.java | 19 +--- .../player/AttackEntityPacketState.java | 18 ++-- .../player/InteractAtEntityPacketState.java | 92 ------------------- .../player/InteractEntityPacketState.java | 17 ++-- .../common/item/SpongeItemStack.java | 8 +- .../item/recipe/SpongeRecipeRegistration.java | 5 +- .../recipe/cooking/SpongeBlastingRecipe.java | 18 +++- .../cooking/SpongeCampfireCookingRecipe.java | 16 +++- .../cooking/SpongeCookingRecipeBuilder.java | 11 +-- .../recipe/cooking/SpongeSmeltingRecipe.java | 18 +++- .../recipe/cooking/SpongeSmokingRecipe.java | 18 +++- .../crafting/custom/SpongeSpecialRecipe.java | 3 +- .../SpongeShapedCraftingRecipeBuilder.java | 2 +- .../crafting/shaped/SpongeShapedRecipe.java | 23 ++--- .../SpongeShapelessCraftingRecipeBuilder.java | 2 +- .../shapeless/SpongeShapelessRecipe.java | 25 ++--- .../recipe/ingredient/SpongeIngredient.java | 7 +- .../recipe/smithing/SpongeSmithingRecipe.java | 11 +-- .../smithing/SpongeSmithingRecipeBuilder.java | 2 +- .../SpongeStoneCutterRecipeBuilder.java | 2 +- .../SpongeStonecuttingRecipe.java | 15 ++- .../common/item/util/ItemStackUtil.java | 25 +++-- .../world/server/SpongeWorldTypeBuilder.java | 10 +- .../world/volume/VolumeStreamUtils.java | 3 +- .../advancements/DisplayInfoMixin_API.java | 4 +- .../minecraft/world/item/ItemMixin_API.java | 20 ++-- .../world/item/ItemStackMixin_API.java | 1 - .../world/item/crafting/RecipeMixin_API.java | 6 +- .../level/chunk/LevelChunkMixin_API.java | 4 +- .../level/storage/LevelDataMixin_API.java | 4 +- .../storage/ServerLevelDataMixin_API.java | 22 ++++- .../resources/RegistryDataLoaderMixin.java | 16 +++- .../core/server/level/ServerPlayerMixin.java | 4 +- .../ServerGamePacketListenerImplMixin.java | 35 +++++++ .../ServerGamePacketListenerImpl_1Mixin.java | 84 ----------------- .../core/world/entity/LivingEntityMixin.java | 9 ++ .../entity/npc/villager/VillagerMixin.java | 18 ---- .../core/world/entity/player/PlayerMixin.java | 4 +- .../mixin/core/world/item/ItemStackMixin.java | 2 +- .../item/crafting/ShapedRecipeMixin.java | 8 +- .../item/crafting/ShapelessRecipeMixin.java | 6 +- .../item/crafting/SingleItemRecipeMixin.java | 6 +- .../SmithingTransformRecipeMixin.java | 10 +- .../world/level/block/FarmBlockMixin.java | 6 +- .../AbstractFurnaceBlockEntityMixin.java | 2 +- ...erBlockBlockEntityMixin_Inventory_API.java | 2 +- src/mixins/resources/mixins.sponge.core.json | 1 - ...actFurnaceBlockEntityAccessor_Vanilla.java | 3 +- .../RegistryDataLoaderMixin_Vanilla.java | 51 ++++++---- ...eloadableServerResourcesMixin_Vanilla.java | 17 ++-- ...stractFurnaceBlockEntityMixin_Vanilla.java | 62 ++++++++----- 68 files changed, 401 insertions(+), 591 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacketAccessor.java delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionActionAccessor.java delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionAtLocationActionAccessor.java delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java rename src/accessors/java/org/spongepowered/common/accessor/resources/{RegistryDataLoader_LoaderAccessor.java => RegistryLoadTaskAccessor.java} (92%) delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractAtEntityPacketState.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImpl_1Mixin.java diff --git a/gradle.properties b/gradle.properties index 55c6546af72..17b37283158 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-2 +minecraftVersion=26.1-snapshot-3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 718aff0bad8..d529d949de5 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -34,8 +34,8 @@ - + diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacketAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacketAccessor.java deleted file mode 100644 index 5e9220c9a0e..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacketAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.network.protocol.game; - -import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerboundInteractPacket.class) -public interface ServerboundInteractPacketAccessor { - - @Accessor("action") ServerboundInteractPacket.Action accessor$action(); - -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionActionAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionActionAccessor.java deleted file mode 100644 index 33e1391a1d8..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionActionAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.network.protocol.game; - -import net.minecraft.world.InteractionHand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(targets = "net.minecraft.network.protocol.game.ServerboundInteractPacket$InteractionAction") -public interface ServerboundInteractPacket_InteractionActionAccessor { - - @Accessor("hand") InteractionHand accessor$hand(); - -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionAtLocationActionAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionAtLocationActionAccessor.java deleted file mode 100644 index 16b27acb95a..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/network/protocol/game/ServerboundInteractPacket_InteractionAtLocationActionAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.network.protocol.game; - -import net.minecraft.world.InteractionHand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(targets = "net.minecraft.network.protocol.game.ServerboundInteractPacket$InteractionAtLocationAction") -public interface ServerboundInteractPacket_InteractionAtLocationActionAccessor { - - @Accessor("hand") InteractionHand accessor$hand(); - -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java deleted file mode 100644 index 3b927cd1540..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_RegistryLoadTaskAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.resources; - -import net.minecraft.core.WritableRegistry; -import net.minecraft.resources.RegistryDataLoader; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(RegistryDataLoader.RegistryLoadTask.class) -public interface RegistryDataLoader_RegistryLoadTaskAccessor { - - @Accessor("registry") WritableRegistry accessor$getRegistry(); - -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java index 57eb8b7ee10..f5a2981f554 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor.java @@ -24,11 +24,12 @@ */ package org.spongepowered.common.accessor.resources; +import net.minecraft.resources.ResourceManagerRegistryLoadTask; import net.minecraft.server.packs.resources.ResourceManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(targets = "net/minecraft/resources/RegistryDataLoader$ResourceManagerRegistryLoadTask") +@Mixin(ResourceManagerRegistryLoadTask.class) public interface RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor { @Accessor("resourceManager") ResourceManager accessor$getResourceManager(); diff --git a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryLoadTaskAccessor.java similarity index 92% rename from src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/resources/RegistryLoadTaskAccessor.java index b9503c3ba0a..536d38c1ad5 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryDataLoader_LoaderAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/resources/RegistryLoadTaskAccessor.java @@ -26,11 +26,12 @@ import net.minecraft.core.WritableRegistry; import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.RegistryLoadTask; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(RegistryDataLoader.RegistryLoadTask.class) -public interface RegistryDataLoader_LoaderAccessor { +@Mixin(RegistryLoadTask.class) +public interface RegistryLoadTaskAccessor { @Accessor("data") RegistryDataLoader.RegistryData accessor$data(); diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 55755f0d9b2..2b01563879f 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -24,14 +24,10 @@ "network.chat.StyleAccessor", "network.protocol.game.ClientboundAddEntityPacketAccessor", "network.protocol.game.ClientboundPlayerInfoUpdatePacketAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor", - "network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor", - "network.protocol.game.ServerboundInteractPacketAccessor", "network.protocol.game.ServerboundMovePlayerPacketAccessor", "network.protocol.game.ServerboundMoveVehiclePacketAccessor", "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.RegistryDataLoader_LoaderAccessor", - "resources.RegistryDataLoader_RegistryLoadTaskAccessor", + "resources.RegistryLoadTaskAccessor", "resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor", "resources.ResourceKeyAccessor", "server.MinecraftServer_ReloadableResourcesAccessor", diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index 5f9dda5e4a2..b4705b771cc 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -114,7 +114,7 @@ public Advancement build() { final AdvancementRewards rewards = AdvancementRewards.EMPTY; var displayInfo = Optional.ofNullable(this.displayInfo).map(di -> new net.minecraft.advancements.DisplayInfo( - ItemStackUtil.fromSnapshotToNative(di.icon()), + ItemStackUtil.toTemplate(di.icon()), SpongeAdventure.asVanilla(di.title()), SpongeAdventure.asVanilla(di.description()), // TODO - Define how we want to expose ClientResource that is a combo of resource location and asset location diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeDisplayInfoBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeDisplayInfoBuilder.java index 0f38a02050e..c83404595b6 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeDisplayInfoBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeDisplayInfoBuilder.java @@ -26,13 +26,13 @@ import net.kyori.adventure.text.Component; -import net.minecraft.world.item.ItemStack; import org.spongepowered.api.advancement.AdvancementType; import org.spongepowered.api.advancement.AdvancementTypes; import org.spongepowered.api.advancement.DisplayInfo; import org.spongepowered.api.item.inventory.ItemStackLike; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.common.adventure.SpongeAdventure; +import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.Preconditions; import java.util.Objects; @@ -105,7 +105,7 @@ public DisplayInfo build() { final net.minecraft.network.chat.Component title = SpongeAdventure.asVanilla(this.title); final net.minecraft.network.chat.Component description = SpongeAdventure.asVanilla(this.description); final net.minecraft.advancements.AdvancementType frameType = (net.minecraft.advancements.AdvancementType) (Object) this.advancementType; - final ItemStack icon = (ItemStack) (Object) this.icon.asMutable(); + final var icon = ItemStackUtil.toTemplate(this.icon); return (DisplayInfo) new net.minecraft.advancements.DisplayInfo(icon, title, description, null, frameType, this.showToast, this.announceToChat, this.hidden); } diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 99bcf9053bc..3faa90eaf0d 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -99,7 +99,7 @@ import net.minecraft.world.BossEvent; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.component.ResolvableProfile; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -552,8 +552,8 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); yield HoverEvent.showItem( SpongeAdventure.asAdventure(stack.typeHolder().unwrap().map(ResourceKey::identifier, itemRegistry::getKey)), - stack.getCount(), - SpongeAdventure.asAdventure(stack.getComponentsPatch()) + stack.count(), + SpongeAdventure.asAdventure(stack.components()) ); case net.minecraft.network.chat.HoverEvent.ShowEntity se: final net.minecraft.network.chat.HoverEvent.EntityTooltipInfo value = se.entity(); @@ -641,8 +641,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv final HoverEvent.ShowItem value = (HoverEvent.ShowItem) event.value(); final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); final var item = Holder.direct(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))); - final var stack = new ItemStack(item, value.count(), SpongeAdventure.asVanilla(value.dataComponents())); - return new net.minecraft.network.chat.HoverEvent.ShowItem(stack); + return new net.minecraft.network.chat.HoverEvent.ShowItem(new ItemStackTemplate(item, value.count(), SpongeAdventure.asVanilla(value.dataComponents()))); } throw new IllegalArgumentException(event.toString()); } diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/FarmlandData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/FarmlandData.java index 24a93f29e8e..b72a93ef5fa 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/FarmlandData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/FarmlandData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.block.state; -import net.minecraft.world.level.block.FarmBlock; +import net.minecraft.world.level.block.FarmlandBlock; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -40,10 +40,10 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(BlockState.class) .create(Keys.MOISTURE) - .constructValue((h, v) -> BoundedUtil.constructImmutableValueInteger(v, Keys.MOISTURE, FarmBlock.MOISTURE)) - .get(h -> h.getValue(FarmBlock.MOISTURE)) - .set((h, v) -> BoundedUtil.setInteger(h, v, FarmBlock.MOISTURE)) - .supports(h -> h.getBlock() instanceof FarmBlock); + .constructValue((h, v) -> BoundedUtil.constructImmutableValueInteger(v, Keys.MOISTURE, FarmlandBlock.MOISTURE)) + .get(h -> h.getValue(FarmlandBlock.MOISTURE)) + .set((h, v) -> BoundedUtil.setInteger(h, v, FarmlandBlock.MOISTURE)) + .supports(h -> h.getBlock() instanceof FarmlandBlock); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index c26c7d9207d..5edc29a8be4 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -109,7 +109,7 @@ public static void register(final DataProviderRegistrator registrator) { } }) .create(Keys.CONTAINER_ITEM) - .get(h -> (ItemType) h.getItem().getCraftingRemainder().getItem()) + .get(h -> (ItemType) h.getItem().getCraftingRemainder().item()) .create(Keys.DISPLAY_NAME) .get(h -> SpongeAdventure.asAdventure(h.getDisplayName())) .create(Keys.CUSTOM_MODEL_DATA_FLOATS) @@ -259,9 +259,9 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.FOOD_CONVERTS_TO) .get(h -> { final var remainder = h.get(DataComponents.USE_REMAINDER); - return remainder == null ? null : ItemStackUtil.fromNative(remainder.convertInto()); + return remainder == null ? null : ItemStackUtil.fromTemplate(remainder.convertInto()); }) - .set((h, v) -> h.set(DataComponents.USE_REMAINDER, new UseRemainder(ItemStackUtil.toNative(v)))) + .set((h, v) -> h.set(DataComponents.USE_REMAINDER, new UseRemainder(ItemStackUtil.toTemplate(v)))) .delete(h -> h.remove(DataComponents.USE_REMAINDER)) .create(Keys.REPAIR_COST) .get(h -> h.getOrDefault(DataComponents.REPAIR_COST, 0)) @@ -272,8 +272,8 @@ public static void register(final DataProviderRegistrator registrator) { .set((stack, value) -> stack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, value)) .delete(stack -> stack.remove(DataComponents.ENCHANTMENT_GLINT_OVERRIDE)) .create(Keys.CHARGED_PROJECTILES) - .get(h -> ItemStackUtil.snapshotOf(h.getOrDefault(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.EMPTY).getItems())) - .set((stack, value) -> stack.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(ItemStackUtil.fromSnapshotToNativeList(value)))) + .get(h -> ItemStackUtil.snapshotOf(h.getOrDefault(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.EMPTY).items())) + .set((stack, value) -> stack.set(DataComponents.CHARGED_PROJECTILES, new ChargedProjectiles(ItemStackUtil.toTemplate(value)))) .delete(stack -> stack.remove(DataComponents.CHARGED_PROJECTILES)) .create(Keys.INTANGIBLE_PROJECTILE) .get(h -> h.get(DataComponents.INTANGIBLE_PROJECTILE) != null) @@ -442,7 +442,7 @@ private static Inventory inventoryFromItemContainerContents(final ItemContainerC if (contents == null) { return null; } - var slots = contents.stream().map(ItemStackUtil::cloneDefensive).toList(); + var slots = contents.allItemsCopyStream().map(ItemStackUtil::fromNative).toList(); if (slots.isEmpty()) { return null; } diff --git a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java index e4507a3123e..04aff666ee7 100644 --- a/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java +++ b/src/main/java/org/spongepowered/common/effect/particle/SpongeParticleHelper.java @@ -130,7 +130,7 @@ private static CachedParticlePacket getNamedPacket(final ParticleEffect effect, final ItemStackSnapshot snapshot = effect.optionOrDefault(ParticleOptions.ITEM_STACK_SNAPSHOT).get(); final ItemParticleOption particleData = new ItemParticleOption( (net.minecraft.core.particles.ParticleType) internalType, - ItemStackUtil.fromSnapshotToNative(snapshot)); + ItemStackUtil.toTemplate(snapshot)); return new NamedCachedPacket(particleData, offset, quantity, velocity); } else if (internalType == ParticleTypes.SCULK_CHARGE) { final double roll = effect.optionOrDefault(ParticleOptions.ROLL).get(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java b/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java index f3e3883ef7f..12e1eab6fd9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhasePrinter.java @@ -25,7 +25,6 @@ package org.spongepowered.common.event.tracking; import net.minecraft.core.BlockPos; -import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Block; import org.apache.logging.log4j.Level; @@ -152,7 +151,7 @@ static void printExceptionSpawningEntity(final PhaseTracker tracker, final Phase } static void printNullSourceBlockWithTile( - final BlockPos pos, final Block blockIn, final BlockPos otherPos, final Identifier type, final boolean useTile, + final BlockPos pos, final Block blockIn, final BlockPos otherPos, final String type, final boolean useTile, final NullPointerException e) { final PhaseTracker instance = PhaseTracker.getInstance(); final PrettyPrinter printer = new PrettyPrinter(60).add("Null Source Block on TileEntity!").centre().hr() @@ -161,7 +160,7 @@ static void printNullSourceBlockWithTile( + "attempting to perform a neighbor notification with it. Because " + "this is guaranteed to lead to a crash or a spam of reports, " + "Sponge is going ahead and fixing the issue. The offending Tile " - + "is " + type.toString()) + + "is " + type) .add() .add("%s : %s", "Source position", pos) .add("%s : %s", "Source TileEntity", type) diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 5751ccd5f6b..7e3cf86e528 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -29,7 +29,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Queues; import net.minecraft.core.BlockPos; -import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.LevelAccessor; @@ -178,11 +177,8 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world final @Nullable BlockEntityType type = Optional.ofNullable(source) .map(BlockEntity::getType) .orElse(null); - if (type != null) { - @Nullable Identifier id = BlockEntityType.getKey(type); - if (id == null) { - id = Identifier.parse(source.getClass().getCanonicalName()); - } + if (source != null) { + String id = source.typeHolder().getRegisteredName(); final Map autoFixedTiles = trackerConfig.autoFixNullSourceBlockProvidingBlockEntities; final boolean contained = autoFixedTiles.containsKey(type.toString()); // If we didn't map the tile entity yet, we should apply the mapping diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java index caffa2aac64..079ee2d903a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhase.java @@ -31,6 +31,7 @@ import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket; import net.minecraft.network.protocol.common.ServerboundResourcePackPacket; +import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.network.protocol.game.ServerboundChatPacket; import net.minecraft.network.protocol.game.ServerboundClientCommandPacket; import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket; @@ -55,7 +56,6 @@ import net.minecraft.network.protocol.game.ServerboundUseItemPacket; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.accessor.network.protocol.game.ServerboundInteractPacketAccessor; import org.spongepowered.common.event.tracking.IPhaseState; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.phase.packet.drag.DragInventoryAddSlotState; @@ -85,7 +85,6 @@ import org.spongepowered.common.event.tracking.phase.packet.player.AnimationPacketState; import org.spongepowered.common.event.tracking.phase.packet.player.AttackEntityPacketState; import org.spongepowered.common.event.tracking.phase.packet.player.IgnoredPacketState; -import org.spongepowered.common.event.tracking.phase.packet.player.InteractAtEntityPacketState; import org.spongepowered.common.event.tracking.phase.packet.player.InteractEntityPacketState; import org.spongepowered.common.event.tracking.phase.packet.player.InteractionPacketContext; import org.spongepowered.common.event.tracking.phase.packet.player.InteractionPacketState; @@ -115,7 +114,6 @@ public static final class General { static final IPhaseState IGNORED = new IgnoredPacketState(); static final IPhaseState INTERACT_ENTITY = new InteractEntityPacketState(); static final IPhaseState ATTACK_ENTITY = new AttackEntityPacketState(); - static final IPhaseState INTERACT_AT_ENTITY = new InteractAtEntityPacketState(); static final IPhaseState CREATIVE_INVENTORY = new CreativeInventoryPacketState(); static final IPhaseState PLACE_BLOCK = new PlaceBlockPacketState(); static final IPhaseState REQUEST_RESPAWN = new BasicPacketState(); @@ -281,19 +279,8 @@ private static final class Holder { private void setupPacketToStateMapping() { this.packetTranslationMap.put(ServerboundKeepAlivePacket.class, packet -> PacketPhase.General.IGNORED); this.packetTranslationMap.put(ServerboundChatPacket.class, packet -> PacketPhase.General.CHAT_COMMAND); - this.packetTranslationMap.put(ServerboundInteractPacket.class, packet -> { - final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packet; - final ServerboundInteractPacket.ActionType action = ((ServerboundInteractPacketAccessor) useEntityPacket).accessor$action().getType(); - if (action == ServerboundInteractPacket.ActionType.INTERACT) { - return PacketPhase.General.INTERACT_ENTITY; - } else if (action == ServerboundInteractPacket.ActionType.ATTACK) { - return PacketPhase.General.ATTACK_ENTITY; - } else if (action == ServerboundInteractPacket.ActionType.INTERACT_AT) { - return PacketPhase.General.INTERACT_AT_ENTITY; - } else { - return PacketPhase.General.INVALID; - } - }); + this.packetTranslationMap.put(ServerboundInteractPacket.class, packet -> PacketPhase.General.INTERACT_ENTITY); + this.packetTranslationMap.put(ServerboundAttackPacket.class, packet -> PacketPhase.General.ATTACK_ENTITY); this.packetTranslationMap.put(ServerboundMovePlayerPacket.class, packet -> PacketPhase.General.MOVEMENT); this.packetTranslationMap.put(ServerboundMovePlayerPacket.Pos.class, packet -> PacketPhase.General.MOVEMENT); this.packetTranslationMap.put(ServerboundMovePlayerPacket.Rot.class, packet -> PacketPhase.General.MOVEMENT); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java index ec7bc34185d..a5a36cb0b2e 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/AttackEntityPacketState.java @@ -25,7 +25,7 @@ package org.spongepowered.common.event.tracking.phase.packet.player; import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ServerboundInteractPacket; +import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.LivingEntity; @@ -51,9 +51,9 @@ public final class AttackEntityPacketState extends BasicPacketState { private final BiConsumer ATTACK_MODIFIER = super.getFrameModifier().andThen((frame, ctx) -> { frame.addContext(EventContextKeys.USED_ITEM, ctx.getItemUsedSnapshot()); - final ServerboundInteractPacket useEntityPacket = ctx.getPacket(); + final ServerboundAttackPacket useEntityPacket = ctx.getPacket(); final ServerPlayer player = ctx.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); + final net.minecraft.world.entity.@Nullable Entity entity = player.level().getEntityOrPart(useEntityPacket.entityId()); if (entity != null) { // hand is not populated if we don't have an entity in scope that caused this. frame.addContext(EventContextKeys.USED_HAND, ctx.getHandUsed()); @@ -69,10 +69,10 @@ public BiConsumer getFrameModi @Override public boolean isPacketIgnored(final Packet packetIn, final ServerPlayer packetPlayer) { - final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packetIn; + final ServerboundAttackPacket useEntityPacket = (ServerboundAttackPacket) packetIn; // There are cases where a player is interacting with an entity that // doesn't exist on the server. - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(packetPlayer.level()); + final net.minecraft.world.entity.@Nullable Entity entity = packetPlayer.level().getEntityOrPart(useEntityPacket.entityId()); return entity == null; } @@ -86,9 +86,9 @@ public void populateContext(final ServerPlayer playerMP, final Packet packet, public Supplier getSpawnTypeForTransaction( final BasicPacketContext context, final net.minecraft.world.entity.Entity entityToSpawn ) { - final ServerboundInteractPacket useEntityPacket = context.getPacket(); + final ServerboundAttackPacket useEntityPacket = context.getPacket(); final ServerPlayer player = context.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); + final net.minecraft.world.entity.@Nullable Entity entity = player.level().getEntityOrPart(useEntityPacket.entityId()); if (entity != null && (entity.isRemoved() || entity instanceof LivingEntity && ((LivingEntity) entity).isDeadOrDying())) { return entityToSpawn instanceof ExperienceOrb ? SpawnTypes.EXPERIENCE : SpawnTypes.DROPPED_ITEM; } @@ -101,9 +101,9 @@ public Supplier getSpawnTypeForTransaction( @Override public void unwind(final BasicPacketContext context) { if (!TrackingUtil.processBlockCaptures(context)) { - final ServerboundInteractPacket useEntityPacket = context.getPacket(); + final ServerboundAttackPacket useEntityPacket = context.getPacket(); final ServerPlayer player = context.getPacketPlayer(); - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(player.level()); + final net.minecraft.world.entity.@Nullable Entity entity = player.level().getEntityOrPart(useEntityPacket.entityId()); if (entity instanceof Entity) { ((Entity) entity).offer(Keys.NOTIFIER, player.getUUID()); } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractAtEntityPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractAtEntityPacketState.java deleted file mode 100644 index 02a3a781ff5..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractAtEntityPacketState.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.phase.packet.player; - -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.type.HandType; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.world.World; -import org.spongepowered.common.accessor.network.protocol.game.ServerboundInteractPacketAccessor; -import org.spongepowered.common.accessor.network.protocol.game.ServerboundInteractPacket_InteractionAtLocationActionAccessor; -import org.spongepowered.common.bridge.CreatorTrackedBridge; -import org.spongepowered.common.entity.PlayerTracker; -import org.spongepowered.common.event.tracking.TrackingUtil; -import org.spongepowered.common.event.tracking.phase.packet.BasicPacketContext; -import org.spongepowered.common.event.tracking.phase.packet.BasicPacketState; -import org.spongepowered.common.item.util.ItemStackUtil; - -public final class InteractAtEntityPacketState extends BasicPacketState { - - @Override - public boolean isPacketIgnored(final Packet packetIn, final ServerPlayer packetPlayer) { - final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packetIn; - // There are cases where a player is interacting with an entity that doesn't exist on the server. - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget((ServerLevel) packetPlayer.level()); - return entity == null; - } - - @Override - public void populateContext(final ServerPlayer playerMP, final Packet packet, final BasicPacketContext context) { - final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packet; - final ServerboundInteractPacket_InteractionAtLocationActionAccessor accessor = (ServerboundInteractPacket_InteractionAtLocationActionAccessor) ((ServerboundInteractPacketAccessor) useEntityPacket).accessor$action(); - final ItemStack stack = ItemStackUtil.cloneDefensive(playerMP.getItemInHand(accessor.accessor$hand())); - if (stack != null) { - context.itemUsed(stack); - } - final HandType handType = (HandType) (Object) accessor.accessor$hand(); - context.handUsed(handType); - } - - @Override - public void unwind(final BasicPacketContext context) { - final ServerPlayer player = context.getPacketPlayer(); - - final ServerboundInteractPacket useEntityPacket = context.getPacket(); - final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget((ServerLevel) player.level()); - if (entity == null) { - // Something happened? - return; - } - final World spongeWorld = (World) player.level(); - if (entity instanceof CreatorTrackedBridge) { - ((CreatorTrackedBridge) entity).tracker$setTrackedUUID(PlayerTracker.Type.CREATOR, player.getUUID()); - } else { - ((Entity) entity).offer(Keys.NOTIFIER, player.getUUID()); - } - - - // TODO - Determine if we need to pass the supplier or perform some parameterized - // process if not empty method on the capture object. - TrackingUtil.processBlockCaptures(context); - } - - -} diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java index 50e3268b092..976ed38c017 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/player/InteractEntityPacketState.java @@ -32,8 +32,6 @@ import org.spongepowered.api.data.type.HandType; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.common.accessor.network.protocol.game.ServerboundInteractPacketAccessor; -import org.spongepowered.common.accessor.network.protocol.game.ServerboundInteractPacket_InteractionActionAccessor; import org.spongepowered.common.bridge.CreatorTrackedBridge; import org.spongepowered.common.entity.PlayerTracker; import org.spongepowered.common.event.tracking.TrackingUtil; @@ -43,36 +41,37 @@ public final class InteractEntityPacketState extends BasicPacketState { + @SuppressWarnings("deprecation") // getEntityOrPart is the easiest way to check if the entity is valid @Override public boolean isPacketIgnored(final Packet packetIn, final ServerPlayer packetPlayer) { final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packetIn; // There are cases where a player is interacting with an entity that doesn't exist on the server. - final net.minecraft.world.entity.@Nullable Entity entity = useEntityPacket.getTarget(packetPlayer.level()); + final net.minecraft.world.entity.@Nullable Entity entity = packetPlayer.level().getEntityOrPart(useEntityPacket.entityId()); return entity == null; } + @SuppressWarnings("deprecation") // getEntityOrPart is the easiest way to check if the entity is valid @Override public void populateContext(final ServerPlayer player, final Packet packet, final BasicPacketContext context) { final ServerboundInteractPacket useEntityPacket = (ServerboundInteractPacket) packet; - final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.level()); + final net.minecraft.world.entity.@Nullable Entity entity = player.level().getEntityOrPart(useEntityPacket.entityId()); if (entity != null) { - final ServerboundInteractPacket_InteractionActionAccessor accessor = (ServerboundInteractPacket_InteractionActionAccessor) ((ServerboundInteractPacketAccessor) useEntityPacket).accessor$action(); - final ItemStack stack = ItemStackUtil.cloneDefensive(player.getItemInHand(accessor.accessor$hand())); + final ItemStack stack = ItemStackUtil.cloneDefensive(player.getItemInHand(useEntityPacket.hand())); if (stack != null) { context.itemUsed(stack); } - final HandType handType = (HandType) (Object) accessor.accessor$hand(); + final HandType handType = (HandType) (Object) useEntityPacket.hand(); context.handUsed(handType); } } + @SuppressWarnings("deprecation") // getEntityOrPart is the easiest way to check if the entity is valid @Override public void unwind(final BasicPacketContext phaseContext) { - final ServerPlayer player = phaseContext.getPacketPlayer(); final ServerboundInteractPacket useEntityPacket = phaseContext.getPacket(); - final net.minecraft.world.entity.Entity entity = useEntityPacket.getTarget(player.level()); + final net.minecraft.world.entity.@Nullable Entity entity = player.level().getEntityOrPart(useEntityPacket.entityId()); if (entity == null) { // Something happened? return; diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java index 9253d64cdc6..18154ace5b7 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStack.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStack.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; +import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; @@ -141,11 +142,8 @@ public ItemStack.Builder attributeModifier(final AttributeType attributeType, fi Objects.requireNonNull(modifier, "AttributeModifier cannot be null"); Objects.requireNonNull(equipmentType, "EquipmentType cannot be null"); - var existing = this.components.get(DataComponents.ATTRIBUTE_MODIFIERS); - if (existing == null) { - existing = Optional.empty(); - } - var modifiers = existing.map(ItemAttributeModifiers.class::cast).orElse(ItemAttributeModifiers.EMPTY); + final var existing = Optional.ofNullable(this.components.get(Holder.direct(this.type).components(), DataComponents.ATTRIBUTE_MODIFIERS)); + var modifiers = existing.orElse(ItemAttributeModifiers.EMPTY); var attribute = BuiltInRegistries.ATTRIBUTE.wrapAsHolder((Attribute) attributeType); var slotGroup = SpongeItemStack.asEquipmentSlotGroup(equipmentType); diff --git a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java index 6d07b8dacb6..8fee718ae2d 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java +++ b/src/main/java/org/spongepowered/common/item/recipe/SpongeRecipeRegistration.java @@ -26,6 +26,7 @@ import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeInput; import org.spongepowered.common.item.recipe.ingredient.SpongeIngredient; @@ -35,11 +36,11 @@ public final class SpongeRecipeRegistration { - public static boolean isVanillaSerializer(final ItemStack resultStack, + public static boolean isVanillaSerializer(final ItemStackTemplate resultStack, final Function resultFunction, final Function> remainingItemsFunction, final Collection ingredients) { - if (!resultStack.getComponents().isEmpty() || resultFunction != null || remainingItemsFunction != null) { + if (!resultStack.components().isEmpty() || resultFunction != null || remainingItemsFunction != null) { return false; } return ingredients.stream().noneMatch(value -> value instanceof SpongeIngredient); diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java index e86a6dee95f..75ffc4de030 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.item.recipe.cooking; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.BlastingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; @@ -37,19 +37,27 @@ public class SpongeBlastingRecipe extends BlastingRecipe { private final Function function; - public SpongeBlastingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { + public SpongeBlastingRecipe( + final String group, + final CookingBookCategory category, + final Ingredient ingredient, + final ItemStackTemplate result, + final float experience, + final int cookingTime, + final Function function + ) { super(group, category, ingredient, result, experience, cookingTime); this.function = function; } @Override - public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SingleRecipeInput input) { if (this.function != null) { - final ItemStack result = this.function.apply($$0); + final ItemStack result = this.function.apply(input); result.setCount(1); return result; } - return super.assemble($$0, $$1); + return super.assemble(input); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java index 27169173be6..0f700eb1cd6 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.item.recipe.cooking; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; @@ -37,19 +37,27 @@ public class SpongeCampfireCookingRecipe extends CampfireCookingRecipe { private final Function function; - public SpongeCampfireCookingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { + public SpongeCampfireCookingRecipe( + final String group, + final CookingBookCategory category, + final Ingredient ingredient, + final ItemStackTemplate result, + final float experience, + final int cookingTime, + final Function function + ) { super(group, category, ingredient, result, experience, cookingTime); this.function = function; } @Override - public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SingleRecipeInput $$0) { if (this.function != null) { final ItemStack result = this.function.apply($$0); result.setCount(1); return result; } - return super.assemble($$0, $$1); + return super.assemble($$0); } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java index b84cee4eb3e..d32c27b18ce 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java @@ -25,8 +25,7 @@ package org.spongepowered.common.item.recipe.cooking; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.BlastingRecipe; import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; @@ -55,7 +54,7 @@ public final class SpongeCookingRecipeBuilder implements CookingRecipe.Builder.R private net.minecraft.world.item.crafting.RecipeType type; private Ingredient ingredient; - private ItemStack result; + private ItemStackTemplate result; private Function resultFunction; private @Nullable Float experience; @@ -85,21 +84,21 @@ public CookingRecipe.Builder reset() { @Override public EndStep result(final ItemType result) { - this.result = new ItemStack((Item) result); + this.result = ItemStackUtil.toTemplate(org.spongepowered.api.item.inventory.ItemStack.of(result)); this.resultFunction = null; return this; } @Override public EndStep result(final ItemStackLike result) { - this.result = ItemStackUtil.fromLikeToNative(result); + this.result = ItemStackUtil.toTemplate(result); this.resultFunction = null; return this; } // currently unused public EndStep result(final Function resultFunction, final ItemStackLike exemplaryResult) { - this.result = ItemStackUtil.fromLikeToNative(exemplaryResult); + this.result = ItemStackUtil.toTemplate(exemplaryResult); this.resultFunction = (inv) -> ItemStackUtil.fromLikeToNative(resultFunction.apply(InventoryUtil.toSponge(inv))); return this; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java index 8fba2a264a2..6e28ad47619 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.item.recipe.cooking; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; @@ -37,19 +37,27 @@ public class SpongeSmeltingRecipe extends SmeltingRecipe { private final Function function; - public SpongeSmeltingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { + public SpongeSmeltingRecipe( + final String group, + final CookingBookCategory category, + final Ingredient ingredient, + final ItemStackTemplate result, + final float experience, + final int cookingTime, + final Function function + ) { super(group, category, ingredient, result, experience, cookingTime); this.function = function; } @Override - public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SingleRecipeInput input) { if (this.function != null) { - final ItemStack result = this.function.apply($$0); + final ItemStack result = this.function.apply(input); result.setCount(1); return result; } - return super.assemble($$0, $$1); + return super.assemble(input); } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java index 8b0f4ae63e4..156e16f906d 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.item.recipe.cooking; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; @@ -37,19 +37,27 @@ public class SpongeSmokingRecipe extends SmokingRecipe { private final Function function; - public SpongeSmokingRecipe(final String group, final CookingBookCategory category, final Ingredient ingredient, final ItemStack result, final float experience, final int cookingTime, final Function function) { + public SpongeSmokingRecipe( + final String group, + final CookingBookCategory category, + final Ingredient ingredient, + final ItemStackTemplate result, + final float experience, + final int cookingTime, + final Function function + ) { super(group, category, ingredient, result, experience, cookingTime); this.function = function; } @Override - public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SingleRecipeInput input) { if (this.function != null) { - final ItemStack result = this.function.apply($$0); + final ItemStack result = this.function.apply(input); result.setCount(1); return result; } - return super.assemble($$0, $$1); + return super.assemble(input); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index 1fe006055f1..1122f8a61e4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.item.recipe.crafting.custom; -import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; @@ -63,7 +62,7 @@ public boolean matches(final CraftingInput input, final Level level) { } @Override - public ItemStack assemble(final CraftingInput input, final HolderLookup.Provider lookup) { + public ItemStack assemble(final CraftingInput input) { return ItemStackUtil.toNative(this.resultFunction.apply(InventoryUtil.toSponge(input))); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java index c529193919f..983d0482ac4 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedCraftingRecipeBuilder.java @@ -186,7 +186,7 @@ public ShapedCraftingRecipe build() { // ingredientsMap.putIfAbsent(' ', net.minecraft.item.crafting.Ingredient.EMPTY); final ShapedRecipePattern pattern = ShapedRecipePattern.of(ingredientsMap, this.aisle); return (ShapedCraftingRecipe) new SpongeShapedRecipe(this.group == null ? "": this.group, this.craftingBookCategory, pattern, true, - ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction); + ItemStackUtil.toTemplate(this.result), this.resultFunction, this.remainingItemsFunction); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java index dad53506b17..188f394caef 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java @@ -25,9 +25,9 @@ package org.spongepowered.common.item.recipe.crafting.shaped; -import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.ShapedRecipe; @@ -41,13 +41,14 @@ public class SpongeShapedRecipe extends ShapedRecipe { private final Function> remainingItemsFunction; public SpongeShapedRecipe( - final String groupIn, - final CraftingBookCategory category, - final ShapedRecipePattern pattern, - final boolean showNotification, - final ItemStack resultStack, - final Function resultFunction, - final Function> remainingItemsFunction) { + final String groupIn, + final CraftingBookCategory category, + final ShapedRecipePattern pattern, + final boolean showNotification, + final ItemStackTemplate resultStack, + final Function resultFunction, + final Function> remainingItemsFunction + ) { super(groupIn, category, pattern, resultStack, showNotification); this.resultFunction = resultFunction; this.remainingItemsFunction = remainingItemsFunction; @@ -62,11 +63,11 @@ public NonNullList getRemainingItems(final CraftingInput $$0) { } @Override - public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final CraftingInput input) { if (this.resultFunction != null) { - return this.resultFunction.apply($$0); + return this.resultFunction.apply(input); } - return super.assemble($$0, $$1); + return super.assemble(input); } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java index a84eb2c9dc7..5fa09531b17 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessCraftingRecipeBuilder.java @@ -117,7 +117,7 @@ public EndStep group(final @Nullable String name) { public ShapelessCraftingRecipe build() { Preconditions.checkState(!this.ingredients.isEmpty(), "The ingredients are not set."); return (ShapelessCraftingRecipe) new SpongeShapelessRecipe(this.group == null ? "": this.group, this.craftingBookCategory, this.ingredients, - ItemStackUtil.toNative(this.result), this.resultFunction, this.remainingItemsFunction); + ItemStackUtil.toTemplate(this.result), this.resultFunction, this.remainingItemsFunction); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index 3ec7775eeff..009931b4bed 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.item.recipe.crafting.shapeless; -import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.Ingredient; @@ -55,12 +55,14 @@ public class SpongeShapelessRecipe extends ShapelessRecipe { private final Function resultFunction; private final Function> remainingItemsFunction; - public SpongeShapelessRecipe(final String groupIn, - final CraftingBookCategory category, - final List recipeItemsIn, - final ItemStack spongeResultStack, - final Function resultFunction, - final Function> remainingItemsFunction) { + public SpongeShapelessRecipe( + final String groupIn, + final CraftingBookCategory category, + final List recipeItemsIn, + final ItemStackTemplate spongeResultStack, + final Function resultFunction, + final Function> remainingItemsFunction + ) { super(groupIn, category, spongeResultStack, recipeItemsIn); this.onlyVanillaIngredients = recipeItemsIn.stream().noneMatch(i -> i instanceof SpongeIngredient); this.resultFunction = resultFunction; @@ -85,11 +87,11 @@ public NonNullList getRemainingItems(final CraftingInput $$0) { @Override - public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final CraftingInput input) { if (this.resultFunction != null) { - return this.resultFunction.apply($$0); + return this.resultFunction.apply(input); } - return super.assemble($$0, $$1); + return super.assemble(input); } private static boolean @@ -109,7 +111,8 @@ public ItemStack assemble(final CraftingInput $$0, final HolderLookup.Provider $ for (int j = 0; j < stacks.size(); j++) { final ItemStack stack = stacks.get(j); if (!stack.isEmpty() && ingredient.test(stack)) { - matchesMap.computeIfAbsent(j, k -> new ArrayList<>()).add(i);; + matchesMap.computeIfAbsent(j, k -> new ArrayList<>()).add(i); + ; noMatch = false; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java index 0c264b19b9c..c9be75eea61 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java +++ b/src/main/java/org/spongepowered/common/item/recipe/ingredient/SpongeIngredient.java @@ -31,6 +31,7 @@ import net.minecraft.core.HolderSet; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.display.SlotDisplay; import org.apache.commons.lang3.NotImplementedException; @@ -134,7 +135,11 @@ public boolean test(final ItemStack testStack) { @Override public SlotDisplay display() { - return new SlotDisplay.Composite(this.itemList.getItems().stream().map(SlotDisplay.ItemStackSlotDisplay::new).map(SlotDisplay.class::cast).toList()); + return new SlotDisplay.Composite(this.itemList.getItems().stream() + .filter(ItemStack::isEmpty) + .map(ItemStackTemplate::fromNonEmptyStack) + .map(SlotDisplay.ItemStackSlotDisplay::new) + .map(SlotDisplay.class::cast).toList()); } public static SpongeIngredient spongeFromStacks(net.minecraft.world.item.ItemStack... stacks) { diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index 4ce2588f399..33e17f29045 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -25,12 +25,11 @@ package org.spongepowered.common.item.recipe.smithing; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingRecipeInput; import net.minecraft.world.item.crafting.SmithingTransformRecipe; -import net.minecraft.world.item.crafting.TransmuteResult; import java.util.Optional; import java.util.function.Function; @@ -40,18 +39,18 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe { private Function resultFunction; public SpongeSmithingRecipe(final Optional template, final Ingredient base, - final Optional addition, final TransmuteResult spongeResult, final Function resultFunction) { + final Optional addition, final ItemStackTemplate spongeResult, final Function resultFunction) { super(template, base, addition, spongeResult); this.resultFunction = resultFunction; } @Override - public ItemStack assemble(final SmithingRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SmithingRecipeInput input) { if (this.resultFunction != null) { - return this.resultFunction.apply($$0); + return this.resultFunction.apply(input); } - return super.assemble($$0, $$1); + return super.assemble(input); } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java index 219578e12fb..4e1c8bbc666 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipeBuilder.java @@ -123,7 +123,7 @@ public EndStep group(@Nullable String name) { @Override public SmithingRecipe build() { return (SmithingRecipe) new SpongeSmithingRecipe(Optional.ofNullable(this.template), this.base, Optional.ofNullable(this.addition), - ItemStackUtil.toTransmute(this.result), this.resultFunction); + ItemStackUtil.toTemplate(this.result), this.resultFunction); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java index 57a78fc0a74..ac1c2c1971a 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStoneCutterRecipeBuilder.java @@ -92,7 +92,7 @@ public EndStep group(@Nullable String name) { @Override public StoneCutterRecipe build() { return (StoneCutterRecipe) new SpongeStonecuttingRecipe(this.group == null ? "": this.group, this.ingredient, - ItemStackUtil.toNative(this.result), this.resultFunction); + ItemStackUtil.toTemplate(this.result), this.resultFunction); } @Override diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index b3f5b62ad75..682fe3b8e2c 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.item.recipe.stonecutting; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.item.crafting.StonecutterRecipe; @@ -37,17 +37,22 @@ public class SpongeStonecuttingRecipe extends StonecutterRecipe { private Function resultFunction; - public SpongeStonecuttingRecipe(final String groupIn, final Ingredient ingredientIn, final ItemStack spongeResult, final Function resultFunction) { + public SpongeStonecuttingRecipe( + final String groupIn, + final Ingredient ingredientIn, + final ItemStackTemplate spongeResult, + final Function resultFunction + ) { super(groupIn, ingredientIn, spongeResult); this.resultFunction = resultFunction; } @Override - public ItemStack assemble(final SingleRecipeInput $$0, final HolderLookup.Provider $$1) { + public ItemStack assemble(final SingleRecipeInput input) { if (this.resultFunction != null) { - return this.resultFunction.apply($$0); + return this.resultFunction.apply(input); } - return super.assemble($$0, $$1); + return super.assemble(input); } } diff --git a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java index 60df08f6f06..af14773258a 100644 --- a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java +++ b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java @@ -25,9 +25,10 @@ package org.spongepowered.common.item.util; import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.TransmuteResult; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackLike; @@ -51,16 +52,16 @@ public static net.minecraft.world.item.ItemStack toNative(final @Nullable ItemSt throw new NativeStackException("The supplied item stack was not native to the current platform"); } - public static TransmuteResult toTransmute(final @Nullable ItemStackLike stack) { + public static ItemStackTemplate toTemplate(final @Nullable ItemStackLike stack) { if (stack == null) { - return new TransmuteResult(Items.AIR); + return new ItemStackTemplate(Items.AIR); } return switch ((Object) stack) { case net.minecraft.world.item.ItemStack itemStack: - yield new TransmuteResult(itemStack.typeHolder(), itemStack.getCount(), itemStack.getComponentsPatch()); + yield new ItemStackTemplate(itemStack.typeHolder(), itemStack.getCount(), itemStack.getComponentsPatch()); case SpongeItemStackSnapshot snapshot: final var direct = Holder.direct(((Item) stack.type())); - yield new TransmuteResult(direct, snapshot.quantity(), snapshot.getComponentsPatch()); + yield new ItemStackTemplate(direct, snapshot.quantity(), snapshot.getComponentsPatch()); default: throw new NativeStackException("The supplied item stack was not native to the current platform"); }; @@ -86,8 +87,8 @@ public static net.minecraft.world.item.ItemStack[] fromSnapshotToNative(List fromSnapshotToNativeList(List items) { - return items.stream().map(ItemStackUtil::fromSnapshotToNative).toList(); + public static List toTemplate(List items) { + return items.stream().map(ItemStackUtil::toTemplate).toList(); } public static ItemStack fromNative(net.minecraft.world.item.ItemStack stack) { @@ -97,6 +98,10 @@ public static ItemStack fromNative(net.minecraft.world.item.ItemStack stack) { throw new NativeStackException("The supplied native item stack was not compatible with the target environment"); } + public static ItemStack fromTemplate(ItemStackTemplate template) { + return ItemStackUtil.fromNative(template.apply(DataComponentPatch.EMPTY)); + } + /** * Converts an Array of native ItemStacks to a List of SpongeAPI ItemStacks * @@ -159,6 +164,10 @@ public static boolean compareIgnoreQuantity(ItemStack stack1, net.minecraft.worl return ItemStackUtil.compareIgnoreQuantity(ItemStackUtil.toNative(stack1), stack2); } + public static ItemStackSnapshot snapshotOf(ItemStackTemplate template) { + return template == null ? ItemStackSnapshot.empty() : ItemStackUtil.snapshotOf(template.apply(DataComponentPatch.EMPTY)); + } + public static ItemStackSnapshot snapshotOf(net.minecraft.world.item.ItemStack itemStack) { if (itemStack == null) { return ItemStackSnapshot.empty(); @@ -170,7 +179,7 @@ public static ItemStackSnapshot snapshotOf(@Nullable ItemStackLike itemStack) { return itemStack == null ? ItemStackSnapshot.empty() : itemStack.isEmpty() ? ItemStackSnapshot.empty() : itemStack.asImmutable(); } - public static List snapshotOf(final List items) { + public static List snapshotOf(final List items) { return items.stream().map(ItemStackUtil::snapshotOf).toList(); } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index d05db9aaf4c..3cbe4ada94b 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -24,11 +24,15 @@ */ package org.spongepowered.common.world.server; +import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.Registries; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.attribute.BedRule; import net.minecraft.world.attribute.EnvironmentAttributeMap; import net.minecraft.world.attribute.EnvironmentAttributes; +import net.minecraft.world.clock.WorldClock; +import net.minecraft.world.clock.WorldClocks; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,6 +47,7 @@ import org.spongepowered.api.util.Range; import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.WorldTypeEffect; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.tags.TagBridge; import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; import org.spongepowered.common.data.SpongeDataManager; @@ -106,7 +111,7 @@ public WorldType.Builder from(final WorldType type) { final SpongeDimensionTypes.SpongeDataSection spongeData = new SpongeDimensionTypes.SpongeDataSection(createDragonFight); try { - + final var clocks = SpongeCommon.vanillaRegistry(Registries.WORLD_CLOCK); final var attributes = EnvironmentAttributeMap.builder(); attributes.set(EnvironmentAttributes.PIGLINS_ZOMBIFY, !piglinSafe); attributes.set(EnvironmentAttributes.BED_RULE, bedsUsable ? BedRule.CAN_SLEEP_WHEN_DARK : BedRule.EXPLODES); @@ -127,7 +132,8 @@ public WorldType.Builder from(final WorldType type) { DimensionType.Skybox.OVERWORLD, DimensionType.CardinalLightType.DEFAULT, attributes.build(), - HolderSet.empty() + HolderSet.empty(), + clocks.get(WorldClocks.OVERWORLD).map(r -> (Holder) r) ); if ((Object) dimensionType instanceof DimensionTypeBridge bridge) { bridge.bridge$decorateData(spongeData); diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index 41c51879d30..b319501bd5f 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -40,7 +40,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ImposterProtoChunk; @@ -275,7 +274,7 @@ public static BiConsumer String.format( - "TileEntityType[%s] creates a null TileEntity!", BlockEntityType.getKey(tile.getType())) + "TileEntityType[%s] creates a null TileEntity!", tile.typeHolder().getRegisteredName()) ).loadWithComponents(input); if (level != null) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/DisplayInfoMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/DisplayInfoMixin_API.java index 110ea019c19..8e2c102a228 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/DisplayInfoMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/DisplayInfoMixin_API.java @@ -26,7 +26,7 @@ import net.kyori.adventure.text.Component; import net.minecraft.advancements.DisplayInfo; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import org.spongepowered.api.advancement.Advancement; import org.spongepowered.api.advancement.AdvancementType; import org.spongepowered.api.advancement.TreeLayoutElement; @@ -56,7 +56,7 @@ public abstract class DisplayInfoMixin_API implements TreeLayoutElement, org.spo @Shadow public abstract boolean shadow$shouldAnnounceChat(); @Shadow public abstract boolean shadow$isHidden(); - @Shadow @Final private ItemStack icon; + @Shadow @Final private ItemStackTemplate icon; @Shadow @Final private boolean hidden; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java index 2005cabafd4..3a27fc1346c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java @@ -28,7 +28,9 @@ import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStackTemplate; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.item.ItemRarity; @@ -36,6 +38,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeImmutableDataHolder; import java.util.Arrays; @@ -46,16 +49,15 @@ public abstract class ItemMixin_API implements ItemType, SpongeImmutableDataHolder { // @formatter:off - @Shadow @Final private Holder.Reference builtInRegistryHolder; - @Shadow @Final private DataComponentMap components; + @Shadow @Final @Nullable private ItemStackTemplate craftingRemainingItem; @Shadow public abstract String shadow$getDescriptionId(); - @Shadow @Final @Nullable private Item craftingRemainingItem; - + @Shadow public abstract DataComponentMap shadow$components(); @Shadow public abstract int shadow$getDefaultMaxStackSize(); // @formatter:on + @Nullable protected BlockType api$blockType = null; @Override @@ -70,7 +72,7 @@ public int maxStackQuantity() { @Override public ItemRarity rarity() { - return (ItemRarity) (Object) this.components.get(DataComponents.RARITY); + return (ItemRarity) (Object) this.shadow$components().get(DataComponents.RARITY); } @Override @@ -90,7 +92,11 @@ public boolean isAnyOf(ItemType... types) { @Override public Optional container() { - final @Nullable Item craftingRemainingItem = this.craftingRemainingItem; - return Optional.ofNullable((ItemType) craftingRemainingItem); + return this.craftingRemainingItem.item().unwrap() + .mapLeft(key -> SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ITEM).get(key)) + .mapLeft(ref -> ref.map(Holder::value)) + .mapRight(Optional::of) + .map(l -> l, o -> o) + .map(ItemType.class::cast); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemStackMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemStackMixin_API.java index cca0e04b102..3e978d21e53 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemStackMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemStackMixin_API.java @@ -74,7 +74,6 @@ public abstract class ItemStackMixin_API implements SerializableDataHolder.Mutab // @formatter:off @Shadow public abstract int shadow$getCount(); @Shadow public abstract void shadow$setCount(int size); // Do not use field directly as Minecraft tracks the empty state - @Shadow public abstract int shadow$getMaxStackSize(); @Shadow public abstract boolean shadow$isEmpty(); @Shadow public abstract net.minecraft.world.item.ItemStack shadow$copy(); @Shadow public abstract Item shadow$getItem(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java index 99c6a0396bc..b982e6454d4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/crafting/RecipeMixin_API.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.item.crafting; -import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeInput; import net.minecraft.world.item.crafting.display.RecipeDisplay; @@ -38,7 +37,6 @@ import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.inventory.util.InventoryUtil; import org.spongepowered.common.item.recipe.crafting.RecipeUtil; import org.spongepowered.common.item.util.ItemStackUtil; @@ -52,7 +50,7 @@ public interface RecipeMixin_API extends Recipe { // @formatter:off - @Shadow ItemStack shadow$assemble(I inv, HolderLookup.Provider registryAccess); + @Shadow ItemStack shadow$assemble(I inv); @Shadow boolean shadow$isSpecial(); @Shadow boolean shadow$matches(I inv, net.minecraft.world.level.Level worldIn); @Shadow net.minecraft.world.item.crafting.RecipeType shadow$getType(); @@ -79,7 +77,7 @@ default boolean isValid(@NonNull final I2 inv, @NonNull final ServerWorld world) @NonNull @Override default ItemStackSnapshot result(@NonNull final I2 inv) { - return ItemStackUtil.snapshotOf(this.shadow$assemble((I) InventoryUtil.toCraftingInputOrThrow(inv), SpongeCommon.server().registryAccess())); + return ItemStackUtil.snapshotOf(this.shadow$assemble((I) InventoryUtil.toCraftingInputOrThrow(inv))); } @NonNull diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index db9845f52eb..7234ed4c606 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -181,7 +181,7 @@ public double regionalDifficultyFactor() { if (!(this.level instanceof ServerLevel sl)) { return 0; } - return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), + return new DifficultyInstance(this.level.getDifficulty(), this.level.getOverworldClockTime(), this.inhabitedTime().ticks(), sl.getMoonBrightness(sl.getRespawnData().pos())).getEffectiveDifficulty(); } @@ -190,7 +190,7 @@ public double regionalDifficultyPercentage() { if (!(this.level instanceof ServerLevel sl)) { return 0; } - return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), + return new DifficultyInstance(this.level.getDifficulty(), this.level.getOverworldClockTime(), this.inhabitedTime().ticks(), sl.getMoonBrightness(sl.getRespawnData().pos())).getSpecialMultiplier(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java index cc207d515f5..327538f9165 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/LevelDataMixin_API.java @@ -37,7 +37,6 @@ public interface LevelDataMixin_API extends WorldProperties { // @formatter:off @Shadow long shadow$getGameTime(); - @Shadow long shadow$getDayTime(); // @formatter:on @Override @@ -47,7 +46,8 @@ default MinecraftDayTime gameTime() { @Override default MinecraftDayTime dayTime() { - return new SpongeMinecraftDayTime(this.shadow$getDayTime()); + // TODO + return this.gameTime(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java index d269ea28f49..b5d863d95dc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; +import net.minecraft.world.clock.PackedClockStates; +import net.minecraft.world.clock.WorldClocks; import net.minecraft.world.level.gamerules.GameRuleMap; import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.ServerLevelData; @@ -44,6 +46,7 @@ import org.spongepowered.common.accessor.world.level.GameRulesAccessor; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.util.Constants; +import org.spongepowered.common.util.SpongeMinecraftDayTime; import org.spongepowered.common.util.SpongeTicks; import java.util.HashMap; @@ -63,10 +66,15 @@ public interface ServerLevelDataMixin_API extends ServerWorldProperties { @Shadow void shadow$setWanderingTraderSpawnChance(int p_230397_1_); @Shadow void shadow$setWanderingTraderId(UUID p_230394_1_); @Shadow @Nullable UUID shadow$getWanderingTraderId(); - @Shadow void shadow$setDayTime(long p_76068_1_); @Shadow GameRules shadow$getGameRules(); // @formatter:on + @Shadow + PackedClockStates clockStates(); + + @Shadow + void setClockStates(PackedClockStates packedClocks); + @Override default ResourceKey key() { return Objects.requireNonNull(((ServerLevelDataBridge) this).bridge$spongeData().key()); @@ -115,7 +123,8 @@ default void setGameRule(final GameRule gameRule, final V value) { @Override default void setDayTime(final MinecraftDayTime dayTime) { - this.shadow$setDayTime(dayTime.asTicks().ticks()); + // TODO - adjust to world clocks now +// this.setClockStates(this.clockStates().clocks()); } @Override @@ -158,4 +167,13 @@ default void setWeather(final WeatherType type, final Ticks ticks) { this.offer(Keys.WEATHER, Weather.of(Objects.requireNonNull(type, "type"), Objects.requireNonNull(ticks, "ticks"))); } + @Override + default MinecraftDayTime dayTime() { + final var clockstate = this.clockStates().clocks().get(WorldClocks.OVERWORLD); + if (clockstate == null) { + return new SpongeMinecraftDayTime(0); + } + final var totalTicks = clockstate.totalTicks(); + return new SpongeMinecraftDayTime(totalTicks); + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java index ba751df790c..1fe07db5263 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java @@ -29,14 +29,16 @@ import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ChatTypeDecoration; import net.minecraft.resources.Identifier; +import net.minecraft.resources.NetworkRegistryLoadTask; import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.RegistryLoadTask; import net.minecraft.resources.ResourceKey; import org.spongepowered.api.adventure.ChatTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.accessor.resources.RegistryDataLoader_RegistryLoadTaskAccessor; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.accessor.resources.RegistryLoadTaskAccessor; import java.util.Map; @@ -44,11 +46,15 @@ public class RegistryDataLoaderMixin { @SuppressWarnings("unchecked") - @Inject(method = "lambda$load$3", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/WritableRegistry;freeze()Lnet/minecraft/core/Registry;")) + @Inject(method = "lambda$load$3", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/RegistryLoadTask;freezeRegistry(Ljava/util/Map;)Z")) private static void impl$afterLoadRegistryContents( - final Map loadingErrors, final RegistryDataLoader.RegistryLoadTask p, CallbackInfo ci + Map, Exception> loadingErrors, RegistryLoadTask task, CallbackInfoReturnable cir ) { - final var registry = ((RegistryDataLoader_RegistryLoadTaskAccessor) p).accessor$getRegistry(); + if (task instanceof NetworkRegistryLoadTask) { + // On the client side, this ought to already be registered through the network + return; + } + final var registry = ((RegistryLoadTaskAccessor) task).accessor$registry(); if (Registries.CHAT_TYPE.equals(registry.key())) { final ChatTypeDecoration narration = ChatTypeDecoration.withSender("chat.type.text.narrate"); registry.register(ResourceKey.create(registry.key(), (Identifier) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 904ddf9309d..31f8239eb76 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -70,6 +70,7 @@ import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; @@ -641,7 +642,8 @@ public void sendMessage(final OutgoingChatMessage $$0, final boolean $$1, final @Override protected void impl$onRightClickEntity( - final Entity entityToInteractOn, final InteractionHand hand, final CallbackInfoReturnable cir + final Entity entityToInteractOn, final InteractionHand hand, + final Vec3 location, final CallbackInfoReturnable cir ) { final ItemStack itemInHand = this.shadow$getItemInHand(hand); final InteractEntityEvent.Secondary event = SpongeCommonEventFactory.callInteractEntityEventSecondary((net.minecraft.server.level.ServerPlayer) (Object) this, diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java index 1213ff4f06c..f31b3df3c90 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImplMixin.java @@ -42,8 +42,10 @@ import net.minecraft.network.protocol.game.ClientboundMoveVehiclePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.network.protocol.game.ServerboundChatCommandSignedPacket; import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket; +import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.protocol.game.ServerboundMoveVehiclePacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; @@ -84,6 +86,7 @@ import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.block.entity.ChangeSignEvent; import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.api.event.entity.InteractEntityEvent; import org.spongepowered.api.event.entity.living.AnimateHandEvent; import org.spongepowered.api.event.network.ServerSideConnectionEvent; import org.spongepowered.asm.mixin.Mixin; @@ -569,6 +572,38 @@ public abstract class ServerGamePacketListenerImplMixin extends ServerCommonPack } } + @Inject(method = "handleInteract", at = @At("HEAD"), cancellable = true) + private void impl$throwInteractItemEventForInteract(ServerboundInteractPacket packet, CallbackInfo ci) { + final @Nullable Entity entity = this.player.level().getEntityOrPart(packet.entityId()); + final var hand = packet.hand(); + final var pos = packet.location(); + + final ItemStack itemInHand = hand == null ? ItemStack.EMPTY : player.getItemInHand(hand); + final InteractEntityEvent.Secondary event = SpongeCommonEventFactory + .callInteractEntityEventSecondary(player, itemInHand, entity, hand, VecHelper.toVector3d(pos)); + if (event.isCancelled()) { + ci.cancel(); + } else { + this.bridge$incrementIgnorePackets(); + } + } + + @Inject(method = "handleAttack", at = @At("HEAD"), cancellable = true) + private void impl$throwInteractPrimaryEventForAttack(ServerboundAttackPacket packet, CallbackInfo ci) { + final @Nullable Entity entity = this.player.level().getEntityOrPart(packet.entityId()); + if (entity == null) { + return; + } + + final InteractEntityEvent.Primary event = SpongeCommonEventFactory.callInteractEntityEventPrimary(player, + player.getItemInHand(player.getUsedItemHand()), entity, player.getUsedItemHand()); + if (event.isCancelled()) { + ci.cancel(); + } else { + this.bridge$incrementIgnorePackets(); + } + } + @Override public SpongeTabList bridge$tabList() { return this.impl$tabList; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImpl_1Mixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImpl_1Mixin.java deleted file mode 100644 index bad7f84c38a..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/network/ServerGamePacketListenerImpl_1Mixin.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.server.network; - -import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.api.event.entity.InteractEntityEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.bridge.server.network.ServerGamePacketListenerImplBridge; -import org.spongepowered.common.event.SpongeCommonEventFactory; -import org.spongepowered.common.util.VecHelper; - -@Mixin(targets = "net.minecraft.server.network.ServerGamePacketListenerImpl$1") -public abstract class ServerGamePacketListenerImpl_1Mixin implements ServerboundInteractPacket.Handler { - - @Shadow(aliases = { - // Forge mapped synthetic class member - "val$entity" - }) @Final Entity val$target; - @Shadow @Final ServerGamePacketListenerImpl this$0; - - // Anonymous class - @Inject(method = "onAttack()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;attack(Lnet/minecraft/world/entity/Entity;)V"), cancellable = true) - public void impl$fireLeftClickEvent(final CallbackInfo ci) { - final Entity entity = this.val$target; - final ServerPlayer player = this.this$0.player; - - final InteractEntityEvent.Primary event = SpongeCommonEventFactory.callInteractEntityEventPrimary(player, - player.getItemInHand(player.getUsedItemHand()), entity, player.getUsedItemHand()); - if (event.isCancelled()) { - ci.cancel(); - } else { - ((ServerGamePacketListenerImplBridge) this.this$0).bridge$incrementIgnorePackets(); - } - } - - @Inject(method = "onInteraction(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/Vec3;)V", at = @At("HEAD"), cancellable = true) - public void impl$fireRightClickEvent(final InteractionHand hand, final Vec3 pos, final CallbackInfo ci) { - final Entity entity = this.val$target; - final ServerPlayer player = this.this$0.player; - - final ItemStack itemInHand = hand == null ? ItemStack.EMPTY : player.getItemInHand(hand); - final InteractEntityEvent.Secondary event = SpongeCommonEventFactory - .callInteractEntityEventSecondary(player, itemInHand, entity, hand, VecHelper.toVector3d(pos)); - if (event.isCancelled()) { - ci.cancel(); - } else { - ((ServerGamePacketListenerImplBridge) this.this$0).bridge$incrementIgnorePackets(); - } - } - -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 86ef29443ac..2b0a1e705fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -545,4 +545,13 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } + @Inject(method = "startSleeping", at = @At("HEAD"), cancellable = true) + private void impl$callPreSleepingEvent(BlockPos param0, CallbackInfo ci) { + final Cause currentCause = PhaseTracker.getInstance().currentCause(); + final BlockSnapshot snapshot = ((ServerWorld) this.shadow$level()).createSnapshot(param0.getX(), param0.getY(), param0.getZ()); + if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventPre(currentCause, snapshot, (Living) this))) { + ci.cancel(); + } + } + } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java index eb5d8f41915..67310f78691 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/npc/villager/VillagerMixin.java @@ -24,21 +24,11 @@ */ package org.spongepowered.common.mixin.core.world.entity.npc.villager; -import net.minecraft.core.BlockPos; import net.minecraft.world.entity.npc.villager.Villager; import org.slf4j.Logger; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.block.BlockSnapshot; -import org.spongepowered.api.entity.living.Living; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.common.event.tracking.PhaseTracker; @Mixin(Villager.class) public abstract class VillagerMixin extends AbstractVillagerMixin { @@ -53,12 +43,4 @@ public abstract class VillagerMixin extends AbstractVillagerMixin { //noop } - @Inject(method = "startSleeping", at = @At("HEAD"), cancellable = true) - private void impl$callPreSleepingEvent(BlockPos param0, CallbackInfo ci) { - final Cause currentCause = PhaseTracker.getInstance().currentCause(); - final BlockSnapshot snapshot = ((ServerWorld) this.shadow$level()).createSnapshot(param0.getX(), param0.getY(), param0.getZ()); - if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventPre(currentCause, snapshot, (Living) this))) { - ci.cancel(); - } - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java index 8af4121ddf0..30c7c390251 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin.java @@ -48,6 +48,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.pattern.BlockInWorld; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Team; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.entity.living.Living; @@ -286,7 +287,8 @@ public abstract class PlayerMixin extends AvatarMixin implements PlayerBridge, G } @Inject(method = "interactOn", at = @At(value = "HEAD"), cancellable = true) - protected void impl$onRightClickEntity(final Entity entityToInteractOn, final InteractionHand hand, + protected void impl$onRightClickEntity( + final Entity entity, final InteractionHand hand, final Vec3 location, final CallbackInfoReturnable cir) { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java index 8a3eac09178..9b956c758fa 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java @@ -114,7 +114,7 @@ public abstract class ItemStackMixin implements SpongeDataHolderBridge, DataComp } // Read custom data from nbt - @Inject(method = "(Lnet/minecraft/world/level/ItemLike;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At("RETURN")) + @Inject(method = "(Lnet/minecraft/core/Holder;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At("RETURN")) private void impl$onRead(final CallbackInfo ci) { if (!this.shadow$isEmpty()) { DataUtil.syncTagToData(this); // Deserialize diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipeMixin.java index dc3d3956890..ed0e11f615b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapedRecipeMixin.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; import org.spongepowered.asm.mixin.Final; @@ -36,8 +38,8 @@ public abstract class ShapedRecipeMixin implements ShapedRecipeBridge { // @formatter=off - @Shadow @Final ItemStack result; - @Shadow @Final ShapedRecipePattern pattern; + @Shadow @Final private ItemStackTemplate result; + @Shadow @Final private ShapedRecipePattern pattern; // @formatter=on @@ -49,7 +51,7 @@ public abstract class ShapedRecipeMixin implements ShapedRecipeBridge { @Override public ItemStack bridge$result() { - return this.result; + return this.result.apply(DataComponentPatch.EMPTY); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipeMixin.java index 25d9dd221c1..3f89c899b33 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/ShapelessRecipeMixin.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.ShapelessRecipe; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -35,13 +37,13 @@ public abstract class ShapelessRecipeMixin implements RecipeResultBridge { // @formatter=off - @Shadow @Final ItemStack result; + @Shadow @Final private ItemStackTemplate result; // @formatter=on @Override public ItemStack bridge$result() { - return this.result; + return this.result.apply(DataComponentPatch.EMPTY); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java index b0925a42a67..72278d3a397 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SingleItemRecipeMixin.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SingleItemRecipe; import org.spongepowered.asm.mixin.Final; @@ -39,13 +41,13 @@ public abstract class SingleItemRecipeMixin implements RecipeResultBridge { // @formatter=off - @Shadow @Final private ItemStack result; + @Shadow @Final private ItemStackTemplate result; @Shadow public abstract Ingredient shadow$input(); // @formatter=on @Override public ItemStack bridge$result() { - return this.result; + return this.result.apply(DataComponentPatch.EMPTY); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java index d40ff2d2be8..4cb4f374159 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/SmithingTransformRecipeMixin.java @@ -25,9 +25,9 @@ package org.spongepowered.common.mixin.core.world.item.crafting; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.SmithingTransformRecipe; -import net.minecraft.world.item.crafting.TransmuteResult; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,10 +39,10 @@ public abstract class SmithingTransformRecipeMixin implements SmithingRecipeBridge { // @formatter=off - @Shadow @Final Optional template; - @Shadow @Final Ingredient base; - @Shadow @Final Optional addition; - @Shadow @Final TransmuteResult result; + @Shadow @Final private Optional template; + @Shadow @Final private Ingredient base; + @Shadow @Final private Optional addition; + @Shadow @Final private ItemStackTemplate result; // @formatter=on @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/FarmBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/FarmBlockMixin.java index 8a0db18f320..3d1d6fc6559 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/FarmBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/FarmBlockMixin.java @@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.FarmBlock; +import net.minecraft.world.level.block.FarmlandBlock; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -36,7 +36,7 @@ import org.spongepowered.common.bridge.world.entity.GrieferBridge; import org.spongepowered.common.mixin.core.block.BlockMixin; -@Mixin(FarmBlock.class) +@Mixin(FarmlandBlock.class) public abstract class FarmBlockMixin extends BlockMixin { // @formatter:off @@ -46,7 +46,7 @@ public abstract class FarmBlockMixin extends BlockMixin { @Redirect(method = "fallOn", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/FarmBlock;turnToDirt(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V" + target = "Lnet/minecraft/world/level/block/FarmlandBlock;turnToDirt(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V" ) ) private void impl$CheckIfGrieferCanGrief(Entity entityIn, BlockState state, Level world, BlockPos pos) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 40a3a3a8be7..6b83dda2dc4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -123,7 +123,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock slice = @Slice( from = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z" ), to = @At( value = "INVOKE", diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java index 09a74c9bb08..38482b14627 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/CrafterBlockBlockEntityMixin_Inventory_API.java @@ -80,7 +80,7 @@ public boolean craftItem() { } final var recipeHolder = potentialResults.get(); final var recipe = recipeHolder.value(); - final var craftedStack = recipe.assemble(input, this.level.registryAccess()); + final var craftedStack = recipe.assemble(input); if (craftedStack.isEmpty()) { return false; } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index f5cc8df6ab0..dbc26c9c299 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -89,7 +89,6 @@ "server.network.LegacyQueryHandlerMixin", "server.network.ServerCommonPacketListenerImplMixin", "server.network.ServerConfigurationPacketListenerImplMixin", - "server.network.ServerGamePacketListenerImpl_1Mixin", "server.network.ServerGamePacketListenerImplMixin", "server.network.ServerHandshakePacketListenerImplMixin", "server.network.ServerLoginPacketListenerImplMixin", diff --git a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java b/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java index 86fdaf869e4..c6ed616dff7 100644 --- a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java +++ b/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java @@ -25,7 +25,6 @@ package org.spongepowered.vanilla.accessor.world.level.block.entity; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.SingleRecipeInput; @@ -39,7 +38,7 @@ public interface AbstractFurnaceBlockEntityAccessor_Vanilla { @Invoker("canBurn") - static boolean invoker$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { + static boolean invoker$canBurn(@Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { throw new UntransformedInvokerError(); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java index 1bedf274bc7..57beef60efc 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java @@ -28,6 +28,8 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.RegistryLoadTask; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.DependencySorter; import org.spongepowered.api.registry.Registry; import org.spongepowered.api.registry.RegistryHolder; @@ -35,8 +37,9 @@ import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor; +import org.spongepowered.common.accessor.resources.RegistryLoadTaskAccessor; import org.spongepowered.common.bridge.core.WritableRegistryBridge; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; @@ -44,9 +47,7 @@ import org.spongepowered.common.registry.SpongeRegistryHolder; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -54,29 +55,47 @@ public class RegistryDataLoaderMixin_Vanilla { @SuppressWarnings({"rawtypes", "unchecked"}) - @WrapOperation(method = "lambda$load$2(Ljava/util/List;Ljava/util/Map;Ljava/lang/Void;)Lnet/minecraft/core/RegistryAccess$Frozen;", - at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V")) - private static void impl$onLoad(final List> instance, final Consumer consumer, Operation original) { + @WrapOperation(method = "lambda$load$2", + at = @At(value = "INVOKE", target = "Ljava/util/List;stream()Ljava/util/stream/Stream;", ordinal = 0)) + private static Stream impl$onLoad( + List> instance, Operation original + ) { // TODO: Remote layer - final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - instance.stream() - .filter(l -> l instanceof RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor) - .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor)l).accessor$getResourceManager(), Collectors.toSet())) + final var collect = instance.stream() + .collect(Collectors.groupingBy(l -> { + if (l instanceof RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor accessor) { + return accessor.accessor$getResourceManager(); + } + return ResourceManager.Empty.INSTANCE; + }, Collectors.toSet())); + collect .forEach((k, v) -> { - final var registryHolder = (RegistryHolder) k; - ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(registryHolder.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); + final RegistryHolder registryHolder; + if (k == ResourceManager.Empty.INSTANCE) { + // on the client side, we don't have a real resource manager + registryHolder = SpongeCommon.game(); + } else { + registryHolder = (RegistryHolder) k; + } + ((SpongeRegistryHolder) registryHolder).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat(registryHolder.streamRegistries(RegistryRoots.MINECRAFT), v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .map(RegistryLoadTaskAccessor::accessor$registry)).toList())); lifecycle.processServerRegistries(registryHolder, v.stream() + .map(RegistryLoadTaskAccessor.class::cast) .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! .map(l -> (Registry) l.accessor$registry())); - v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + v + .stream().map(RegistryLoadTaskAccessor.class::cast) + .forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); }); - List> loaders = new ArrayList<>(instance.size()); + List> loaders = new ArrayList<>(collect.size()); dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); - original.call(Collections.unmodifiableList(loaders), consumer); + return original.call(loaders); } } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java index 7e78174810a..3643202d34a 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/ReloadableServerResourcesMixin_Vanilla.java @@ -30,7 +30,6 @@ import net.minecraft.commands.Commands; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.permissions.PermissionSet; @@ -45,13 +44,19 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Vanilla { - @WrapOperation(method = "lambda$loadResources$0", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) + @WrapOperation(method = "lambda$loadResources$2", at = @At(value = "NEW", target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;Ljava/util/List;)Lnet/minecraft/server/ReloadableServerResources;")) private static ReloadableServerResources impl$onCreateResources( - final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, - final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager + final LayeredRegistryAccess fullLayers, + final HolderLookup.Provider loadingContext, + final FeatureFlagSet enabledFeatures, + final Commands.CommandSelection commandSelection, + final List postponedTags, + final PermissionSet functionCompilationPermissions, + final List newComponents, + final Operation original, + final @Local(argsOnly = true) ResourceManager resourceManager ) { - final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); + final ReloadableServerResources instance = original.call(fullLayers, loadingContext, enabledFeatures, commandSelection, postponedTags, functionCompilationPermissions, newComponents); if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 8fb75d67d7f..a23f0dd5113 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -26,7 +26,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; @@ -35,7 +34,6 @@ import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.block.entity.carrier.furnace.FurnaceBlockEntity; @@ -78,19 +76,27 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // Tick up and Start @Redirect(method = "serverTick", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", - ordinal = 1)) + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", + ordinal = 1 + ) + ) private static boolean vanilla$checkIfCanSmelt( - final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final SingleRecipeInput input, - final NonNullList slots, final int maxStackSize, final ServerLevel level, final BlockPos entityPos, - final BlockState state, final AbstractFurnaceBlockEntity entityIn) { - if (!AbstractFurnaceBlockEntityAccessor_Vanilla.invoker$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { + final @org.jspecify.annotations.Nullable RecipeHolder recipe, + final SingleRecipeInput input, + final NonNullList items, + final int maxStackSize, + final ServerLevel level, + final BlockPos entityPos, + final BlockState state, + final AbstractFurnaceBlockEntity entityIn + ) { + if (!AbstractFurnaceBlockEntityAccessor_Vanilla.invoker$canBurn(recipe, input, items, maxStackSize)) { return false; } final var entity = (AbstractFurnaceBlockEntityMixin_Vanilla) (Object) (entityIn); - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(slots.get(1)); + final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(items.get(1)); final Cause cause = PhaseTracker.getInstance().currentCause(); if (entity.cookingTimer == 0) { // Start @@ -120,7 +126,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final var recipe = entity.bridge$getCurrentRecipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); + recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -133,11 +139,14 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;"), slice = @Slice( from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) - )) + )) private static void vanilla$captureBucketFill( - final RegistryAccess registryAccess, final RecipeHolder recipe, - final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, - final CallbackInfoReturnable cir) { + final @org.jspecify.annotations.Nullable RecipeHolder recipe, + final SingleRecipeInput input, + final NonNullList items, + final int maxStackSize, + final CallbackInfoReturnable cir + ) { final Cause cause = PhaseTracker.getInstance().currentCause(); final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); @@ -147,16 +156,19 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", shift = At.Shift.AFTER)) // final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int var2, final CallbackInfoReturnable cir private static void vanilla$afterSmeltItem( - final RegistryAccess registryAccess, final RecipeHolder recipe, - final SingleRecipeInput input, final NonNullList slots, final int $$4, - final CallbackInfoReturnable cir) { - final ItemStack itemIn = slots.get(0); - final ItemStack recipeResult = recipe.value().assemble(input, registryAccess); - final ItemStack itemOut = slots.get(2); + @org.jspecify.annotations.Nullable RecipeHolder recipe, + SingleRecipeInput input, + NonNullList items, + int maxStackSize, + CallbackInfoReturnable cir + ) { + final ItemStack itemIn = items.get(0); + final ItemStack recipeResult = recipe.value().assemble(input); + final ItemStack itemOut = items.get(2); final Cause cause = PhaseTracker.getInstance().currentCause(); final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) - .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); + .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); final List transactions = new ArrayList<>(); itemIn.grow(1); @@ -166,7 +178,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final boolean hasFuel = !((AbstractFurnaceBlockEntityMixin_Vanilla) entity).vanilla$filledWaterBucket; if (((AbstractFurnaceBlockEntityMixin_Vanilla) entity).vanilla$filledWaterBucket) { - transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(slots.get(1)))); + transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(items.get(1)))); } ((AbstractFurnaceBlockEntityMixin_Vanilla) entity).vanilla$filledWaterBucket = false; @@ -178,13 +190,13 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai itemOut.grow(1); transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), originalResult, ItemStackUtil.snapshotOf(itemOut))); } - final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); + final Optional fuel = hasFuel && !items.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(items.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { - transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); + transaction.custom().ifPresent(item -> items.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } From f2871c5be50d3185b2ea61d113f9ca11a15e33ec Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Feb 2026 21:57:09 -0800 Subject: [PATCH 468/586] fix(generator): update for compilation See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_3 --- SpongeAPI | 2 +- .../java/org/spongepowered/vanilla/generator/GeneratorMain.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 8c8590b8943..cb917fd335c 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 8c8590b894393a3dfebec41a9e7dd9c1c39875c3 +Subproject commit cb917fd335c608bd8567e0e61dab541e6162b274 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index a54e2ea98e0..5c3b120971b 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -164,7 +164,7 @@ private static Pair loadVanill } executor.shutdown(); }).thenApply(resources -> { - resources.updateStaticRegistryTags(); + resources.updateComponentsAndStaticRegistryTags(); return resources; }); From fed98affe62e20d89ab33bb04864405fce4bff36 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 19 Feb 2026 09:45:38 -0800 Subject: [PATCH 469/586] feat(minecraft): update to 26.1-snapshot-4 See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_4 --- SpongeAPI | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index cb917fd335c..dc968984dcf 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit cb917fd335c608bd8567e0e61dab541e6162b274 +Subproject commit dc968984dcffb89009ce32a27acddadf254e91d7 diff --git a/gradle.properties b/gradle.properties index 17b37283158..771ff1a47fb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-3 +minecraftVersion=26.1-snapshot-4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From a8aa2a7f249edab994e477f1641a4eb6f2e0e851 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 19 Feb 2026 21:56:02 -0800 Subject: [PATCH 470/586] feat(minecraft): update to 26.1-snapshot-5 See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_5 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 5 + .../item/stack/DyeableItemStackData.java | 3 +- .../inventory/PlaceRecipeTransaction.java | 110 ------------ .../tracking/phase/general/GeneralPhase.java | 1 + .../tracking/phase/general/RecipeContext.java | 156 ++++++++++++++++++ .../phase/general/RecipeCraftingState.java | 74 +++++++++ .../recipe/cooking/SpongeBlastingRecipe.java | 2 +- .../cooking/SpongeCampfireCookingRecipe.java | 2 +- .../cooking/SpongeCookingRecipeBuilder.java | 10 +- .../recipe/cooking/SpongeSmeltingRecipe.java | 2 +- .../recipe/cooking/SpongeSmokingRecipe.java | 2 +- .../crafting/custom/SpongeSpecialRecipe.java | 12 +- .../crafting/shaped/SpongeShapedRecipe.java | 2 +- .../shapeless/SpongeShapelessRecipe.java | 2 +- .../recipe/smithing/SpongeSmithingRecipe.java | 2 +- .../SpongeStonecuttingRecipe.java | 2 +- .../loader/CommandRegistryLoader.java | 2 +- .../AbstractFurnaceBlockEntityMixin.java | 35 ++-- ...actFurnaceBlockEntityAccessor_Vanilla.java | 44 ----- .../mixins.spongevanilla.accessors.json | 1 - ...stractFurnaceBlockEntityMixin_Vanilla.java | 99 +++++++---- 22 files changed, 348 insertions(+), 222 deletions(-) delete mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeContext.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeCraftingState.java delete mode 100644 vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java diff --git a/gradle.properties b/gradle.properties index 771ff1a47fb..afd97b2037c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-4 +minecraftVersion=26.1-snapshot-5 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d529d949de5..6816171ad11 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1806,6 +1806,11 @@ + + + + + diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java index dba8988f85f..78bea623dd7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java @@ -25,7 +25,6 @@ package org.spongepowered.common.data.provider.item.stack; import net.minecraft.core.component.DataComponents; -import net.minecraft.tags.ItemTags; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.DyedItemColor; import org.spongepowered.api.data.Keys; @@ -45,7 +44,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.has(DataComponents.DYED_COLOR) ? Color.ofRgb(h.get(DataComponents.DYED_COLOR).rgb()) : null) .set((h, v) -> h.update(DataComponents.DYED_COLOR, new DyedItemColor(0), prev -> new DyedItemColor(v.rgb()))) .delete(h -> h.set(DataComponents.DYED_COLOR, null)) - .supports(h -> h.is(ItemTags.DYEABLE)); + .supports(h -> h.has(DataComponents.DYED_COLOR)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java deleted file mode 100644 index 1e6febe2a6f..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/PlaceRecipeTransaction.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.event.tracking.context.transaction.inventory; - -import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.crafting.RecipeHolder; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.data.Transaction; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.event.Cause; -import org.spongepowered.api.event.SpongeEventFactory; -import org.spongepowered.api.event.item.inventory.container.ClickContainerEvent; -import org.spongepowered.api.item.inventory.Container; -import org.spongepowered.api.item.inventory.ItemStackSnapshot; -import org.spongepowered.api.item.inventory.crafting.CraftingInventory; -import org.spongepowered.api.item.inventory.transaction.SlotTransaction; -import org.spongepowered.api.item.recipe.crafting.CraftingRecipe; -import org.spongepowered.common.event.tracking.PhaseContext; -import org.spongepowered.common.event.tracking.phase.packet.inventory.InventoryPacketContext; -import org.spongepowered.common.item.util.ItemStackUtil; - -import java.util.List; -import java.util.Optional; - -public class PlaceRecipeTransaction extends ContainerBasedTransaction { - - private final ServerPlayer player; - private final ItemStackSnapshot originalCursor; - private boolean shift; - private RecipeHolder recipe; - private CraftingInventory craftingInventory; - - public PlaceRecipeTransaction(final ServerPlayer player, final boolean shift, final RecipeHolder recipe, CraftingInventory craftingInventory) { - super(player.containerMenu); - this.player = player; - this.originalCursor = ItemStackUtil.snapshotOf(player.containerMenu.getCarried()); - this.shift = shift; - this.recipe = recipe; - this.craftingInventory = craftingInventory; - } - - @Override - Optional createInventoryEvent( - final List slotTransactions, final List entities, - final PhaseContext<@NonNull ?> context, - final Cause cause - ) { - final SlotTransaction preview = this.getPreviewTransaction(this.craftingInventory.result(), slotTransactions); - final Transaction cursorTransaction = new Transaction<>(this.originalCursor, ItemStackUtil.snapshotOf(this.player.containerMenu.getCarried())); - ClickContainerEvent.Recipe event; - if (this.shift) { - event = SpongeEventFactory.createClickContainerEventRecipeAll(cause, (Container) this.menu, - this.craftingInventory, cursorTransaction, preview, - Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().identifier()), - Optional.empty(), slotTransactions); - } else { - event = SpongeEventFactory.createClickContainerEventRecipeSingle(cause, (Container) this.menu, - this.craftingInventory, cursorTransaction, preview, - Optional.of(this.recipe).map(RecipeHolder::value).map(CraftingRecipe.class::cast), - Optional.of(this.recipe).map(r -> (ResourceKey) (Object) r.id().identifier()), - Optional.empty(), slotTransactions); - } - return Optional.of(event); - } - - @Override - public void restore(final PhaseContext<@NonNull ?> context, final ClickContainerEvent event) { - this.handleEventResults(this.player, event); - } - - @Override - public void postProcessEvent(PhaseContext<@NonNull ?> context, ClickContainerEvent event) { - this.handleEventResults(this.player, event); - } - - @Override - boolean isContainerEventAllowed(final PhaseContext<@Nullable ?> context) { - if (!(context instanceof InventoryPacketContext)) { - return false; - } - final int containerId = ((InventoryPacketContext) context).getPacket().containerId(); - return containerId != this.player.containerMenu.containerId; - } -} diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/GeneralPhase.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/GeneralPhase.java index dc7277a207c..3f424b0d213 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/general/GeneralPhase.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/GeneralPhase.java @@ -35,6 +35,7 @@ public static final class State { public static final IPhaseState COMMAND = new CommandState(); public static final IPhaseState EXPLOSION = new ExplosionState(); public static final IPhaseState COMPLETE = new CompletePhase(); + public static final IPhaseState RECIPE_CRAFTING = new RecipeCraftingState(); private State() { } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeContext.java new file mode 100644 index 00000000000..86ba8df7dd2 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeContext.java @@ -0,0 +1,156 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.phase.general; + + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.Identifier; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.SingleItemRecipe; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; +import org.spongepowered.api.world.BlockChangeFlags; +import org.spongepowered.common.block.SpongeBlockSnapshot; +import org.spongepowered.common.event.tracking.IPhaseState; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.util.Preconditions; +import org.spongepowered.common.util.VecHelper; + +public class RecipeContext extends PhaseContext { + + protected PhaseContext priorContext; + ItemStackSnapshot usedItem; + Level world; + BlockState blockState; + BlockPos pos; + SpongeBlockSnapshot snapshot; + SingleItemRecipe recipe; + Identifier recipeID; + AbstractFurnaceBlockEntity furnace; + + protected RecipeContext(final IPhaseState state, final PhaseTracker tracker) { + super(state, tracker); + } + + public RecipeContext provideItem(final ItemStack stack) { + this.usedItem = ItemStackUtil.snapshotOf(stack); + return this; + } + + public ItemStackSnapshot usedItem() { + return this.usedItem; + } + + public RecipeContext world(final Level worldIn) { + this.world = worldIn; + return this; + } + + public RecipeContext block(final BlockState blockState) { + this.blockState = blockState; + return this; + } + + public RecipeContext pos(final BlockPos pos) { + this.pos = pos; + return this; + } + + @Override + public RecipeContext buildAndSwitch() { + Preconditions.checkState(this.pos != null, "BlockPos is null"); + Preconditions.checkState(this.blockState != null, "BlockState is null"); + if (this.usedItem == null) { + this.usedItem = ItemStackSnapshot.empty(); // No used item when growing naturally + } + Preconditions.checkState(this.world != null, "World is null"); + this.priorContext = this.createdTracker.getPhaseContext(); + Preconditions.checkState(this.priorContext != null, "Prior context is null"); + final SpongeBlockSnapshot.BuilderImpl builder = SpongeBlockSnapshot.BuilderImpl.pooled() + .world(((ServerLevel) this.world)) + .position(VecHelper.toVector3i(this.pos)) + .blockState(this.blockState) + .flag(BlockChangeFlags.NONE.withPhysics(true).withUpdateNeighbors(true).withNotifyObservers(true)); + this.priorContext.applyOwnerIfAvailable(builder::creator); + this.priorContext.applyNotifierIfAvailable(builder::notifier); + this.snapshot = builder.build(); + return super.buildAndSwitch(); + } + + @Override + protected void reset() { + super.reset(); + this.priorContext = null; + this.usedItem = null; + this.world = null; + this.blockState = null; + this.pos = null; + this.snapshot = null; + this.furnace = null; + this.recipeID = null; + this.recipe = null; + } + + @Override + protected RecipeContext defensiveCopy(PhaseTracker tracker) { + final RecipeContext newCopy = super.defensiveCopy(tracker); + return newCopy; + } + + public SingleItemRecipe recipe() { + return this.recipe; + } + + public RecipeContext recipe(SingleItemRecipe value) { + this.recipe = value; + return this; + } + + public RecipeContext furnace(AbstractFurnaceBlockEntity entityIn) { + this.world = entityIn.getLevel(); + this.pos = entityIn.getBlockPos(); + this.blockState = entityIn.getBlockState(); + this.furnace = entityIn; + return this; + } + + public RecipeContext recipeID(Identifier identifier) { + this.recipeID = identifier; + return this; + } + + public Identifier recipeID() { + return recipeID; + } + + public AbstractFurnaceBlockEntity furnace() { + return furnace; + } +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeCraftingState.java b/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeCraftingState.java new file mode 100644 index 00000000000..77cf85d93f9 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/general/RecipeCraftingState.java @@ -0,0 +1,74 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.phase.general; + +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.common.event.tracking.IPhaseState; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.PooledPhaseState; +import org.spongepowered.common.event.tracking.TrackingUtil; +import org.spongepowered.common.util.VecHelper; + +import java.util.function.BiConsumer; + +@SuppressWarnings({"unchecked", "rawTypes"}) +public class RecipeCraftingState extends PooledPhaseState implements IPhaseState { + + private final BiConsumer FRAME_MODIFIER = super.getFrameModifier() + .andThen((stackFrame, recipeContext) -> { + if (!recipeContext.usedItem.isEmpty()) { + stackFrame.addContext(EventContextKeys.USED_ITEM, recipeContext.usedItem); + } + + if (recipeContext.furnace != null && recipeContext.world instanceof ServerWorld sw) { + stackFrame.addContext(EventContextKeys.LOCATION, ServerLocation.of(sw, VecHelper.toVector3d(recipeContext.pos))); + } + }); + + @Override + public RecipeContext createNewContext(final PhaseTracker tracker) { + return new RecipeContext(this, tracker); + } + + @Override + public void unwind(final RecipeContext phaseContext) { + TrackingUtil.processBlockCaptures(phaseContext); + } + + @Override + public BiConsumer getFrameModifier() { + return this.FRAME_MODIFIER; + } + + private final String desc = TrackingUtil.phaseStateToString("Recipe", this); + + @Override + public String toString() { + return this.desc; + } +} diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java index 75ffc4de030..d22500345c5 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeBlastingRecipe.java @@ -46,7 +46,7 @@ public SpongeBlastingRecipe( final int cookingTime, final Function function ) { - super(group, category, ingredient, result, experience, cookingTime); + super(new CommonInfo(false), new CookingBookInfo(category, group), ingredient, result, experience, cookingTime); this.function = function; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java index 0f700eb1cd6..19797584844 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCampfireCookingRecipe.java @@ -46,7 +46,7 @@ public SpongeCampfireCookingRecipe( final int cookingTime, final Function function ) { - super(group, category, ingredient, result, experience, cookingTime); + super(new CommonInfo(false), new CookingBookInfo(category, group), ingredient, result, experience, cookingTime); this.function = function; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java index d32c27b18ce..ed4b2cfa2e1 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeCookingRecipeBuilder.java @@ -26,10 +26,12 @@ import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.world.item.ItemStackTemplate; +import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.BlastingRecipe; import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.item.crafting.SmeltingRecipe; import net.minecraft.world.item.crafting.SmokingRecipe; @@ -147,28 +149,28 @@ public CookingRecipe build() { if (!isVanilla) { return (CookingRecipe) new SpongeBlastingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); } - return (CookingRecipe) new BlastingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + return (CookingRecipe) new BlastingRecipe(new Recipe.CommonInfo(false), new AbstractCookingRecipe.CookingBookInfo(this.cookingCategory, group), this.ingredient, this.result, experience, ticksCookingTime); } if (this.type == net.minecraft.world.item.crafting.RecipeType.CAMPFIRE_COOKING) { final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(600); if (!isVanilla) { return (CookingRecipe) new SpongeCampfireCookingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); } - return (CookingRecipe) new CampfireCookingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + return (CookingRecipe) new CampfireCookingRecipe(new Recipe.CommonInfo(false), new AbstractCookingRecipe.CookingBookInfo(this.cookingCategory, group), this.ingredient, this.result, experience, ticksCookingTime); } if (this.type == net.minecraft.world.item.crafting.RecipeType.SMOKING) { final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(100); if (!isVanilla) { return (CookingRecipe) new SpongeSmokingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); } - return (CookingRecipe) new SmokingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + return (CookingRecipe) new SmokingRecipe(new Recipe.CommonInfo(false), new AbstractCookingRecipe.CookingBookInfo(this.cookingCategory, group), this.ingredient, this.result, experience, ticksCookingTime); } if (this.type == net.minecraft.world.item.crafting.RecipeType.SMELTING) { final int ticksCookingTime = Optional.ofNullable(this.cookingTime).map(SpongeTicks::toSaturatedIntOrInfinite).orElse(200); if (!isVanilla) { return (CookingRecipe) new SpongeSmeltingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime, this.resultFunction); } - return (CookingRecipe) new SmeltingRecipe(group, this.cookingCategory, this.ingredient, this.result, experience, ticksCookingTime); + return (CookingRecipe) new SmeltingRecipe(new Recipe.CommonInfo(false), new AbstractCookingRecipe.CookingBookInfo(this.cookingCategory, group), this.ingredient, this.result, experience, ticksCookingTime); } throw new IllegalArgumentException("Unknown RecipeType " + this.type); } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java index 6e28ad47619..c95aee6ac37 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmeltingRecipe.java @@ -46,7 +46,7 @@ public SpongeSmeltingRecipe( final int cookingTime, final Function function ) { - super(group, category, ingredient, result, experience, cookingTime); + super(new CommonInfo(false), new CookingBookInfo(category, group), ingredient, result, experience, cookingTime); this.function = function; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java index 156e16f906d..138bc51e24c 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/cooking/SpongeSmokingRecipe.java @@ -46,7 +46,7 @@ public SpongeSmokingRecipe( final int cookingTime, final Function function ) { - super(group, category, ingredient, result, experience, cookingTime); + super(new CommonInfo(false), new CookingBookInfo(category, group), ingredient, result, experience, cookingTime); this.function = function; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java index 1122f8a61e4..9546e24df0f 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/custom/SpongeSpecialRecipe.java @@ -26,6 +26,7 @@ import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.BannerDuplicateRecipe; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.CustomRecipe; @@ -45,17 +46,24 @@ public final class SpongeSpecialRecipe extends CustomRecipe { private final BiPredicate biPredicate; private final Function> remainingItemsFunction; private final Function resultFunction; + private final CraftingBookCategory category; public SpongeSpecialRecipe(CraftingBookCategory category, BiPredicate biPredicate, Function> remainingItemsFunction, Function resultFunction) { - super(category); + super(); + this.category = category; this.biPredicate = biPredicate; this.remainingItemsFunction = remainingItemsFunction; this.resultFunction = resultFunction; } + @Override + public CraftingBookCategory category() { + return this.category; + } + @Override public boolean matches(final CraftingInput input, final Level level) { return this.biPredicate.test(InventoryUtil.toSponge(input), (ServerWorld) level); @@ -82,6 +90,6 @@ public RecipeSerializer getSerializer() { // Fake special crafting serializer // because of Unknown recipe serializer when using our serializer with a vanilla client // return Registry.RECIPE_SERIALIZER.getOrDefault(this.id()); - return RecipeSerializer.BANNER_DUPLICATE; + return BannerDuplicateRecipe.SERIALIZER; } } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java index 188f394caef..80fc2a55a40 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shaped/SpongeShapedRecipe.java @@ -49,7 +49,7 @@ public SpongeShapedRecipe( final Function resultFunction, final Function> remainingItemsFunction ) { - super(groupIn, category, pattern, resultStack, showNotification); + super(new CommonInfo(showNotification), new CraftingBookInfo(category, groupIn), pattern, resultStack); this.resultFunction = resultFunction; this.remainingItemsFunction = remainingItemsFunction; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java index 009931b4bed..d40a96f2782 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/crafting/shapeless/SpongeShapelessRecipe.java @@ -63,7 +63,7 @@ public SpongeShapelessRecipe( final Function resultFunction, final Function> remainingItemsFunction ) { - super(groupIn, category, spongeResultStack, recipeItemsIn); + super(new CommonInfo(false), new CraftingBookInfo(category, groupIn), spongeResultStack, recipeItemsIn); this.onlyVanillaIngredients = recipeItemsIn.stream().noneMatch(i -> i instanceof SpongeIngredient); this.resultFunction = resultFunction; this.remainingItemsFunction = remainingItemsFunction; diff --git a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java index 33e17f29045..712c8b8ceb7 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/smithing/SpongeSmithingRecipe.java @@ -40,7 +40,7 @@ public class SpongeSmithingRecipe extends SmithingTransformRecipe { public SpongeSmithingRecipe(final Optional template, final Ingredient base, final Optional addition, final ItemStackTemplate spongeResult, final Function resultFunction) { - super(template, base, addition, spongeResult); + super(new CommonInfo(false), template, base, addition, spongeResult); this.resultFunction = resultFunction; } diff --git a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java index 682fe3b8e2c..e332d66ba08 100644 --- a/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java +++ b/src/main/java/org/spongepowered/common/item/recipe/stonecutting/SpongeStonecuttingRecipe.java @@ -43,7 +43,7 @@ public SpongeStonecuttingRecipe( final ItemStackTemplate spongeResult, final Function resultFunction ) { - super(groupIn, ingredientIn, spongeResult); + super(new CommonInfo(false), ingredientIn, spongeResult); this.resultFunction = resultFunction; } diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index 79bff7ba900..11bd01ebfad 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -152,7 +152,7 @@ public static RegistryLoader> valueParameter() { l.add(ResourceKeyedValueParameters.GAME_PROFILE, SpongeGameProfileValueParameter::new); l.add(ResourceKeyedValueParameters.INTEGER, k -> ClientNativeArgumentParser.createIdentity(k, IntegerArgumentType.integer())); l.add(ResourceKeyedValueParameters.IP, SpongeIPAddressValueParameter::new); - l.add(ResourceKeyedValueParameters.ITEM_STACK_SNAPSHOT, k -> new BindableValueParameter<>(k, h -> ClientNativeArgumentParser.createConverter(k, ItemArgument.item(CommandBuildContext.simple((HolderLookup.Provider) h, ((CommandBuildContext) h).enabledFeatures())), (reader, cause, converter) -> new SpongeItemStackSnapshot((ItemStack) (Object) converter.createItemStack(1, true))))); + l.add(ResourceKeyedValueParameters.ITEM_STACK_SNAPSHOT, k -> new BindableValueParameter<>(k, h -> ClientNativeArgumentParser.createConverter(k, ItemArgument.item(CommandBuildContext.simple((HolderLookup.Provider) h, ((CommandBuildContext) h).enabledFeatures())), (reader, cause, converter) -> new SpongeItemStackSnapshot((ItemStack) (Object) converter.createItemStack(1))))); l.add(ResourceKeyedValueParameters.LOCATION, SpongeServerLocationValueParameter::new); l.add(ResourceKeyedValueParameters.LONG, k -> ClientNativeArgumentParser.createIdentity(k, LongArgumentType.longArg())); l.add(ResourceKeyedValueParameters.MANY_ENTITIES, k -> ClientNativeArgumentParser.createConverter(k, EntityArgument.entities(), (reader, cause, selector) -> selector.findEntities((CommandSourceStack) cause).stream().map(x -> (Entity) x).collect( diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 6b83dda2dc4..c041cffe4b2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -55,6 +55,7 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.phase.general.RecipeContext; import org.spongepowered.common.item.util.ItemStackUtil; import java.util.Collections; @@ -65,27 +66,35 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock // @Formatter:off @Shadow protected NonNullList items; - @Shadow int cookingTimer; - @Shadow int cookingTotalTime; + @Shadow private int cookingTimer; + @Shadow private int cookingTotalTime; // @Formatter:on @Shadow @Final private RecipeManager.CachedCheck quickCheck; // Shrink Fuel - @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) + @Redirect(method = "consumeFuel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) private static void impl$throwFuelEventIfOrShrink( - final ItemStack itemStack, final int quantity, final ServerLevel var0, final BlockPos var1, - final BlockState var2, final AbstractFurnaceBlockEntity entity) { + ItemStack instance, int amount, + final NonNullList slots, final ItemStack fuel + ) { final Cause cause = PhaseTracker.getInstance().currentCause(); + // This is injected or switched in as a context by the platform dependent mixins + if (!(PhaseTracker.getInstance().getPhaseContext() instanceof RecipeContext rCtx)) { + instance.shrink(amount); + return; + } + final var entity = rCtx.furnace(); + final var recipe = rCtx.recipe(); + final var recipeID = rCtx.recipeID(); - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(itemStack); - final ItemStackSnapshot shrinkedFuel = ItemStackUtil.snapshotOf(ItemStackUtil.cloneDefensive(itemStack, itemStack.getCount() - 1)); + final ItemStackSnapshot fuelSnapshot = ItemStackUtil.snapshotOf(fuel); + final ItemStackSnapshot shrinkedFuel = ItemStackUtil.snapshotOf(ItemStackUtil.cloneDefensive(fuel, fuel.getCount() - 1)); - final SlotTransaction transaction = new SlotTransaction(((FurnaceBlockEntity) entity).inventory().slot(1).get(), fuel, shrinkedFuel); - final var recipe = ((AbstractFurnaceBlockEntityMixin) (Object) entity).bridge$getCurrentRecipe(); - final CookingEvent.ConsumeFuel event = SpongeEventFactory.createCookingEventConsumeFuel(cause, (FurnaceBlockEntity) entity, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier()), Collections.singletonList(transaction)); + final SlotTransaction transaction = new SlotTransaction(((FurnaceBlockEntity) entity).inventory().slot(1).get(), fuelSnapshot, shrinkedFuel); + final CookingEvent.ConsumeFuel event = SpongeEventFactory.createCookingEventConsumeFuel(cause, (FurnaceBlockEntity) entity, Optional.of(fuelSnapshot), + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) recipeID), Collections.singletonList(transaction)); SpongeCommon.post(event); if (event.isCancelled()) { ((AbstractFurnaceBlockEntityMixin) (Object) entity).cookingTotalTime = 0; @@ -99,7 +108,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock if (transaction.custom().isPresent()) { ((AbstractFurnaceBlockEntityMixin) (Object) entity).items.set(1, ItemStackUtil.fromSnapshotToNative(transaction.finalReplacement())); } else { // vanilla - itemStack.shrink(quantity); + instance.shrink(amount); } } @@ -123,7 +132,7 @@ public abstract class AbstractFurnaceBlockEntityMixin extends BaseContainerBlock slice = @Slice( from = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;burn(Lnet/minecraft/core/NonNullList;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V" ), to = @At( value = "INVOKE", diff --git a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java b/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java deleted file mode 100644 index c6ed616dff7..00000000000 --- a/vanilla/src/accessors/java/org/spongepowered/vanilla/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Vanilla.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.vanilla.accessor.world.level.block.entity; - -import net.minecraft.core.NonNullList; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.SingleRecipeInput; -import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; - -@Mixin(AbstractFurnaceBlockEntity.class) -public interface AbstractFurnaceBlockEntityAccessor_Vanilla { - - @Invoker("canBurn") - static boolean invoker$canBurn(@Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { - throw new UntransformedInvokerError(); - } -} diff --git a/vanilla/src/accessors/resources/mixins.spongevanilla.accessors.json b/vanilla/src/accessors/resources/mixins.spongevanilla.accessors.json index ce65de30a97..4cd6f66f91f 100644 --- a/vanilla/src/accessors/resources/mixins.spongevanilla.accessors.json +++ b/vanilla/src/accessors/resources/mixins.spongevanilla.accessors.json @@ -3,6 +3,5 @@ "parent": "mixins.sponge.parent.json", "package": "org.spongepowered.vanilla.accessor", "mixins": [ - "world.level.block.entity.AbstractFurnaceBlockEntityAccessor_Vanilla" ] } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index a23f0dd5113..712209efaf6 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -24,6 +24,9 @@ */ package org.spongepowered.vanilla.mixin.core.world.level.block.entity; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.server.level.ServerLevel; @@ -31,7 +34,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.objectweb.asm.Opcodes; @@ -50,14 +52,14 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; +import org.spongepowered.common.event.tracking.phase.general.RecipeContext; import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.mixin.core.world.level.block.entity.BaseContainerBlockEntityMixin; -import org.spongepowered.vanilla.accessor.world.level.block.entity.AbstractFurnaceBlockEntityAccessor_Vanilla; import java.util.ArrayList; import java.util.Collections; @@ -69,50 +71,77 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // @formatter:off @Shadow protected NonNullList items; - @Shadow int cookingTimer; + @Shadow private int cookingTimer; // @formatter:on + private static RecipeContext switched; private boolean vanilla$filledWaterBucket; // Tick up and Start - @Redirect(method = "serverTick", + @WrapOperation(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", - ordinal = 1 + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/NonNullList;ILnet/minecraft/world/item/ItemStack;)Z" ) ) private static boolean vanilla$checkIfCanSmelt( - final @org.jspecify.annotations.Nullable RecipeHolder recipe, - final SingleRecipeInput input, final NonNullList items, final int maxStackSize, + final ItemStack burnResult, + final Operation original, final ServerLevel level, - final BlockPos entityPos, + final BlockPos pos, final BlockState state, - final AbstractFurnaceBlockEntity entityIn + final AbstractFurnaceBlockEntity entityIn, + final @Local RecipeHolder recipe ) { - if (!AbstractFurnaceBlockEntityAccessor_Vanilla.invoker$canBurn(recipe, input, items, maxStackSize)) { + if (!original.call(items, maxStackSize, burnResult)) { return false; } + final var cookingRecipe = recipe.value(); + final var entity = (AbstractFurnaceBlockEntityMixin_Vanilla) (Object) (entityIn); final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(items.get(1)); - final Cause cause = PhaseTracker.getInstance().currentCause(); + final var identifier = recipe.id().identifier(); + // Prepare a phase stack to capture the recipe in use + final var context = GeneralPhase.State.RECIPE_CRAFTING.createPhaseContext(PhaseTracker.getInstance()) + .recipe(recipe.value()) + .recipeID(identifier) + .furnace(entityIn) + .provideItem(items.get(1)) + .buildAndSwitch(); + switched = context; if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } } + @Inject(method = "serverTick", at = @At("RETURN")) + private static void vanilla$closeRecipeContext( + final ServerLevel level, + final BlockPos pos, final BlockState state, + final AbstractFurnaceBlockEntity entity, + final CallbackInfo ci) { + if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); + } + final var closing = switched; + switched = null; + if (closing != null) { + closing.close(); + } + } + // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) private static int vanilla$resetCookTimeIfCancelled( @@ -121,12 +150,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Vanilla) (Object) entityIn; - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + // we're in an invariant state + return clampedCookTime; + } + final var fuel = switched.usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = entity.bridge$getCurrentRecipe(); + final var recipe = switched.recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -138,14 +171,10 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai // Finish @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;"), slice = @Slice( - from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) + from = @At(value = "FIELD", target = "Lnet/minecraft/world/item/Items;WET_SPONGE:Lnet/minecraft/world/item/Item;", opcode = Opcodes.GETSTATIC) )) private static void vanilla$captureBucketFill( - final @org.jspecify.annotations.Nullable RecipeHolder recipe, - final SingleRecipeInput input, - final NonNullList items, - final int maxStackSize, - final CallbackInfoReturnable cir + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci ) { final Cause cause = PhaseTracker.getInstance().currentCause(); final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) @@ -156,20 +185,18 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", shift = At.Shift.AFTER)) // final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int var2, final CallbackInfoReturnable cir private static void vanilla$afterSmeltItem( - @org.jspecify.annotations.Nullable RecipeHolder recipe, - SingleRecipeInput input, - NonNullList items, - int maxStackSize, - CallbackInfoReturnable cir + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci ) { final ItemStack itemIn = items.get(0); - final ItemStack recipeResult = recipe.value().assemble(input); final ItemStack itemOut = items.get(2); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + return; + } final Cause cause = PhaseTracker.getInstance().currentCause(); - final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) - .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); - + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); + final var recipe = switched.recipe(); + final var recipeID = switched.recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); @@ -183,8 +210,8 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai ((AbstractFurnaceBlockEntityMixin_Vanilla) entity).vanilla$filledWaterBucket = false; if (itemOut.isEmpty()) { - transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(recipeResult))); - } else if (ItemStack.isSameItemSameComponents(itemOut, recipeResult)) { + transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(result))); + } else if (ItemStack.isSameItemSameComponents(itemOut, result)) { itemOut.shrink(1); final ItemStackSnapshot originalResult = ItemStackUtil.snapshotOf(itemOut); itemOut.grow(1); @@ -192,7 +219,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai } final Optional fuel = hasFuel && !items.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(items.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) recipeID), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { From 378556dc5512ea69fd133cff0225c4b2eceb9d70 Mon Sep 17 00:00:00 2001 From: aromaa Date: Tue, 24 Feb 2026 22:26:04 +0200 Subject: [PATCH 471/586] Fix event listener signature parsing Was mistakenly restarting parsing when encountering another parameter --- .../common/event/manager/ListenerClassVisitor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java b/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java index 6a0e523db70..46b564d3116 100644 --- a/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java +++ b/src/main/java/org/spongepowered/common/event/manager/ListenerClassVisitor.java @@ -194,7 +194,7 @@ public AnnotationVisitor visitParameterAnnotation( static final class ListenerSignatureVisitor extends SignatureVisitor { private final ListenerParameter parameter; - private State state; + private @Nullable State state; public ListenerSignatureVisitor(final ListenerParameter parameter) { super(ListenerClassVisitor.ASM_VERSION); @@ -203,7 +203,9 @@ public ListenerSignatureVisitor(final ListenerParameter parameter) { @Override public SignatureVisitor visitParameterType() { - this.state = State.PARSING; + if (this.state == null) { + this.state = State.PARSING; + } return this; } From cd317e20df886ddd7b6ba35a0a4c11367ff073ce Mon Sep 17 00:00:00 2001 From: Aapo Katila <81980535+abola2@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:29:17 +0200 Subject: [PATCH 472/586] Fix pig IS_SADDLED (#4279) --- .../spongepowered/common/data/provider/entity/PigData.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java index 539849f5758..b31457fab98 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/PigData.java @@ -48,9 +48,9 @@ public static void register(final DataProviderRegistrator registrator) { .get(Pig::isSaddled) .set((h, v) -> { if (v) { - h.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); - } else { h.setItemSlot(EquipmentSlot.SADDLE, new ItemStack(Items.SADDLE)); + } else { + h.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); } }) .create(Keys.PIG_TYPE) From 9290ab517b89a8a69ea59b6ff8adcd34ddf98e73 Mon Sep 17 00:00:00 2001 From: Vilperi221 <58680173+Vilsu221@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:35:32 +0200 Subject: [PATCH 473/586] Fix villager PROFESSION_TYPE (#4274) --- .../spongepowered/common/data/provider/entity/VillagerData.java | 2 +- .../common/data/provider/entity/ZombieVillagerData.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java index cc7a7f11909..3138dab208b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java @@ -54,7 +54,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.getVillagerData().level()) .set((h, v) -> h.setVillagerData(h.getVillagerData().withLevel(v))) .create(Keys.PROFESSION_TYPE) - .get(h -> (ProfessionType) (Object) h.getVillagerData().profession()) + .get(h -> (ProfessionType) (Object) h.getVillagerData().profession().value()) .set((h, v) -> { final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_PROFESSION) .wrapAsHolder((VillagerProfession) (Object) v); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java index 990da40d732..a26f51b2643 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java @@ -46,7 +46,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.getVillagerData().level()) .set((h, v) -> h.setVillagerData(h.getVillagerData().withLevel(v))) .create(Keys.PROFESSION_TYPE) - .get(h -> (ProfessionType) (Object) h.getVillagerData().profession()) + .get(h -> (ProfessionType) (Object) h.getVillagerData().profession().value()) .set((h, v) -> { final var villagerProfession = SpongeCommon.vanillaRegistry(Registries.VILLAGER_PROFESSION).wrapAsHolder((VillagerProfession) (Object) v); h.setVillagerData(h.getVillagerData().withProfession(villagerProfession)); From 0b6ead9dd1f62d2ba7fe4334e74c48c738ec8184 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 9 Mar 2026 18:50:28 +0100 Subject: [PATCH 474/586] Fix VILLAGER_TYPE and re-enable corresponding test --- .../spongepowered/common/data/provider/entity/VillagerData.java | 2 +- .../common/data/provider/entity/ZombieVillagerData.java | 2 +- src/test/java/org/spongepowered/common/data/EntityDataTest.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java index 3138dab208b..406573d18e2 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/VillagerData.java @@ -77,7 +77,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> h.getOffers().stream().map(TradeOffer.class::cast).collect(Collectors.toList())) .set((h, v) -> h.setOffers(v.stream().map(MerchantOffer.class::cast).collect(Collectors.toCollection(MerchantOffers::new)))) .create(Keys.VILLAGER_TYPE) - .get(h -> (VillagerType) (Object) h.getVillagerData().type()) + .get(h -> (VillagerType) (Object) h.getVillagerData().type().value()) .set((h, v) -> { final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE) .wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java index a26f51b2643..0c95de3cb88 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ZombieVillagerData.java @@ -52,7 +52,7 @@ public static void register(final DataProviderRegistrator registrator) { h.setVillagerData(h.getVillagerData().withProfession(villagerProfession)); }) .create(Keys.VILLAGER_TYPE) - .get(h -> (VillagerType) (Object) h.getVillagerData().type()) + .get(h -> (VillagerType) (Object) h.getVillagerData().type().value()) .set((h, v) -> { final var villagerType = SpongeCommon.vanillaRegistry(Registries.VILLAGER_TYPE).wrapAsHolder((net.minecraft.world.entity.npc.VillagerType) (Object) v); h.setVillagerData(h.getVillagerData().withType(villagerType)); diff --git a/src/test/java/org/spongepowered/common/data/EntityDataTest.java b/src/test/java/org/spongepowered/common/data/EntityDataTest.java index f30dc767aa8..1c3af4ec7fc 100644 --- a/src/test/java/org/spongepowered/common/data/EntityDataTest.java +++ b/src/test/java/org/spongepowered/common/data/EntityDataTest.java @@ -646,7 +646,6 @@ public void testPolarBear() { DataTest.checkOfferData(polarBear, Keys.IS_STANDING, true); } - @Disabled @Test public void testVillager() { final Entity villager = this.location.createEntity(EntityTypes.VILLAGER.get()); From 1e55d9c3f5c6b29c69bb60d064a528fdc2313f4c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 11 Mar 2026 23:17:16 -0700 Subject: [PATCH 475/586] feat(minecraft): update to 26.1-snapshot-6 wip There's still some compiler errors, but mostly focused on the dramatic changes to SpongeWorldManager and how save data needs to persist for multi-world handling. See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_6 --- gradle.properties | 2 +- .../bossevents/CustomBossEventsAccessor.java | 14 ++ ...sor.java => EnderDragonFightAccessor.java} | 6 +- .../resources/mixins.sponge.accessors.json | 5 +- .../data/provider/entity/EnderDragonData.java | 8 +- .../provider/world/WorldPropertiesData.java | 18 +-- .../phase/world/dragon/DragonContext.java | 8 +- .../spongepowered/common/util/Constants.java | 5 +- .../SpongeWorldGenerationConfigBuilder.java | 2 +- .../world/server/SpongeServerLevelData.java | 52 +++++++ .../world/server/SpongeWorldManager.java | 123 +++++++++-------- .../world/server/SpongeWorldTemplate.java | 4 +- .../world/server/SpongeWorldTypeBuilder.java | 1 + .../common/world/weather/SpongeWeather.java | 58 ++++---- .../server/MinecraftServerMixin_API.java | 17 ++- .../server/level/ServerLevelMixin_API.java | 17 ++- .../core/server/MinecraftServerMixin.java | 2 +- .../commands/DifficultyCommandMixin.java | 6 +- .../core/server/level/ServerLevelMixin.java | 127 +++++++++++------- .../LegacyStructureDataHandlerMixin.java | 58 -------- .../storage/DimensionDataSotrageMixin.java | 60 --------- .../level/storage/PrimaryLevelDataMixin.java | 58 ++++---- ...eMixin.java => SavedDataStorageMixin.java} | 28 +++- .../end/EndDragonFightMixin_Tracker.java | 58 ++++---- src/mixins/resources/mixins.sponge.core.json | 4 +- 25 files changed, 378 insertions(+), 363 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java rename src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/{EndDragonFightAccessor.java => EnderDragonFightAccessor.java} (91%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java rename src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/{DimensionDataStorageMixin.java => SavedDataStorageMixin.java} (72%) diff --git a/gradle.properties b/gradle.properties index afd97b2037c..1a9340cf112 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-5 +minecraftVersion=26.1-snapshot-6 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java new file mode 100644 index 00000000000..3fd03f73bda --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java @@ -0,0 +1,14 @@ +package org.spongepowered.common.accessor.server.bossevents; + +import com.mojang.serialization.Codec; +import net.minecraft.server.bossevents.CustomBossEvents; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.common.UntransformedAccessorError; + +@Mixin(CustomBossEvents.class) +public interface CustomBossEventsAccessor { + @Accessor("CODEC") static Codec accessor$codec() { + throw new UntransformedAccessorError(); + } +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EndDragonFightAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EnderDragonFightAccessor.java similarity index 91% rename from src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EndDragonFightAccessor.java rename to src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EnderDragonFightAccessor.java index 7999d25ef76..3c0c90170cc 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EndDragonFightAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/dimension/end/EnderDragonFightAccessor.java @@ -25,12 +25,12 @@ package org.spongepowered.common.accessor.world.level.dimension.end; import net.minecraft.server.level.ServerBossEvent; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(EndDragonFight.class) -public interface EndDragonFightAccessor { +@Mixin(EnderDragonFight.class) +public interface EnderDragonFightAccessor { @Accessor("dragonEvent") ServerBossEvent accessor$dragonEvent(); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 2b01563879f..d8f22a0bbf0 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -27,11 +27,12 @@ "network.protocol.game.ServerboundMovePlayerPacketAccessor", "network.protocol.game.ServerboundMoveVehiclePacketAccessor", "network.protocol.handshake.ClientIntentionPacketAccessor", - "resources.RegistryLoadTaskAccessor", "resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor", + "resources.RegistryLoadTaskAccessor", "resources.ResourceKeyAccessor", "server.MinecraftServer_ReloadableResourcesAccessor", "server.MinecraftServerAccessor", + "server.bossevents.CustomBossEventsAccessor", "server.level.ChunkMap_TrackedEntityAccessor", "server.level.ChunkMapAccessor", "server.level.ServerChunkCacheAccessor", @@ -205,7 +206,7 @@ "world.level.chunk.storage.RegionFileAccessor", "world.level.chunk.storage.SimpleRegionStorageAccessor", "world.level.dimension.DimensionTypeAccessor", - "world.level.dimension.end.EndDragonFightAccessor", + "world.level.dimension.end.EnderDragonFightAccessor", "world.level.entity.EntityTickListAccessor", "world.level.entity.PersistentEntitySectionManagerAccessor", "world.level.levelgen.NoiseSettingsAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EnderDragonData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EnderDragonData.java index 1e7e9210906..7f8155cd4ef 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EnderDragonData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EnderDragonData.java @@ -25,11 +25,11 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.explosive.EndCrystal; -import org.spongepowered.common.accessor.world.level.dimension.end.EndDragonFightAccessor; +import org.spongepowered.common.accessor.world.level.dimension.end.EnderDragonFightAccessor; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -47,9 +47,9 @@ public static void register(final DataProviderRegistrator registrator) { .set((h, v) -> h.nearestCrystal = (net.minecraft.world.entity.boss.enderdragon.EndCrystal) v) .create(Keys.BOSS_BAR) .get(h -> { - final @Nullable EndDragonFight fight = h.getDragonFight(); + final @Nullable EnderDragonFight fight = h.getDragonFight(); if (fight != null) { - return SpongeAdventure.asAdventure(((EndDragonFightAccessor) fight).accessor$dragonEvent()); + return SpongeAdventure.asAdventure(((EnderDragonFightAccessor) fight).accessor$dragonEvent()); } else { return null; } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index 467d744bbbd..50582ffedcf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -80,15 +80,13 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.INITIALIZED) .get(ServerLevelData::isInitialized) .create(Keys.WORLD_BORDER) - .get(h -> (WorldBorder) (Object) h.getLegacyWorldBorderSettings().orElse(null)) - .create(Keys.WEATHER) - .get(SpongeWeather::of) - .set(SpongeWeather::apply) + // TODO - 26.1 changes how borders are decided + .get(h -> (WorldBorder) (Object) ((ServerLevelDataBridge)h).bridge$level().getWorldBorder()) .asMutable(ServerLevelDataBridge.class) .create(Keys.WORLD_TYPE) .get(h -> (WorldType) (Object) h.bridge$dimensionType()) .create(Keys.PVP) - .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().getWorldData().getGameRules().get(GameRules.PVP))) + .get(h -> h.bridge$pvp().orElseGet(() -> SpongeCommon.server().getGameRules().get(GameRules.PVP))) .create(Keys.SERIALIZATION_BEHAVIOR) .get(h -> h.bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC)) .create(Keys.VIEW_DISTANCE) @@ -104,8 +102,6 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(PrimaryLevelData.class) .create(Keys.WORLD_DIFFICULTY) .set((h, v) -> h.setDifficulty((net.minecraft.world.Difficulty) (Object) v)) - .create(Keys.WORLD_GEN_CONFIG) - .get(h -> (WorldGenerationConfig) h.worldGenOptions()) .asMutable(PrimaryLevelDataBridge.class) .create(Keys.WORLD_TYPE) .set((h, v) -> h.bridge$dimensionType((DimensionType) (Object) v, true)) @@ -126,7 +122,13 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.IS_LOAD_ON_STARTUP) .set(PrimaryLevelDataBridge::bridge$setLoadOnStartup) .create(Keys.WORLD_ARCHETYPE) - .get(h -> WorldArchetype.of((WorldArchetypeType) (Object) h.bridge$levelStem(), (WorldGenerationConfig) ((PrimaryLevelData) h).worldGenOptions())) + .get(h -> WorldArchetype.of((WorldArchetypeType) (Object) h.bridge$levelStem(), (WorldGenerationConfig) h.bridge$spongeData().worldGenOptions())) + .create(Keys.WORLD_GEN_CONFIG) + .get(h -> (WorldGenerationConfig) h.bridge$spongeData().worldGenOptions()) + .asMutable(ServerLevelDataBridge.class) + .create(Keys.WEATHER) + .get(h -> SpongeWeather.of(h.bridge$level().getWeatherData())) + .set(SpongeWeather::apply) ; } // @formatter:on diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/world/dragon/DragonContext.java b/src/main/java/org/spongepowered/common/event/tracking/phase/world/dragon/DragonContext.java index db84c4f5088..f8e83634e8a 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/world/dragon/DragonContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/world/dragon/DragonContext.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.event.tracking.phase.world.dragon; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.IPhaseState; import org.spongepowered.common.event.tracking.PhaseContext; @@ -35,18 +35,18 @@ @SuppressWarnings("unchecked") public abstract class DragonContext> extends PhaseContext { - private @Nullable EndDragonFight manager; + private @Nullable EnderDragonFight manager; public DragonContext(final IPhaseState state, final PhaseTracker tracker) { super(state, tracker); } - public D manager(EndDragonFight manager) { + public D manager(EnderDragonFight manager) { this.manager = Objects.requireNonNull(manager); return (D) this; } - public EndDragonFight getManager() { + public EnderDragonFight getManager() { return Objects.requireNonNull(this.manager); } } diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index 28650d694b1..81e55bcc13a 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -155,6 +155,7 @@ public static final class V3 { public static final DataQuery SPONGE_DATA_ROOT = DataQuery.of("sponge-data"); public static final DataQuery CONTENT_VERSION = DataQuery.of("version"); public static final DataQuery CONTENT = DataQuery.of("content"); + public static final String SPONGE_WORLD_DATA = "SpongeData"; } } @@ -429,7 +430,7 @@ public static final class World { .of(net.minecraft.core.Direction.WEST, net.minecraft.core.Direction.EAST, net.minecraft.core.Direction.DOWN, net.minecraft.core.Direction.UP, net.minecraft.core.Direction.NORTH, net.minecraft.core.Direction.SOUTH); public static final ResourceKey INVALID_WORLD_KEY = ResourceKey.sponge("invalid_world"); - public static final String LEVEL_DAT_OLD = LevelResource.LEVEL_DATA_FILE.getId() + "_old"; + public static final String LEVEL_DAT_OLD = LevelResource.LEVEL_DATA_FILE.id() + "_old"; public static final int DEFAULT_BLOCK_CHANGE_LIMIT = 512; } @@ -983,7 +984,7 @@ public static final class BlockChangeFlags { * Tell the block being changed that it's being moved, rather than being replaced/removed. * The flag, if set, is set as a boolean to {@link BlockState#onPlace(Level, BlockPos, BlockState, boolean)} * by means of calling - * {@link net.minecraft.world.level.chunk.LevelChunk#setBlockState(BlockPos, BlockState, boolean)} + * {@link net.minecraft.world.level.chunk.LevelChunk#setBlockState(BlockPos, BlockState, int)} */ public static final int BLOCK_MOVING = 1 << 6; // 64 /** diff --git a/src/main/java/org/spongepowered/common/world/generation/SpongeWorldGenerationConfigBuilder.java b/src/main/java/org/spongepowered/common/world/generation/SpongeWorldGenerationConfigBuilder.java index 4a2c4806dce..9fe37611274 100644 --- a/src/main/java/org/spongepowered/common/world/generation/SpongeWorldGenerationConfigBuilder.java +++ b/src/main/java/org/spongepowered/common/world/generation/SpongeWorldGenerationConfigBuilder.java @@ -61,7 +61,7 @@ public WorldGenerationConfig.Builder generateBonusChest(final boolean generateBo @Override public WorldGenerationConfig.Builder reset() { - final WorldOptions defaultSettings = SpongeCommon.server().getWorldData().worldGenOptions(); + final WorldOptions defaultSettings = SpongeCommon.server().getWorldGenSettings().options(); this.seed = defaultSettings.seed(); this.generateFeatures = defaultSettings.generateStructures(); this.generateBonusChest = defaultSettings.generateBonusChest(); diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java index 8ced7779669..705e136b9ce 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java @@ -24,22 +24,58 @@ */ package org.spongepowered.common.world.server; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.Registries; +import net.minecraft.server.bossevents.CustomBossEvents; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.WorldOptions; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; +import org.spongepowered.common.accessor.server.bossevents.CustomBossEventsAccessor; import org.spongepowered.common.config.inheritable.InheritableConfigHandle; import org.spongepowered.common.config.inheritable.WorldConfig; +import java.util.Optional; import java.util.UUID; public final class SpongeServerLevelData { + + public static final Codec CODEC = RecordCodecBuilder.create( + i -> i.group( + WorldOptions.CODEC.fieldOf("world_gen_options").stable().forGetter(SpongeServerLevelData::worldGenOptions), + CustomBossEventsAccessor.accessor$codec().optionalFieldOf("custom_boss_events").stable().forGetter(SpongeServerLevelData::customBossEvents), + UUIDUtil.CODEC.fieldOf("uuid").stable().forGetter(SpongeServerLevelData::uniqueId), + net.minecraft.resources.ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").stable().forGetter(SpongeServerLevelData::resourceKey) + ) + .apply(i, i.stable(SpongeServerLevelData::new)) + ); private @Nullable ResourceKey key; private UUID uniqueId = UUID.randomUUID(); private @Nullable InheritableConfigHandle configAdapter; + private WorldOptions worldGenOptions; + private @Nullable CustomBossEvents customBossEvents; + + public SpongeServerLevelData() { + } + + public SpongeServerLevelData(WorldOptions worldOptions, Optional customBossEvents, UUID uuid, Optional> levelResourceKey) { + this.worldGenOptions = worldOptions; + this.customBossEvents = customBossEvents.orElse(null); + this.uniqueId = uuid; + this.key = (ResourceKey) levelResourceKey.orElse(null); + } public @Nullable ResourceKey key() { return this.key; } + public Optional> resourceKey() { + return Optional.ofNullable((net.minecraft.resources.ResourceKey) (Object) this.key); + } + public void setKey(final ResourceKey key) { this.key = key; } @@ -52,6 +88,14 @@ public void setUniqueId(final UUID uniqueId) { this.uniqueId = uniqueId; } + public void setWorldGenOptions(final WorldGenSettings worldGenSettings) { + this.worldGenOptions = worldGenSettings.options(); + } + + public WorldOptions worldGenOptions() { + return this.worldGenOptions; + } + public @Nullable InheritableConfigHandle configAdapter() { return this.configAdapter; } @@ -59,4 +103,12 @@ public void setUniqueId(final UUID uniqueId) { public void setConfigAdapter(final InheritableConfigHandle adapter) { this.configAdapter = adapter; } + + public Optional customBossEvents() { + return Optional.ofNullable(this.customBossEvents); + } + + public void setCustomBossEvents(final CustomBossEvents customBossEvents) { + this.customBossEvents = customBossEvents; + } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 2874e4f0513..65214f10242 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -32,6 +32,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.MiscOverworldFeatures; import net.minecraft.resources.Identifier; @@ -76,7 +77,6 @@ import org.spongepowered.api.util.file.DeleteFileVisitor; import org.spongepowered.api.world.DefaultWorldKeys; import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.api.world.server.WorldArchetype; import org.spongepowered.api.world.server.WorldArchetypeType; @@ -158,7 +158,7 @@ public Path getDefaultWorldDirectory() { @Override public Optional world(final ResourceKey key) { return Optional.ofNullable((ServerWorld) this.worlds.get(SpongeWorldManager.createRegistryKey(Objects - .requireNonNull(key, "key")))); + .requireNonNull(key, "key")))); } @Override @@ -313,20 +313,20 @@ public CompletableFuture> loadWorld(final ResourceKey key, } private CompletableFuture> loadWorld0(final WorldOperationTask task, final net.minecraft.resources.ResourceKey registryKey, - final LevelDataLoadResult levelData, final LevelStorageSource.LevelStorageAccess storageSource) { + final LevelDataLoadResult levelData, final LevelStorageSource.LevelStorageAccess storageSource) { return CompletableFuture.>supplyAsync(() -> { - if (task.isCancelled()) { - return CompletableFuture.failedFuture(new CancellationException()); - } + if (task.isCancelled()) { + return CompletableFuture.failedFuture(new CancellationException()); + } - final ServerLevel world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); + final ServerLevel world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); - this.prepareLevel(world); + this.prepareLevel(world); - ((MinecraftServerAccessor) this.server).invoker$forceDifficulty(); + ((MinecraftServerAccessor) this.server).invoker$forceDifficulty(); - return this.loadSpawnChunksAsync(task, world); - }, SpongeCommon.server()) + return this.loadSpawnChunksAsync(task, world); + }, SpongeCommon.server()) .thenCompose(Function.identity()) .thenApply(w -> Optional.of((ServerWorld) w)); } @@ -411,7 +411,7 @@ public CompletableFuture> loadProperties(final R final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOptions.loadOperation().orElse(null); if (loadOperation != null && this.worldExists(key)) { try { - final Optional result = this.loadLevelData(registryKey, loadOperation); + final Optional result = this.loadLevelData(registryKey, loadOperation); if (result.isPresent()) { final ServerWorldProperties properties = (ServerWorldProperties) result.get().data(); loadOperation.loadCallback().ifPresent(c -> c.accept(properties)); @@ -458,7 +458,7 @@ public CompletableFuture saveProperties(final ServerWorldProperties pro private void saveLevelDat(final WorldData worldData, final ResourceKey key) throws IOException { try (var storageSource = this.createLevelStorageAccess(key)) { - storageSource.saveDataTag(this.server.registryAccess(), worldData, null); + storageSource.saveDataTag(worldData); } } @@ -556,7 +556,7 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr } try { - final Optional levelData = this.loadLevelData(copyRegistryKey, null); + final Optional levelData = this.loadLevelData(copyRegistryKey, null); if (levelData.isPresent()) { this.saveLevelDat(levelData.get().data(), copyKey); } @@ -628,7 +628,7 @@ private CompletableFuture moveWorld0(final ResourceKey key, final Resou } try { - final Optional levelData = this.loadLevelData(movedRegistryKey, null); + final Optional levelData = this.loadLevelData(movedRegistryKey, null); if (levelData.isPresent()) { this.saveLevelDat(levelData.get().data(), movedKey); } @@ -700,14 +700,14 @@ private CompletableFuture deleteWorld0(final ResourceKey key) { //to the overworld's level data where the level persist even when the data pack is removed. //This forcible removes it from there too. final Registry levelStemRegistry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM); - final net.minecraft.resources.ResourceKey levelStemKey = Registries.levelToLevelStem(registryKey); + final net.minecraft.resources.ResourceKey levelStemKey = Registries.levelToLevelStem(registryKey); if (levelStemRegistry.containsKey(levelStemKey)) { ((MappedRegistryBridge) levelStemRegistry).bridge$forceRemoveValue(Registries.levelToLevelStem(registryKey)); } final LevelStorageSource.LevelStorageAccess storageSource = ((MinecraftServerAccessor) this.server).accessor$storageSource(); final PrimaryLevelData levelData = (PrimaryLevelData) this.server.getWorldData(); - storageSource.saveDataTag(SpongeCommon.server().registryAccess(), levelData, null); + storageSource.saveDataTag(levelData); return true; }, SpongeCommon.server()); @@ -805,15 +805,18 @@ public void createNonDefaultLevels() { } private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey, - final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) throws IOException { + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) throws IOException { try (final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess((ResourceKey) (Object) registryKey.identifier())) { return this.loadLevelData(storageSource, registryKey, loadOperation); } } - private Optional loadLevelData(final LevelStorageSource.LevelStorageAccess storageSource, - final net.minecraft.resources.ResourceKey registryKey, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { - return Optional.ofNullable(this.loadLevelTag(storageSource)).map(t -> this.readLevelData(registryKey, t, loadOperation)); + private Optional loadLevelData( + final LevelStorageSource.LevelStorageAccess storageSource, + final net.minecraft.resources.ResourceKey registryKey, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation + ) { + return Optional.ofNullable(this.loadLevelTag(storageSource)).map(t -> this.readLevelData(storageSource, registryKey, t, loadOperation)); } private LevelDataLoadResult initializeLevelData(final ResourceKey key, final PrimaryLevelData data, final LevelStem stem) { @@ -826,10 +829,10 @@ private LevelDataLoadResult initializeLevelData(final ResourceKey key, final Pri private @Nullable Dynamic loadLevelTag(final LevelStorageSource.LevelStorageAccess storageSource) { try { - return storageSource.getDataTag(); + return storageSource.getUnfixedDataTag(false); } catch (final IOException e) { try { - final Dynamic dataTag = storageSource.getDataTagFallback(); + final Dynamic dataTag = storageSource.getUnfixedDataTagWithFallback(); storageSource.restoreLevelDataFromOld(); return dataTag; } catch (final IOException ex) { @@ -838,15 +841,19 @@ private LevelDataLoadResult initializeLevelData(final ResourceKey key, final Pri } } - private LevelDataLoadResult readLevelData(final net.minecraft.resources.ResourceKey registryKey, final Dynamic dataTag, - final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { + private LevelDataLoadResult readLevelData( + final LevelStorageSource.LevelStorageAccess worldAccess, + final net.minecraft.resources.ResourceKey registryKey, + final Dynamic dataTag, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation + ) { final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - final net.minecraft.core.RegistryAccess.Frozen access = this.server.registryAccess(); - final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions( + final RegistryAccess.Frozen access = this.server.registryAccess(); + final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions(worldAccess, dataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); final WorldArchetype worldArchetype = SpongeWorldManager.resolveWorldArchetype(levelData, registryKey, loadOperation); final LevelStem levelStem = (LevelStem) (Object) worldArchetype.type(); - final PrimaryLevelData worldData = (PrimaryLevelData) levelData.worldData(); + final PrimaryLevelData worldData = (PrimaryLevelData) levelData.worldDataAndGenSettings().data(); worldArchetype.generationConfig().ifPresent(o -> ((PrimaryLevelDataAccessor) worldData).accessor$worldOptions((WorldOptions) o)); ((PrimaryLevelDataAccessor) worldData).accessor$specialWorldProperty(SpongeWorldManager.specialWorldProperty(levelStem)); @@ -854,13 +861,13 @@ private LevelDataLoadResult readLevelData(final net.minecraft.resources.Resource } private static WorldArchetype resolveWorldArchetype(final LevelDataAndDimensions levelData, final net.minecraft.resources.ResourceKey registryKey, - final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { if (loadOperation != null && loadOperation.overrideWorldArchetype().isPresent()) { return loadOperation.overrideWorldArchetype().get(); } // Worlds that were loaded with Sponge know the associated world archetype. - final Optional spongeWorldKeyStem = Optional.ofNullable(((PrimaryLevelDataBridge) levelData.worldData()).bridge$spongeData().key()) + final Optional spongeWorldKeyStem = Optional.ofNullable(((PrimaryLevelDataBridge) levelData.worldDataAndGenSettings().data()).bridge$spongeData().key()) .flatMap(worldKey -> levelData.dimensions().dimensions().getOptional( Registries.levelToLevelStem(SpongeWorldManager.createRegistryKey(worldKey)))); if (spongeWorldKeyStem.isPresent()) { @@ -887,7 +894,7 @@ private LevelDataLoadResult createLevelData(final net.minecraft.resources.Resour final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.identifier())); return this.initializeLevelData( (ResourceKey) (Object) registryKey.identifier(), - new PrimaryLevelData(levelSettings, (WorldOptions) archetype.generationConfig().orElse((WorldGenerationConfig) defaultLevelData.worldGenOptions()), + new PrimaryLevelData(levelSettings, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem ); @@ -897,50 +904,53 @@ private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelDat return new LevelSettings( directoryName, defaultLevelData.getGameType(), - defaultLevelData.isHardcore(), - defaultLevelData.getDifficulty(), + defaultLevelData.getLevelSettings().difficultySettings(), defaultLevelData.isAllowCommands(), - defaultLevelData.getGameRules().copy(defaultLevelData.enabledFeatures()), - defaultLevelData.getDataConfiguration()); + defaultLevelData.getDataConfiguration() + ); } private ServerLevel createLevel( final net.minecraft.resources.ResourceKey registryKey, final LevelStem levelStem, final LevelStorageSource.LevelStorageAccess storageSource, - final PrimaryLevelData levelData) { + final PrimaryLevelData levelData + ) { final ResourceKey worldKey = (ResourceKey) (Object) registryKey.identifier(); final Registry dimensionTypes = this.server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); + final var saveDataSotrage = this.server.getDataStorage(); MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); final List spawners; if (levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD) || levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD_CAVES)) { - spawners = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(levelData)); + // TODO - 26.1-snapshot-6 figure out if we need to do anything here per world? + spawners = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(saveDataSotrage)); } else { spawners = ImmutableList.of(); } levelData.setModdedInfo(this.server.getServerModName(), this.server.getModdedStatus().shouldReportAsModified()); - - final long seed = BiomeManager.obfuscateSeed(levelData.worldGenOptions().seed()); + final var spongeData = ((PrimaryLevelDataBridge) levelData).bridge$spongeData(); + final var seed = BiomeManager.obfuscateSeed(spongeData.worldGenOptions().seed()); final Executor executor = ((MinecraftServerAccessor) this.server).accessor$executor(); final ServerLevel world = new ServerLevel(this.server, executor, storageSource, levelData, - registryKey, levelStem, levelData.isDebugWorld(), seed, spawners, true, null); + registryKey, levelStem, levelData.isDebugWorld(), seed, spawners, true); this.worlds.put(registryKey, world); // Ensure that the world border is registered. - levelData.getLegacyWorldBorderSettings().ifPresent(legacy -> { - final var border = world.getWorldBorder(); - border.setSize(legacy.size()); - border.setCenter(legacy.centerX(), legacy.centerZ()); - border.setSafeZone(legacy.safeZone()); - border.setDamagePerBlock(legacy.damagePerBlock()); - border.setWarningTime(legacy.warningTime()); - border.setWarningBlocks(legacy.warningBlocks()); - }); + // TODO - 26.1-snapshot-6 figure out if this is still required +// levelData.getLegacyWorldBorderSettings().ifPresent(legacy -> { +// final var border = world.getWorldBorder(); +// border.setSize(legacy.size()); +// border.setCenter(legacy.centerX(), legacy.centerZ()); +// border.setSafeZone(legacy.safeZone()); +// border.setDamagePerBlock(legacy.damagePerBlock()); +// border.setWarningTime(legacy.warningTime()); +// border.setWarningBlocks(legacy.warningBlocks()); +// }); PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); return world; } @@ -964,13 +974,14 @@ private ServerLevel prepareLevel(final ServerLevel level) { try { final boolean isDebugGeneration = worldData.isDebugWorld(); final boolean hasSpawnAlready = levelDataBridge.bridge$customSpawnPosition(); + final var spongeLevelData = levelDataBridge.bridge$spongeData(); if (!hasSpawnAlready) { if (levelDataBridge.bridge$performsSpawnLogic()) { - MinecraftServerAccessor.invoker$setInitialSpawn(level, levelData, worldData.worldGenOptions().generateBonusChest(), isDebugGeneration, server.getLevelLoadListener()); + MinecraftServerAccessor.invoker$setInitialSpawn(level, levelData, spongeLevelData.worldGenOptions().generateBonusChest(), isDebugGeneration, server.getLevelLoadListener()); } else if (Level.END.equals(level.dimension())) { levelData.setSpawn(new LevelData.RespawnData(new GlobalPos(level.dimension(), ServerLevel.END_SPAWN_POINT), 0, 0)); } - } else if (worldData.worldGenOptions().generateBonusChest()) { + } else if (spongeLevelData.worldGenOptions().generateBonusChest()) { final BlockPos pos = levelData.getRespawnData().pos(); final ConfiguredFeature bonusChestFeature = SpongeCommon.vanillaRegistry(Registries.CONFIGURED_FEATURE).getValue(MiscOverworldFeatures.BONUS_CHEST); bonusChestFeature.place(level, level.getChunkSource().getGenerator(), level.getRandom(), pos); @@ -980,7 +991,7 @@ private ServerLevel prepareLevel(final ServerLevel level) { ((MinecraftServerAccessor) this.server).invoker$setupDebugLevel(worldData); } } catch (final Throwable throwable) { - final CrashReport crashReport = CrashReport.forThrowable(throwable, "Exception initializing world '" + level.dimension().identifier() + "'"); + final CrashReport crashReport = CrashReport.forThrowable(throwable, "Exception initializing world '" + level.dimension().identifier() + "'"); try { level.fillReportDetails(crashReport); } catch (final Throwable ignore) { @@ -996,8 +1007,10 @@ private ServerLevel prepareLevel(final ServerLevel level) { // Initialize PlayerData in PlayerList, add WorldBorder listener. We change the method in PlayerList to handle per-world border this.server.getPlayerList().addWorldborderListener(level); - if (levelData instanceof WorldData worldData && worldData.getCustomBossEvents() != null) { - ((ServerLevelBridge) level).bridge$getBossBarManager().load(worldData.getCustomBossEvents(), level.registryAccess()); + final var customBossEvents = levelDataBridge.bridge$spongeData().customBossEvents(); + if (levelData instanceof WorldData worldData && customBossEvents != null) { + // TODO - re-add load to bossbarmanager +// ((ServerLevelBridge) level).bridge$getBossBarManager().load(customBossEvents, level.registryAccess()); } return level; @@ -1092,7 +1105,7 @@ private static PrimaryLevelData.SpecialWorldProperty specialWorldProperty(final } private CompletableFuture performWorldOperation(final net.minecraft.resources.ResourceKey worldKey, final WorldOperationType type, - final Function> function) { + final Function> function) { if (SpongeCommon.server().isStopped()) { return ExecutorUtil.serverManagedBlock(SpongeCommon.server(), function.apply(new WorldOperationTask(type, null))); } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java index 71665c9ac17..a95c4f80967 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTemplate.java @@ -51,7 +51,7 @@ public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem) { .group( SpongeAdventure.STRING_CODEC.optionalFieldOf("display_name").forGetter(v -> Optional.ofNullable(v.displayName)), Identifier.CODEC.optionalFieldOf("game_mode").forGetter(v -> Optional.ofNullable(v.gameMode).map(t -> Identifier.fromNamespaceAndPath("sponge", t.getName()))), - Identifier.CODEC.optionalFieldOf("difficulty").forGetter(v -> Optional.ofNullable(v.difficulty).map(t -> Identifier.fromNamespaceAndPath("sponge", t.getKey()))), + Identifier.CODEC.optionalFieldOf("difficulty").forGetter(v -> Optional.ofNullable(v.difficulty).map(t -> Identifier.fromNamespaceAndPath("sponge", t.getSerializedName()))), EnumCodec.create(SerializationBehavior.class).optionalFieldOf("serialization_behavior") .forGetter(v -> Optional.ofNullable(v.serializationBehavior)), Codec.INT.optionalFieldOf("view_distance").forGetter(v -> Optional.ofNullable(v.viewDistance)), @@ -74,7 +74,7 @@ public record SpongeWorldTemplate(ResourceKey key, LevelStem levelStem) { ) ); - public static final Codec DIRECT_CODEC = new MapCodec.MapCodecCodec(new SpongeDataCodec<>(LevelStem.CODEC, + public static final Codec DIRECT_CODEC = new MapCodec.MapCodecCodec(new SpongeDataCodec(LevelStem.CODEC, SpongeWorldTemplate.SPONGE_CODEC, (type, data) -> ((LevelStemBridge) (Object) type).bridge$decorateData(data), type -> null)); diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index 3cbe4ada94b..d325d82eb3f 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -122,6 +122,7 @@ public WorldType.Builder from(final WorldType type) { fixedTime != null, hasSkylight, hasCeiling, + false, coordinateMultiplier, floor, height, diff --git a/src/main/java/org/spongepowered/common/world/weather/SpongeWeather.java b/src/main/java/org/spongepowered/common/world/weather/SpongeWeather.java index a8281fe8437..ce0d59f14f9 100644 --- a/src/main/java/org/spongepowered/common/world/weather/SpongeWeather.java +++ b/src/main/java/org/spongepowered/common/world/weather/SpongeWeather.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.world.weather; -import net.minecraft.world.level.storage.ServerLevelData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.saveddata.WeatherData; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.Queries; import org.spongepowered.api.registry.RegistryTypes; @@ -32,11 +34,14 @@ import org.spongepowered.api.world.weather.Weather; import org.spongepowered.api.world.weather.WeatherType; import org.spongepowered.api.world.weather.WeatherTypes; +import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; public final class SpongeWeather implements Weather { + private static final RandomSource RANDOM = RandomSource.create(); + private final SpongeWeatherType type; private final Ticks remainingDuration, runningDuration; @@ -46,54 +51,55 @@ public SpongeWeather(final SpongeWeatherType type, final Ticks remainingDuration this.runningDuration = runningDuration; } - public static Weather of(final ServerLevelData levelData) { - final boolean thundering = levelData.isThundering(); + public static Weather of(final WeatherData weatherData) { + final boolean thundering = weatherData.isThundering(); if (thundering) { - final Ticks thunderTime = SpongeTicks.ticksOrInfinite(levelData.getThunderTime()); + final Ticks thunderTime = SpongeTicks.ticksOrInfinite(weatherData.getThunderTime()); return new SpongeWeather((SpongeWeatherType) WeatherTypes.THUNDER.get(), thunderTime, thunderTime.isInfinite() ? thunderTime - : new SpongeTicks(6000 - thunderTime.ticks())); + : new SpongeTicks(ServerLevel.THUNDER_DURATION.sample(RANDOM))); } - final boolean raining = levelData.isRaining(); + final boolean raining = weatherData.isRaining(); if (raining) { - final Ticks rainTime = SpongeTicks.ticksOrInfinite(levelData.getRainTime()); + final Ticks rainTime = SpongeTicks.ticksOrInfinite(weatherData.getRainTime()); return new SpongeWeather((SpongeWeatherType) WeatherTypes.RAIN.get(), rainTime, rainTime.isInfinite() ? rainTime - : new SpongeTicks(6000 - rainTime.ticks())); + : new SpongeTicks(ServerLevel.RAIN_DURATION.sample(RANDOM))); } - final Ticks clearWeatherTime = SpongeTicks.ticksOrInfinite(levelData.getClearWeatherTime()); + final Ticks clearWeatherTime = SpongeTicks.ticksOrInfinite(weatherData.getClearWeatherTime()); return new SpongeWeather((SpongeWeatherType) WeatherTypes.CLEAR.get(), clearWeatherTime, clearWeatherTime.isInfinite() ? clearWeatherTime - : new SpongeTicks(6000 - clearWeatherTime.ticks())); + : new SpongeTicks(ServerLevel.RAIN_DURATION.sample(RANDOM) + ServerLevel.THUNDER_DURATION.sample(RANDOM))); } - public static void apply(final ServerLevelData levelData, final Weather weather) { + public static void apply(final ServerLevelDataBridge levelData, final Weather weather) { + final var weatherData = levelData.bridge$level().getWeatherData(); final int time = SpongeTicks.toSaturatedIntOrInfinite(weather.remainingDuration()); final WeatherType type = weather.type(); if (type == WeatherTypes.CLEAR.get()) { - levelData.setClearWeatherTime(time); - levelData.setRaining(false); - levelData.setRainTime(0); - levelData.setThundering(false); - levelData.setThunderTime(0); + weatherData.setClearWeatherTime(time); + weatherData.setRaining(false); + weatherData.setRainTime(0); + weatherData.setThundering(false); + weatherData.setThunderTime(0); } else if (type == WeatherTypes.RAIN.get()) { - levelData.setRaining(true); - levelData.setRainTime(time); - levelData.setThundering(false); - levelData.setThunderTime(0); - levelData.setClearWeatherTime(0); + weatherData.setRaining(true); + weatherData.setRainTime(time); + weatherData.setThundering(false); + weatherData.setThunderTime(0); + weatherData.setClearWeatherTime(0); } else if (type == WeatherTypes.THUNDER.get()) { - levelData.setRaining(true); - levelData.setRainTime(time); - levelData.setThundering(true); - levelData.setThunderTime(time); - levelData.setClearWeatherTime(0); + weatherData.setRaining(true); + weatherData.setRainTime(time); + weatherData.setThundering(true); + weatherData.setThunderTime(time); + weatherData.setClearWeatherTime(0); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index 7b8631107ef..a81b0fa604c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -80,6 +80,7 @@ import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.commands.CommandsBridge; import org.spongepowered.common.bridge.server.MinecraftServerBridge; +import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.command.manager.SpongeCommandManager; import org.spongepowered.common.command.sponge.SpongeCommand; import org.spongepowered.common.datapack.SpongeDataPackManager; @@ -129,6 +130,7 @@ public abstract class MinecraftServerMixin_API implements SpongeServer, SpongeRe @Shadow public abstract PackRepository shadow$getPackRepository(); @Shadow public abstract net.minecraft.server.packs.resources.ResourceManager shadow$getResourceManager(); @Shadow public abstract WorldData shadow$getWorldData(); + @Shadow public abstract GameRules shadow$getGameRules(); // @formatter:on @@ -248,17 +250,17 @@ public boolean isGameModeEnforced() { @Override public boolean isPVPEnabled() { - return this.worldData.getGameRules().get(GameRules.PVP); + return this.shadow$getGameRules().get(GameRules.PVP); } @Override public boolean areCommandBlocksEnabled() { - return this.worldData.getGameRules().get(GameRules.COMMAND_BLOCKS_WORK); + return this.shadow$getGameRules().get(GameRules.COMMAND_BLOCKS_WORK); } @Override public boolean isMonsterSpawnsEnabled() { - return this.worldData.getGameRules().get(GameRules.SPAWN_MONSTERS); + return this.shadow$getGameRules().get(GameRules.SPAWN_MONSTERS); } @Override @@ -271,17 +273,13 @@ public boolean isAnimalSpawnsEnabled() { */ @Override public boolean isMultiWorldEnabled() { - return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getWorldData().getGameRules().get(GameRules.ALLOW_ENTERING_NETHER_USING_PORTALS); + return this.isSingleplayer() || ((Object) this instanceof DedicatedServer ds) && ds.getGameRules().get(GameRules.ALLOW_ENTERING_NETHER_USING_PORTALS); } @Override public WorldGenerationConfig worldGenerationConfig() { final WorldData overworldData = this.shadow$getWorldData(); - - final WorldGenSettings settings = new WorldGenSettings(overworldData.worldGenOptions(), - new WorldDimensions(this.registryAccess().lookupOrThrow(Registries.LEVEL_STEM))); - - return (WorldGenerationConfig) (Object) settings; + return (WorldGenerationConfig) (Object) ((PrimaryLevelDataBridge) overworldData.overworldData()).bridge$spongeData().worldGenOptions(); } @Override @@ -482,6 +480,7 @@ public BlockDestructionIdCache getBlockDestructionIdCache() { return this.api$blockDestructionIdCache; } + @SuppressWarnings("UnstableApiUsage") @Override public void sendMessage(final Identity identity, final Component message, final MessageType type) { this.shadow$getPlayerList().broadcastSystemMessage(SpongeAdventure.asVanilla(message), false); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index ff77c80f070..60bdb65d43c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -37,12 +37,11 @@ import net.minecraft.world.entity.raid.Raid; import net.minecraft.world.entity.raid.Raids; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.CollisionGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.storage.RegionFile; import net.minecraft.world.level.chunk.storage.RegionStorageInfo; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.storage.LevelResource; @@ -75,7 +74,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.entity.raid.RaidsAccessor; -import org.spongepowered.common.accessor.world.level.dimension.end.EndDragonFightAccessor; +import org.spongepowered.common.accessor.world.level.dimension.end.EnderDragonFightAccessor; import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.level.border.WorldBorderBridge; @@ -125,8 +124,9 @@ public abstract class ServerLevelMixin_API extends LevelMixin_API shadow$players(); @Shadow public abstract Raids shadow$getRaids(); @Nullable @Shadow public abstract Raid shadow$getRaidAt(BlockPos p_217475_1_); - @Nullable @Shadow public abstract EndDragonFight shadow$getDragonFight(); + @Nullable @Shadow public abstract EnderDragonFight shadow$getDragonFight(); @Shadow public abstract long shadow$getSeed(); + @Shadow public abstract net.minecraft.world.level.border.WorldBorder shadow$getWorldBorder(); // @formatter:on private volatile @MonotonicNonNull Pointers api$pointers; @@ -264,9 +264,9 @@ public Optional raidAt(final Vector3i blockPosi @Override public Optional dragonFightBossBar() { - final @Nullable EndDragonFight fight = this.shadow$getDragonFight(); + final @Nullable EnderDragonFight fight = this.shadow$getDragonFight(); if (fight != null) { - return Optional.of(SpongeAdventure.asAdventure(((EndDragonFightAccessor) fight).accessor$dragonEvent())); + return Optional.of(SpongeAdventure.asAdventure(((EnderDragonFightAccessor) fight).accessor$dragonEvent())); } else { return Optional.empty(); } @@ -339,14 +339,13 @@ public ChunkLayout chunkLayout() { @SuppressWarnings("deprecation") @Override public WorldBorder setBorder(final WorldBorder border) { - - final WorldBorderBridge borderBridge = (WorldBorderBridge) ((CollisionGetter) this).getWorldBorder(); + final var old = this.shadow$getWorldBorder(); + final WorldBorderBridge borderBridge = (WorldBorderBridge) old; borderBridge.bridge$setAssociatedWorld(this.key()); final WorldBorder worldBorder = borderBridge.bridge$applyFrom(border); if (worldBorder == null) { return (WorldBorder) (Object) net.minecraft.world.level.border.WorldBorder.Settings.DEFAULT; } - this.serverLevelData.setLegacyWorldBorderSettings(Optional.of((net.minecraft.world.level.border.WorldBorder.Settings) (Object) border)); return worldBorder; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index f8e589d5ac6..31ff6a5889f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -422,7 +422,7 @@ public boolean saveAllChunks(final boolean suppressLog, final boolean flush, fin // ServerLevel var2 = this.overworld(); // ServerLevelData var3 = this.worldData.overworldData(); // var3.setWorldBorder(var2.getWorldBorder().createSettings()); -// this.worldData.setCustomBossEvents(this.getCustomBossEvents().save(this.registryAccess())); +// this.worldData.setCustomBossEvents(this.customBossEvents().save(this.registryAccess())); // this.storageSource.saveDataTag(this.registryHolder, this.worldData, this.shadow$getPlayerList().getSingleplayerData()); // Sponge end diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java index 8888c156c8e..50c8cf45de0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/DifficultyCommandMixin.java @@ -44,7 +44,7 @@ public abstract class DifficultyCommandMixin { // @formatter:off - @Shadow @Final private static DynamicCommandExceptionType ERROR_ALREADY_DIFFICULT; + @Shadow @Final private static DynamicCommandExceptionType ERROR_ALREADY_SAME_DIFFICULTY; // @formatter:on /** @@ -54,11 +54,11 @@ public abstract class DifficultyCommandMixin { @Overwrite public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException { if (source.getLevel().getDifficulty() == difficulty) { - throw DifficultyCommandMixin.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); + throw DifficultyCommandMixin.ERROR_ALREADY_SAME_DIFFICULTY.create(difficulty.getSerializedName()); } else { final LevelData levelData = source.getLevel().getLevelData(); ((ServerWorldProperties) levelData).setDifficulty((org.spongepowered.api.world.difficulty.Difficulty) (Object) difficulty); - source.getLevel().setSpawnSettings(SpongeCommon.server().getWorldData().getGameRules().get(GameRules.SPAWN_MONSTERS)); + source.getLevel().setSpawnSettings(SpongeCommon.server().getGameRules().get(GameRules.SPAWN_MONSTERS)); source.getLevel().getPlayers(p -> true).forEach(p -> p.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()))); source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 7e6537ba98e..e5847a5afd3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -50,7 +50,6 @@ import net.minecraft.util.Util; import net.minecraft.util.random.WeightedList; import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.RandomSequences; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.LightningBolt; @@ -73,16 +72,18 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity; -import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.storage.DimensionDataStorage; +import net.minecraft.world.level.saveddata.WeatherData; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.SavedDataStorage; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.phys.Vec3; @@ -131,6 +132,7 @@ import org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge; import org.spongepowered.common.bridge.world.level.dimension.DimensionTypeBridge; import org.spongepowered.common.bridge.world.level.storage.DimensionDataStorageBridge; +import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.bridge.world.ticks.LevelTicksBridge; import org.spongepowered.common.config.SpongeGameConfigs; @@ -168,11 +170,12 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Shadow @NonNull public abstract MinecraftServer shadow$getServer(); @Shadow @Final private MinecraftServer server; - @Shadow @Nullable private EndDragonFight dragonFight; + @Shadow @Nullable private EnderDragonFight dragonFight; @Shadow @Final List players; - @Shadow public abstract DimensionDataStorage shadow$getDataStorage(); + @Shadow public abstract SavedDataStorage shadow$getDataStorage(); @Shadow public abstract DifficultyInstance shadow$getCurrentDifficultyAt(BlockPos p_175649_1_); + @Shadow public abstract WeatherData shadow$getWeatherData(); // @formatter:on @@ -187,10 +190,17 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Inject(method = "", at = @At("TAIL")) private void impl$onInit( - final MinecraftServer server, final Executor executor, final LevelStorageSource.LevelStorageAccess storage, - final ServerLevelData levelData, final net.minecraft.resources.ResourceKey key, final LevelStem levelStem, - final boolean debug, final long biomeSeed, final List spawners, final boolean tick, - final RandomSequences randomSequences, final CallbackInfo ci + final MinecraftServer server, + final Executor executor, + final LevelStorageSource.LevelStorageAccess storage, + final ServerLevelData levelData, + final net.minecraft.resources.ResourceKey dimension, + final LevelStem levelStem, + final boolean isDebug, + final long biomeZoomSeed, + final List customSpawners, + final boolean tickTime, + final CallbackInfo ci ) { final SpongeServerLevelData spongeData = ((ServerLevelDataBridge) levelData).bridge$spongeData(); @@ -215,8 +225,9 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final Boolean createDragonFight = ((DimensionTypeBridge) (Object) this.shadow$dimensionType()).bridge$createDragonFight(); if (createDragonFight != null) { if (createDragonFight) { - final long seed = server.getWorldData().worldGenOptions().seed(); - this.dragonFight = new EndDragonFight((ServerLevel) (Object) this, seed, server.getWorldData().endDragonFightData()); + final long seed = spongeData.worldGenOptions().seed(); + this.dragonFight = this.shadow$getDataStorage().computeIfAbsent(EnderDragonFight.TYPE); + this.dragonFight.init((ServerLevel) (Object) this, seed, BlockPos.ZERO); } else { this.dragonFight = null; } @@ -290,8 +301,8 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final ServerExplosion mcExplosion = (ServerExplosion) explosion; try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker) - .explosion(mcExplosion) - .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { + .explosion(mcExplosion) + .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { ignored.buildAndSwitch(); mcExplosion.explode(); @@ -322,6 +333,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel var newPacket = new ClientboundExplodePacket(packet.center(), packet.radius(), packet.blockCount(), packet.playerKnockback(), particleData, soundEvent, packet.blockParticles()); instance.send(newPacket); } + @Override public void bridge$setManualSave(final boolean state) { this.impl$isManualSave = state; @@ -340,10 +352,10 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } final SpongeBlockSnapshot.BuilderImpl builder = SpongeBlockSnapshot.BuilderImpl.pooled(); builder.world((ServerLevel) (Object) this).position(new Vector3i(x, y, z)); - final net.minecraft.world.level.chunk.LevelChunk chunk = this.shadow$getChunkAt(pos); - final net.minecraft.world.level.block.state.BlockState state = chunk.getBlockState(pos); + final LevelChunk chunk = this.shadow$getChunkAt(pos); + final BlockState state = chunk.getBlockState(pos); builder.blockState(state); - final net.minecraft.world.level.block.entity.BlockEntity blockEntity = chunk.getBlockEntity(pos, net.minecraft.world.level.chunk.LevelChunk.EntityCreationType.CHECK); + final BlockEntity blockEntity = chunk.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); if (blockEntity != null) { TrackingUtil.addTileEntityToBuilder(blockEntity, builder); } @@ -393,13 +405,18 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel if (behavior != SerializationBehavior.NONE) { original.call(self, flush); - // per-world WorldInfo/WorldBorder/BossBars - final var border = this.getWorldBorder(); - levelData.setLegacyWorldBorderSettings(Optional.of(new WorldBorder.Settings(border))); - if (levelData instanceof WorldData worldData) { - worldData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); - this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), worldData, this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null); - } + // per-world WorldInfo/WorldBorder/BossBars/WorldGen + // TODO - 26.1-snapshot-6 figure out if this is still required +// final var border = this.getWorldBorder(); +// if (levelData instanceof PrimaryLevelDataBridge pldb) { +// final var spongeData = pldb.bridge$spongeData(); +// this.bridge$getLevelSave().saveLevelData(); +// } +// levelData.setLegacyWorldBorderSettings(Optional.of(new WorldBorder.Settings(border))); +// if (levelData instanceof WorldData worldData) { +// worldData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); +// this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), worldData, this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null); +// } } } @@ -416,9 +433,22 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPost(currentCause, (ServerWorld) this)); } + @WrapOperation(method = "advanceWeatherCycle", + at = { + @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/WeatherData;isThundering()Z"), + @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/WeatherData;isRaining()Z") + } + ) + private boolean impl$handleIsThunderingIfHasCeiling(final WeatherData instance, final Operation original) { + if (this.levelData instanceof PrimaryLevelDataBridge pldb && pldb.bridge$dimensionType() != null) { + return pldb.bridge$dimensionType().hasCeiling() && original.call(instance); + } + return original.call(instance); + } + @Inject(method = "advanceWeatherCycle", - locals = LocalCapture.CAPTURE_FAILEXCEPTION, - at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerLevel;oRainLevel:F", shift = At.Shift.BEFORE, ordinal = 1)) + locals = LocalCapture.CAPTURE_FAILEXCEPTION, + at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerLevel;oRainLevel:F", shift = At.Shift.BEFORE, ordinal = 1)) public void impl$onSetWeatherParameters(final CallbackInfo ci, final boolean $$0) { final boolean isRaining = this.shadow$isRaining(); if (this.oRainLevel != this.rainLevel || this.oThunderLevel != this.thunderLevel || $$0 != isRaining) { @@ -433,24 +463,27 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } // Set event results + // TODO - 26.1-snapshot-6 revamp weather with a timelines api. this.impl$prevWeather = newWeather; if (newWeather.type() == WeatherTypes.CLEAR.get()) { - this.serverLevelData.setThunderTime(0); - this.serverLevelData.setRainTime(0); - this.serverLevelData.setClearWeatherTime(SpongeTicks.toSaturatedIntOrInfinite(newWeather.remainingDuration())); - this.serverLevelData.setThundering(false); - this.serverLevelData.setRaining(false); + final var weatherData = this.shadow$getWeatherData(); + weatherData.setClearWeatherTime(SpongeTicks.toSaturatedIntOrInfinite(newWeather.remainingDuration())); + weatherData.setRainTime(0); + weatherData.setRaining(false); + weatherData.setThunderTime(0); + weatherData.setThundering(false); } else { final int newTime = SpongeTicks.toSaturatedIntOrInfinite(newWeather.remainingDuration()); - this.serverLevelData.setRaining(true); - this.serverLevelData.setClearWeatherTime(0); - this.serverLevelData.setRainTime(newTime); + final var weatherData = this.shadow$getWeatherData(); + weatherData.setRaining(true); + weatherData.setRainTime(newTime); + weatherData.setClearWeatherTime(0); if (newWeather.type() == WeatherTypes.THUNDER.get()) { - this.serverLevelData.setThunderTime(newTime); - this.serverLevelData.setThundering(true); + weatherData.setThundering(true); + weatherData.setThunderTime(newTime); } else { - this.serverLevelData.setThunderTime(0); - this.serverLevelData.setThundering(false); + weatherData.setThunderTime(0); + weatherData.setThundering(false); } } } @@ -458,7 +491,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } @WrapOperation(method = "tickThunder", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;isRainingAt(Lnet/minecraft/core/BlockPos;)Z")) + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;isRainingAt(Lnet/minecraft/core/BlockPos;)Z")) private boolean impl$onBeforeThunder( final ServerLevel serverLevel, final BlockPos param0, final Operation wrapped ) { @@ -502,17 +535,17 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Inject(method = "levelEvent", at = @At("HEAD"), cancellable = true) private void impl$throwBroadcastEvent(final Entity player, final int eventID, final BlockPos pos, final int dataID, CallbackInfo ci) { - if(eventID == Constants.WorldEvents.PLAY_RECORD_EVENT && ShouldFire.PLAY_SOUND_EVENT_FROM_JUKEBOX) { + if (eventID == Constants.WorldEvents.PLAY_RECORD_EVENT && ShouldFire.PLAY_SOUND_EVENT_FROM_JUKEBOX) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { final BlockEntity tileEntity = this.shadow$getBlockEntity(pos); - if(tileEntity instanceof JukeboxBlockEntity) { + if (tileEntity instanceof JukeboxBlockEntity) { final JukeboxBlockEntity jukebox = (JukeboxBlockEntity) tileEntity; final ItemStack record = jukebox.getItem(0); frame.pushCause(jukebox); frame.addContext(EventContextKeys.USED_ITEM, ItemStackUtil.snapshotOf(record)); if (!record.isEmpty()) { final Optional recordProperty = ((org.spongepowered.api.item.inventory.ItemStack) (Object) record).get(Keys.MUSIC_DISC); - if(!recordProperty.isPresent()) { + if (!recordProperty.isPresent()) { //Safeguard for https://github.com/SpongePowered/SpongeCommon/issues/2337 return; } @@ -577,9 +610,9 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel public String toString() { final Optional worldTypeKey = Optional.ofNullable(this.server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE).getKey(this.shadow$dimensionType())).map(ResourceKey.class::cast); return new StringJoiner(",", ServerLevel.class.getSimpleName() + "[", "]") - .add("key=" + this.shadow$dimension()) - .add("worldType=" + worldTypeKey.map(ResourceKey::toString).orElse("inline")) - .toString(); + .add("key=" + this.shadow$dimension()) + .add("worldType=" + worldTypeKey.map(ResourceKey::toString).orElse("inline")) + .toString(); } @Redirect( @@ -605,11 +638,11 @@ public String toString() { throw new IllegalArgumentException("A Player cannot be created by the API!"); } - net.minecraft.world.entity.Entity entity = null; + Entity entity = null; final double x = position.x(); final double y = position.y(); final double z = position.z(); - final net.minecraft.world.level.Level thisWorld = (net.minecraft.world.level.Level) (Object) this; + final Level thisWorld = (Level) (Object) this; // Not all entities have a single World parameter as their constructor if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java deleted file mode 100644 index 5f9a39ba240..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/structure/LegacyStructureDataHandlerMixin.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.level.levelgen.structure; - -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.mojang.datafixers.DataFixer; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.storage.LegacyTagFixer; -import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; -import net.minecraft.world.level.storage.DimensionDataStorage; -import org.jspecify.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.bridge.world.level.storage.DimensionDataStorageBridge; - -import java.util.function.Supplier; - -@Mixin(LegacyStructureDataHandler.class) -public abstract class LegacyStructureDataHandlerMixin { - - @WrapMethod(method = "getLegacyTagFixer") - private static Supplier impl$fixupLevelDimension(final ResourceKey dimension, final Supplier<@Nullable DimensionDataStorage> dataStorage, - final DataFixer fixer, final Operation> original) { - return () -> { - ResourceKey dim = dimension; - final Identifier dimKey = ((DimensionDataStorageBridge) dataStorage.get()).bridge$dimensionKey(); - if (dimKey != null) { - dim = ResourceKey.create(Registries.DIMENSION, dimKey); - } - return original.call(dim, dataStorage, fixer).get(); - }; - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java deleted file mode 100644 index da13a3800b3..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataSotrageMixin.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.core.world.level.storage; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.saveddata.SavedData; -import net.minecraft.world.level.saveddata.SavedDataType; -import net.minecraft.world.level.storage.DimensionDataStorage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.bridge.data.DataCompoundHolder; -import org.spongepowered.common.data.DataUtil; - -@Mixin(DimensionDataStorage.class) -public abstract class DimensionDataSotrageMixin { - - @WrapOperation(method = "encodeUnchecked", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;" - ) - ) - public Tag impl$writeAdditionalMapNBT( - final CompoundTag instance, final String key, final Tag encoded, - final Operation original, final SavedDataType type, - final SavedData data, final RegistryOps registry - ) { - if (data instanceof DataCompoundHolder dch) { - if (DataUtil.syncDataToTag(dch)) { - instance.merge(dch.data$getCompound()); - } - } - return original.call(instance, key, encoded); - } -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 7f91e1ac0d6..579b73fee6d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -98,9 +98,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Shadow public abstract void shadow$setSpawn(LevelData.RespawnData $$0); // @formatter:on - @Shadow - private boolean difficultyLocked; - private final SpongeServerLevelData impl$spongeData = new SpongeServerLevelData(); + private SpongeServerLevelData impl$spongeData = new SpongeServerLevelData(); private DimensionType impl$dimensionType; private ChunkGenerator impl$chunkGenerator; @@ -238,14 +236,17 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat if (gameType != null) { this.impl$customGameType = true; } + final var difficultySettings = new LevelSettings.DifficultySettings( + difficulty == null ? this.settings.difficultySettings().difficulty() : difficulty, + isHardcore == null ? this.settings.difficultySettings().hardcore() : isHardcore, + false + ); this.settings = new LevelSettings( this.settings.levelName(), gameType == null ? this.settings.gameType() : gameType, - isHardcore == null ? this.settings.hardcore() : isHardcore, - difficulty == null ? this.settings.difficulty() : difficulty, + difficultySettings, allowCommands == null ? this.settings.allowCommands() : allowCommands, - this.settings.gameRules(), - this.settings.getDataConfiguration()); + this.settings.dataConfiguration()); final Vector3i spawnPos = bridge.bridge$spawnPosition(); if (spawnPos != null) { @@ -291,7 +292,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat } else if (server.isSingleplayer()) { level.setSpawnSettings(difficulty != Difficulty.PEACEFUL); } else { - level.setSpawnSettings(server.getWorldData().getGameRules().get(GameRules.SPAWN_MONSTERS)); + level.setSpawnSettings(server.getGameRules().get(GameRules.SPAWN_MONSTERS)); } level.players().forEach(player -> player.connection.send(new ClientboundChangeDifficultyPacket(difficulty, isLocked))); @@ -310,6 +311,9 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Override @SuppressWarnings({"deprecated","deprecation"}) public void bridge$readSpongeLevelData(final Dynamic dynamic) { + dynamic.get(Constants.Sponge.Data.V3.SPONGE_WORLD_DATA).read(SpongeServerLevelData.CODEC).ifSuccess(ssld -> { + this.impl$spongeData = ssld; + }); dynamic.get(Constants.Sponge.Data.V2.SPONGE_DATA).get().ifSuccess(v2 -> { v2.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(this.impl$spongeData::setUniqueId); v2.get(Constants.Sponge.World.WORLD_KEY).read(Identifier.CODEC).result() @@ -368,21 +372,6 @@ public String toString() { .add("difficulty=" + this.getDifficulty()) .toString(); } - - @Inject(method = "isRaining", at = @At(value = "HEAD"), cancellable = true) - private void impl$onIsRaining(final CallbackInfoReturnable cir) { - if (this.impl$dimensionType.hasCeiling()) { - cir.setReturnValue(false); - } - } - - @Inject(method = "isThundering", at = @At(value = "HEAD"), cancellable = true) - private void impl$onIsThundering(final CallbackInfoReturnable cir) { - if (this.impl$dimensionType.hasCeiling()) { - cir.setReturnValue(false); - } - } - @Override public CompoundTag data$getCompound() { return this.impl$compound; @@ -393,15 +382,16 @@ public String toString() { this.impl$compound = nbt; } - @Redirect(method = "setTagData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldGenSettings;encode(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/world/level/levelgen/WorldOptions;Lnet/minecraft/core/RegistryAccess;)Lcom/mojang/serialization/DataResult;")) - private DataResult impl$onEncodeWorldGenSettings(final DynamicOps $$0, final WorldOptions $$1, final RegistryAccess $$2) { - final Map, LevelStem> dimensions = $$2.lookupOrThrow(Registries.LEVEL_STEM) - .listElements() - .collect(Collectors.toMap(Holder.Reference::key, Holder.Reference::value)); - if (this.impl$dimensionType != null && this.impl$chunkGenerator != null) { - dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (Identifier) (Object) this.impl$spongeData.key()), - $ -> new LevelStem($$2.lookupOrThrow(Registries.DIMENSION_TYPE).wrapAsHolder(this.impl$dimensionType), this.impl$chunkGenerator)); - } - return WorldGenSettings.encode($$0, $$1, new WorldDimensions(dimensions)); - } + // TODO - 26.1-snapshot-6 - figure out where to shove this in now? Do we just append it to the level data or keep it in sponge data? +// @Redirect(method = "setTagData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldGenSettings;encode(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/world/level/levelgen/WorldOptions;Lnet/minecraft/core/RegistryAccess;)Lcom/mojang/serialization/DataResult;")) +// private DataResult impl$onEncodeWorldGenSettings(final DynamicOps $$0, final WorldOptions $$1, final RegistryAccess $$2) { +// final Map, LevelStem> dimensions = $$2.lookupOrThrow(Registries.LEVEL_STEM) +// .listElements() +// .collect(Collectors.toMap(Holder.Reference::key, Holder.Reference::value)); +// if (this.impl$dimensionType != null && this.impl$chunkGenerator != null) { +// dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (Identifier) (Object) this.impl$spongeData.key()), +// $ -> new LevelStem($$2.lookupOrThrow(Registries.DIMENSION_TYPE).wrapAsHolder(this.impl$dimensionType), this.impl$chunkGenerator)); +// } +// return WorldGenSettings.encode($$0, $$1, new WorldDimensions(dimensions)); +// } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java similarity index 72% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java index 2d0dffbf6df..907e2aca975 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java @@ -28,8 +28,12 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.resources.Identifier; -import net.minecraft.world.level.storage.DimensionDataStorage; +import net.minecraft.resources.RegistryOps; +import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.saveddata.SavedDataType; +import net.minecraft.world.level.storage.SavedDataStorage; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -39,13 +43,31 @@ import java.util.Optional; -@Mixin(DimensionDataStorage.class) -public abstract class DimensionDataStorageMixin implements DimensionDataStorageBridge { +@Mixin(SavedDataStorage.class) +public abstract class SavedDataStorageMixin implements DimensionDataStorageBridge { // @formatter:off private @Nullable Identifier impl$dimensionKey; // @formatter:on + @WrapOperation(method = "encodeUnchecked", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;" + ) + ) + public Tag impl$writeAdditionalMapNBT( + final CompoundTag instance, final String key, final Tag encoded, + final Operation original, final SavedDataType type, + final SavedData data, final RegistryOps registry + ) { + if (data instanceof DataCompoundHolder dch) { + if (DataUtil.syncDataToTag(dch)) { + instance.merge(dch.data$getCompound()); + } + } + return original.call(instance, key, encoded); + } + @WrapOperation(method = "readSavedData", at = @At(value = "INVOKE", target = "Ljava/util/Optional;orElse(Ljava/lang/Object;)Ljava/lang/Object;")) public T readSpongeMapData( final Optional instance, final T other, final Operation original, diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java index 0f5e5193d68..b25739c6ebf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.tracker.world.level.dimension.end; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; @@ -31,10 +33,9 @@ import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.dimension.end.DragonRespawnAnimation; -import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.level.dimension.end.DragonRespawnStage; +import net.minecraft.world.level.dimension.end.EnderDragonFight; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -47,27 +48,26 @@ import java.util.List; -@Mixin(EndDragonFight.class) +@Mixin(EnderDragonFight.class) public abstract class EndDragonFightMixin_Tracker { // @formatter:off - @Shadow @Final private ServerLevel level; - - @Shadow protected abstract EnderDragon shadow$createNewDragon(); + @Shadow private ServerLevel level; // @formatter:on @Redirect(method = "lambda$spawnNewGateway$1", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/feature/ConfiguredFeature;place(Lnet/minecraft/world/level/WorldGenLevel;Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/util/RandomSource;Lnet/minecraft/core/BlockPos;)Z")) - private boolean tracker$switchToFeatureState(final ConfiguredFeature configuredFeature, final WorldGenLevel worldIn, final ChunkGenerator generator, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/feature/ConfiguredFeature;place(Lnet/minecraft/world/level/WorldGenLevel;Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/util/RandomSource;Lnet/minecraft/core/BlockPos;)Z")) + private boolean tracker$switchToFeatureState( + final ConfiguredFeature configuredFeature, final WorldGenLevel worldIn, final ChunkGenerator generator, final RandomSource rand, final BlockPos pos ) { try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn.getLevel()))) { context - .world((ServerLevel) worldIn) - .generator(generator) - .feature(configuredFeature.feature()) - .origin(pos) + .world((ServerLevel) worldIn) + .generator(generator) + .feature(configuredFeature.feature()) + .origin(pos) ; context.buildAndSwitch(); @@ -75,30 +75,32 @@ public abstract class EndDragonFightMixin_Tracker { } } - @Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/DragonRespawnAnimation;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/dimension/end/EndDragonFight;Ljava/util/List;ILnet/minecraft/core/BlockPos;)V")) - private void tracker$switchToSpawnDragonState(final DragonRespawnAnimation dragonSpawnState, final ServerLevel worldIn, - final EndDragonFight manager, final List crystals, int respawnStateTicks, final BlockPos exitPortalLocation) { - try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(worldIn))) { + @WrapOperation(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/DragonRespawnStage;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/dimension/end/EnderDragonFight;Ljava/util/List;I)V")) + private void tracker$switchToSpawnDragonState( + final DragonRespawnStage instance, final ServerLevel serverLevel, final EnderDragonFight manager, + final List endCrystals, int i, final Operation original + ) { + try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(serverLevel))) { context - .manager(manager) - .setIsRespawn(true) - .buildAndSwitch() + .manager(manager) + .setIsRespawn(true) + .buildAndSwitch() ; - ++respawnStateTicks; - dragonSpawnState.tick(worldIn, manager, crystals, respawnStateTicks, exitPortalLocation); + ++i; + original.call(instance, serverLevel, manager, endCrystals, i); } } - @Redirect(method = "findOrCreateDragon", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/EndDragonFight;createNewDragon()Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;")) - private EnderDragon tracker$switchToSpawnDragonState(final EndDragonFight manager) { + @WrapOperation(method = "findOrCreateDragon", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/EnderDragonFight;createNewDragon()Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;")) + private EnderDragon tracker$switchToSpawnDragonState(final EnderDragonFight manager, final Operation original) { try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(this.level))) { context - .manager(manager) - .setIsRespawn(false) - .buildAndSwitch() + .manager(manager) + .setIsRespawn(false) + .buildAndSwitch() ; - return this.shadow$createNewDragon(); + return original.call(manager); } } } diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 169bfccd565..6b6125c3a40 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -276,11 +276,9 @@ "world.level.levelgen.WorldDimensionsMixin", "world.level.levelgen.flat.FlatLayerInfoMixin", "world.level.levelgen.flat.FlatLevelGeneratorSettingsMixin", - "world.level.levelgen.structure.LegacyStructureDataHandlerMixin", "world.level.saveddata.MapIdTrackerMixin", "world.level.storage.DerivedLevelDataMixin", - "world.level.storage.DimensionDataSotrageMixin", - "world.level.storage.DimensionDataStorageMixin", + "world.level.storage.SavedDataStorageMixin", "world.level.storage.LevelDataMixin", "world.level.storage.LevelStorageSource_LevelStorageAccessMixin", "world.level.storage.PlayerDataStorageMixin", From 327e722d1412b555df0973e17618478658f1e0c7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 15 Mar 2026 00:26:39 -0700 Subject: [PATCH 476/586] feat(minecraft): update to 26.1-snapshot-6 wip More compile and application fixes. See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_6 --- .../world/level/LevelSettingsAccessor.java | 40 ------------------ .../storage/PrimaryLevelDataAccessor.java | 3 -- .../resources/mixins.sponge.accessors.json | 1 - .../world/server/SpongeServerLevelData.java | 4 ++ .../world/server/SpongeWorldManager.java | 2 +- .../storage/ServerLevelDataMixin_API.java | 42 +++++++++---------- .../HackyBossBarPlatformBridgeMixin.java | 9 +++- .../core/server/MinecraftServerMixin.java | 17 +++++--- .../bossevents/CustomBossEventMixin.java | 5 ++- ...StorageSource_LevelStorageAccessMixin.java | 9 ++-- .../level/storage/PrimaryLevelDataMixin.java | 35 ++++++++-------- .../LevelStorageSourceMixin_Vanilla.java | 13 +++--- 12 files changed, 74 insertions(+), 106 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/level/LevelSettingsAccessor.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/LevelSettingsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/LevelSettingsAccessor.java deleted file mode 100644 index 75e65bc5b83..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/LevelSettingsAccessor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.level; - -import net.minecraft.world.level.LevelSettings; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(LevelSettings.class) -public interface LevelSettingsAccessor { - - @Accessor("hardcore") - @Mutable void accessor$hardcore(final boolean hardcore); - - @Accessor("allowCommands") - @Mutable void accessor$allowCommands(final boolean allowCommands); -} diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java index a0ea05e5271..aa58bcfdee3 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/level/storage/PrimaryLevelDataAccessor.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.accessor.world.level.storage; -import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.PrimaryLevelData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -33,7 +32,5 @@ @Mixin(PrimaryLevelData.class) public interface PrimaryLevelDataAccessor { - @Accessor("worldOptions") @Mutable void accessor$worldOptions(WorldOptions worldOptions); - @Accessor("specialWorldProperty") @Mutable void accessor$specialWorldProperty(PrimaryLevelData.SpecialWorldProperty specialWorldProperty); } diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index d8f22a0bbf0..3cc65ae0fc2 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -157,7 +157,6 @@ "world.level.GameRules_ValueAccessor", "world.level.GameRulesAccessor", "world.level.LevelAccessor", - "world.level.LevelSettingsAccessor", "world.level.NaturalSpawnerAccessor", "world.level.ServerExplosionAccessor", "world.level.TicketStorageAccessor", diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java index 705e136b9ce..c8281d8d7f1 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java @@ -92,6 +92,10 @@ public void setWorldGenOptions(final WorldGenSettings worldGenSettings) { this.worldGenOptions = worldGenSettings.options(); } + public void setWorldOptions(final WorldOptions options) { + this.worldGenOptions = options; + } + public WorldOptions worldGenOptions() { return this.worldGenOptions; } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 65214f10242..31b00fce843 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -855,7 +855,7 @@ private LevelDataLoadResult readLevelData( final LevelStem levelStem = (LevelStem) (Object) worldArchetype.type(); final PrimaryLevelData worldData = (PrimaryLevelData) levelData.worldDataAndGenSettings().data(); worldArchetype.generationConfig().ifPresent(o -> - ((PrimaryLevelDataAccessor) worldData).accessor$worldOptions((WorldOptions) o)); + ((PrimaryLevelDataBridge) worldData).bridge$spongeData().setWorldOptions((WorldOptions) o)); ((PrimaryLevelDataAccessor) worldData).accessor$specialWorldProperty(SpongeWorldManager.specialWorldProperty(levelStem)); return this.initializeLevelData((ResourceKey) (Object) registryKey.identifier(), worldData, levelStem); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java index b5d863d95dc..4dc6fe1b452 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.clock.PackedClockStates; import net.minecraft.world.clock.WorldClocks; import net.minecraft.world.level.gamerules.GameRuleMap; @@ -43,6 +44,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.accessor.server.level.ServerLevelAccessor; import org.spongepowered.common.accessor.world.level.GameRulesAccessor; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.util.Constants; @@ -60,21 +62,8 @@ public interface ServerLevelDataMixin_API extends ServerWorldProperties { // @formatter:off - @Shadow int shadow$getWanderingTraderSpawnDelay(); - @Shadow void shadow$setWanderingTraderSpawnDelay(int p_230396_1_); - @Shadow int shadow$getWanderingTraderSpawnChance(); - @Shadow void shadow$setWanderingTraderSpawnChance(int p_230397_1_); - @Shadow void shadow$setWanderingTraderId(UUID p_230394_1_); - @Shadow @Nullable UUID shadow$getWanderingTraderId(); - @Shadow GameRules shadow$getGameRules(); // @formatter:on - @Shadow - PackedClockStates clockStates(); - - @Shadow - void setClockStates(PackedClockStates packedClocks); - @Override default ResourceKey key() { return Objects.requireNonNull(((ServerLevelDataBridge) this).bridge$spongeData().key()); @@ -97,7 +86,7 @@ default UUID uniqueId() { @Override default V gameRule(GameRule gameRule) { - final var value = this.shadow$getGameRules().get((net.minecraft.world.level.gamerules.GameRule) (Object) Objects.requireNonNull(gameRule, + final var value = ((ServerLevelDataBridge) this).bridge$level().getGameRules().get((net.minecraft.world.level.gamerules.GameRule) (Object) Objects.requireNonNull(gameRule, "gameRule")); return (V) value; } @@ -107,12 +96,12 @@ default void setGameRule(final GameRule gameRule, final V value) { Objects.requireNonNull(gameRule, "gameRule"); Objects.requireNonNull(value, "value"); - this.shadow$getGameRules().set((net.minecraft.world.level.gamerules.GameRule) (Object) gameRule, value, SpongeCommon.server()); + ((ServerLevelDataBridge) this).bridge$level().getGameRules().set((net.minecraft.world.level.gamerules.GameRule) (Object) gameRule, value, SpongeCommon.server()); } @Override default Map, ?> gameRules() { - final GameRuleMap rules = ((GameRulesAccessor) this.shadow$getGameRules()).accessor$rules(); + final GameRuleMap rules = ((GameRulesAccessor) ((ServerLevelDataBridge) this).bridge$level().getGameRules()).accessor$rules(); final Map, Object> apiRules = new HashMap<>(); for (final var rule : rules.keySet()) { final GameRule key = (GameRule) (Object) rule; @@ -129,32 +118,39 @@ default void setDayTime(final MinecraftDayTime dayTime) { @Override default Ticks wanderingTraderSpawnDelay() { - return SpongeTicks.ticksOrInfinite(this.shadow$getWanderingTraderSpawnDelay()); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + final var level = ((ServerLevelDataBridge) this).bridge$level(); + if (level instanceof ServerLevelAccessor sla) { + sla.cu + } + return SpongeTicks.ticksOrInfinite(0); } @Override default void setWanderingTraderSpawnDelay(final Ticks delay) { - this.shadow$setWanderingTraderSpawnDelay(SpongeTicks.toSaturatedIntOrInfinite(delay)); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer } @Override default int wanderingTraderSpawnChance() { - return this.shadow$getWanderingTraderSpawnChance(); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer } @Override default void setWanderingTraderSpawnChance(final int chance) { - this.shadow$setWanderingTraderSpawnChance(chance); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer } @Override default void setWanderingTrader(@Nullable final WanderingTrader trader) { - this.shadow$setWanderingTraderId(trader == null ? null : trader.uniqueId()); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + } @Override default Optional wanderTraderUniqueId() { - return Optional.ofNullable(this.shadow$getWanderingTraderId()); + // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + return Optional.empty(); } @Override @@ -169,7 +165,7 @@ default void setWeather(final WeatherType type, final Ticks ticks) { @Override default MinecraftDayTime dayTime() { - final var clockstate = this.clockStates().clocks().get(WorldClocks.OVERWORLD); + final var clockstate = ((ServerLevelDataBridge) this).bridge$level().clockManager().packState().clocks().get(WorldClocks.OVERWORLD); if (clockstate == null) { return new SpongeMinecraftDayTime(0); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/bossbar/HackyBossBarPlatformBridgeMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/bossbar/HackyBossBarPlatformBridgeMixin.java index 81b02c109e1..6a0aa5e063d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/adventure/bossbar/HackyBossBarPlatformBridgeMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/adventure/bossbar/HackyBossBarPlatformBridgeMixin.java @@ -33,6 +33,8 @@ import org.spongepowered.common.bridge.adventure.BossBarBridge; import org.spongepowered.common.bridge.world.BossEventBridge; +import java.util.UUID; + @Mixin(targets = "net.kyori.adventure.bossbar.HackyBossBarPlatformBridge", remap = false) public abstract class HackyBossBarPlatformBridgeMixin implements BossBarBridge { @@ -42,7 +44,12 @@ public abstract class HackyBossBarPlatformBridgeMixin implements BossBarBridge { public ServerBossEvent bridge$asVanillaServerBar() { if (this.bridge$vanillaServerBar == null) { final BossBar $this = (BossBar) this; - this.bridge$vanillaServerBar = new ServerBossEvent(SpongeAdventure.asVanilla($this.name()), SpongeAdventure.asVanilla($this.color()), SpongeAdventure.asVanilla($this.overlay())); + this.bridge$vanillaServerBar = new ServerBossEvent( + UUID.randomUUID(), + SpongeAdventure.asVanilla($this.name()), + SpongeAdventure.asVanilla($this.color()), + SpongeAdventure.asVanilla($this.overlay()) + ); final BossEventBridge bridge = (BossEventBridge) this.bridge$vanillaServerBar; bridge.bridge$copy($this); bridge.bridge$setAdventure($this); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 31ff6a5889f..c601603bd98 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -49,6 +49,7 @@ import net.minecraft.world.Difficulty; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; @@ -114,6 +115,7 @@ import java.net.Proxy; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; @Mixin(MinecraftServer.class) @@ -195,12 +197,12 @@ public Subject subject() { @Inject(method = "", at = @At("RETURN")) private void impl$setThreadOnServerPhaseTracker( - Thread thread, LevelStorageSource.LevelStorageAccess storageAccess, PackRepository packRepo, - WorldStem stem, Proxy proxy, DataFixer fixer, - Services services, LevelLoadListener progress, CallbackInfo ci + Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, + WorldStem worldStem, Optional gameRules, Proxy proxy, DataFixer fixerUpper, Services services, + LevelLoadListener levelLoadListener, CallbackInfo ci ) { try { - PhaseTracker.getServerInstanceExplicitly().setThread(thread); + PhaseTracker.getServerInstanceExplicitly().setThread(serverThread); } catch (final IllegalAccessException e) { throw new RuntimeException("Could not initialize the server PhaseTracker!"); } @@ -231,10 +233,13 @@ public Subject subject() { } @Inject(method = "createLevels", at = @At(value = "NEW", - target = "(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;ZJLjava/util/List;ZLnet/minecraft/world/RandomSequences;)Lnet/minecraft/server/level/ServerLevel;" + target = "(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;ZJLjava/util/List;Z)Lnet/minecraft/server/level/ServerLevel;" ), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/core/Registry;getValue(Lnet/minecraft/resources/ResourceKey;)Ljava/lang/Object;"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getDataStorage()Lnet/minecraft/world/level/storage/DimensionDataStorage;") + to = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/storage/SavedDataStorage;computeIfAbsent(Lnet/minecraft/world/level/saveddata/SavedDataType;)Lnet/minecraft/world/level/saveddata/SavedData;", + ordinal = 0 + ) )) private void impl$onCreateDefaultLevel(final CallbackInfo ci, @Local final ServerLevelData levelData, @Local final LevelStem levelStem) { ((PrimaryLevelDataBridge) levelData).bridge$populateFromLevelStem(levelStem); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java index 11d930abbeb..1ca1d10d932 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/bossevents/CustomBossEventMixin.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.core.server.bossevents; import net.minecraft.server.bossevents.CustomBossEvent; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -35,8 +36,8 @@ public abstract class CustomBossEventMixin extends ServerBossEventMixin { @Shadow private int max; - @Redirect(method = {"getValue"}, - at = @At(value = "FIELD", target = "Lnet/minecraft/server/bossevents/CustomBossEvent;value:I")) + @Redirect(method = {"value"}, + at = @At(value = "FIELD", target = "Lnet/minecraft/server/bossevents/CustomBossEvent;value:I", opcode = Opcodes.GETFIELD)) private int impl$valueRead(final CustomBossEvent $this) { return (int) (this.bridge$asAdventure().progress() * this.max); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java index 115cb9de4a7..9f1b4eae9fb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java @@ -26,11 +26,9 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.WorldData; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -69,15 +67,16 @@ private String modifyMinecraftExceptionOutputIfNotInitializationTime(final Strin } @WrapOperation( - method = "saveDataTag(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/storage/WorldData;Lnet/minecraft/nbt/CompoundTag;)V", + method = "saveDataTag(Lnet/minecraft/world/level/storage/WorldData;Ljava/util/UUID;)V", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V" ) ) @SuppressWarnings("deprecation") - private void impl$saveSpongeLevelData(final LevelStorageSource.LevelStorageAccess instance, final CompoundTag root, final Operation original, - final RegistryAccess registry, final WorldData levelData, final @Nullable CompoundTag tag) { + private void impl$saveSpongeLevelData( + final LevelStorageSource.LevelStorageAccess instance, final CompoundTag root, + final Operation original, final WorldData levelData) { root.put(Constants.Sponge.Data.V2.SPONGE_DATA, ((PrimaryLevelDataBridge) levelData).bridge$writeSpongeLevelData()); if (DataUtil.syncDataToTag(levelData)) { root.merge(((DataCompoundHolder) levelData).data$getCompound()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index 579b73fee6d..a9c74b583d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -28,22 +28,16 @@ import com.google.common.collect.HashBiMap; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; -import com.mojang.serialization.DynamicOps; import net.kyori.adventure.text.Component; import net.minecraft.core.GlobalPos; -import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.UUIDUtil; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntArrayTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; @@ -53,9 +47,6 @@ import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.gamerules.GameRules; -import net.minecraft.world.level.levelgen.WorldDimensions; -import net.minecraft.world.level.levelgen.WorldGenSettings; -import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; @@ -64,11 +55,6 @@ import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.accessor.world.level.LevelSettingsAccessor; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; @@ -81,11 +67,9 @@ import org.spongepowered.math.vector.Vector3i; import java.util.Collections; -import java.util.Map; import java.util.Optional; import java.util.StringJoiner; import java.util.UUID; -import java.util.stream.Collectors; @Mixin(PrimaryLevelData.class) public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldData, PrimaryLevelDataBridge, DataCompoundHolder { @@ -300,12 +284,27 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Override public void bridge$hardcore(final boolean hardcore) { - ((LevelSettingsAccessor) (Object) this.settings).accessor$hardcore(hardcore); + final var oldDifficulty = this.settings.difficultySettings(); + final var newDifficulty = new LevelSettings.DifficultySettings(oldDifficulty.difficulty(), hardcore, oldDifficulty.locked()); + this.settings = new LevelSettings( + this.settings.levelName(), + this.settings.gameType(), + newDifficulty, + this.settings.allowCommands(), + this.settings.dataConfiguration() + ); } @Override public void bridge$allowCommands(final boolean allowCommands) { - ((LevelSettingsAccessor) (Object) this.settings).accessor$allowCommands(allowCommands); + final var oldDifficulty = this.settings.difficultySettings(); + this.settings = new LevelSettings( + this.settings.levelName(), + this.settings.gameType(), + oldDifficulty, + allowCommands, + this.settings.dataConfiguration() + ); } @Override diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java index fa2556bca4e..1e945e8ab1e 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java @@ -32,7 +32,6 @@ import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.world.level.LevelSettings; -import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; import org.spongepowered.asm.mixin.Mixin; @@ -45,7 +44,7 @@ public abstract class LevelStorageSourceMixin_Vanilla { private static Dynamic impl$spongeLevelData; @WrapOperation( - method = "readLevelDataTagFixed", + method = "readExistingSavedData", at = @At( value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;getCompoundOrEmpty(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;", @@ -61,13 +60,15 @@ public abstract class LevelStorageSourceMixin_Vanilla { method = "getLevelDataAndDimensions", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;parse(Lcom/mojang/serialization/Dynamic;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/storage/PrimaryLevelData$SpecialWorldProperty;Lnet/minecraft/world/level/levelgen/WorldOptions;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/world/level/storage/PrimaryLevelData;" + target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;parse(Lcom/mojang/serialization/Dynamic;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/storage/PrimaryLevelData$SpecialWorldProperty;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/world/level/storage/PrimaryLevelData;" ) ) - private static PrimaryLevelData impl$readSpongeLevelData(final Dynamic dynamic, final LevelSettings settings, - final PrimaryLevelData.SpecialWorldProperty special, final WorldOptions options, final Lifecycle lifecycle, final Operation original) + private static PrimaryLevelData impl$readSpongeLevelData( + final Dynamic input, final LevelSettings settings, + final PrimaryLevelData.SpecialWorldProperty specialWorldProperty, final Lifecycle worldGenSettingsLifecycle, + final Operation original) { - final PrimaryLevelData levelData = original.call(dynamic, settings, special, options, lifecycle); + final PrimaryLevelData levelData = original.call(input, settings, specialWorldProperty, worldGenSettingsLifecycle); ((PrimaryLevelDataBridge) levelData).bridge$readSpongeLevelData(LevelStorageSourceMixin_Vanilla.impl$spongeLevelData); From 0d1f7421b86aaa6bebad5804c51a20a5a2484ba1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 16 Mar 2026 08:24:58 -0700 Subject: [PATCH 477/586] feat(worlds): get worlds to load, still a wip We may have to revamp how we've managed world data in the past to adapt to the new system. --- .../server/level/ServerLevelAccessor.java | 5 ++ .../WanderingTraderSpawnerAccessor.java | 38 ++++++++++++ .../resources/mixins.sponge.accessors.json | 1 + .../world/server/SpongeServerLevelData.java | 53 +++++++++++++++- .../world/server/SpongeWorldManager.java | 23 ++++++- .../storage/ServerLevelDataMixin_API.java | 53 +++++++++++----- .../server/commands/WeatherCommandMixin.java | 24 ++++++- .../dedicated/DedicatedServerMixin.java | 5 +- .../core/server/level/ServerLevelMixin.java | 62 ++++++++++++++++++- 9 files changed, 238 insertions(+), 26 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java index aaa7ac898ae..092b199e59f 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/level/ServerLevelAccessor.java @@ -28,12 +28,15 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.BlockEventData; +import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.common.UntransformedAccessorError; +import java.util.List; + @Mixin(ServerLevel.class) public interface ServerLevelAccessor { @@ -44,6 +47,8 @@ public interface ServerLevelAccessor { @Accessor("blockEvents") ObjectLinkedOpenHashSet accessor$blockEvents(); + @Accessor("customSpawners") List accessor$customSpawners(); + @Accessor("entityManager") PersistentEntitySectionManager accessor$getEntityManager(); } diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java new file mode 100644 index 00000000000..a257265ce1a --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.world.entity.npc.wanderingtrader; + +import net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner; +import net.minecraft.world.level.saveddata.WanderingTraderData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.common.UntransformedInvokerError; + +@Mixin(WanderingTraderSpawner.class) +public interface WanderingTraderSpawnerAccessor { + + @Invoker("getTraderData") WanderingTraderData invoker$getTraderData(); + +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 3cc65ae0fc2..75037b81f1c 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -117,6 +117,7 @@ "world.entity.monster.illager.VindicatorAccessor", "world.entity.monster.zombie.ZombifiedPiglinAccessor", "world.entity.npc.villager.AbstractVillagerAccessor", + "world.entity.npc.wanderingtrader.WanderingTraderSpawnerAccessor", "world.entity.player.AbilitiesAccessor", "world.entity.player.PlayerAccessor", "world.entity.projectile.EyeOfEnderAccessor", diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java index c8281d8d7f1..bd30a63b51c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java @@ -32,6 +32,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions; +import net.minecraft.world.level.saveddata.WeatherData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.common.accessor.server.bossevents.CustomBossEventsAccessor; @@ -43,12 +44,47 @@ public final class SpongeServerLevelData { + /** + * Stores per-world weather state for persistence. This is necessary because + * vanilla's {@link WeatherData} is stored in a shared {@link net.minecraft.world.level.storage.SavedDataStorage} + * across all dimensions, making it impossible to have independent per-world weather + * through the vanilla persistence mechanism alone. + */ + public record WeatherState(int clearWeatherTime, int rainTime, int thunderTime, boolean raining, boolean thundering) { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + Codec.INT.fieldOf("clear_weather_time").forGetter(WeatherState::clearWeatherTime), + Codec.INT.fieldOf("rain_time").forGetter(WeatherState::rainTime), + Codec.INT.fieldOf("thunder_time").forGetter(WeatherState::thunderTime), + Codec.BOOL.fieldOf("raining").forGetter(WeatherState::raining), + Codec.BOOL.fieldOf("thundering").forGetter(WeatherState::thundering) + ).apply(i, WeatherState::new)); + + public static WeatherState fromWeatherData(final WeatherData weatherData) { + return new WeatherState( + weatherData.getClearWeatherTime(), + weatherData.getRainTime(), + weatherData.getThunderTime(), + weatherData.isRaining(), + weatherData.isThundering() + ); + } + + public void applyTo(final WeatherData weatherData) { + weatherData.setClearWeatherTime(this.clearWeatherTime); + weatherData.setRainTime(this.rainTime); + weatherData.setThunderTime(this.thunderTime); + weatherData.setRaining(this.raining); + weatherData.setThundering(this.thundering); + } + } + public static final Codec CODEC = RecordCodecBuilder.create( i -> i.group( WorldOptions.CODEC.fieldOf("world_gen_options").stable().forGetter(SpongeServerLevelData::worldGenOptions), CustomBossEventsAccessor.accessor$codec().optionalFieldOf("custom_boss_events").stable().forGetter(SpongeServerLevelData::customBossEvents), UUIDUtil.CODEC.fieldOf("uuid").stable().forGetter(SpongeServerLevelData::uniqueId), - net.minecraft.resources.ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").stable().forGetter(SpongeServerLevelData::resourceKey) + net.minecraft.resources.ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").stable().forGetter(SpongeServerLevelData::resourceKey), + WeatherState.CODEC.optionalFieldOf("weather_state").stable().forGetter(SpongeServerLevelData::weatherState) ) .apply(i, i.stable(SpongeServerLevelData::new)) ); @@ -57,15 +93,20 @@ public final class SpongeServerLevelData { private @Nullable InheritableConfigHandle configAdapter; private WorldOptions worldGenOptions; private @Nullable CustomBossEvents customBossEvents; + private @Nullable WeatherState weatherState; public SpongeServerLevelData() { } - public SpongeServerLevelData(WorldOptions worldOptions, Optional customBossEvents, UUID uuid, Optional> levelResourceKey) { + public SpongeServerLevelData( + WorldOptions worldOptions, Optional customBossEvents, UUID uuid, + Optional> levelResourceKey, Optional weatherState + ) { this.worldGenOptions = worldOptions; this.customBossEvents = customBossEvents.orElse(null); this.uniqueId = uuid; this.key = (ResourceKey) levelResourceKey.orElse(null); + this.weatherState = weatherState.orElse(null); } public @Nullable ResourceKey key() { @@ -115,4 +156,12 @@ public Optional customBossEvents() { public void setCustomBossEvents(final CustomBossEvents customBossEvents) { this.customBossEvents = customBossEvents; } + + public Optional weatherState() { + return Optional.ofNullable(this.weatherState); + } + + public void setWeatherState(final @Nullable WeatherState weatherState) { + this.weatherState = weatherState; + } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 31b00fce843..16b04a0e0d4 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -65,6 +65,8 @@ import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WorldData; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.worldupdate.UpgradeProgress; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -821,8 +823,12 @@ private Optional loadLevelData( private LevelDataLoadResult initializeLevelData(final ResourceKey key, final PrimaryLevelData data, final LevelStem stem) { final DimensionType dimensionType = stem.type().value(); - ((PrimaryLevelDataBridge) data).bridge$spongeData().setKey(key); - ((PrimaryLevelDataBridge) data).bridge$spongeData().setConfigAdapter(SpongeGameConfigs.load(dimensionType, key)); + final var spongeData = ((PrimaryLevelDataBridge) data).bridge$spongeData(); + spongeData.setKey(key); + spongeData.setConfigAdapter(SpongeGameConfigs.load(dimensionType, key)); + if (spongeData.worldGenOptions() == null) { + spongeData.setWorldGenOptions(this.server.getWorldGenSettings()); + } ((PrimaryLevelDataBridge) data).bridge$populateFromLevelStem(stem); return new LevelDataLoadResult(data, stem); } @@ -847,10 +853,21 @@ private LevelDataLoadResult readLevelData( final Dynamic dataTag, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation ) { + // Apply file-fixing and data-fixing before parsing. In 26.1, FileFixerUpper + // requires all level data to be fixed before getLevelDataAndDimensions() can parse it. + // Vanilla handles this for the overworld via the WorldLoader pipeline, but Sponge's + // per-world level.dat files need the same treatment. + final Dynamic fixedDataTag; + try { + fixedDataTag = DataFixers.getFileFixer().fix(worldAccess, dataTag, new UpgradeProgress()); + } catch (final IOException e) { + throw new RuntimeException(String.format("Failed to apply data fixes for world '%s'", registryKey.identifier()), e); + } + final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); final RegistryAccess.Frozen access = this.server.registryAccess(); final LevelDataAndDimensions levelData = LevelStorageSource.getLevelDataAndDimensions(worldAccess, - dataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); + fixedDataTag, defaultLevelData.getDataConfiguration(), access.lookupOrThrow(Registries.LEVEL_STEM), access); final WorldArchetype worldArchetype = SpongeWorldManager.resolveWorldArchetype(levelData, registryKey, loadOperation); final LevelStem levelStem = (LevelStem) (Object) worldArchetype.type(); final PrimaryLevelData worldData = (PrimaryLevelData) levelData.worldDataAndGenSettings().data(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java index 4dc6fe1b452..22c2051b23c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/storage/ServerLevelDataMixin_API.java @@ -24,11 +24,10 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.storage; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.clock.PackedClockStates; import net.minecraft.world.clock.WorldClocks; +import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.gamerules.GameRuleMap; -import net.minecraft.world.level.gamerules.GameRules; +import net.minecraft.world.level.saveddata.WanderingTraderData; import net.minecraft.world.level.storage.ServerLevelData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -42,9 +41,9 @@ import org.spongepowered.api.world.weather.Weather; import org.spongepowered.api.world.weather.WeatherType; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.server.level.ServerLevelAccessor; +import org.spongepowered.common.accessor.world.entity.npc.wanderingtrader.WanderingTraderSpawnerAccessor; import org.spongepowered.common.accessor.world.level.GameRulesAccessor; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.util.Constants; @@ -116,43 +115,67 @@ default void setDayTime(final MinecraftDayTime dayTime) { // this.setClockStates(this.clockStates().clocks()); } + @SuppressWarnings("removal") @Override default Ticks wanderingTraderSpawnDelay() { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer - final var level = ((ServerLevelDataBridge) this).bridge$level(); - if (level instanceof ServerLevelAccessor sla) { - sla.cu + final var data = this.api$wanderingTraderData(); + if (data == null) { + return SpongeTicks.ticksOrInfinite(0); } - return SpongeTicks.ticksOrInfinite(0); + return SpongeTicks.ticksOrInfinite(data.spawnDelay()); } + @SuppressWarnings("removal") @Override default void setWanderingTraderSpawnDelay(final Ticks delay) { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + final var data = this.api$wanderingTraderData(); + if (data != null) { + data.setSpawnDelay((int) delay.ticks()); + } } + @SuppressWarnings("removal") @Override default int wanderingTraderSpawnChance() { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + final var data = this.api$wanderingTraderData(); + if (data == null) { + return 0; + } + return data.spawnChance(); } + @SuppressWarnings("removal") @Override default void setWanderingTraderSpawnChance(final int chance) { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + final var data = this.api$wanderingTraderData(); + if (data != null) { + data.setSpawnChance(chance); + } } + @SuppressWarnings("removal") @Override default void setWanderingTrader(@Nullable final WanderingTrader trader) { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer - + // Wandering trader is no longer tracked in WanderingTraderData as of 26.1-snapshot-6 } + @SuppressWarnings("removal") @Override default Optional wanderTraderUniqueId() { - // TODO - 26.1-snapshot-6 make this per-world instead of just MinecraftServer + // Wandering trader is no longer tracked in WanderingTraderData as of 26.1-snapshot-6 return Optional.empty(); } + private @Nullable WanderingTraderData api$wanderingTraderData() { + final var level = ((ServerLevelDataBridge) this).bridge$level(); + for (final CustomSpawner spawner : ((ServerLevelAccessor) level).accessor$customSpawners()) { + if (spawner instanceof WanderingTraderSpawnerAccessor wtsa) { + return wtsa.invoker$getTraderData(); + } + } + return null; + } + @Override default void setWeather(final WeatherType type) { this.offer(Keys.WEATHER, Weather.of(Objects.requireNonNull(type, "type"), 6000 / Constants.TickConversions.TICK_DURATION_MS)); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java index e4014c116cf..12f99720095 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/commands/WeatherCommandMixin.java @@ -27,9 +27,11 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.commands.WeatherCommand; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; +import net.minecraft.world.level.saveddata.WeatherData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -44,15 +46,31 @@ public abstract class WeatherCommandMixin { return original.call(source.getLevel()); } + /** + * Redirects weather parameter changes to the command source's current world + * instead of the global server weather. This enables per-world weather control + * via the {@code /weather} command. + * + *

The vanilla implementation calls {@link MinecraftServer#setWeatherParameters(int, int, boolean, boolean)} + * which sets weather on the global {@link WeatherData}. Since {@code ServerLevel} does not extend + * {@code MinecraftServer}, we cannot pass the level to {@code original.call()}. Instead, we + * directly manipulate the per-world {@link WeatherData} obtained from the source's level.

+ */ @WrapOperation(method = { "setClear", "setRain", "setThunder" - }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setWeatherParameters(IIZZ)V")) + }, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;setWeatherParameters(IIZZ)V")) private static void impl$useCurrentWorld( - ServerLevel instance, int delay, int duration, boolean rain, boolean thunder, Operation original, + final MinecraftServer instance, final int clearTime, final int rainTime, final boolean raining, + final boolean thundering, final Operation original, final CommandSourceStack source ) { - original.call(source.getLevel(), delay, duration, rain, thunder); + final WeatherData weatherData = source.getLevel().getWeatherData(); + weatherData.setClearWeatherTime(clearTime); + weatherData.setRainTime(rainTime); + weatherData.setThunderTime(rainTime); + weatherData.setRaining(raining); + weatherData.setThundering(thundering); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java index 8f29486072b..b74ecd8d485 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java @@ -35,6 +35,7 @@ import net.minecraft.server.dedicated.DedicatedServerSettings; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.UserNameToIdResolver; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -56,9 +57,9 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin { @Inject(method = "", at = @At("TAIL")) private void impl$setServerOnGame( final Thread $$0, final LevelStorageSource.LevelStorageAccess $$1, final PackRepository $$2, final WorldStem $$3, - final DedicatedServerSettings $$4, final DataFixer $$5, final Services $$6, final CallbackInfo ci + final Optional $$4, final DedicatedServerSettings $$5, final DataFixer $$6, final Services $$7, final CallbackInfo ci ) { - $$4.getProperties().serverResourcePackInfo.ifPresent(packInfo -> { + $$5.getProperties().serverResourcePackInfo.ifPresent(packInfo -> { try { this.impl$resourcePack = ResourcePackRequest.resourcePackRequest() .packs(ResourcePackInfo.resourcePackInfo(packInfo.id(), new URI(packInfo.url()), packInfo.hash())) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index e5847a5afd3..95ae5252d28 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -116,6 +116,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -148,6 +149,7 @@ import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; import org.spongepowered.common.world.server.SpongeServerLevelData; +import org.spongepowered.common.world.weather.SpongeWeather; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.math.vector.Vector3i; @@ -183,11 +185,47 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel private LevelStorageSource.LevelStorageAccess impl$levelSave; private CustomBossEvents impl$bossBarManager; + @Unique private @Nullable WeatherData impl$perWorldWeatherData; private Weather impl$prevWeather; private boolean impl$isManualSave = false; private long impl$preTickTime = 0L; private boolean impl$closed = false; + /** + * Initializes per-world {@link WeatherData}, replacing the global server weather data. + * This intercepts the {@code server.getWeatherData()} call used by {@code prepareWeather} + * in the constructor, ensuring each world has independent weather state from creation. + * + *

A new {@link WeatherData} instance is created per world rather than using + * {@link SavedDataStorage#computeIfAbsent}, because all dimensions share the same + * {@link SavedDataStorage} (the overworld's). Weather state is instead persisted through + * {@link SpongeServerLevelData.WeatherState} in the Sponge level data.

+ */ + @WrapOperation( + method = "", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWeatherData()Lnet/minecraft/world/level/saveddata/WeatherData;") + ) + private WeatherData impl$initPerWorldWeatherData(final MinecraftServer instance, final Operation original) { + this.impl$perWorldWeatherData = new WeatherData(); + return this.impl$perWorldWeatherData; + } + + /** + * Redirects {@link ServerLevel#getWeatherData()} to return the per-world {@link WeatherData} + * instead of the global server weather data. This enables independent weather cycles, commands, + * and API access for each world. + */ + @WrapOperation( + method = "getWeatherData", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWeatherData()Lnet/minecraft/world/level/saveddata/WeatherData;") + ) + private WeatherData impl$usePerWorldWeatherData(final MinecraftServer instance, final Operation original) { + if (this.impl$perWorldWeatherData != null) { + return this.impl$perWorldWeatherData; + } + return original.call(instance); + } + @Inject(method = "", at = @At("TAIL")) private void impl$onInit( final MinecraftServer server, @@ -204,6 +242,22 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel ) { final SpongeServerLevelData spongeData = ((ServerLevelDataBridge) levelData).bridge$spongeData(); + // Restore per-world weather state from Sponge level data if available. + // On first load (migration from global weather), the overworld inherits the + // server's global WeatherData state, while other worlds start with clear weather. + if (this.impl$perWorldWeatherData != null) { + spongeData.weatherState().ifPresentOrElse( + ws -> ws.applyTo(this.impl$perWorldWeatherData), + () -> { + // Migration: for overworld, copy the server's global weather state + if (Level.OVERWORLD.equals(dimension)) { + final WeatherData globalWeather = server.getWeatherData(); + SpongeServerLevelData.WeatherState.fromWeatherData(globalWeather).applyTo(this.impl$perWorldWeatherData); + } + } + ); + } + final ResourceKey worldKey = ((ServerWorld) this).key(); if (spongeData.key() == null) { SpongeCommon.logger().warn("Level data ({}) has no key associated but is used by world {} ({}).", levelData.getClass().getSimpleName(), worldKey, this.getClass().getSimpleName()); @@ -218,7 +272,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel } this.impl$levelSave = storage; - this.impl$prevWeather = ((ServerWorld) this).weather(); + this.impl$prevWeather = SpongeWeather.of(this.shadow$getWeatherData()); ((LevelTicksBridge) this.blockTicks).bridge$level((ServerLevel) (Object) this); ((LevelTicksBridge) this.fluidTicks).bridge$level((ServerLevel) (Object) this); @@ -403,6 +457,12 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final SerializationBehavior behavior = ((ServerLevelDataBridge) levelData).bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC); if (behavior != SerializationBehavior.NONE) { + // Persist per-world weather state to Sponge level data before saving + if (this.impl$perWorldWeatherData != null) { + ((ServerLevelDataBridge) levelData).bridge$spongeData() + .setWeatherState(SpongeServerLevelData.WeatherState.fromWeatherData(this.impl$perWorldWeatherData)); + } + original.call(self, flush); // per-world WorldInfo/WorldBorder/BossBars/WorldGen From 522ed8dde2163ed848f916c9bcdad43f28287740 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 16 Mar 2026 21:04:00 -0700 Subject: [PATCH 478/586] feat(worlds): overhaul per-world storage architecture for 26.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, SpongeWorldManager created a separate LevelStorageAccess per dimension via createLevelStorageAccess(), with bridge$setDedicated(true) overriding getDimensionPath() to bypass vanilla's DimensionType.getStorageFolder(). This produced the old DIM-1/DIM1 directory layout with per-dimension level.dat files containing a SpongeData compound (UUID, key, WeatherState, CustomBossEvents, WorldOptions). Each dimension had its own session.lock and the SpongeData was injected into level.dat during saveDataTag() and extracted during getLevelDataAndDimensions() via bridge$readSpongeLevelData/writeSpongeLevelData. Now, all dimensions share the server's single LevelStorageAccess. Vanilla's DimensionType.getStorageFolder() handles path resolution, placing all dimensions under dimensions/{namespace}/{path}/. Each ServerLevel's ServerChunkCache creates an independent SavedDataStorage at getDimensionPath(dim)/data/, enabling per-world data through vanilla's own SavedData mechanism. Per-world features now use vanilla SavedDataType instances directly: - WeatherData.TYPE (minecraft:weather) via ServerLevel.getWeatherData() override - GameRuleMap.TYPE (minecraft:game_rules) via ServerLevel.getGameRules() override - CustomBossEvents.TYPE via bridge$getBossBarManager() using per-dim storage - WorldBorder already per-dimension in vanilla 26.1 (no override needed) Sponge-specific identity (UUID, ResourceKey) is stored as SpongeRegistryData, a custom SavedData at data/sponge/registry.dat per dimension. Global map/player UUID indices are stored as SpongeMapUUIDData at data/sponge/map_uuids.dat in the server-level SavedDataStorage. level.dat no longer contains any SpongeData — it is pure vanilla format. The SpongeData injection in LevelStorageSource_LevelStorageAccessMixin and the read hooks in LevelStorageSourceMixin_Vanilla and PrimaryLevelDataMixin are removed. Migration from old Sponge format is handled by FileFixerUpperMixin, which hooks into FileFixerUpper.fix() at HEAD to extract UUIDs from SpongeData in level.dat and DIM-1/DIM1 level.dat files before vanilla's DimensionStorageFileFix deletes those directories. Legacy SavedData files (random_sequences.dat, etc.) left behind by vanilla's fixer are moved to the correct namespaced paths and the old directories are cleaned up. Extracted identities are cached in SpongeLevelMigration (static volatile, cross-thread from main to Server thread) and written to per-dimension registry.dat during MinecraftServer.loadLevel() HEAD inject, before any ServerLevel is created. Additional fixes: - SavedDataStorageMixin.readSpongeMapData() was returning null unconditionally, breaking ALL SavedData persistence (return null -> return result) - Weather hasCeiling() logic in advanceWeatherCycle was inverted, preventing weather visual effects in overworld-type dimensions - DedicatedServerMixin constructor signature updated for new Optional parameter in 26.1-snapshot-6 Signed-off-by: Gabriel Harris-Rouquette --- .../bossevents/CustomBossEventsAccessor.java | 24 + .../WanderingTraderSpawnerAccessor.java | 1 - .../storage/LevelStorageAccessBridge.java | 30 -- .../level/storage/PrimaryLevelDataBridge.java | 7 - .../common/map/SpongeMapStorage.java | 5 +- .../world/server/SpongeLevelMigration.java | 162 +++++++ .../world/server/SpongeMapUUIDData.java | 92 ++++ .../world/server/SpongeRegistryData.java | 99 +++++ .../world/server/SpongeServerLevelData.java | 49 +-- .../world/server/SpongeWorldManager.java | 413 ++++++++++-------- .../server/MinecraftServerMixin_API.java | 3 - .../server/level/ServerLevelMixin_API.java | 3 +- .../mixin/core/commands/CommandsMixin.java | 4 +- .../core/server/MinecraftServerMixin.java | 34 +- .../core/server/level/ServerLevelMixin.java | 107 ++--- .../util/filefix/FileFixerUpperMixin.java | 211 +++++++++ .../level/levelgen/WorldDimensionsMixin.java | 6 +- ...StorageSource_LevelStorageAccessMixin.java | 47 +- .../level/storage/PrimaryLevelDataMixin.java | 102 +---- .../level/storage/SavedDataStorageMixin.java | 2 +- src/mixins/resources/mixins.sponge.core.json | 1 + .../LevelStorageSourceMixin_Vanilla.java | 51 +-- 22 files changed, 927 insertions(+), 526 deletions(-) delete mode 100644 src/main/java/org/spongepowered/common/bridge/world/level/storage/LevelStorageAccessBridge.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeLevelMigration.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java create mode 100644 src/main/java/org/spongepowered/common/world/server/SpongeRegistryData.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/util/filefix/FileFixerUpperMixin.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java index 3fd03f73bda..b4d7bb53c3d 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/server/bossevents/CustomBossEventsAccessor.java @@ -1,3 +1,27 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package org.spongepowered.common.accessor.server.bossevents; import com.mojang.serialization.Codec; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java index a257265ce1a..e704ff22e78 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/npc/wanderingtrader/WanderingTraderSpawnerAccessor.java @@ -28,7 +28,6 @@ import net.minecraft.world.level.saveddata.WanderingTraderData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedInvokerError; @Mixin(WanderingTraderSpawner.class) public interface WanderingTraderSpawnerAccessor { diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/storage/LevelStorageAccessBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/storage/LevelStorageAccessBridge.java deleted file mode 100644 index 5d717840102..00000000000 --- a/src/main/java/org/spongepowered/common/bridge/world/level/storage/LevelStorageAccessBridge.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.bridge.world.level.storage; - -public interface LevelStorageAccessBridge { - - void bridge$setDedicated(boolean dedicated); -} diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/storage/PrimaryLevelDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/storage/PrimaryLevelDataBridge.java index eed8045ff8b..102f4e1353d 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/storage/PrimaryLevelDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/storage/PrimaryLevelDataBridge.java @@ -25,10 +25,7 @@ package org.spongepowered.common.bridge.world.level.storage; import com.google.common.collect.BiMap; -import com.mojang.serialization.Dynamic; import net.kyori.adventure.text.Component; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; import net.minecraft.world.Difficulty; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; @@ -67,8 +64,4 @@ public interface PrimaryLevelDataBridge extends ServerLevelDataBridge { void bridge$hardcore(boolean hardcore); void bridge$allowCommands(boolean commands); - - void bridge$readSpongeLevelData(Dynamic impl$spongeLevelData); - - CompoundTag bridge$writeSpongeLevelData(); } diff --git a/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java b/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java index 97db4c78a90..f7a3408423f 100644 --- a/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java +++ b/src/main/java/org/spongepowered/common/map/SpongeMapStorage.java @@ -35,9 +35,9 @@ import org.spongepowered.api.world.DefaultWorldKeys; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.accessor.world.level.saveddata.maps.MapIndexAccessor; -import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.world.server.SpongeMapUUIDData; import java.util.Collection; import java.util.HashMap; @@ -120,7 +120,8 @@ public void addMapInfo(final MapInfo mapInfo) { private void ensureHasMapUUIDIndex() { if (this.mapIdUUIDIndex == null) { - this.mapIdUUIDIndex = ((PrimaryLevelDataBridge) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get().properties()).bridge$getMapUUIDIndex(); + this.mapIdUUIDIndex = SpongeCommon.server().getDataStorage() + .computeIfAbsent(SpongeMapUUIDData.TYPE).mapUUIDIndex(); } } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeLevelMigration.java b/src/main/java/org/spongepowered/common/world/server/SpongeLevelMigration.java new file mode 100644 index 00000000000..bf4362256be --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeLevelMigration.java @@ -0,0 +1,162 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.SpongeCommon; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** + * Handles migration of old Sponge world data (UUID, key) from the pre-26.1 format + * to the new per-dimension {@link SpongeRegistryData} SavedData format. + * + *

The migration flow is:

+ *
    + *
  1. {@code FileFixerUpperMixin} extracts UUIDs from old {@code SpongeData} in level.dat + * and per-dimension level.dat files BEFORE vanilla's file fixer rewrites them.
  2. + *
  3. Cached identities are stored via {@link #cacheIdentities(Map)}.
  4. + *
  5. {@code MinecraftServerMixin.loadLevel()} calls {@link #writeCachedRegistryData(Path)} + * AFTER the file fix completes but BEFORE any ServerLevel is created.
  6. + *
+ */ +public final class SpongeLevelMigration { + + // Static fields (not ThreadLocal) because fix() runs on "main" thread + // but loadLevel() runs on "Server thread". + private static volatile @Nullable Map, UUID> cachedIdentities; + private static volatile @Nullable CompoundTag cachedGlobalSpongeData; + + private SpongeLevelMigration() { + } + + public static void cacheIdentities(final Map, UUID> identities) { + cachedIdentities = identities; + } + + public static void cacheGlobalSpongeData(final CompoundTag spongeData) { + cachedGlobalSpongeData = spongeData; + } + + /** + * Writes cached migrated identities to per-dimension {@code data/sponge/registry.dat} files. + * Must be called AFTER FileFixerUpper.fix() completes (directory structure is final) + * and BEFORE any ServerLevel is created (so SavedDataStorage finds files on disk). + */ + public static void writeCachedRegistryData(final Path worldDir) { + final @Nullable Map, UUID> identities = cachedIdentities; + if (identities == null || identities.isEmpty()) { + cachedIdentities = null; + return; + } + cachedIdentities = null; + + for (final var entry : identities.entrySet()) { + final ResourceKey dimKey = entry.getKey(); + final UUID uuid = entry.getValue(); + try { + final Path dimDir = DimensionType.getStorageFolder(dimKey, worldDir); + final Path dataDir = dimDir.resolve("data").resolve("sponge"); + final Path registryFile = dataDir.resolve("registry.dat"); + if (Files.exists(registryFile)) { + continue; + } + Files.createDirectories(dataDir); + final SpongeRegistryData registryData = new SpongeRegistryData(uuid, Optional.of(dimKey)); + final var encoded = SpongeRegistryData.CODEC.encodeStart(NbtOps.INSTANCE, registryData); + if (encoded.isSuccess()) { + final CompoundTag savedDataTag = new CompoundTag(); + savedDataTag.put("data", encoded.getOrThrow()); + NbtUtils.addCurrentDataVersion(savedDataTag); + NbtIo.writeCompressed(savedDataTag, registryFile); + SpongeCommon.logger().info("[Sponge] Wrote migrated {} UUID {} -> {}", dimKey.identifier(), uuid, registryFile); + } + } catch (final IOException e) { + SpongeCommon.logger().warn("[Sponge] Failed to write registry.dat for {}", dimKey.identifier(), e); + } + } + + // Write global Sponge data (MapUUIDs, player-uuid-table) to server-level SavedData + writeGlobalSpongeData(worldDir); + } + + private static void writeGlobalSpongeData(final Path worldDir) { + final @Nullable CompoundTag spongeData = cachedGlobalSpongeData; + cachedGlobalSpongeData = null; + if (spongeData == null) { + return; + } + + final Path dataDir = worldDir.resolve("data").resolve("sponge"); + final Path mapUUIDFile = dataDir.resolve("map_uuids.dat"); + if (Files.exists(mapUUIDFile)) { + return; // Already migrated + } + + // Extract MapUUIDs and player-uuid-table from old SpongeData + final var mapUUIDs = spongeData.getCompound("MapUUIDs").orElse(null); + final var playerTable = spongeData.getList("player-uuid-table").orElse(null); + + // Only write if there's actual data to migrate + final boolean hasMapData = mapUUIDs != null && !mapUUIDs.isEmpty(); + final boolean hasPlayerData = playerTable != null && !playerTable.isEmpty(); + if (!hasMapData && !hasPlayerData) { + return; + } + + try { + Files.createDirectories(dataDir); + // Write as a raw compound since the old format doesn't match the new codec exactly. + // The SpongeMapUUIDData.CODEC will read the proper format; here we just preserve the raw data + // for potential manual migration. The new SavedData will be created fresh on first access. + final CompoundTag savedDataTag = new CompoundTag(); + final CompoundTag data = new CompoundTag(); + if (hasMapData) { + data.put("legacy_map_uuids", mapUUIDs); + } + if (hasPlayerData) { + data.put("legacy_player_uuids", playerTable); + } + savedDataTag.put("data", data); + NbtUtils.addCurrentDataVersion(savedDataTag); + NbtIo.writeCompressed(savedDataTag, mapUUIDFile); + SpongeCommon.logger().info("[Sponge] Preserved global MapUUIDs/player-uuid-table -> {}", mapUUIDFile); + } catch (final IOException e) { + SpongeCommon.logger().warn("[Sponge] Failed to write global Sponge data", e); + } + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java b/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java new file mode 100644 index 00000000000..8797570acbd --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java @@ -0,0 +1,92 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.UUIDUtil; +import net.minecraft.resources.Identifier; +import net.minecraft.util.datafix.DataFixTypes; +import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.saveddata.SavedDataType; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Stores Sponge's map ID → UUID index and player UUID table as server-global SavedData. + * Previously stored in {@code SpongeData} within {@code level.dat}. + * + *

Persisted at {@code data/sponge/map_uuids.dat} in the server-level data directory.

+ */ +public final class SpongeMapUUIDData extends SavedData { + + private static final Codec> MAP_INDEX_CODEC = + Codec.unboundedMap(Codec.INT, UUIDUtil.CODEC); + + public static final Codec CODEC = RecordCodecBuilder.create( + i -> i.group( + MAP_INDEX_CODEC.optionalFieldOf("map_uuids", Map.of()).forGetter(SpongeMapUUIDData::mapIndex), + MAP_INDEX_CODEC.optionalFieldOf("player_uuids", Map.of()).forGetter(SpongeMapUUIDData::playerIndex) + ) + .apply(i, SpongeMapUUIDData::new) + ); + + public static final SavedDataType TYPE = new SavedDataType<>( + Identifier.fromNamespaceAndPath("sponge", "map_uuids"), SpongeMapUUIDData::new, CODEC, DataFixTypes.LEVEL + ); + + private final BiMap mapUUIDIndex; + private final BiMap playerUUIDIndex; + + public SpongeMapUUIDData() { + this.mapUUIDIndex = HashBiMap.create(); + this.playerUUIDIndex = HashBiMap.create(); + } + + public SpongeMapUUIDData(final Map mapIndex, final Map playerIndex) { + this.mapUUIDIndex = HashBiMap.create(mapIndex); + this.playerUUIDIndex = HashBiMap.create(playerIndex); + } + + private Map mapIndex() { + return new HashMap<>(this.mapUUIDIndex); + } + + private Map playerIndex() { + return new HashMap<>(this.playerUUIDIndex); + } + + public BiMap mapUUIDIndex() { + return this.mapUUIDIndex; + } + + public BiMap playerUUIDIndex() { + return this.playerUUIDIndex; + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeRegistryData.java b/src/main/java/org/spongepowered/common/world/server/SpongeRegistryData.java new file mode 100644 index 00000000000..41c789bdd8e --- /dev/null +++ b/src/main/java/org/spongepowered/common/world/server/SpongeRegistryData.java @@ -0,0 +1,99 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.server; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.datafix.DataFixTypes; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.saveddata.SavedDataType; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Optional; +import java.util.UUID; + +/** + * A {@link SavedData} implementation that stores per-dimension Sponge identity, + * consisting of a unique {@link UUID} and a {@link ResourceKey} for the world. + * + *

This is persisted as {@code data/sponge/registry.dat} within each dimension's + * saved data directory.

+ */ +public final class SpongeRegistryData extends SavedData { + + public static final Codec CODEC = RecordCodecBuilder.create( + i -> i.group( + UUIDUtil.CODEC.fieldOf("uuid").forGetter(SpongeRegistryData::uniqueId), + ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").forGetter(SpongeRegistryData::resourceKey) + ) + .apply(i, SpongeRegistryData::new) + ); + + public static final SavedDataType TYPE = new SavedDataType<>( + Identifier.fromNamespaceAndPath("sponge", "registry"), SpongeRegistryData::new, CODEC, DataFixTypes.LEVEL + ); + + private UUID uniqueId; + private @Nullable ResourceKey key; + + public SpongeRegistryData() { + this.uniqueId = UUID.randomUUID(); + } + + public SpongeRegistryData(final UUID uniqueId, final Optional> key) { + this.uniqueId = uniqueId; + this.key = key.orElse(null); + } + + public UUID uniqueId() { + return this.uniqueId; + } + + public void setUniqueId(final UUID uniqueId) { + this.uniqueId = uniqueId; + this.setDirty(); + } + + public org.spongepowered.api.@Nullable ResourceKey key() { + if (this.key == null) { + return null; + } + return (org.spongepowered.api.ResourceKey) (Object) this.key.identifier(); + } + + public Optional> resourceKey() { + return Optional.ofNullable(this.key); + } + + public void setKey(final org.spongepowered.api.ResourceKey key) { + this.key = SpongeWorldManager.createRegistryKey(key); + this.setDirty(); + } +} diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java index bd30a63b51c..6315915997c 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeServerLevelData.java @@ -32,7 +32,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.saveddata.WeatherData; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.common.accessor.server.bossevents.CustomBossEventsAccessor; @@ -44,47 +43,12 @@ public final class SpongeServerLevelData { - /** - * Stores per-world weather state for persistence. This is necessary because - * vanilla's {@link WeatherData} is stored in a shared {@link net.minecraft.world.level.storage.SavedDataStorage} - * across all dimensions, making it impossible to have independent per-world weather - * through the vanilla persistence mechanism alone. - */ - public record WeatherState(int clearWeatherTime, int rainTime, int thunderTime, boolean raining, boolean thundering) { - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - Codec.INT.fieldOf("clear_weather_time").forGetter(WeatherState::clearWeatherTime), - Codec.INT.fieldOf("rain_time").forGetter(WeatherState::rainTime), - Codec.INT.fieldOf("thunder_time").forGetter(WeatherState::thunderTime), - Codec.BOOL.fieldOf("raining").forGetter(WeatherState::raining), - Codec.BOOL.fieldOf("thundering").forGetter(WeatherState::thundering) - ).apply(i, WeatherState::new)); - - public static WeatherState fromWeatherData(final WeatherData weatherData) { - return new WeatherState( - weatherData.getClearWeatherTime(), - weatherData.getRainTime(), - weatherData.getThunderTime(), - weatherData.isRaining(), - weatherData.isThundering() - ); - } - - public void applyTo(final WeatherData weatherData) { - weatherData.setClearWeatherTime(this.clearWeatherTime); - weatherData.setRainTime(this.rainTime); - weatherData.setThunderTime(this.thunderTime); - weatherData.setRaining(this.raining); - weatherData.setThundering(this.thundering); - } - } - public static final Codec CODEC = RecordCodecBuilder.create( i -> i.group( WorldOptions.CODEC.fieldOf("world_gen_options").stable().forGetter(SpongeServerLevelData::worldGenOptions), CustomBossEventsAccessor.accessor$codec().optionalFieldOf("custom_boss_events").stable().forGetter(SpongeServerLevelData::customBossEvents), UUIDUtil.CODEC.fieldOf("uuid").stable().forGetter(SpongeServerLevelData::uniqueId), - net.minecraft.resources.ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").stable().forGetter(SpongeServerLevelData::resourceKey), - WeatherState.CODEC.optionalFieldOf("weather_state").stable().forGetter(SpongeServerLevelData::weatherState) + net.minecraft.resources.ResourceKey.codec(Registries.DIMENSION).optionalFieldOf("key").stable().forGetter(SpongeServerLevelData::resourceKey) ) .apply(i, i.stable(SpongeServerLevelData::new)) ); @@ -93,20 +57,18 @@ public void applyTo(final WeatherData weatherData) { private @Nullable InheritableConfigHandle configAdapter; private WorldOptions worldGenOptions; private @Nullable CustomBossEvents customBossEvents; - private @Nullable WeatherState weatherState; public SpongeServerLevelData() { } public SpongeServerLevelData( WorldOptions worldOptions, Optional customBossEvents, UUID uuid, - Optional> levelResourceKey, Optional weatherState + Optional> levelResourceKey ) { this.worldGenOptions = worldOptions; this.customBossEvents = customBossEvents.orElse(null); this.uniqueId = uuid; this.key = (ResourceKey) levelResourceKey.orElse(null); - this.weatherState = weatherState.orElse(null); } public @Nullable ResourceKey key() { @@ -157,11 +119,4 @@ public void setCustomBossEvents(final CustomBossEvents customBossEvents) { this.customBossEvents = customBossEvents; } - public Optional weatherState() { - return Optional.ofNullable(this.weatherState); - } - - public void setWeatherState(final @Nullable WeatherState weatherState) { - this.weatherState = weatherState; - } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 16b04a0e0d4..aa242cce150 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -35,12 +35,19 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.features.MiscOverworldFeatures; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtAccounter; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.NbtUtils; import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkLoadCounter; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.LevelLoadListener; import net.minecraft.server.level.progress.LoggingLevelLoadListener; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.worldupdate.UpgradeProgress; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; import net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner; @@ -57,6 +64,8 @@ import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.PatrolSpawner; import net.minecraft.world.level.levelgen.PhantomSpawner; +import net.minecraft.world.level.levelgen.WorldDimensions; +import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.storage.LevelData; @@ -65,8 +74,6 @@ import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WorldData; -import net.minecraft.util.datafix.DataFixers; -import net.minecraft.util.worldupdate.UpgradeProgress; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -88,10 +95,8 @@ import org.spongepowered.common.accessor.server.MinecraftServerAccessor; import org.spongepowered.common.accessor.world.level.storage.PrimaryLevelDataAccessor; import org.spongepowered.common.bridge.core.MappedRegistryBridge; -import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.world.level.chunk.storage.IOWorkerBridge; import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; -import org.spongepowered.common.bridge.world.level.storage.LevelStorageAccessBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; import org.spongepowered.common.bridge.world.level.storage.ServerLevelDataBridge; import org.spongepowered.common.config.SpongeGameConfigs; @@ -102,7 +107,6 @@ import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.ExecutorUtil; -import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -179,26 +183,21 @@ public List worldKeys() { final List worldKeys = new ArrayList<>(); worldKeys.add(DefaultWorldKeys.DEFAULT); - if (Files.exists(this.getDirectory(DefaultWorldKeys.THE_NETHER))) { - worldKeys.add(DefaultWorldKeys.THE_NETHER); - } - - if (Files.exists(this.getDirectory(DefaultWorldKeys.THE_END))) { - worldKeys.add(DefaultWorldKeys.THE_END); - } - + // All dimensions are stored under dimensions/{namespace}/{value}/ try { - for (final Path namespacedDirectory : Files.list(this.customWorldsDirectory).toList()) { - if (this.customWorldsDirectory.equals(namespacedDirectory)) { - continue; - } - - for (final Path valueDirectory : Files.list(namespacedDirectory).toList()) { - if (namespacedDirectory.equals(valueDirectory)) { + if (Files.exists(this.customWorldsDirectory)) { + for (final Path namespacedDirectory : Files.list(this.customWorldsDirectory).toList()) { + if (!Files.isDirectory(namespacedDirectory) || this.customWorldsDirectory.equals(namespacedDirectory)) { continue; } - worldKeys.add(ResourceKey.of(namespacedDirectory.getFileName().toString(), valueDirectory.getFileName().toString())); + for (final Path valueDirectory : Files.list(namespacedDirectory).toList()) { + if (!Files.isDirectory(valueDirectory) || namespacedDirectory.equals(valueDirectory)) { + continue; + } + + worldKeys.add(ResourceKey.of(namespacedDirectory.getFileName().toString(), valueDirectory.getFileName().toString())); + } } } } catch (final IOException e) { @@ -220,7 +219,8 @@ public boolean worldExists(final ResourceKey key) { return true; } - return Files.exists(this.getDirectory(key)); + final Path dimensionDir = this.getDirectory(key); + return Files.exists(dimensionDir); } @Override @@ -271,42 +271,22 @@ public CompletableFuture> loadWorld(final ResourceKey key, return CompletableFuture.failedFuture(new CancellationException()); } + final LevelStorageSource.LevelStorageAccess storageSource = this.serverStorageSource(); + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOption.loadOperation().orElse(null); if (loadOperation != null && this.worldExists(key)) { - try { - final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess(key); - try { - final Optional result = this.loadLevelData(storageSource, registryKey, loadOperation); - if (result.isPresent()) { - loadOperation.loadCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.get().data())); - return this.loadWorld0(t, registryKey, result.get(), storageSource); - } else { - storageSource.close(); - } - } catch (final Exception e) { - storageSource.close(); - return CompletableFuture.failedFuture(e); - } - } catch (final IOException e) { - return CompletableFuture.failedFuture(e); + final Optional result = this.loadLevelData(storageSource, registryKey, loadOperation); + if (result.isPresent()) { + loadOperation.loadCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.get().data())); + return this.loadWorld0(t, registryKey, result.get(), storageSource); } } final ServerWorldProperties.LoadOptions.@Nullable CreateOperation createOperation = propertiesLoadOption.createOperation().orElse(null); if (createOperation != null) { - try { - final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess(key); - try { - final LevelDataLoadResult result = this.createLevelData(registryKey, createOperation.worldArchetype()); - createOperation.createCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.data())); - return this.loadWorld0(t, registryKey, result, storageSource); - } catch (final Exception e) { - storageSource.close(); - return CompletableFuture.failedFuture(e); - } - } catch (final IOException e) { - return CompletableFuture.failedFuture(e); - } + final LevelDataLoadResult result = this.createLevelData(registryKey, createOperation.worldArchetype()); + createOperation.createCallback().ifPresent(c -> c.accept((ServerWorldProperties) result.data())); + return this.loadWorld0(t, registryKey, result, storageSource); } return CompletableFuture.completedFuture(Optional.empty()); @@ -333,17 +313,8 @@ private CompletableFuture> loadWorld0(final WorldOperation .thenApply(w -> Optional.of((ServerWorld) w)); } - private LevelStorageSource.LevelStorageAccess createLevelStorageAccess(final ResourceKey worldKey) throws IOException { - LevelStorageSource.LevelStorageAccess storageAccess; - if (this.isVanillaWorld(worldKey)) { - final String directoryName = this.getDirectoryName(worldKey); - storageAccess = LevelStorageSource.createDefault(this.defaultWorldDirectory).createAccess(directoryName); - } else { - final String name = worldKey.namespace() + File.separator + worldKey.value(); - storageAccess = LevelStorageSource.createDefault(this.customWorldsDirectory).createAccess(name); - } - ((LevelStorageAccessBridge) storageAccess).bridge$setDedicated(true); - return storageAccess; + private LevelStorageSource.LevelStorageAccess serverStorageSource() { + return ((MinecraftServerAccessor) this.server).accessor$storageSource(); } @Override @@ -412,15 +383,11 @@ public CompletableFuture> loadProperties(final R final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation = propertiesLoadOptions.loadOperation().orElse(null); if (loadOperation != null && this.worldExists(key)) { - try { - final Optional result = this.loadLevelData(registryKey, loadOperation); - if (result.isPresent()) { - final ServerWorldProperties properties = (ServerWorldProperties) result.get().data(); - loadOperation.loadCallback().ifPresent(c -> c.accept(properties)); - return Optional.of(properties); - } - } catch (final IOException e) { - throw new RuntimeException(e); + final Optional result = this.loadLevelData(registryKey, loadOperation); + if (result.isPresent()) { + final ServerWorldProperties properties = (ServerWorldProperties) result.get().data(); + loadOperation.loadCallback().ifPresent(c -> c.accept(properties)); + return Optional.of(properties); } } @@ -441,27 +408,29 @@ public CompletableFuture saveProperties(final ServerWorldProperties pro final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(properties, "properties").key()); return this.performWorldOperation(registryKey, WorldOperationType.SAVE, t -> { - if (this.worlds.get(registryKey) != null) { - return CompletableFuture.completedFuture(false); + final ServerLevel level = this.worlds.get(registryKey); + if (level != null) { + // World is loaded — save it through the level's normal save mechanism + return SpongeCommon.asyncScheduler().submit(() -> { + level.save(null, true, level.noSave); + return true; + }); } + // World is not loaded — save the properties to the level.dat on disk return SpongeCommon.asyncScheduler().submit(() -> { if (properties instanceof WorldData worldData) { this.saveLevelDat(worldData, properties.key()); + return true; } - // TODO else: what about DerivedDataLevel? - - // Properties doesn't have everything we need...namely the generator, load the template and set values we actually got - throw new IllegalArgumentException("TODO!"); + return false; }); }); } - private void saveLevelDat(final WorldData worldData, final ResourceKey key) throws IOException { - try (var storageSource = this.createLevelStorageAccess(key)) { - storageSource.saveDataTag(worldData); - } + private void saveLevelDat(final WorldData worldData, final ResourceKey key) { + this.serverStorageSource().saveDataTag(worldData); } @Override @@ -494,8 +463,6 @@ public CompletableFuture copyWorld(final ResourceKey key, final Resourc disableLevelSaving = false; } - final boolean isDefaultWorld = DefaultWorldKeys.DEFAULT.equals(key); - return CompletableFuture.runAsync(() -> { final Path originalDirectory = this.getDirectory(key); final Path copyDirectory = this.getDirectory(copyKey); @@ -504,16 +471,6 @@ public CompletableFuture copyWorld(final ResourceKey key, final Resourc Files.walkFileTree(originalDirectory, new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { - // Silly recursion if the default world is being copied - if (dir.getFileName().toString().equals(Constants.Sponge.World.DIMENSIONS_DIRECTORY)) { - return FileVisitResult.SKIP_SUBTREE; - } - - // Silly copying of vanilla sub worlds if the default world is being copied - if (isDefaultWorld && SpongeWorldManager.this.isVanillaSubWorld(dir.getFileName().toString())) { - return FileVisitResult.SKIP_SUBTREE; - } - final Path relativize = originalDirectory.relativize(dir); final Path directory = copyDirectory.resolve(relativize); Files.createDirectories(directory); @@ -557,13 +514,9 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr throw new CompletionException(e); } - try { - final Optional levelData = this.loadLevelData(copyRegistryKey, null); - if (levelData.isPresent()) { - this.saveLevelDat(levelData.get().data(), copyKey); - } - } catch (final IOException e) { - throw new CompletionException(e); + final Optional levelData = this.loadLevelData(copyRegistryKey, null); + if (levelData.isPresent()) { + this.saveLevelDat(levelData.get().data(), copyKey); } }).thenApplyAsync($ -> { if (loadedWorld != null) { @@ -629,13 +582,9 @@ private CompletableFuture moveWorld0(final ResourceKey key, final Resou throw new CompletionException(e); } - try { - final Optional levelData = this.loadLevelData(movedRegistryKey, null); - if (levelData.isPresent()) { - this.saveLevelDat(levelData.get().data(), movedKey); - } - } catch (final IOException e) { - throw new CompletionException(e); + final Optional levelData = this.loadLevelData(movedRegistryKey, null); + if (levelData.isPresent()) { + this.saveLevelDat(levelData.get().data(), movedKey); } return true; @@ -755,7 +704,7 @@ private CompletableFuture unloadWorld0(final WorldOperationTask task, f try { level.save(null, true, level.noSave); level.close(); - ((ServerLevelBridge) level).bridge$getLevelSave().close(); + // No longer closing per-world storageAccess -- all worlds share the server's single LevelStorageAccess } catch (final Exception ex) { return CompletableFuture.failedFuture(new IOException(ex)); } @@ -767,6 +716,9 @@ private CompletableFuture unloadWorld0(final WorldOperationTask task, f } public void createNonDefaultLevels() { + // Migration from old SpongeData format is handled by FileFixerUpperMixin + // which runs BEFORE any ServerLevel is created, preserving UUIDs in + // per-dimension data/sponge/registry.dat files. final Registry registry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM); for (final LevelStem levelStem : registry) { final ResourceKey worldKey = (ResourceKey) (Object) registry.getKey(levelStem); @@ -781,44 +733,145 @@ public void createNonDefaultLevels() { } final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(worldKey); + final LevelStorageSource.LevelStorageAccess storageSource = this.serverStorageSource(); try { - final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess(worldKey); - try { - final LevelDataLoadResult levelData = this.loadLevelData(storageSource, registryKey, null) - .orElseGet(() -> this.createLevelData(registryKey, WorldArchetype.of((WorldArchetypeType) (Object) levelStem))); - if (!((PrimaryLevelDataBridge) levelData.data()).bridge$loadOnStartup()) { - SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey); - continue; - } - - final ServerLevel world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); - this.prepareLevel(world); - } catch (final Exception e) { - storageSource.close(); - throw e; + final LevelDataLoadResult levelData = this.loadLevelData(storageSource, registryKey, null) + .orElseGet(() -> this.createLevelData(registryKey, WorldArchetype.of((WorldArchetypeType) (Object) levelStem))); + if (!((PrimaryLevelDataBridge) levelData.data()).bridge$loadOnStartup()) { + SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey); + continue; } - } catch (final IOException e) { - throw new RuntimeException(String.format("Failed to create level data for world '%s'!", worldKey), e); + + final ServerLevel world = this.createLevel(registryKey, levelData.stem(), storageSource, levelData.data()); + this.prepareLevel(world); } catch (final Exception e) { throw new IllegalStateException(String.format("Failed to create level data for world '%s'!", worldKey), e); } } } - private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey, - final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) throws IOException { - try (final LevelStorageSource.LevelStorageAccess storageSource = this.createLevelStorageAccess((ResourceKey) (Object) registryKey.identifier())) { - return this.loadLevelData(storageSource, registryKey, loadOperation); + /** + * Migrates old Sponge world data from previous formats. + * + *

In pre-26.1 Sponge, per-world identity (UUID, key) was stored in a {@code SpongeData} + * compound inside each dimension's {@code level.dat}. In the new format, this data lives + * in {@code data/sponge/registry.dat} per-dimension via {@link SpongeRegistryData}.

+ * + *

This method handles:

+ *
    + *
  • Reading {@code SpongeData} from the root {@code level.dat} (overworld identity)
  • + *
  • Writing it to {@code dimensions/minecraft/overworld/data/sponge/registry.dat}
  • + *
  • Stripping {@code SpongeData} from the root {@code level.dat}
  • + *
+ * + *

Note: Per-dimension {@code level.dat} files for nether/end are lost during vanilla's + * {@code DimensionStorageFileFix} (which deletes {@code DIM-1/} and {@code DIM1/} after + * moving region/entities/poi/data). Those dimensions get fresh UUIDs on first load.

+ */ + private void migrateOldSpongeData() { + final Path rootLevelDat = this.defaultWorldDirectory.resolve("level.dat"); + if (!Files.exists(rootLevelDat)) { + return; + } + + try { + final CompoundTag root = NbtIo.readCompressed(rootLevelDat, NbtAccounter.defaultQuota()); + final CompoundTag spongeData = root.getCompound("SpongeData").orElse(null); + if (spongeData == null || spongeData.isEmpty()) { + return; // No old SpongeData to migrate + } + + SpongeCommon.logger().info("Migrating old SpongeData from level.dat files to per-dimension SavedData..."); + + // Migrate each dimension that has SpongeData + // Root level.dat = overworld, check dimensions/ for nether/end level.dat + // (vanilla's DimensionStorageFileFix moves region/entities/poi/data from DIM-1/DIM1 + // to dimensions/minecraft/the_nether|the_end but does NOT move level.dat — those are lost. + // However, if someone manually placed them or they survived, we handle them.) + this.migrateOneDimension(spongeData, Level.OVERWORLD, "overworld"); + + // Check for per-dimension level.dat files that may survive in the new directories + for (final var entry : Map.of( + Level.NETHER, "the_nether", + Level.END, "the_end" + ).entrySet()) { + final Path dimLevelDat = DimensionType.getStorageFolder(entry.getKey(), this.defaultWorldDirectory) + .resolve("level.dat"); + if (Files.exists(dimLevelDat)) { + try { + final CompoundTag dimRoot = NbtIo.readCompressed(dimLevelDat, NbtAccounter.defaultQuota()); + final @Nullable CompoundTag dimSpongeData = dimRoot.getCompound("SpongeData").orElse(null); + if (dimSpongeData != null && !dimSpongeData.isEmpty()) { + this.migrateOneDimension(dimSpongeData, entry.getKey(), entry.getValue()); + dimRoot.remove("SpongeData"); + NbtIo.writeCompressed(dimRoot, dimLevelDat); + } + } catch (final Exception e) { + SpongeCommon.logger().warn(" Failed to migrate SpongeData from {}", dimLevelDat, e); + } + } + } + + // Strip SpongeData from root level.dat + root.remove("SpongeData"); + NbtIo.writeCompressed(root, rootLevelDat); + SpongeCommon.logger().info(" Stripped SpongeData from root level.dat"); + + } catch (final Exception e) { + SpongeCommon.logger().warn("Failed to migrate old SpongeData from level.dat — worlds will get fresh UUIDs", e); } } + private void migrateOneDimension( + final CompoundTag spongeData, + final net.minecraft.resources.ResourceKey dimensionKey, + final String dimensionName + ) { + try { + final Path dataDir = DimensionType.getStorageFolder(dimensionKey, this.defaultWorldDirectory) + .resolve("data").resolve("sponge"); + final Path registryFile = dataDir.resolve("registry.dat"); + if (Files.exists(registryFile)) { + return; // Already migrated + } + + final int[] uuidArray = spongeData.getIntArray("UUID").orElse(null); + if (uuidArray == null || uuidArray.length != 4) { + return; + } + + final UUID uuid = new UUID( + (long) uuidArray[0] << 32 | uuidArray[1] & 0xFFFFFFFFL, + (long) uuidArray[2] << 32 | uuidArray[3] & 0xFFFFFFFFL + ); + + Files.createDirectories(dataDir); + final SpongeRegistryData registryData = new SpongeRegistryData(uuid, Optional.of(dimensionKey)); + final var encoded = SpongeRegistryData.CODEC.encodeStart(NbtOps.INSTANCE, registryData); + if (encoded.isSuccess()) { + final CompoundTag savedDataTag = new CompoundTag(); + savedDataTag.put("data", encoded.getOrThrow()); + NbtUtils.addCurrentDataVersion(savedDataTag); + NbtIo.writeCompressed(savedDataTag, registryFile); + SpongeCommon.logger().info(" Migrated {} UUID {} to {}", dimensionName, uuid, registryFile); + } + } catch (final Exception e) { + SpongeCommon.logger().warn(" Failed to migrate SpongeData for dimension {}", dimensionName, e); + } + } + + private Optional loadLevelData(final net.minecraft.resources.ResourceKey registryKey, + final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation) { + return this.loadLevelData(this.serverStorageSource(), registryKey, loadOperation); + } + private Optional loadLevelData( final LevelStorageSource.LevelStorageAccess storageSource, final net.minecraft.resources.ResourceKey registryKey, final ServerWorldProperties.LoadOptions.@Nullable LoadOperation loadOperation ) { - return Optional.ofNullable(this.loadLevelTag(storageSource)).map(t -> this.readLevelData(storageSource, registryKey, t, loadOperation)); + return Optional.ofNullable(this.loadLevelTag(registryKey)).map(t -> this.readLevelData(storageSource, registryKey, t, loadOperation)); } private LevelDataLoadResult initializeLevelData(final ResourceKey key, final PrimaryLevelData data, final LevelStem stem) { @@ -833,17 +886,27 @@ private LevelDataLoadResult initializeLevelData(final ResourceKey key, final Pri return new LevelDataLoadResult(data, stem); } - private @Nullable Dynamic loadLevelTag(final LevelStorageSource.LevelStorageAccess storageSource) { + /** + * Attempts to load a per-dimension level.dat from the dimension's directory. + * With the shared LevelStorageAccess, we cannot use storageSource.getUnfixedDataTag() + * (which reads from the ROOT level.dat). Instead, check the dimension-specific path. + * + *

In the new architecture, non-overworld dimensions do NOT have their own level.dat + * (Sponge no longer writes per-dimension level.dat files). This method returns null + * for dimensions without one, causing loadLevelData to fall through to createLevelData.

+ */ + private @Nullable Dynamic loadLevelTag(final net.minecraft.resources.ResourceKey registryKey) { + final Path dimensionDir = DimensionType.getStorageFolder(registryKey, this.defaultWorldDirectory); + final Path levelDat = dimensionDir.resolve("level.dat"); + if (!Files.exists(levelDat)) { + return null; + } try { - return storageSource.getUnfixedDataTag(false); + final CompoundTag root = NbtIo.readCompressed(levelDat, NbtAccounter.defaultQuota()); + return new Dynamic<>(NbtOps.INSTANCE, root.getCompoundOrEmpty("Data")); } catch (final IOException e) { - try { - final Dynamic dataTag = storageSource.getUnfixedDataTagWithFallback(); - storageSource.restoreLevelDataFromOld(); - return dataTag; - } catch (final IOException ex) { - return null; - } + SpongeCommon.logger().warn("Failed to load level data from {}", levelDat, e); + return null; } } @@ -908,13 +971,17 @@ private static WorldArchetype resolveWorldArchetype(final LevelDataAndDimensions private LevelDataLoadResult createLevelData(final net.minecraft.resources.ResourceKey registryKey, final WorldArchetype archetype) { final LevelStem levelStem = (LevelStem) (Object) archetype.type(); final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData(); - final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, this.getDirectoryName((ResourceKey) (Object) registryKey.identifier())); - return this.initializeLevelData( + final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, registryKey.identifier().toString()); + final LevelDataLoadResult result = this.initializeLevelData( (ResourceKey) (Object) registryKey.identifier(), new PrimaryLevelData(levelSettings, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable()), levelStem ); + // Apply custom generation config from the archetype (e.g. custom seed) + archetype.generationConfig().ifPresent(o -> + ((PrimaryLevelDataBridge) result.data()).bridge$spongeData().setWorldOptions((WorldOptions) o)); + return result; } private LevelSettings createLevelSettings(final PrimaryLevelData defaultLevelData, final String directoryName) { @@ -957,17 +1024,28 @@ private ServerLevel createLevel( registryKey, levelStem, levelData.isDebugWorld(), seed, spawners, true); this.worlds.put(registryKey, world); - // Ensure that the world border is registered. - // TODO - 26.1-snapshot-6 figure out if this is still required -// levelData.getLegacyWorldBorderSettings().ifPresent(legacy -> { -// final var border = world.getWorldBorder(); -// border.setSize(legacy.size()); -// border.setCenter(legacy.centerX(), legacy.centerZ()); -// border.setSafeZone(legacy.safeZone()); -// border.setDamagePerBlock(legacy.damagePerBlock()); -// border.setWarningTime(legacy.warningTime()); -// border.setWarningBlocks(legacy.warningBlocks()); -// }); + // Persist the LevelStem in the server's WorldGenSettings so custom dimensions survive restart. + // WorldGenSettings is a SavedData in the server-level SavedDataStorage. The dimensions() map + // may be immutable (from codec deserialization), so we replace the WorldGenSettings entirely + // with a new instance containing the updated dimensions map. + final net.minecraft.resources.ResourceKey stemKey = Registries.levelToLevelStem(registryKey); + final WorldGenSettings currentSettings = this.server.getWorldGenSettings(); + if (!currentSettings.dimensions().dimensions().containsKey(stemKey)) { + final Map, LevelStem> mutableDims = new HashMap<>(currentSettings.dimensions().dimensions()); + mutableDims.put(stemKey, levelStem); + final WorldGenSettings updated = new WorldGenSettings(currentSettings.options(), new WorldDimensions(mutableDims)); + this.server.getDataStorage().set(WorldGenSettings.TYPE, updated); + } + + // Store per-dimension WorldGenSettings in the dimension's own SavedDataStorage. + // This gives each world its own world_gen_settings.dat with the correct seed/options. + final var levelSpongeData = ((PrimaryLevelDataBridge) levelData).bridge$spongeData(); + final WorldOptions perWorldOptions = levelSpongeData.worldGenOptions() != null + ? levelSpongeData.worldGenOptions() : currentSettings.options(); + final WorldGenSettings perDimSettings = new WorldGenSettings( + perWorldOptions, new WorldDimensions(Map.of(stemKey, levelStem))); + world.getDataStorage().set(WorldGenSettings.TYPE, perDimSettings); + PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); return world; } @@ -1072,38 +1150,9 @@ public static net.minecraft.resources.ResourceKey createRegistryKey(final return net.minecraft.resources.ResourceKey.create(Registries.DIMENSION, (Identifier) (Object) key); } - private String getDirectoryName(final ResourceKey key) { - if (DefaultWorldKeys.DEFAULT.equals(key)) { - return ""; - } - if (DefaultWorldKeys.THE_NETHER.equals(key)) { - return "DIM-1"; - } - if (DefaultWorldKeys.THE_END.equals(key)) { - return "DIM1"; - } - return key.value(); - } - private Path getDirectory(final ResourceKey key) { - if (DefaultWorldKeys.DEFAULT.equals(key)) { - return this.defaultWorldDirectory; - } - if (DefaultWorldKeys.THE_NETHER.equals(key)) { - return this.defaultWorldDirectory.resolve("DIM-1"); - } - if (DefaultWorldKeys.THE_END.equals(key)) { - return this.defaultWorldDirectory.resolve("DIM1"); - } - return this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value()); - } - - private boolean isVanillaWorld(final ResourceKey key) { - return DefaultWorldKeys.DEFAULT.equals(key) || DefaultWorldKeys.THE_NETHER.equals(key) || DefaultWorldKeys.THE_END.equals(key); - } - - private boolean isVanillaSubWorld(final String directoryName) { - return "DIM-1".equals(directoryName) || "DIM1".equals(directoryName); + final net.minecraft.resources.ResourceKey registryKey = SpongeWorldManager.createRegistryKey(key); + return DimensionType.getStorageFolder(registryKey, this.defaultWorldDirectory); } private Path getConfigFile(final ResourceKey key) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java index a81b0fa604c..94dd423ee8b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/MinecraftServerMixin_API.java @@ -34,7 +34,6 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minecraft.commands.Commands; import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerScoreboard; import net.minecraft.server.dedicated.DedicatedServer; @@ -42,8 +41,6 @@ import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.PlayerList; import net.minecraft.world.level.gamerules.GameRules; -import net.minecraft.world.level.levelgen.WorldDimensions; -import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.WorldData; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 60bdb65d43c..c449a78f738 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -44,7 +44,6 @@ import net.minecraft.world.level.dimension.end.EnderDragonFight; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.ticks.LevelTicks; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -208,7 +207,7 @@ public boolean restoreSnapshot(final int x, final int y, final int z, final Bloc @Override public Path directory() { - return ((ServerLevelBridge) this).bridge$getLevelSave().getLevelPath(LevelResource.ROOT); + return ((ServerLevelBridge) this).bridge$getLevelSave().getDimensionPath(this.shadow$dimension()); } private boolean impl$save(final boolean flush) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 6af2d4d8b82..861612758cb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -31,10 +31,10 @@ import net.minecraft.server.commands.AdvancementCommands; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.commands.CommandsBridge; import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; import org.spongepowered.common.command.manager.SpongeCommandManager; @@ -58,7 +58,7 @@ public abstract class CommandsMixin implements CommandsBridge { return new CommandDispatcher<>(); } final SpongeCommandManager manager = Launch.instance().lifecycle().platformInjector().getInstance(SpongeCommandManager.class); - manager.init((RegistryHolder) context); + manager.init(SpongeCommon.game()); this.impl$commandManager = manager; return new DelegatingCommandDispatcher(manager.getBrigadierRegistrar()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index c601603bd98..c4bc5db8016 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -83,13 +83,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.SpongeServer; +import org.spongepowered.common.accessor.server.MinecraftServerAccessor; import org.spongepowered.common.accessor.util.BlockableEventLoopAccessor; import org.spongepowered.common.adventure.NativeComponentRenderer; import org.spongepowered.common.bridge.commands.CommandSourceBridge; import org.spongepowered.common.bridge.commands.CommandSourceProviderBridge; import org.spongepowered.common.bridge.network.chat.SpongeChatDecorator; import org.spongepowered.common.bridge.server.MinecraftServerBridge; -import org.spongepowered.common.bridge.server.level.ServerLevelBridge; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.bridge.server.players.GameProfileCacheBridge; import org.spongepowered.common.bridge.server.players.PlayerListBridge; @@ -109,9 +109,9 @@ import org.spongepowered.common.service.server.SpongeServerScopedServiceProvider; import org.spongepowered.common.user.SpongeUserManager; import org.spongepowered.common.util.AutoSaveMapQueue; +import org.spongepowered.common.world.server.SpongeLevelMigration; import org.spongepowered.common.world.server.SpongeWorldManager; -import java.io.IOException; import java.net.Proxy; import java.util.Locale; import java.util.Map; @@ -232,6 +232,18 @@ public Subject subject() { frame.pushCause(Sponge.systemSubject()); } + /** + * Writes migrated SpongeRegistryData files AFTER FileFixerUpper.fix() has completed + * (the COW swap is done, directory structure is final) but BEFORE any ServerLevel is created. + * This ensures SavedDataStorage.computeIfAbsent() finds the files on disk. + */ + @Inject(method = "loadLevel", at = @At("HEAD")) + private void impl$writeMigratedSpongeRegistryData(final CallbackInfo ci) { + SpongeLevelMigration.writeCachedRegistryData( + ((MinecraftServerAccessor) this).accessor$storageSource().getLevelDirectory().path() + ); + } + @Inject(method = "createLevels", at = @At(value = "NEW", target = "(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;ZJLjava/util/List;Z)Lnet/minecraft/server/level/ServerLevel;" ), slice = @Slice( @@ -292,21 +304,9 @@ public String getServerModName() { } } - @Inject(method = "stopServer", at = @At(value = "TAIL")) - private void impl$closeLevelSaveForOtherWorlds(final CallbackInfo ci) { - for (final Map.Entry, ServerLevel> entry : this.levels.entrySet()) { - if (entry.getKey() == Level.OVERWORLD) { - continue; - } - - final LevelStorageSource.LevelStorageAccess levelSave = ((ServerLevelBridge) entry.getValue()).bridge$getLevelSave(); - try { - levelSave.close(); - } catch (final IOException e) { - MinecraftServerMixin.LOGGER.error("Failed to unlock level {}", levelSave.getLevelId(), e); - } - } - } + // Phase 1+2: All worlds now share the server's single LevelStorageAccess. + // The server's storageSource is closed by vanilla's stopServer() itself, + // so we no longer need to close per-world storage access instances. /** * Render localized/formatted chat components diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 95ae5252d28..13676d5ed1b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -79,6 +79,8 @@ import net.minecraft.world.level.dimension.end.EnderDragonFight; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.gamerules.GameRuleMap; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.saveddata.WeatherData; import net.minecraft.world.level.storage.LevelData; @@ -148,6 +150,7 @@ import org.spongepowered.common.mixin.core.world.level.LevelMixin; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.SpongeTicks; +import org.spongepowered.common.world.server.SpongeRegistryData; import org.spongepowered.common.world.server.SpongeServerLevelData; import org.spongepowered.common.world.weather.SpongeWeather; import org.spongepowered.math.vector.Vector3d; @@ -185,45 +188,69 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel private LevelStorageSource.LevelStorageAccess impl$levelSave; private CustomBossEvents impl$bossBarManager; - @Unique private @Nullable WeatherData impl$perWorldWeatherData; private Weather impl$prevWeather; private boolean impl$isManualSave = false; private long impl$preTickTime = 0L; private boolean impl$closed = false; + @Unique private @Nullable GameRules impl$gameRules; /** - * Initializes per-world {@link WeatherData}, replacing the global server weather data. + * Initializes per-world {@link WeatherData} via vanilla's {@link SavedDataStorage}. * This intercepts the {@code server.getWeatherData()} call used by {@code prepareWeather} * in the constructor, ensuring each world has independent weather state from creation. * - *

A new {@link WeatherData} instance is created per world rather than using - * {@link SavedDataStorage#computeIfAbsent}, because all dimensions share the same - * {@link SavedDataStorage} (the overworld's). Weather state is instead persisted through - * {@link SpongeServerLevelData.WeatherState} in the Sponge level data.

+ *

Since each dimension has its own {@link SavedDataStorage} (created by + * {@link ServerChunkCache} at {@code getDimensionPath(dim).resolve("data")}), + * {@code computeIfAbsent(WeatherData.TYPE)} creates a per-dimension {@code weather.dat} + * file automatically.

*/ @WrapOperation( method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWeatherData()Lnet/minecraft/world/level/saveddata/WeatherData;") ) private WeatherData impl$initPerWorldWeatherData(final MinecraftServer instance, final Operation original) { - this.impl$perWorldWeatherData = new WeatherData(); - return this.impl$perWorldWeatherData; + return this.shadow$getDataStorage().computeIfAbsent(WeatherData.TYPE); } /** * Redirects {@link ServerLevel#getWeatherData()} to return the per-world {@link WeatherData} - * instead of the global server weather data. This enables independent weather cycles, commands, - * and API access for each world. + * from this dimension's {@link SavedDataStorage} instead of the global server weather data. + * This enables independent weather cycles, commands, and API access for each world. */ @WrapOperation( method = "getWeatherData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWeatherData()Lnet/minecraft/world/level/saveddata/WeatherData;") ) private WeatherData impl$usePerWorldWeatherData(final MinecraftServer instance, final Operation original) { - if (this.impl$perWorldWeatherData != null) { - return this.impl$perWorldWeatherData; + return this.shadow$getDataStorage().computeIfAbsent(WeatherData.TYPE); + } + + /** + * Overrides {@link ServerLevel#getGameRules()} to return per-dimension game rules + * backed by a per-dimension {@link GameRuleMap} stored via {@link SavedDataStorage}. + * + *

The per-dimension {@code GameRuleMap} is loaded (or created) via + * {@code computeIfAbsent(GameRuleMap.TYPE)}, which stores/reads from + * each dimension's own {@code data/} directory as {@code game_rules.dat}.

+ */ + @WrapOperation( + method = "getGameRules", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getGameRules()Lnet/minecraft/world/level/gamerules/GameRules;") + ) + private GameRules impl$perWorldGameRules(final MinecraftServer instance, final Operation original) { + if (this.impl$gameRules == null) { + final GameRuleMap perWorldMap = this.shadow$getDataStorage().computeIfAbsent(GameRuleMap.TYPE); + final boolean isNewWorld = perWorldMap.size() == 0; + this.impl$gameRules = new GameRules( + instance.getWorldData().enabledFeatures(), + perWorldMap + ); + if (isNewWorld) { + // New world — copy the server's current game rule values as initial defaults + this.impl$gameRules.setAll(original.call(instance), null); + } } - return original.call(instance); + return this.impl$gameRules; } @Inject(method = "", at = @At("TAIL")) @@ -242,25 +269,16 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel ) { final SpongeServerLevelData spongeData = ((ServerLevelDataBridge) levelData).bridge$spongeData(); - // Restore per-world weather state from Sponge level data if available. - // On first load (migration from global weather), the overworld inherits the - // server's global WeatherData state, while other worlds start with clear weather. - if (this.impl$perWorldWeatherData != null) { - spongeData.weatherState().ifPresentOrElse( - ws -> ws.applyTo(this.impl$perWorldWeatherData), - () -> { - // Migration: for overworld, copy the server's global weather state - if (Level.OVERWORLD.equals(dimension)) { - final WeatherData globalWeather = server.getWeatherData(); - SpongeServerLevelData.WeatherState.fromWeatherData(globalWeather).applyTo(this.impl$perWorldWeatherData); - } - } - ); - } - final ResourceKey worldKey = ((ServerWorld) this).key(); + + // Load per-dimension identity from SpongeRegistryData (SavedDataStorage) + final SpongeRegistryData registryData = this.shadow$getDataStorage().computeIfAbsent(SpongeRegistryData.TYPE); + if (registryData.key() == null) { + registryData.setKey(worldKey); + } + // Populate SpongeServerLevelData from registry data + spongeData.setUniqueId(registryData.uniqueId()); if (spongeData.key() == null) { - SpongeCommon.logger().warn("Level data ({}) has no key associated but is used by world {} ({}).", levelData.getClass().getSimpleName(), worldKey, this.getClass().getSimpleName()); spongeData.setKey(worldKey); } else if (!spongeData.key().equals(worldKey)) { SpongeCommon.logger().warn("Level data ({}) has key {} but is used by world {} ({}).", levelData.getClass().getSimpleName(), spongeData.key(), worldKey, this.getClass().getSimpleName()); @@ -329,10 +347,10 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Override public CustomBossEvents bridge$getBossBarManager() { if (this.impl$bossBarManager == null) { - if (Level.OVERWORLD.equals(this.shadow$dimension()) || this.bridge$isFake()) { + if (this.bridge$isFake()) { this.impl$bossBarManager = this.shadow$getServer().getCustomBossEvents(); } else { - this.impl$bossBarManager = new CustomBossEvents(); + this.impl$bossBarManager = this.shadow$getDataStorage().computeIfAbsent(CustomBossEvents.TYPE); } } @@ -457,26 +475,10 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final SerializationBehavior behavior = ((ServerLevelDataBridge) levelData).bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC); if (behavior != SerializationBehavior.NONE) { - // Persist per-world weather state to Sponge level data before saving - if (this.impl$perWorldWeatherData != null) { - ((ServerLevelDataBridge) levelData).bridge$spongeData() - .setWeatherState(SpongeServerLevelData.WeatherState.fromWeatherData(this.impl$perWorldWeatherData)); - } - original.call(self, flush); - - // per-world WorldInfo/WorldBorder/BossBars/WorldGen - // TODO - 26.1-snapshot-6 figure out if this is still required -// final var border = this.getWorldBorder(); -// if (levelData instanceof PrimaryLevelDataBridge pldb) { -// final var spongeData = pldb.bridge$spongeData(); -// this.bridge$getLevelSave().saveLevelData(); -// } -// levelData.setLegacyWorldBorderSettings(Optional.of(new WorldBorder.Settings(border))); -// if (levelData instanceof WorldData worldData) { -// worldData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); -// this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), worldData, this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null); -// } + // In 26.1, per-world WorldBorder, BossEvents, Weather, and GameRules are all + // SavedData instances in per-dimension SavedDataStorage. They are automatically + // saved by vanilla's saveLevelData() → SavedDataStorage.saveAndJoin(). } } @@ -501,7 +503,8 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel ) private boolean impl$handleIsThunderingIfHasCeiling(final WeatherData instance, final Operation original) { if (this.levelData instanceof PrimaryLevelDataBridge pldb && pldb.bridge$dimensionType() != null) { - return pldb.bridge$dimensionType().hasCeiling() && original.call(instance); + // Dimensions with a ceiling (e.g. nether) should not have visible weather effects + return !pldb.bridge$dimensionType().hasCeiling() && original.call(instance); } return original.call(instance); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/util/filefix/FileFixerUpperMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/util/filefix/FileFixerUpperMixin.java new file mode 100644 index 00000000000..dcee32e25ec --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/util/filefix/FileFixerUpperMixin.java @@ -0,0 +1,211 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.util.filefix; + +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Dynamic; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtAccounter; +import net.minecraft.nbt.NbtIo; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.filefix.FileFixerUpper; +import net.minecraft.util.worldupdate.UpgradeProgress; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.storage.LevelStorageSource; +import org.apache.commons.io.file.PathUtils; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.world.server.SpongeLevelMigration; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Mixin on {@link FileFixerUpper} to preserve Sponge's per-world identity (UUID, key) + * during vanilla's file-fixing process, which rewrites {@code level.dat} and strips + * unknown tags including the {@code SpongeData} compound. + * + *

This also cleans up old Sponge-created files ({@code DIM-1/level.dat}, + * {@code DIM1/level.dat}, {@code session.lock}) so that vanilla's + * {@code DimensionStorageFileFix} can fully delete the legacy directories.

+ */ +@Mixin(FileFixerUpper.class) +public abstract class FileFixerUpperMixin { + + @Unique private static final Logger SPONGE_LOGGER = LogUtils.getLogger(); + + // TODO: Also cache MapUUIDs and player-uuid-table from old SpongeData for migration + // to separate SavedData files (sponge:map_uuids, etc.) — see follow-up task + + /** + * Extracts SpongeData from level.dat and per-dimension level.dat files BEFORE + * vanilla's file fixer rewrites them. Also cleans up old Sponge files so + * vanilla can fully delete DIM-1/DIM1 directories. + */ + @Inject(method = "fix(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/serialization/Dynamic;Lnet/minecraft/util/worldupdate/UpgradeProgress;)Lcom/mojang/serialization/Dynamic;", + at = @At("HEAD")) + private void sponge$extractSpongeDataBeforeFix( + final LevelStorageSource.LevelStorageAccess worldAccess, + final Dynamic levelDataTag, + final UpgradeProgress upgradeProgress, + final CallbackInfoReturnable> cir + ) { + final Map, UUID> identities = new HashMap<>(); + final Path worldDir = worldAccess.getLevelDirectory().path(); + + // 1. Extract overworld UUID from root level.dat's SpongeData (in the Dynamic) + // Note: levelDataTag is the "Data" compound, but SpongeData is a SIBLING of Data + // at the root level. We need to re-read the raw file to get it. + try { + final CompoundTag root = NbtIo.readCompressed(worldDir.resolve("level.dat"), NbtAccounter.defaultQuota()); + final CompoundTag spongeData = root.getCompound("SpongeData").orElse(null); + if (spongeData != null && !spongeData.isEmpty()) { + sponge$extractUuid(spongeData, Level.OVERWORLD, identities); + // Also cache MapUUIDs and player-uuid-table for global migration + SpongeLevelMigration.cacheGlobalSpongeData(spongeData); + } + } catch (final IOException e) { + // No level.dat or can't read — skip + } + + // 2. Extract nether/end UUIDs from their per-dimension level.dat files + // and clean up old Sponge files so vanilla can delete the directories + sponge$extractAndCleanDimension(worldDir, "DIM-1", Level.NETHER, identities); + sponge$extractAndCleanDimension(worldDir, "DIM1", Level.END, identities); + + if (!identities.isEmpty()) { + SPONGE_LOGGER.info("[Sponge] Preserved {} world UUID(s) from old SpongeData during file fix", identities.size()); + // Cache for writing AFTER the fix completes and the COW swap is done. + // The actual write happens in MinecraftServerMixin.loadLevel() via SpongeLevelMigration. + SpongeLevelMigration.cacheIdentities(identities); + } + } + + // Registry.dat writing is deferred to MinecraftServerMixin.loadLevel() HEAD inject, + // which runs AFTER fix() completes (COW swap done) but BEFORE any ServerLevel is created. + + /** + * Extracts a UUID from a SpongeData compound's "UUID" IntArray field. + */ + @Unique + private static void sponge$extractUuid( + final CompoundTag spongeData, + final ResourceKey dimKey, + final Map, UUID> identities + ) { + final int[] uuidArray = spongeData.getIntArray("UUID").orElse(null); + if (uuidArray != null && uuidArray.length == 4) { + final UUID uuid = new UUID( + (long) uuidArray[0] << 32 | uuidArray[1] & 0xFFFFFFFFL, + (long) uuidArray[2] << 32 | uuidArray[3] & 0xFFFFFFFFL + ); + identities.put(dimKey, uuid); + } + } + + /** + * Reads SpongeData from an old per-dimension level.dat (e.g. DIM-1/level.dat), + * extracts the UUID, then deletes all Sponge-created files so vanilla's + * DimensionStorageFileFix can fully remove the legacy directory. + */ + @Unique + private static void sponge$extractAndCleanDimension( + final Path worldDir, + final String legacyDirName, + final ResourceKey dimKey, + final Map, UUID> identities + ) { + final Path legacyDir = worldDir.resolve(legacyDirName); + final Path legacyLevelDat = legacyDir.resolve("level.dat"); + + if (!Files.exists(legacyLevelDat)) { + return; + } + + // Extract SpongeData + try { + final CompoundTag root = NbtIo.readCompressed(legacyLevelDat, NbtAccounter.defaultQuota()); + final CompoundTag spongeData = root.getCompound("SpongeData").orElse(null); + if (spongeData != null && !spongeData.isEmpty()) { + sponge$extractUuid(spongeData, dimKey, identities); + } + } catch (final IOException e) { + SPONGE_LOGGER.warn("[Sponge] Failed to read SpongeData from {}", legacyLevelDat, e); + } + + // Migrate any remaining SavedData files that vanilla didn't move + // (e.g. random_sequences.dat that was left behind in DIM-1/data/) + // Old format: DIM-1/data/random_sequences.dat (flat, no namespace) + // New format: dimensions/minecraft/the_nether/data/minecraft/random_sequences.dat (namespaced) + final Path legacyDataDir = legacyDir.resolve("data"); + final Path newDimDir = DimensionType.getStorageFolder(dimKey, worldDir); + final Path newDataDir = newDimDir.resolve("data").resolve("minecraft"); // namespace subdirectory + try { + if (Files.exists(legacyDataDir) && Files.isDirectory(legacyDataDir)) { + Files.createDirectories(newDataDir); + try (var stream = Files.list(legacyDataDir)) { + stream.filter(Files::isRegularFile).forEach(source -> { + final Path target = newDataDir.resolve(source.getFileName()); + try { + if (!Files.exists(target)) { + Files.move(source, target); + SPONGE_LOGGER.info("[Sponge] Migrated {} -> {}", source.getFileName(), target); + } + } catch (final IOException e) { + SPONGE_LOGGER.warn("[Sponge] Failed to migrate {}", source, e); + } + }); + } + } + } catch (final IOException e) { + SPONGE_LOGGER.warn("[Sponge] Failed to migrate data files from {}", legacyDirName, e); + } + + // Clean up old Sponge files so vanilla can delete the legacy directory + try { + Files.deleteIfExists(legacyLevelDat); + Files.deleteIfExists(legacyDir.resolve("session.lock")); + if (Files.exists(legacyDataDir)) { + PathUtils.deleteDirectory(legacyDataDir); + } + // Delete the now-empty legacy directory + if (Files.exists(legacyDir) && Files.list(legacyDir).findFirst().isEmpty()) { + Files.delete(legacyDir); + } + SPONGE_LOGGER.info("[Sponge] Cleaned up legacy directory {}", legacyDirName); + } catch (final IOException e) { + SPONGE_LOGGER.warn("[Sponge] Failed to clean up {}", legacyDirName, e); + } + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java index 82bf8dc0b92..406e8ebd404 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java @@ -33,6 +33,8 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; +import net.minecraft.core.Holder; + import java.util.Map; @Mixin(WorldDimensions.class) @@ -52,7 +54,9 @@ private Object findOverworldStem(final Map instance, final Object key) { // ends up being a double lookup for all worlds but the overworld but I feel it is a small price to pay vs. a very complicated series // of mixins to remove retrieving the level stem settings solely for all worlds but the overworld if (val == null) { - return SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).get((ResourceKey) key); + // Registry.get() returns Optional> in 26.1, not the value directly + return SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).get((ResourceKey) key) + .map(ref -> (Object) ref.value()).orElse(null); } return val; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java index 9f1b4eae9fb..807136191f0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/LevelStorageSource_LevelStorageAccessMixin.java @@ -24,68 +24,23 @@ */ package org.spongepowered.common.mixin.core.world.level.storage; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.WorldData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.common.bridge.data.DataCompoundHolder; -import org.spongepowered.common.bridge.world.level.storage.LevelStorageAccessBridge; -import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; -import org.spongepowered.common.data.DataUtil; -import org.spongepowered.common.util.Constants; - -import java.nio.file.Path; @Mixin(LevelStorageSource.LevelStorageAccess.class) -public abstract class LevelStorageSource_LevelStorageAccessMixin implements LevelStorageAccessBridge { +public abstract class LevelStorageSource_LevelStorageAccessMixin { // @formatter:off @Shadow @Final LevelStorageSource.LevelDirectory levelDirectory; // @formatter:on - private boolean impl$dedicated = false; - - @Inject(method = "getDimensionPath", at = @At("HEAD"), cancellable = true) - public void impl$dedicatedDimensionPath(final CallbackInfoReturnable cir) { - if (this.impl$dedicated) { - cir.setReturnValue(this.levelDirectory.path()); - } - } - @ModifyArg(method = "checkLock", at = @At(value = "INVOKE", target = "Ljava/lang/IllegalStateException;(Ljava/lang/String;)V", ordinal = 0, remap = false)) private String modifyMinecraftExceptionOutputIfNotInitializationTime(final String message) { return "Lock for world " + this.levelDirectory.path() + " is no longer valid!"; } - - @WrapOperation( - method = "saveDataTag(Lnet/minecraft/world/level/storage/WorldData;Ljava/util/UUID;)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V" - ) - ) - @SuppressWarnings("deprecation") - private void impl$saveSpongeLevelData( - final LevelStorageSource.LevelStorageAccess instance, final CompoundTag root, - final Operation original, final WorldData levelData) { - root.put(Constants.Sponge.Data.V2.SPONGE_DATA, ((PrimaryLevelDataBridge) levelData).bridge$writeSpongeLevelData()); - if (DataUtil.syncDataToTag(levelData)) { - root.merge(((DataCompoundHolder) levelData).data$getCompound()); - } - original.call(instance, root); - } - - @Override - public void bridge$setDedicated(final boolean dedicated) { - this.impl$dedicated = dedicated; - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java index a9c74b583d5..be6885b2847 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/PrimaryLevelDataMixin.java @@ -25,19 +25,10 @@ package org.spongepowered.common.mixin.core.world.level.storage; import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.Codec; -import com.mojang.serialization.Dynamic; import net.kyori.adventure.text.Component; import net.minecraft.core.GlobalPos; -import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.IntArrayTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; -import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Difficulty; @@ -55,18 +46,15 @@ import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.data.DataCompoundHolder; import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge; import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; -import org.spongepowered.common.data.DataUtil; -import org.spongepowered.common.data.fixer.LegacyUUIDCodec; -import org.spongepowered.common.util.Constants; -import org.spongepowered.common.util.MapUtil; import org.spongepowered.common.util.VecHelper; +import org.spongepowered.common.world.server.SpongeMapUUIDData; import org.spongepowered.common.world.server.SpongeServerLevelData; import org.spongepowered.math.vector.Vector3i; -import java.util.Collections; import java.util.Optional; import java.util.StringJoiner; import java.util.UUID; @@ -87,11 +75,7 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat private DimensionType impl$dimensionType; private ChunkGenerator impl$chunkGenerator; - private final BiMap impl$playerUniqueIdMap = HashBiMap.create(); - private boolean impl$customDifficulty = false, impl$customGameType = false, impl$customSpawnPosition = false; - - private BiMap impl$mapUUIDIndex = HashBiMap.create(); private @Nullable CompoundTag impl$compound; @Override @@ -247,24 +231,30 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat @Override public BiMap bridge$getMapUUIDIndex() { - return this.impl$mapUUIDIndex; + return this.impl$getMapUUIDData().mapUUIDIndex(); } @Override public int bridge$getIndexForUniqueId(final UUID uuid) { - final Integer index = this.impl$playerUniqueIdMap.inverse().get(uuid); + final var data = this.impl$getMapUUIDData(); + final Integer index = data.playerUUIDIndex().inverse().get(uuid); if (index != null) { return index; } - final int newIndex = this.impl$playerUniqueIdMap.size(); - this.impl$playerUniqueIdMap.put(newIndex, uuid); + final int newIndex = data.playerUUIDIndex().size(); + data.playerUUIDIndex().put(newIndex, uuid); + data.setDirty(); return newIndex; } @Override public Optional bridge$getUniqueIdForIndex(final int index) { - return Optional.ofNullable(this.impl$playerUniqueIdMap.get(index)); + return Optional.ofNullable(this.impl$getMapUUIDData().playerUUIDIndex().get(index)); + } + + private SpongeMapUUIDData impl$getMapUUIDData() { + return SpongeCommon.server().getDataStorage().computeIfAbsent(SpongeMapUUIDData.TYPE); } void impl$updateWorldForDifficultyChange(final ServerLevel level, final boolean isLocked) { @@ -307,58 +297,6 @@ public abstract class PrimaryLevelDataMixin implements ServerLevelData, WorldDat ); } - @Override - @SuppressWarnings({"deprecated","deprecation"}) - public void bridge$readSpongeLevelData(final Dynamic dynamic) { - dynamic.get(Constants.Sponge.Data.V3.SPONGE_WORLD_DATA).read(SpongeServerLevelData.CODEC).ifSuccess(ssld -> { - this.impl$spongeData = ssld; - }); - dynamic.get(Constants.Sponge.Data.V2.SPONGE_DATA).get().ifSuccess(v2 -> { - v2.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(this.impl$spongeData::setUniqueId); - v2.get(Constants.Sponge.World.WORLD_KEY).read(Identifier.CODEC).result() - .map(org.spongepowered.api.ResourceKey.class::cast).ifPresent(this.impl$spongeData::setKey); - - v2.get(Constants.Map.MAP_UUID_INDEX).readMap(Codec.STRING, UUIDUtil.CODEC).result().ifPresent(value -> { - final BiMap mapIndex = HashBiMap.create(); - for (final Pair pair : value) { - final int id = Integer.parseInt(pair.getFirst()); - mapIndex.put(id, pair.getSecond()); - } - this.impl$mapUUIDIndex = mapIndex; - }); - - // TODO Move this to Schema - v2.get(Constants.Sponge.LEGACY_SPONGE_PLAYER_UUID_TABLE).readList(LegacyUUIDCodec.CODEC).result().orElseGet(() -> - v2.get(Constants.Sponge.SPONGE_PLAYER_UUID_TABLE).readList(UUIDUtil.CODEC).result().orElse(Collections.emptyList()) - ).forEach(uuid -> this.impl$playerUniqueIdMap.inverse().putIfAbsent(uuid, this.impl$playerUniqueIdMap.size())); - }); - - this.data$setCompound((CompoundTag) dynamic.getValue()); - DataUtil.syncTagToData(this); - this.data$setCompound(null); - } - - @Override - public CompoundTag bridge$writeSpongeLevelData() { - final CompoundTag data = new CompoundTag(); - data.store(Constants.Sponge.World.UNIQUE_ID, UUIDUtil.CODEC, this.impl$spongeData.uniqueId()); - - if (this.impl$spongeData.key() != null) { - data.putString(Constants.Sponge.World.WORLD_KEY, this.impl$spongeData.key().formatted()); - } - - // Map Storage - final CompoundTag mapUUIDIndexTag = new CompoundTag(); - MapUtil.saveMapUUIDIndex(mapUUIDIndexTag, this.impl$mapUUIDIndex); - data.put(Constants.Map.MAP_UUID_INDEX, mapUUIDIndexTag); - - final ListTag playerIdList = new ListTag(); - data.put(Constants.Sponge.SPONGE_PLAYER_UUID_TABLE, playerIdList); - this.impl$playerUniqueIdMap.values().forEach(uuid -> playerIdList.add(new IntArrayTag(UUIDUtil.uuidToIntArray(uuid)))); - - return data; - } - @Override public String toString() { return new StringJoiner(", ", PrimaryLevelData.class.getSimpleName() + "[", "]") @@ -381,16 +319,6 @@ public String toString() { this.impl$compound = nbt; } - // TODO - 26.1-snapshot-6 - figure out where to shove this in now? Do we just append it to the level data or keep it in sponge data? -// @Redirect(method = "setTagData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldGenSettings;encode(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/world/level/levelgen/WorldOptions;Lnet/minecraft/core/RegistryAccess;)Lcom/mojang/serialization/DataResult;")) -// private DataResult impl$onEncodeWorldGenSettings(final DynamicOps $$0, final WorldOptions $$1, final RegistryAccess $$2) { -// final Map, LevelStem> dimensions = $$2.lookupOrThrow(Registries.LEVEL_STEM) -// .listElements() -// .collect(Collectors.toMap(Holder.Reference::key, Holder.Reference::value)); -// if (this.impl$dimensionType != null && this.impl$chunkGenerator != null) { -// dimensions.computeIfAbsent(ResourceKey.create(Registries.LEVEL_STEM, (Identifier) (Object) this.impl$spongeData.key()), -// $ -> new LevelStem($$2.lookupOrThrow(Registries.DIMENSION_TYPE).wrapAsHolder(this.impl$dimensionType), this.impl$chunkGenerator)); -// } -// return WorldGenSettings.encode($$0, $$1, new WorldDimensions(dimensions)); -// } + // LevelStem persistence for runtime-created worlds is now handled by SpongeWorldManager.createLevel() + // which adds the LevelStem to WorldGenSettings.dimensions() (a SavedData in server-level SavedDataStorage). } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java index 907e2aca975..7e299105340 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/SavedDataStorageMixin.java @@ -79,7 +79,7 @@ public T readSpongeMapData( DataUtil.syncTagToData(dch); dch.data$setCompound(null); } - return null; + return result; } @Override diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 6b6125c3a40..e08c1a9e768 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -219,6 +219,7 @@ "world.item.crafting.SingleItemRecipeMixin", "world.item.crafting.SmithingTransformRecipeMixin", "world.item.enchantment.EnchantmentMixin_Attack", + "util.filefix.FileFixerUpperMixin", "world.level.BaseSpawnerMixin", "world.level.BlockGetterMixin", "world.level.Explosion_BlockInteractionMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java index 1e945e8ab1e..bf239b3c537 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/storage/LevelStorageSourceMixin_Vanilla.java @@ -24,55 +24,14 @@ */ package org.spongepowered.vanilla.mixin.core.world.level.storage; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.mojang.serialization.Dynamic; -import com.mojang.serialization.Lifecycle; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; -import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge; +/** + * Previously captured and read SpongeData from level.dat during world loading. + * SpongeData is no longer stored in level.dat; per-world identity (UUID, key) + * is now handled by {@code SpongeRegistryData} via per-dimension SavedDataStorage. + */ @Mixin(LevelStorageSource.class) public abstract class LevelStorageSourceMixin_Vanilla { - - private static Dynamic impl$spongeLevelData; - - @WrapOperation( - method = "readExistingSavedData", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/nbt/CompoundTag;getCompoundOrEmpty(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;", - ordinal = 0 - ) - ) - private static CompoundTag impl$createSpongeLevelData(final CompoundTag compoundNBT, final String path, final Operation original) { - LevelStorageSourceMixin_Vanilla.impl$spongeLevelData = new Dynamic<>(NbtOps.INSTANCE, compoundNBT); - return original.call(compoundNBT, path); - } - - @WrapOperation( - method = "getLevelDataAndDimensions", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;parse(Lcom/mojang/serialization/Dynamic;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/storage/PrimaryLevelData$SpecialWorldProperty;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/world/level/storage/PrimaryLevelData;" - ) - ) - private static PrimaryLevelData impl$readSpongeLevelData( - final Dynamic input, final LevelSettings settings, - final PrimaryLevelData.SpecialWorldProperty specialWorldProperty, final Lifecycle worldGenSettingsLifecycle, - final Operation original) - { - final PrimaryLevelData levelData = original.call(input, settings, specialWorldProperty, worldGenSettingsLifecycle); - - ((PrimaryLevelDataBridge) levelData).bridge$readSpongeLevelData(LevelStorageSourceMixin_Vanilla.impl$spongeLevelData); - - LevelStorageSourceMixin_Vanilla.impl$spongeLevelData = null; - return levelData; - } } From 0e1843750245bdfd5a6afed634a4c9b75f394ef8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 17 Mar 2026 00:03:13 -0700 Subject: [PATCH 479/586] fix(worlds): resolve inline DimensionType holders and fix SavedData codec When WorldArchetypeType.of() created a LevelStem, it used Holder.direct() for the DimensionType, producing an inline holder with no registry ID. The login packet STREAM_CODEC requires a registry reference, causing EncoderException when players join custom worlds. The fix has three parts: - SpongeWorldArchetypeType.build() now uses registry.wrapAsHolder() to produce Holder.Reference for newly created worlds - SpongeWorldManager.resolveInlineDimensionType() resolves inline holders loaded from persisted WorldGenSettings by structural field comparison, since the registry uses IdentityHashMap and HolderSet.Named lacks value-based equals() - ServerLevelDataBridge.bridge$levelStem() uses wrapAsHolder() instead of Holder.direct() for the default implementation Also fixes SpongeMapUUIDData codec crash on server shutdown: NBT CompoundTag keys must be strings, but Codec.unboundedMap(Codec.INT, ...) produced IntTag keys causing "Not a string" IllegalStateException during SavedDataStorage.encodeUnchecked(). Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../level/storage/ServerLevelDataBridge.java | 6 +- .../world/server/SpongeMapUUIDData.java | 3 +- .../server/SpongeWorldArchetypeType.java | 8 +- .../world/server/SpongeWorldManager.java | 74 +++++++++++++++++-- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index c93c8550741..738cdda86b5 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit c93c855074150d1c3dc04c29874a8cc3e140b2fa +Subproject commit 738cdda86b5f30d8f4ab61802178786db1034111 diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java index 9780ca08df2..70ab4a74720 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java @@ -26,7 +26,8 @@ import com.google.common.collect.MapMaker; import net.kyori.adventure.text.Component; -import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -88,7 +89,8 @@ public interface ServerLevelDataBridge { } default LevelStem bridge$levelStem() { - return new LevelStem(Holder.direct(this.bridge$dimensionType()), this.bridge$chunkGenerator()); + final Registry registry = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE); + return new LevelStem(registry.wrapAsHolder(this.bridge$dimensionType()), this.bridge$chunkGenerator()); } default boolean bridge$customDifficulty() { diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java b/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java index 8797570acbd..01fe1358346 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeMapUUIDData.java @@ -46,8 +46,9 @@ */ public final class SpongeMapUUIDData extends SavedData { + // NBT CompoundTag keys must be strings, so use string-based int codec for map keys private static final Codec> MAP_INDEX_CODEC = - Codec.unboundedMap(Codec.INT, UUIDUtil.CODEC); + Codec.unboundedMap(Codec.STRING.xmap(Integer::parseInt, String::valueOf), UUIDUtil.CODEC); public static final Codec CODEC = RecordCodecBuilder.create( i -> i.group( diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java index 5639e6d4cd0..43ffb9faf22 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldArchetypeType.java @@ -24,12 +24,14 @@ */ package org.spongepowered.common.world.server; -import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.generation.ChunkGenerator; import org.spongepowered.api.world.server.WorldArchetypeType; +import org.spongepowered.common.SpongeCommon; public final class SpongeWorldArchetypeType implements WorldArchetypeType.Builder { @@ -68,6 +70,8 @@ public WorldArchetypeType.Builder reset() { @Override public WorldArchetypeType build() { - return (WorldArchetypeType) (Object) new LevelStem(Holder.direct((DimensionType) (Object) this.worldType), (net.minecraft.world.level.chunk.ChunkGenerator) this.chunkGenerator); + final DimensionType dimensionType = (DimensionType) (Object) this.worldType; + final Registry registry = SpongeCommon.vanillaRegistry(Registries.DIMENSION_TYPE); + return (WorldArchetypeType) (Object) new LevelStem(registry.wrapAsHolder(dimensionType), (net.minecraft.world.level.chunk.ChunkGenerator) this.chunkGenerator); } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index aa242cce150..c0e65ffc442 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -31,6 +31,7 @@ import net.minecraft.ReportedException; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; @@ -1005,10 +1006,17 @@ private ServerLevel createLevel( final Registry dimensionTypes = this.server.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); final var saveDataSotrage = this.server.getDataStorage(); + // Resolve inline DimensionType holders to registry references. + // When a LevelStem is deserialized from WorldGenSettings with an inline DimensionType + // (Holder.direct), the login packet encoder fails because STREAM_CODEC expects a registry ID. + // The registry uses IdentityHashMap so wrapAsHolder() won't match deserialized instances. + // Instead, iterate the registry and match by record equals(). + final LevelStem resolvedStem = SpongeWorldManager.resolveInlineDimensionType(levelStem, dimensionTypes); + MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}'", worldKey); final List spawners; - if (levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD) || levelStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD_CAVES)) { + if (resolvedStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD) || resolvedStem.type().value() == dimensionTypes.getValue(BuiltinDimensionTypes.OVERWORLD_CAVES)) { // TODO - 26.1-snapshot-6 figure out if we need to do anything here per world? spawners = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(saveDataSotrage)); } else { @@ -1021,18 +1029,17 @@ private ServerLevel createLevel( final Executor executor = ((MinecraftServerAccessor) this.server).accessor$executor(); final ServerLevel world = new ServerLevel(this.server, executor, storageSource, levelData, - registryKey, levelStem, levelData.isDebugWorld(), seed, spawners, true); + registryKey, resolvedStem, levelData.isDebugWorld(), seed, spawners, true); this.worlds.put(registryKey, world); - // Persist the LevelStem in the server's WorldGenSettings so custom dimensions survive restart. - // WorldGenSettings is a SavedData in the server-level SavedDataStorage. The dimensions() map - // may be immutable (from codec deserialization), so we replace the WorldGenSettings entirely - // with a new instance containing the updated dimensions map. + // Persist the LevelStem (with resolved holder) in the server's WorldGenSettings so custom + // dimensions survive restart. Using the resolved stem ensures the DimensionType is serialized + // as a registry reference, not inline, breaking the inline cycle for future loads. final net.minecraft.resources.ResourceKey stemKey = Registries.levelToLevelStem(registryKey); final WorldGenSettings currentSettings = this.server.getWorldGenSettings(); if (!currentSettings.dimensions().dimensions().containsKey(stemKey)) { final Map, LevelStem> mutableDims = new HashMap<>(currentSettings.dimensions().dimensions()); - mutableDims.put(stemKey, levelStem); + mutableDims.put(stemKey, resolvedStem); final WorldGenSettings updated = new WorldGenSettings(currentSettings.options(), new WorldDimensions(mutableDims)); this.server.getDataStorage().set(WorldGenSettings.TYPE, updated); } @@ -1043,7 +1050,7 @@ private ServerLevel createLevel( final WorldOptions perWorldOptions = levelSpongeData.worldGenOptions() != null ? levelSpongeData.worldGenOptions() : currentSettings.options(); final WorldGenSettings perDimSettings = new WorldGenSettings( - perWorldOptions, new WorldDimensions(Map.of(stemKey, levelStem))); + perWorldOptions, new WorldDimensions(Map.of(stemKey, resolvedStem))); world.getDataStorage().set(WorldGenSettings.TYPE, perDimSettings); PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); @@ -1244,6 +1251,57 @@ void cancel() { } } + /** + * Resolves inline (Holder.direct) DimensionType holders in a LevelStem to registry references. + * + *

When a LevelStem is deserialized from WorldGenSettings with an inline DimensionType, + * the network STREAM_CODEC (ByteBufCodecs.holderRegistry) can't find the registry ID, + * causing login packet encoding to fail. The DimensionType registry uses IdentityHashMap + * for value lookups, so wrapAsHolder() won't match deserialized record instances. + * Record equals() also fails because HolderSet.Named uses identity comparison.

+ * + *

This method matches by comparing the structural primitive/enum/TagKey fields of + * DimensionType, which are reliably comparable across deserialized instances.

+ */ + static LevelStem resolveInlineDimensionType(final LevelStem stem, final Registry dimensionTypes) { + if (stem.type() instanceof Holder.Reference) { + return stem; // Already a registry reference + } + final DimensionType inline = stem.type().value(); + for (final var entry : dimensionTypes.entrySet()) { + final DimensionType registered = entry.getValue(); + if (SpongeWorldManager.dimensionTypeStructurallyEquals(inline, registered)) { + final Optional> ref = dimensionTypes.get(entry.getKey().identifier()); + if (ref.isPresent()) { + return new LevelStem(ref.get(), stem.generator()); + } + } + } + SpongeCommon.logger().warn("Could not resolve inline DimensionType to registry reference. " + + "Login packets for worlds using this dimension type may fail."); + return stem; + } + + /** + * Compares two DimensionType instances by their structural fields, ignoring Holder/HolderSet + * fields that use identity-based equality (HolderSet.Named, Holder.Reference). + */ + private static boolean dimensionTypeStructurallyEquals(final DimensionType a, final DimensionType b) { + return a.hasFixedTime() == b.hasFixedTime() + && a.hasSkyLight() == b.hasSkyLight() + && a.hasCeiling() == b.hasCeiling() + && a.hasEnderDragonFight() == b.hasEnderDragonFight() + && Double.compare(a.coordinateScale(), b.coordinateScale()) == 0 + && a.minY() == b.minY() + && a.height() == b.height() + && a.logicalHeight() == b.logicalHeight() + && a.infiniburn().equals(b.infiniburn()) + && Float.compare(a.ambientLight(), b.ambientLight()) == 0 + && a.monsterSettings().monsterSpawnBlockLightLimit() == b.monsterSettings().monsterSpawnBlockLightLimit() + && a.skybox() == b.skybox() + && a.cardinalLightType() == b.cardinalLightType(); + } + private enum WorldOperationType { LOAD, UNLOAD, From ef6dbc6e416bbd90ad1e68822975689c94b54c64 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 17 Mar 2026 00:08:41 -0700 Subject: [PATCH 480/586] chore(git): update SpongeAPI submodule reference Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 738cdda86b5..97658e06796 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 738cdda86b5f30d8f4ab61802178786db1034111 +Subproject commit 97658e0679679d351490d449137dc2dfd1c74924 From 6030264f920d202583565c0254b2eb9d812ee645 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 17 Mar 2026 00:49:49 -0700 Subject: [PATCH 481/586] feat(minecraft): update generated api data for 26.1-snapshot-7 Notable additions: - Sounds and InstrumentTypes See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_7 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- gradle.properties | 2 +- .../common/data/provider/block/state/SnowyDirtData.java | 8 ++++---- .../common/world/server/SpongeWorldManager.java | 3 ++- .../common/mixin/core/block/BedBlockMixin.java | 2 +- .../common/mixin/core/client/MinecraftMixin.java | 2 +- .../common/mixin/core/server/MinecraftServerMixin.java | 4 ++-- .../level/ServerChunkCache_MainThreadExecutorMixin.java | 2 +- .../mixin/test/server/MinecraftServerMixin_Test.java | 2 +- 9 files changed, 14 insertions(+), 13 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 97658e06796..38ec73c181f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 97658e0679679d351490d449137dc2dfd1c74924 +Subproject commit 38ec73c181f85132c50f08ec1c86740b3976270b diff --git a/gradle.properties b/gradle.properties index 1a9340cf112..885e24fc201 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-6 +minecraftVersion=26.1-snapshot-7 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/SnowyDirtData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/SnowyDirtData.java index fbdd221aea0..12886cba8f5 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/SnowyDirtData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/SnowyDirtData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.block.state; -import net.minecraft.world.level.block.SnowyDirtBlock; +import net.minecraft.world.level.block.SnowyBlock; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.api.data.Keys; import org.spongepowered.common.data.provider.DataProviderRegistrator; @@ -39,9 +39,9 @@ public static void register(final DataProviderRegistrator registrator) { registrator .asImmutable(BlockState.class) .create(Keys.IS_SNOWY) - .get(h -> h.getValue(SnowyDirtBlock.SNOWY)) - .set((h, v) -> h.setValue(SnowyDirtBlock.SNOWY, v)) - .supports(h -> h.getBlock() instanceof SnowyDirtBlock); + .get(h -> h.getValue(SnowyBlock.SNOWY)) + .set((h, v) -> h.setValue(SnowyBlock.SNOWY, v)) + .supports(h -> h.getBlock() instanceof SnowyBlock); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index c0e65ffc442..20befcaa5c9 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -48,6 +48,7 @@ import net.minecraft.server.level.progress.LevelLoadListener; import net.minecraft.server.level.progress.LoggingLevelLoadListener; import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.filefix.FileFixException; import net.minecraft.util.worldupdate.UpgradeProgress; import net.minecraft.world.entity.ai.village.VillageSiege; import net.minecraft.world.entity.npc.CatSpawner; @@ -924,7 +925,7 @@ private LevelDataLoadResult readLevelData( final Dynamic fixedDataTag; try { fixedDataTag = DataFixers.getFileFixer().fix(worldAccess, dataTag, new UpgradeProgress()); - } catch (final IOException e) { + } catch (final FileFixException e) { throw new RuntimeException(String.format("Failed to apply data fixes for world '%s'", registryKey.identifier()), e); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java index dd3357b9c2e..078a6126eae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/block/BedBlockMixin.java @@ -68,7 +68,7 @@ public class BedBlockMixin { if (Sponge.eventManager().post(SpongeEventFactory.createSleepingEventFailed(currentCause, snapshot, (Living) param3))) { param3.startSleepInBed(param2).ifLeft((param1x) -> { if (param1x != null && param1x.message() != null) { - param3.displayClientMessage(param1x.message(), true); + param3.sendOverlayMessage(param1x.message()); } }); cir.setReturnValue(InteractionResult.SUCCESS); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index e2cc02207db..23d069ba04b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -56,7 +56,7 @@ public abstract class MinecraftMixin extends ReentrantBlockableEventLoop impl$spongeMainThreadExecutor = new BlockableEventLoop<>("Sponge") { + private final BlockableEventLoop impl$spongeMainThreadExecutor = new BlockableEventLoop<>("Sponge", false) { //Used to schedule internal Sponge tasks to the main thread //that could be joined on the main thread. Avoiding using the @@ -199,7 +199,7 @@ public Subject subject() { private void impl$setThreadOnServerPhaseTracker( Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, WorldStem worldStem, Optional gameRules, Proxy proxy, DataFixer fixerUpper, Services services, - LevelLoadListener levelLoadListener, CallbackInfo ci + LevelLoadListener levelLoadListener, boolean propagatesCrashes, CallbackInfo ci ) { try { PhaseTracker.getServerInstanceExplicitly().setThread(serverThread); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerChunkCache_MainThreadExecutorMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerChunkCache_MainThreadExecutorMixin.java index 3f6e053ce22..255ba3d6f7f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerChunkCache_MainThreadExecutorMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerChunkCache_MainThreadExecutorMixin.java @@ -34,7 +34,7 @@ public abstract class ServerChunkCache_MainThreadExecutorMixin extends Blockable private volatile boolean impl$closed; protected ServerChunkCache_MainThreadExecutorMixin(final String $$0) { - super($$0); + super($$0, false); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java index 79c6b77ab55..4109e7371c9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java +++ b/src/mixins/java/org/spongepowered/common/mixin/test/server/MinecraftServerMixin_Test.java @@ -54,7 +54,7 @@ public abstract class MinecraftServerMixin_Test extends ReentrantBlockableEventL // @formatter:on public MinecraftServerMixin_Test(final String name) { - super(name); + super(name, false); } @Inject(method = "", at = @At("RETURN")) From 3d49c35b36c8c090535b6da93fe88cdedf24c4bb Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 19 Mar 2026 20:47:48 -0700 Subject: [PATCH 482/586] feat(minecraft): update to 26.1-snapshot-8 Migrates from snapshot-6 to snapshot-8, addressing API changes and fixing several runtime issues. Adventure text: SelectorPattern replaced by CompilableString, NbtContents/BlockDataSource/EntityDataSource now use CompilableString wrappers, and Item hover events use registry.wrapAsHolder() instead of Holder.direct(). Registry loading: skip RegisterRegistryValueEvent on client-side network loads (only SYNCHRONIZED_REGISTRIES available, server-only registries like placed_feature cause dependency validation failures). Fix duplicate registry crash on world re-join by filtering existing keys before concat. Phase tracking: BlockableEventLoopMixin_Tracker now associates the Minecraft plugin container with SCHEDULED_TASK contexts, fixing NPE during integrated server shutdown. See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_8 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- gradle/verification-metadata.xml | 88 +++++++++++++++++++ .../common/adventure/SpongeAdventure.java | 55 ++++++++---- .../level/levelgen/WorldDimensionsMixin.java | 2 - .../BlockableEventLoopMixin_Tracker.java | 4 +- .../RegistryDataLoaderMixin_Vanilla.java | 34 +++++-- 6 files changed, 156 insertions(+), 29 deletions(-) diff --git a/gradle.properties b/gradle.properties index 885e24fc201..9cd3d41b84d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-7 +minecraftVersion=26.1-snapshot-8 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6816171ad11..c6d5095251f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -10158,6 +10158,17 @@
+ + + + + + + + + + + @@ -10195,6 +10206,17 @@ + + + + + + + + + + + @@ -10255,6 +10277,17 @@ + + + + + + + + + + + @@ -10307,6 +10340,17 @@ + + + + + + + + + + + @@ -10359,6 +10403,17 @@ + + + + + + + + + + + @@ -10419,6 +10474,17 @@ + + + + + + + + + + + @@ -10479,6 +10545,17 @@ + + + + + + + + + + + @@ -10539,6 +10616,17 @@ + + + + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index 3faa90eaf0d..aea7bbad43b 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -24,10 +24,12 @@ */ package org.spongepowered.common.adventure; +import com.google.gson.JsonPrimitive; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.Message; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; import com.mojang.serialization.codecs.PrimitiveCodec; import io.netty.util.AttributeKey; import net.kyori.adventure.audience.Audience; @@ -66,8 +68,9 @@ import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.util.TriState; import net.minecraft.ChatFormatting; -import net.minecraft.commands.arguments.selector.SelectorPattern; -import net.minecraft.core.Holder; +import net.minecraft.commands.arguments.NbtPathArgument; +import net.minecraft.commands.arguments.coordinates.Coordinates; +import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.component.DataComponentPatch; @@ -96,6 +99,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerBossEvent; import net.minecraft.sounds.SoundSource; +import net.minecraft.util.CompilableString; import net.minecraft.world.BossEvent; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; @@ -286,6 +290,18 @@ public static Optional asVanillaOpt(final return component == null ? Optional.empty() : Optional.of(((ComponentBridge) component).bridge$asVanillaComponent()); } + private static CompilableString parseSelector(final String pattern) { + return EntitySelector.COMPILABLE_CODEC.parse(JsonOps.INSTANCE, new JsonPrimitive(pattern)).getOrThrow(); + } + + private static CompilableString parseNbtPath(final String path) { + return NbtContents.NBT_PATH_CODEC.parse(JsonOps.INSTANCE, new JsonPrimitive(path)).getOrThrow(); + } + + private static CompilableString parseBlockPos(final String pos) { + return BlockDataSource.BLOCK_POS_CODEC.parse(JsonOps.INSTANCE, new JsonPrimitive(pos)).getOrThrow(); + } + // no caching public static MutableComponent asVanillaMutable(final Component component) { final MutableComponent vanilla = SpongeAdventure.asVanillaMutable0(component); @@ -311,17 +327,20 @@ private static MutableComponent asVanillaMutable0(final Component component) { case KeybindComponent keybind -> net.minecraft.network.chat.Component.keybind(keybind.keybind()); case ScoreComponent score -> net.minecraft.network.chat.Component.score(score.name(), score.objective()); case SelectorComponent selector -> net.minecraft.network.chat.Component.selector( - SelectorPattern.parse(selector.pattern()).getOrThrow(), SpongeAdventure.asVanillaOpt(selector.separator()) + SpongeAdventure.parseSelector(selector.pattern()), SpongeAdventure.asVanillaOpt(selector.separator()) ); - case BlockNBTComponent block -> net.minecraft.network.chat.Component.nbt(block.nbtPath(), block.interpret(), + case BlockNBTComponent block -> net.minecraft.network.chat.Component.nbt( + SpongeAdventure.parseNbtPath(block.nbtPath()), block.interpret(), false, SpongeAdventure.asVanillaOpt(block.separator()), - new BlockDataSource(block.pos().asString())); + new BlockDataSource(SpongeAdventure.parseBlockPos(block.pos().asString()))); case EntityNBTComponent entity -> - net.minecraft.network.chat.Component.nbt(entity.nbtPath(), entity.interpret(), + net.minecraft.network.chat.Component.nbt( + SpongeAdventure.parseNbtPath(entity.nbtPath()), entity.interpret(), false, SpongeAdventure.asVanillaOpt(entity.separator()), - new EntityDataSource(entity.selector())); + new EntityDataSource(SpongeAdventure.parseSelector(entity.selector()))); case StorageNBTComponent storage -> - net.minecraft.network.chat.Component.nbt(storage.nbtPath(), storage.interpret(), + net.minecraft.network.chat.Component.nbt( + SpongeAdventure.parseNbtPath(storage.nbtPath()), storage.interpret(), false, SpongeAdventure.asVanillaOpt(storage.separator()), new StorageDataSource(SpongeAdventure.asVanilla(storage.storage()))); case ObjectComponent obj -> net.minecraft.network.chat.Component.object(SpongeAdventure.asVanilla(obj.contents())); @@ -372,21 +391,21 @@ public static Component asAdventure(final net.minecraft.network.chat.Component c } case KeybindContents kc -> Component.keybind().keybind(kc.getName()); case ScoreContents sc -> - Component.score().name(sc.name().mapLeft(SelectorPattern::pattern).orThrow()).objective(sc.objective()); + Component.score().name(sc.name().mapLeft(CompilableString::source).orThrow()).objective(sc.objective()); case SelectorContents sc -> - Component.selector().pattern(sc.selector().pattern()).separator(SpongeAdventure.asAdventure(sc.separator())); + Component.selector().pattern(sc.selector().source()).separator(SpongeAdventure.asAdventure(sc.separator())); case NbtContents nbt -> { - final NBTComponentBuilder nbtBuilder = switch (nbt.getDataSource()) { + final NBTComponentBuilder nbtBuilder = switch (nbt.dataSource()) { case BlockDataSource bds -> - Component.blockNBT().pos(BlockNBTComponent.Pos.fromString(bds.posPattern())); - case EntityDataSource eds -> Component.entityNBT().selector(eds.selectorPattern()); + Component.blockNBT().pos(BlockNBTComponent.Pos.fromString(bds.coordinates().source())); + case EntityDataSource eds -> Component.entityNBT().selector(eds.selector().source()); case StorageDataSource sds -> Component.storageNBT().storage(SpongeAdventure.asAdventure(sds.id())); default -> - throw new UnsupportedOperationException("Cannot convert NBTContents with DataSource " + nbt.getDataSource().getClass()); + throw new UnsupportedOperationException("Cannot convert NBTContents with DataSource " + nbt.dataSource().getClass()); }; - yield nbtBuilder.nbtPath(nbt.getNbtPath()) - .interpret(nbt.isInterpreting()) - .separator(SpongeAdventure.asAdventure(nbt.getSeparator())); + yield nbtBuilder.nbtPath(nbt.nbtPath().source()) + .interpret(nbt.interpreting()) + .separator(SpongeAdventure.asAdventure(nbt.separator())); } case ObjectContents obj -> Component.object().contents(SpongeAdventure.asAdventure(obj.contents())); default -> @@ -640,7 +659,7 @@ public static HoverEvent asAdventure(final net.minecraft.network.chat.HoverEv } else if (action == HoverEvent.Action.SHOW_ITEM) { final HoverEvent.ShowItem value = (HoverEvent.ShowItem) event.value(); final Registry itemRegistry = SpongeCommon.vanillaRegistry(Registries.ITEM); - final var item = Holder.direct(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))); + final var item = itemRegistry.wrapAsHolder(itemRegistry.getValue(SpongeAdventure.asVanilla(value.item()))); return new net.minecraft.network.chat.HoverEvent.ShowItem(new ItemStackTemplate(item, value.count(), SpongeAdventure.asVanilla(value.dataComponents()))); } throw new IllegalArgumentException(event.toString()); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java index 406e8ebd404..a961a964408 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java @@ -33,8 +33,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; -import net.minecraft.core.Holder; - import java.util.Map; @Mixin(WorldDimensions.class) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java index 701f63ac22d..4e9de405fd7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/util/thread/BlockableEventLoopMixin_Tracker.java @@ -33,6 +33,7 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.phase.plugin.BasicPluginContext; import org.spongepowered.common.event.tracking.phase.plugin.PluginPhase; +import org.spongepowered.common.launch.Launch; @Mixin(BlockableEventLoop.class) public abstract class BlockableEventLoopMixin_Tracker { @@ -54,7 +55,8 @@ public abstract class BlockableEventLoopMixin_Tracker { } try (final BasicPluginContext context = PluginPhase.State.SCHEDULED_TASK.createPhaseContext(PhaseTracker.getInstance()) - .source(instance)) { + .source(instance) + .container(Launch.instance().minecraftPlugin())) { context.buildAndSwitch(); original.call(instance); } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java index 57beef60efc..e8b9aef7d52 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/resources/RegistryDataLoaderMixin_Vanilla.java @@ -79,14 +79,34 @@ public class RegistryDataLoaderMixin_Vanilla { } else { registryHolder = (RegistryHolder) k; } + // Build a combined registry list: new batch registries replace any existing ones + // with the same key (e.g., on re-join, the second load produces fresh registries + // for the same keys that were already in the root from the first load). + final var batchRegistries = v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .map(RegistryLoadTaskAccessor::accessor$registry) + .toList(); + final var batchKeys = batchRegistries.stream() + .map(net.minecraft.core.Registry::key) + .collect(java.util.stream.Collectors.toSet()); ((SpongeRegistryHolder) registryHolder).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(registryHolder.streamRegistries(RegistryRoots.MINECRAFT), v.stream() - .map(RegistryLoadTaskAccessor.class::cast) - .map(RegistryLoadTaskAccessor::accessor$registry)).toList())); - lifecycle.processServerRegistries(registryHolder, v.stream() - .map(RegistryLoadTaskAccessor.class::cast) - .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! - .map(l -> (Registry) l.accessor$registry())); + (List) Stream.concat( + registryHolder.streamRegistries(RegistryRoots.MINECRAFT) + .filter(r -> !batchKeys.contains(((net.minecraft.core.Registry) r).key())), + batchRegistries.stream() + ).toList())); + + // Only fire plugin registry events on the server side (ResourceManager-backed loads). + // Client-side network loads only receive SYNCHRONIZED_REGISTRIES and lack server-only + // registries (placed_feature, configured_feature, etc.) that plugins may declare as + // dependencies, causing freeze validation to fail. + if (k != ResourceManager.Empty.INSTANCE) { + lifecycle.processServerRegistries(registryHolder, v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + } + v .stream().map(RegistryLoadTaskAccessor.class::cast) .forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), From 39365de41c3de13918828429cbf35e1d727bca43 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 19 Mar 2026 21:29:05 -0700 Subject: [PATCH 483/586] feat(minecraft): update to 26.1-snapshot-9 See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_9 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9cd3d41b84d..59dab02ff4a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-8 +minecraftVersion=26.1-snapshot-9 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From b5062d849bc1f8c2c8073f256f0d9e7f878cd211 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 19 Mar 2026 21:58:16 -0700 Subject: [PATCH 484/586] chore(deps): update verification-metadata.xml --- gradle/verification-metadata.xml | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c6d5095251f..65f652f7a04 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -10159,12 +10159,24 @@ + + + + + + + + + + + + @@ -10207,12 +10219,24 @@
+ + + + + + + + + + + + @@ -10278,12 +10302,24 @@ + + + + + + + + + + + + @@ -10341,12 +10377,24 @@ + + + + + + + + + + + + @@ -10404,12 +10452,24 @@ + + + + + + + + + + + + @@ -10475,12 +10535,24 @@ + + + + + + + + + + + + @@ -10546,12 +10618,24 @@ + + + + + + + + + + + + @@ -10617,12 +10701,24 @@ + + + + + + + + + + + + From dcebf781ec804bc8b913340566ac3feba8c43522 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 20 Mar 2026 00:25:55 -0700 Subject: [PATCH 485/586] feat(minecraft): update to 26.1-snapshot-10 Includes updates for API changes: - Simplified DataComponent handling for dyed items. - Updated `CardinalLighting` and `BlockAndLightGetter` references. - Optimized container logic in `ItemMixin_API`. See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_10 --- gradle.properties | 2 +- .../provider/item/stack/DyeableItemStackData.java | 5 ++--- .../common/world/server/SpongeWorldTypeBuilder.java | 3 ++- .../api/minecraft/world/item/ItemMixin_API.java | 13 ++++--------- .../api/minecraft/world/level/LevelMixin_API.java | 4 ++-- .../minecraft/world/level/LevelReaderMixin_API.java | 4 ++-- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/gradle.properties b/gradle.properties index 59dab02ff4a..3885501e683 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-9 +minecraftVersion=26.1-snapshot-10 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java index 78bea623dd7..bc0e486d706 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/DyeableItemStackData.java @@ -42,9 +42,8 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(ItemStack.class) .create(Keys.COLOR) .get(h -> h.has(DataComponents.DYED_COLOR) ? Color.ofRgb(h.get(DataComponents.DYED_COLOR).rgb()) : null) - .set((h, v) -> h.update(DataComponents.DYED_COLOR, new DyedItemColor(0), prev -> new DyedItemColor(v.rgb()))) - .delete(h -> h.set(DataComponents.DYED_COLOR, null)) - .supports(h -> h.has(DataComponents.DYED_COLOR)); + .set((h, v) -> h.set(DataComponents.DYED_COLOR, new DyedItemColor(v.rgb()))) + .delete(h -> h.remove(DataComponents.DYED_COLOR)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index d325d82eb3f..3b417c374a6 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -33,6 +33,7 @@ import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.clock.WorldClock; import net.minecraft.world.clock.WorldClocks; +import net.minecraft.world.level.CardinalLighting; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.NonNull; @@ -131,7 +132,7 @@ public WorldType.Builder from(final WorldType type) { ambientLighting, new DimensionType.MonsterSettings(monsterSpawnLightTest, monsterSpawnBlockLightLimit), DimensionType.Skybox.OVERWORLD, - DimensionType.CardinalLightType.DEFAULT, + CardinalLighting.Type.DEFAULT, attributes.build(), HolderSet.empty(), clocks.get(WorldClocks.OVERWORLD).map(r -> (Holder) r) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java index 3a27fc1346c..e04a721795b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/ItemMixin_API.java @@ -25,10 +25,8 @@ package org.spongepowered.common.mixin.api.minecraft.world.item; import net.kyori.adventure.text.Component; -import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStackTemplate; import org.checkerframework.checker.nullness.qual.Nullable; @@ -38,7 +36,6 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.data.holder.SpongeImmutableDataHolder; import java.util.Arrays; @@ -92,11 +89,9 @@ public boolean isAnyOf(ItemType... types) { @Override public Optional container() { - return this.craftingRemainingItem.item().unwrap() - .mapLeft(key -> SpongeCommon.server().registryAccess().lookupOrThrow(Registries.ITEM).get(key)) - .mapLeft(ref -> ref.map(Holder::value)) - .mapRight(Optional::of) - .map(l -> l, o -> o) - .map(ItemType.class::cast); + if (this.craftingRemainingItem == null) { + return Optional.empty(); + } + return Optional.of((ItemType) this.craftingRemainingItem.item().value()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 400760a2411..0b531f48042 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -33,7 +33,7 @@ import net.minecraft.server.level.ServerChunkCache; import net.minecraft.util.ProblemReporter; import net.minecraft.util.Tuple; -import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockAndLightGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; @@ -473,7 +473,7 @@ public Weather weather() { @Override public int light(final LightType type, final int x, final int y, final int z) { - var thisLevel = ((BlockAndTintGetter) this); + var thisLevel = ((BlockAndLightGetter) this); return thisLevel.getBrightness((LightLayer) (Object) type, new BlockPos(x, y, z)); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java index 0e65824c30c..d56b8ba6e71 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelReaderMixin_API.java @@ -28,7 +28,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; -import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockAndLightGetter; import net.minecraft.world.level.CollisionGetter; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; @@ -122,7 +122,7 @@ default boolean isInBorder(final Entity entity) { @Override default boolean canSeeSky(final int x, final int y, final int z) { - return ((BlockAndTintGetter) this).canSeeSky(new BlockPos(x, y, z)); + return ((BlockAndLightGetter) this).canSeeSky(new BlockPos(x, y, z)); } @Override From 6dda4a46f5761606d3c4acd6ec926c96dd724688 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 20 Mar 2026 23:56:33 -0700 Subject: [PATCH 486/586] feat(minecraft): update to 26.1-snapshot-11 See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_11 --- gradle.properties | 2 +- .../event/tracking/context/transaction/block/ChangeBlock.java | 2 +- .../context/transaction/effect/UpdateLightSideEffect.java | 2 +- .../tracking/context/transaction/pipeline/ChunkPipeline.java | 2 +- .../tracking/context/transaction/pipeline/WorldPipeline.java | 2 +- .../common/mixin/core/world/entity/item/ItemEntityMixin.java | 2 +- .../vanilla/mixin/core/client/MinecraftMixin_Vanilla.java | 2 -- 7 files changed, 6 insertions(+), 8 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3885501e683..66716b0cb90 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-10 +minecraftVersion=26.1-snapshot-11 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java index 2570c63bb01..9e9003ef299 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/block/ChangeBlock.java @@ -75,7 +75,7 @@ public ChangeBlock( this.original = attachedSnapshot; this.newState = newState; this.blockChangeFlag = blockChange; - this.originalOpacity = this.originalState.getLightBlock(); + this.originalOpacity = this.originalState.getLightDampening(); } public BlockState getNewState() { diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java index 31209fee534..62852b50b26 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UpdateLightSideEffect.java @@ -64,7 +64,7 @@ public static UpdateLightSideEffect getInstance() { // (param2 & 128) == 0 // this is handled above as flag.updateLighting() // && var3 != var2 // && ( - // var3.getLightBlock(this, param0) != var2.getLightBlock(this, param0) + // var3.getLightDampening() != var2.getLightDampening() // || var3.getLightEmission() != var2.getLightEmission() // || var3.useShapeForLightOcclusion() // || var2.useShapeForLightOcclusion() diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java index 2c4d8c5ad9c..d5bfcfe180b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/ChunkPipeline.java @@ -112,7 +112,7 @@ public LevelChunkSection getAffectedSection() { return null; } final ServerLevel serverWorld = this.serverWorld.get(); - final int oldOpacity = currentState.getLightBlock(); + final int oldOpacity = currentState.getLightDampening(); final SpongeBlockChangeFlag flag = this.transaction.getBlockChangeFlag(); final @Nullable BlockEntity existing = this.chunkSupplier.get().getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); PipelineCursor formerState = new PipelineCursor(currentState, pos, existing, (Entity) null, limit); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java index 3b6f49db7a9..93a067a988d 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/WorldPipeline.java @@ -99,7 +99,7 @@ public boolean processEffects(final PhaseContext context, final BlockState cu if (oldState == null) { return false; } - final int oldOpacity = oldState.getLightBlock(); + final int oldOpacity = oldState.getLightDampening(); PipelineCursor formerState = new PipelineCursor(oldState, pos, existing, destroyer, limit); for (final ResultingTransactionBySideEffect effect : this.worldEffects) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index a9c266be068..4a1984f08c0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -117,7 +117,7 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;discard()V"), slice = @Slice( - from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;updateInWaterStateAndDoFluidPushing()Z"), + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;updateFluidInteraction()Z"), to = @At("TAIL") ) ) diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java index 9f518fc72df..1a89a3fefeb 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java @@ -40,8 +40,6 @@ @Mixin(Minecraft.class) public abstract class MinecraftMixin_Vanilla implements MinecraftBridge, VanillaClient { - @Shadow public abstract void resizeDisplay(); - @Override public ClientType bridge$getClientType() { return ClientType.SPONGE_VANILLA; From a1f55bd0de9ffa3f8bbc2b12fa9275667326619c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 20 Mar 2026 23:58:10 -0700 Subject: [PATCH 487/586] feat(minecraft): update content for 26.1-snapshot-11 See: https://minecraft.wiki/w/Java_Edition_26.1_Snapshot_11 --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 38ec73c181f..cca781ff62f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 38ec73c181f85132c50f08ec1c86740b3976270b +Subproject commit cca781ff62fc3c994a59f09659d975bbc0650b61 From c31b38461b1ca238f18160311bce5cfd5ff61fc1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 21 Mar 2026 21:23:38 -0700 Subject: [PATCH 488/586] feat(minecraft): update to 26.1-pre-1 Includes updates for API changes: - StateHolder.getValues() returns Stream> instead of Map. - DamageResistant and BlocksAttacks.bypassedBy use HolderSet instead of TagKey. - ComponentUtils.updateForEntity() replaced by ComponentUtils.resolve(ResolutionContext). - Client GUI stubs for GuiGraphicsExtractor rendering pipeline (full rewrite deferred). See: https://minecraft.wiki/w/Java_Edition_26.1_Pre-Release_1 Signed-off-by: Gabriel Harris-Rouquette --- gradle.properties | 2 +- .../adventure/SpongeResolveOperation.java | 10 +- .../provider/item/stack/ItemStackData.java | 8 +- .../item/stack/ShieldItemStackData.java | 13 ++- .../data/provider/world/WorldTypeData.java | 2 +- .../state/AbstractSpongeStateMatcher.java | 9 +- .../spongepowered/common/util/StateUtil.java | 10 +- .../block/state/StateHolderMixin_API.java | 14 +-- .../level/block/state/BlockStateMixin.java | 6 +- .../client/gui/screen/PluginScreen.java | 9 +- .../client/gui/widget/MetadataPanel.java | 47 +++------ .../client/gui/widget/ScrollPanel.java | 98 ++----------------- .../gui/widget/list/FilterableList.java | 59 ++--------- .../gui/widget/list/PluginSelectionList.java | 19 +--- .../core/client/MinecraftMixin_Vanilla.java | 1 - 15 files changed, 81 insertions(+), 226 deletions(-) diff --git a/gradle.properties b/gradle.properties index 66716b0cb90..4dcc389e49b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-snapshot-11 +minecraftVersion=26.1-pre-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java index 96beb63ed18..d4e36896df0 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java @@ -31,6 +31,7 @@ import net.kyori.adventure.translation.GlobalTranslator; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.network.chat.ResolutionContext; import org.apache.commons.lang3.NotImplementedException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -81,10 +82,13 @@ public static SpongeResolveOperation newContextualComponents() { public Component resolve(final Component input, final CommandCause senderContext, final @Nullable Entity viewer) { try { // TODO: Have a pure-Adventure implementation of this - return SpongeAdventure.asAdventure(ComponentUtils.updateForEntity( - (CommandSourceStack) senderContext, + final var source = (CommandSourceStack) senderContext; + final var context = viewer != null + ? ResolutionContext.createWithEntityOverride(source, (net.minecraft.world.entity.Entity) viewer) + : ResolutionContext.create(source); + return SpongeAdventure.asAdventure(ComponentUtils.resolve( + context, ((ComponentBridge) input).bridge$asVanillaComponent(), - (net.minecraft.world.entity.Entity) viewer, /* depth = */ 0 )); } catch (final CommandSyntaxException ex) { diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index 5edc29a8be4..b9e569db022 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -298,12 +298,16 @@ public static void register(final DataProviderRegistrator registrator) { if (resist == null) { return false; } - return resist.types().location().equals(DamageTypes.IN_FIRE.identifier()); + if (resist.types() instanceof net.minecraft.core.HolderSet.Named named) { + return named.key().location().equals(DamageTypes.IN_FIRE.identifier()); + } + return false; }) .set((h, value) -> { if (value) { + final var holderSet = SpongeCommon.vanillaRegistry(net.minecraft.core.registries.Registries.DAMAGE_TYPE).getOrThrow(DamageTypeTags.IS_FIRE); h.applyComponents(DataComponentPatch.builder() - .set(DataComponents.DAMAGE_RESISTANT, new DamageResistant(DamageTypeTags.IS_FIRE)) + .set(DataComponents.DAMAGE_RESISTANT, new DamageResistant(holderSet)) .build()); } else { h.remove(DataComponents.DAMAGE_RESISTANT); diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java index d0438441f6e..cdc9a6da610 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ShieldItemStackData.java @@ -25,7 +25,9 @@ package org.spongepowered.common.data.provider.item.stack; import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.BlocksAttacks; @@ -40,6 +42,7 @@ import org.spongepowered.api.event.cause.entity.damage.DamageType; import org.spongepowered.api.tag.Tag; import org.spongepowered.api.util.Ticks; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.tags.TagBridge; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.util.Constants; @@ -152,16 +155,22 @@ public static void register(final DataProviderRegistrator registrator) { if (blocksAttacks == null || blocksAttacks.bypassedBy().isEmpty()) { return null; } - return (Tag) (Object) blocksAttacks.bypassedBy().get(); + final HolderSet holderSet = blocksAttacks.bypassedBy().get(); + if (holderSet instanceof HolderSet.Named named) { + return (Tag) (Object) named.key(); + } + return null; }) .set((h, v) -> { final @Nullable BlocksAttacks blocksAttacks = h.getOrDefault(DataComponents.BLOCKS_ATTACKS, BLOCKS_ATTACKS_DEFAULTS); + final var tagKey = ((TagBridge) v).bridge$asVanillaTag(); + final var holderSet = SpongeCommon.vanillaRegistry(Registries.DAMAGE_TYPE).getOrThrow(tagKey); h.set(DataComponents.BLOCKS_ATTACKS, new BlocksAttacks( blocksAttacks.blockDelaySeconds(), blocksAttacks.disableCooldownScale(), blocksAttacks.damageReductions(), blocksAttacks.itemDamage(), - Optional.of(((TagBridge) v).bridge$asVanillaTag()), + Optional.of(holderSet), blocksAttacks.blockSound(), blocksAttacks.disableSound() )); diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java index 3eec96adf17..dc44611b1c6 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java @@ -92,7 +92,7 @@ public static void register(final DataProviderRegistrator registrator) { // @formatter:on private static Range lightRange(IntProvider provider) { - return Range.intRange(provider.getMinValue(), provider.getMaxValue()); + return Range.intRange(provider.minInclusive(), provider.maxInclusive()); } private static WorldTypeEffect worldTypeEffect(final DimensionType type) { diff --git a/src/main/java/org/spongepowered/common/state/AbstractSpongeStateMatcher.java b/src/main/java/org/spongepowered/common/state/AbstractSpongeStateMatcher.java index a165d98c495..cec8a48f299 100644 --- a/src/main/java/org/spongepowered/common/state/AbstractSpongeStateMatcher.java +++ b/src/main/java/org/spongepowered/common/state/AbstractSpongeStateMatcher.java @@ -62,14 +62,17 @@ public abstract class AbstractSpongeStateMatcher, T protected final boolean isValid(final StateHolder stateHolder) { for (final Map.Entry, Object> entry : this.properties.entrySet()) { final Property property = (Property) entry.getKey(); - final Object value = stateHolder.getValues().get(property); - if (value == null || !value.equals(entry.getValue())) { + if (!stateHolder.hasProperty(property)) { + return false; + } + final Object value = stateHolder.getValue((Property) property); + if (!value.equals(entry.getValue())) { return false; } } for (final StateProperty<@NonNull ?> entry : this.requiredProperties) { final Property property = (Property) entry; - if (stateHolder.getValues().get(property) == null) { + if (!stateHolder.hasProperty(property)) { return false; } } diff --git a/src/main/java/org/spongepowered/common/util/StateUtil.java b/src/main/java/org/spongepowered/common/util/StateUtil.java index 3b9d0d723e1..81763eb27d5 100644 --- a/src/main/java/org/spongepowered/common/util/StateUtil.java +++ b/src/main/java/org/spongepowered/common/util/StateUtil.java @@ -27,15 +27,15 @@ import net.minecraft.world.level.block.state.StateHolder; import net.minecraft.world.level.block.state.properties.Property; -import java.util.Map; - @SuppressWarnings(value = {"unchecked", "rawtypes"}) public final class StateUtil { public static > S copyStatesFrom(S original, final StateHolder from) { - for (final Map.Entry, Comparable> entry : from.getValues().entrySet()) { - if (original.hasProperty(entry.getKey())) { - original = (S) original.setValue((Property) entry.getKey(), (Comparable) entry.getValue()); + final var values = from.getValues().iterator(); + while (values.hasNext()) { + final Property.Value entry = values.next(); + if (original.hasProperty(entry.property())) { + original = (S) original.setValue((Property) entry.property(), (Comparable) entry.value()); } } return original; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/StateHolderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/StateHolderMixin_API.java index 7ec60477d4b..5192ff21652 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/StateHolderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/StateHolderMixin_API.java @@ -45,9 +45,9 @@ import org.spongepowered.common.util.PortionTypeUtil; import java.util.Collection; -import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; @Mixin(StateHolder.class) public abstract class StateHolderMixin_API, C> implements State, SpongeImmutableDataHolder { @@ -57,7 +57,7 @@ public abstract class StateHolderMixin_API, C> implements Sta @Shadow public abstract > T shadow$getValue(Property property); @Shadow public abstract , V extends T> C shadow$setValue(Property property, V value); @Shadow public abstract > C shadow$cycle(Property property); - @Shadow public abstract Map, Comparable> shadow$getValues(); + @Shadow public abstract Stream> shadow$getValues(); // @formatter:on @SuppressWarnings("unchecked") @@ -79,7 +79,7 @@ public abstract class StateHolderMixin_API, C> implements Sta private , T extends Comparable, V extends T> V api$mapFromApi(final StateProperty stateProperty, final ApiT value) { if (value instanceof final Axis axis) { - return (V) AxisUtil.getFor(axis); + return (V) (Object) AxisUtil.getFor(axis); } if (value instanceof final org.spongepowered.api.util.Direction dir) { final V mappedValue = (V) DirectionUtil.getFor(dir); @@ -152,16 +152,16 @@ public > Optional cycleValue(final Key> stateProperties() { - return (Collection) this.shadow$getValues().keySet(); + return (Collection) this.shadow$getValues().map(Property.Value::property).collect(Collectors.toList()); } @Override public Collection statePropertyValues() { - return this.shadow$getValues().values().stream().map(this::api$mapToApi).toList(); + return this.shadow$getValues().map(v -> this.api$mapToApi(v.value())).toList(); } @Override - public Map, ?> statePropertyMap() { - return (Map) this.shadow$getValues().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> this.api$mapToApi(e.getValue()))); + public java.util.Map, ?> statePropertyMap() { + return (java.util.Map) this.shadow$getValues().collect(Collectors.toMap(v -> v.property(), v -> this.api$mapToApi(v.value()))); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/state/BlockStateMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/state/BlockStateMixin.java index bf80871b97d..0ac217ef7a7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/state/BlockStateMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/state/BlockStateMixin.java @@ -24,8 +24,6 @@ */ package org.spongepowered.common.mixin.core.world.level.block.state; -import com.mojang.serialization.MapCodec; -import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; @@ -42,8 +40,8 @@ @Mixin(BlockState.class) public abstract class BlockStateMixin extends BlockBehaviour.BlockStateBase implements BlockStateBridge { - protected BlockStateMixin(Block $$0, Reference2ObjectArrayMap, Comparable> $$1, MapCodec $$2) { - super($$0, $$1, $$2); + protected BlockStateMixin(Block owner, Property[] propertyKeys, Comparable[] propertyValues) { + super(owner, propertyKeys, propertyValues); } @Override diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java index cc1a6ad18f0..b6324a6a4ae 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java @@ -26,7 +26,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.screens.Screen; @@ -104,10 +104,9 @@ protected void init() { } @Override - public void render(final GuiGraphics stack, final int p_render_1_, final int p_render_2_, final float p_render_3_) { - this.renderBackground(stack, p_render_1_, p_render_2_, p_render_3_); - super.render(stack, p_render_1_, p_render_2_, p_render_3_); // render the widgets - stack.drawCenteredString(this.font, this.title.getString(), this.width / 2, 8, 16777215); + public void extractRenderState(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final float partialTicks) { + super.extractRenderState(graphics, mouseX, mouseY, partialTicks); + // TODO: drawCenteredString needs GuiGraphicsExtractor rewrite (see .docs/plugin-gui-rewrite-plan.md) } private void generateEntries(final List metadatas) { diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 66c37f503b4..36e7b491e86 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -25,12 +25,11 @@ package org.spongepowered.vanilla.client.gui.widget; import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.Tesselator; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; @@ -214,57 +213,33 @@ protected int getScrollAmount() { } @Override - protected void drawPanel(final GuiGraphics stack, final int entryRight, int relativeY, final Tesselator tess, final int mouseX, + protected void drawPanel(final GuiGraphicsExtractor graphics, final int entryRight, int relativeY, final int mouseX, final int mouseY) { - final int baseX = this.left + 4; - - final Font font = this.minecraft.font; + // TODO: Rewrite rendering for GuiGraphicsExtractor pipeline + // The old GuiGraphics.drawString() API no longer exists on GuiGraphicsExtractor. + // This needs a full rewrite to use the new deferred rendering model. if (this.resizedCategories.isEmpty()) { - final int noResultsWidth = font.width(MetadataPanel.NO_RESULTS); - - stack.drawString(font, - MetadataPanel.NO_RESULTS, - (int) (((float) this.width / 2) + this.left - ((float) noResultsWidth / 2)), - this.top + 10, - 0xFFFFFF - ); return; } - // Iterate and draw categories + final int baseX = this.left + 4; + final Font font = this.minecraft.font; for (final Category category : this.resizedCategories) { - // Skip empty categories if (category.getEntries().size() == 0) { continue; } - - // Draw category name - stack.drawString(font, category.name, baseX, relativeY, 0xFFFFFF); relativeY += this.lineHeight; - // Iterate and draw entries for (final Entry entry : category.getEntries()) { if (entry.value == null) { continue; } - final int levelOffset = entry.level * MetadataPanel.INDENT_SIZE; - final int keyX = baseX + MetadataPanel.INDENT_SIZE + levelOffset; - final int separatorX = keyX + this.maxKeyWidth + 4 - levelOffset; - final int valueX = separatorX + font.width(":") + 4; - - // Only draw key and separator if there is any key present - if (entry.key != null) { - stack.drawString(font, entry.key, keyX, relativeY, 0xFFFFFF); - - if (entry.rawValue != null && !entry.rawValue.isEmpty()) { - stack.drawString(font, ":", separatorX, relativeY, 0xFFFFFF); - } - } - - // Draw the value, and update the value bounds if needed - stack.drawString(font, entry.value, valueX, relativeY, 0xFFFFFF); if (entry.value.getStyle().getClickEvent() != null) { + final int levelOffset = entry.level * MetadataPanel.INDENT_SIZE; + final int keyX = baseX + MetadataPanel.INDENT_SIZE + levelOffset; + final int separatorX = keyX + this.maxKeyWidth + 4 - levelOffset; + final int valueX = separatorX + font.width(":") + 4; entry.valueBounds = new Bounds(valueX, relativeY + 1, valueX + font.width(entry.value), relativeY + this.lineHeight); diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java index 4187c5d871f..f60f9af5c13 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/ScrollPanel.java @@ -24,12 +24,8 @@ */ package org.spongepowered.vanilla.client.gui.widget; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -41,6 +37,7 @@ /** * Credit: MinecraftForge * Changes: Minor tweaks, fixed scroll limits able to hit negative + * TODO: Rewrite to use AbstractScrollArea instead of custom scroll logic */ public abstract class ScrollPanel extends AbstractContainerEventHandler implements Renderable { @@ -74,14 +71,7 @@ public ScrollPanel(final Minecraft client, final int width, final int height, fi protected void drawBackground() { } - /** - * Draw anything special on the screen. GL_SCISSOR is enabled for anything that - * is rendered outside of the view box. Do not mess with SCISSOR unless you support this. - * - * @param mouseX - * @param mouseY - */ - protected abstract void drawPanel(final GuiGraphics stack, int entryRight, int relativeY, Tesselator tess, int mouseX, int mouseY); + protected abstract void drawPanel(final GuiGraphicsExtractor graphics, int entryRight, int relativeY, int mouseX, int mouseY); protected boolean clickPanel(final double mouseX, final double mouseY, final int button) { return false; @@ -104,7 +94,7 @@ private void applyScrollLimits() { } @Override - public boolean mouseScrolled(final double mouseX, final double mouseY, final double scroll, final double $$3) { + public boolean mouseScrolled(final double mouseX, final double mouseY, final double scroll, final double scrollY) { if (scroll != 0) { this.scrollDistance += -scroll * this.getScrollAmount(); this.applyScrollLimits(); @@ -123,8 +113,8 @@ public boolean isMouseOver(final double mouseX, final double mouseY) { } @Override - public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated) { - if (super.mouseClicked(event, repeated)) { + public boolean mouseClicked(final MouseButtonEvent event, final boolean doubleClick) { + if (super.mouseClicked(event, doubleClick)) { return true; } @@ -178,82 +168,12 @@ public boolean mouseDragged(final MouseButtonEvent event, final double deltaX, f return false; } - @Override - public void render(final GuiGraphics stack, final int mouseX, final int mouseY, final float partialTicks) { + public void extractRenderState(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final float partialTicks) { this.drawBackground(); - - final Tesselator tess = Tesselator.getInstance(); - - final double scale = this.client.getWindow().getGuiScale(); -// RenderSystem.enableScissor((int) (this.left * scale), (int) (this.client.getWindow().getHeight() - (this.bottom * scale)), (int) (this.width * scale), -// (int) (this.height * scale)); - -// TODO fix me RenderSystem.setShader(GameRenderer::getPositionTexColorShader); -// RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND); -// RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - final float texScale = 32.0F; - BufferBuilder worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); - worldr.addVertex(this.left, this.bottom, 0.0f).setUv(this.left / texScale, (this.bottom + (int) this.scrollDistance) / texScale) - .setColor(0x20, 0x20, 0x20, 0xFF); - worldr.addVertex(this.right, this.bottom, 0.0f).setUv(this.right / texScale, (this.bottom + (int) this.scrollDistance) / texScale) - .setColor(0x20, 0x20, 0x20, 0xFF); - worldr.addVertex(this.right, this.top, 0.0f).setUv(this.right / texScale, (this.top + (int) this.scrollDistance) / texScale) - .setColor(0x20, 0x20, 0x20, 0xFF); - worldr.addVertex(this.left, this.top, 0.0f).setUv(this.left / texScale, (this.top + (int) this.scrollDistance) / texScale) - .setColor(0x20, 0x20, 0x20, 0xFF); - -// VertexBuffer $$3 = RenderSystem.getQuadVertices(); -// $$3.upload(worldr.buildOrThrow()); -// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); - - + // TODO: Rewrite rendering for GuiGraphicsExtractor pipeline final int baseY = this.top + this.border - (int) this.scrollDistance; - this.drawPanel(stack, this.right, baseY, tess, mouseX, mouseY); - -// RenderSystem.disableDepthTest(); - - final int extraHeight = (this.getContentHeight() + this.border) - this.height; - if (extraHeight > 0) { - final int barHeight = this.getBarHeight(); - - int barTop = (int) this.scrollDistance * (this.height - barHeight) / extraHeight + this.top; - if (barTop < this.top) { - barTop = this.top; - } - -// RenderSystem.disableTexture(); - // TODO fix me RenderSystem.setShader(GameRenderer::getPositionColorShader); - worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - worldr.addVertex(this.barLeft, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth, this.bottom, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); - worldr.addVertex(this.barLeft, this.top, 0.0f).setColor(0x00, 0x00, 0x00, 0xFF); -// $$3 = RenderSystem.getQuadVertices(); -// $$3.upload(worldr.buildOrThrow()); -// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); - - worldr =tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - worldr.addVertex(this.barLeft, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth, barTop + barHeight, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); - worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0x80, 0x80, 0x80, 0xFF); -// $$3 = RenderSystem.getQuadVertices(); -// $$3.upload(worldr.buildOrThrow()); -// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); - worldr = tess.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - worldr.addVertex(this.barLeft, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth - 1, barTop + barHeight - 1, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); - worldr.addVertex(this.barLeft + this.barWidth - 1, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); - worldr.addVertex(this.barLeft, barTop, 0.0f).setColor(0xC0, 0xC0, 0xC0, 0xFF); -// $$3 = RenderSystem.getQuadVertices(); -// $$3.upload(worldr.buildOrThrow()); -// $$3.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), null); - } - -// RenderSystem.enableTexture(); -// RenderSystem.disableBlend(); -// RenderSystem.disableScissor(); + this.drawPanel(graphics, this.right, baseY, mouseX, mouseY); } @Override diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java index 9313a6503bd..050272079e4 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/FilterableList.java @@ -24,10 +24,9 @@ */ package org.spongepowered.vanilla.client.gui.widget.list; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractSelectionList; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; @@ -161,45 +160,8 @@ public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated } } - @Override - protected void renderListItems(final GuiGraphics $$0, final int $$1, final int $$2, final float $$3) { - // Most of this is based on AbstractList::renderList logic - final List filteredList = this.filterSupplier == null ? this.children() : this.filterSupplier.get(); - - if (filteredList.isEmpty()) { - final Font font = this.minecraft.font; - final String noResults = "No results..."; - final int noResultsWidth = font.width(noResults); - - $$0.drawString(font, noResults, (this.width / 2) + this.getX() - (noResultsWidth / 2), this.getY() + 10, ChatFormatting.GRAY.getColor()); - - return; - } - - final int $$4 = this.getRowLeft(); - final int $$5 = this.getRowWidth(); -// final int $$6 = this.itemHeight - 4; - final int $$7 = filteredList.size(); - -// for (int $$8 = 0; $$8 < $$7; ++$$8) { -// final int $$9 = this.getRowTop($$8); -// final int $$10 = this.getRowBottom($$8); -// if ($$10 >= this.getY() && $$9 <= this.getBottom()) { -// this.renderItemFromList(filteredList, $$0, $$1, $$2, $$3, $$8, $$4, $$9, $$5, $$6); -// } -// } - } - - private void renderItemFromList(final List list, final GuiGraphics $$0, final int $$1, final int $$2, final float $$3, final int $$4, final int $$5, final int $$6, final int $$7, final int $$8) { - final E $$9 = list.get($$4); -// $$9.render($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); -// if (this.($$4)) { -// final int $$10 = this.isFocused() ? -1 : -8355712; -// this.renderSelection($$0, $$6, $$7, $$8, $$10, -16777216); -// } - -// $$9.render($$0, $$4, $$6, $$5, $$7, $$8, $$1, $$2, Objects.equals(this.getHovered(), $$9), $$3); - } + // TODO: renderListItems was removed in pre-1 — rendering now handled by extractContent on entries + // See .docs/plugin-gui-rewrite-plan.md @Override protected void updateWidgetNarration(final NarrationElementOutput narrationConsumer) { @@ -234,16 +196,9 @@ public P getParentList() { public abstract Bounds getInteractBounds(); -// @SuppressWarnings("unchecked") -// @Override -// public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, -// final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, -// final float p_render_9_) { -// if (this.getInteractBounds().isInBounds(mouseX, mouseY, renderX, renderY)) { -// this.parentList.currentHoveredEntry = (E) this; -// } else if (this.parentList.getCurrentHoveredEntry() == this) { -// this.parentList.currentHoveredEntry = null; -// } -// } + @Override + public void extractContent(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final boolean hovered, final float partialTicks) { + // TODO: Implement rendering via GuiGraphicsExtractor (see .docs/plugin-gui-rewrite-plan.md) + } } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java index b5da68d66fb..6c06365b4e2 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/list/PluginSelectionList.java @@ -24,7 +24,7 @@ */ package org.spongepowered.vanilla.client.gui.widget.list; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.screens.Screen; @@ -55,22 +55,11 @@ public Bounds getInteractBounds() { } @Override - public void renderContent(GuiGraphics var1, int var2, int var3, boolean var4, float var5) { - + public void extractContent(final GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final boolean hovered, final float partialTicks) { + // TODO: Implement rendering via GuiGraphicsExtractor (see .docs/plugin-gui-rewrite-plan.md) + // Should draw: plugin name (or ID), and ID below if name is present } - // @Override -// public void render(final GuiGraphics stack, final int p_render_1_, final int renderY, final int renderX, final int p_render_4_, -// final int p_render_5_, final int mouseX, final int mouseY, final boolean p_render_8_, final float p_render_9_) { -// // Draw the name, or ID if name is not present -// stack.drawString(this.list.fontRenderer, this.metadata.name().orElse(this.metadata.id()), renderX + 2, renderY + 1, 16777215); -// -// // Draw the ID if the name is present -// if (this.metadata.name().isPresent()) { -// stack.drawString(this.list.fontRenderer, this.metadata.id(), renderX + 2, renderY + 12, 8421504); -// } -// } - @Override public boolean mouseClicked(final MouseButtonEvent event, final boolean repeated) { this.getParentList().setSelected(this); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java index 1a89a3fefeb..67f9524d10d 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/MinecraftMixin_Vanilla.java @@ -26,7 +26,6 @@ import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; From ba75a88843b74387b65942e1c994f70fcb96c689 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 21 Mar 2026 22:04:14 -0700 Subject: [PATCH 489/586] feat(minecraft): update features for 26.1-pre-2 See: https://minecraft.wiki/w/Java_Edition_26.1_Pre-Release_2 --- SpongeAPI | 2 +- gradle.properties | 2 +- .../common/adventure/SpongeResolveOperation.java | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index cca781ff62f..a71b70c1941 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit cca781ff62fc3c994a59f09659d975bbc0650b61 +Subproject commit a71b70c1941d9a4dd8833ef915ba2d2f4c961e06 diff --git a/gradle.properties b/gradle.properties index 4dcc389e49b..2eeabb55b17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-pre-1 +minecraftVersion=26.1-pre-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java index d4e36896df0..b20edf5091f 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeResolveOperation.java @@ -83,9 +83,11 @@ public Component resolve(final Component input, final CommandCause senderContext try { // TODO: Have a pure-Adventure implementation of this final var source = (CommandSourceStack) senderContext; - final var context = viewer != null - ? ResolutionContext.createWithEntityOverride(source, (net.minecraft.world.entity.Entity) viewer) - : ResolutionContext.create(source); + final var builder = ResolutionContext.builder().withSource(source); + if (viewer != null) { + builder.withEntityOverride((net.minecraft.world.entity.Entity) viewer); + } + final var context = builder.build(); return SpongeAdventure.asAdventure(ComponentUtils.resolve( context, ((ComponentBridge) input).bridge$asVanillaComponent(), From aef39f08973c20f9d0cdb5f97d645bcd40c1d413 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 21 Mar 2026 22:14:45 -0700 Subject: [PATCH 490/586] feat(minecraft): update features for 26.1-pre-3 See: https://minecraft.wiki/w/Java_Edition_26.1_Pre-Release_3 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2eeabb55b17..48eb265a96b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-pre-2 +minecraftVersion=26.1-pre-3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 65f652f7a04..d0ad73b6c45 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1811,6 +1811,11 @@ + + + + + From 38a8fe0c485ab527e43765115654339d746293fa Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 21 Mar 2026 22:22:52 -0700 Subject: [PATCH 491/586] feat(minecraft): update features for 26.1-rc-1 See: https://minecraft.wiki/w/Java_Edition_26.1_Release_Candidate_1 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 48eb265a96b..c9d0b76727b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,10 +11,10 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-pre-3 +minecraftVersion=26.1-rc-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose org.gradle.jvmargs=-Xss4m org.gradle.parallel=true -org.gradle.caching=false +org.gradle.caching=falser From 59be8ea79f4a901f3baaa5d09bcb460bcb4b92f7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 21 Mar 2026 22:28:46 -0700 Subject: [PATCH 492/586] feat(minecraft): update features for 26.1-rc-2 See: https://minecraft.wiki/w/Java_Edition_26.1_Release_Candidate_2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c9d0b76727b..05f44537dbf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-rc-1 +minecraftVersion=26.1-rc-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 7c2d629d0f675b53dc049f6b71403a4cf6887460 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 23 Mar 2026 21:13:56 -0700 Subject: [PATCH 493/586] feat(minecraft): update features for 26.1-rc-3 See: https://minecraft.wiki/w/Java_Edition_26.1_Release_Candidate_3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 05f44537dbf..040a09921a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-rc-2 +minecraftVersion=26.1-rc-3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From e9af7de69e3a5cdfe0849d181a9d5b515db8398a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 24 Mar 2026 11:11:00 -0700 Subject: [PATCH 494/586] feat(minecraft): update to Minecraft 26.1 This is a rubber stamp release with no code changes. See: https://minecraft.wiki/w/Java_Edition_26.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 040a09921a3..afa75153d02 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1-rc-3 +minecraftVersion=26.1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 93386964b5a710a6787703d3f0a12967e3d553d6 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 24 Mar 2026 19:16:49 -0700 Subject: [PATCH 495/586] feat(neo): update SpongeNeo for 26.1.0.1-beta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update all SpongeNeo mixins to target correct 26.1 bytecode: - RegistryDataLoaderMixin_Neo: full rewrite using RegistryLoadTaskAccessor with @Slice to skip NeoForge's gametest block - ReloadableServerResourcesMixin_Neo: fix lambda index ($3→$2), add 7th constructor param (newComponents) - MinecraftServerMixin_Neo: fix lambda indices ($30/$31→$1/$4) - TagLoaderMixin_NeoForge: fix lambda index ($6→$1) - AbstractFurnaceBlockEntityMixin_Neo: port vanilla's RecipeContext pattern, update burn/canBurn/assemble signatures for 26.1 - AbstractFurnaceBlockEntityAccessor_Neo: update canBurn invoker signature Common mixin changes: - Move ChatType registration from RegistryDataLoaderMixin (fragile lambda target) to new RegistryLoadTaskMixin targeting freezeRegistry at HEAD - Move broadcastAll weather redirect from ServerLevelMixin to vanilla-only ServerLevelMixin_Vanilla (NeoForge already broadcasts per-dimension) Signed-off-by: Gabriel Harris-Rouquette --- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 114 +++++++++++++++++ neoforge/gradle.properties | 2 +- ...bstractFurnaceBlockEntityAccessor_Neo.java | 6 +- .../RegistryDataLoaderMixin_Neo.java | 84 ++++++++++--- .../core/server/MinecraftServerMixin_Neo.java | 4 +- .../ReloadableServerResourcesMixin_Neo.java | 23 ++-- .../core/tags/TagLoaderMixin_NeoForge.java | 4 +- .../AbstractFurnaceBlockEntityMixin_Neo.java | 118 ++++++++++++------ ...rMixin.java => RegistryLoadTaskMixin.java} | 17 ++- .../core/server/level/ServerLevelMixin.java | 12 -- src/mixins/resources/mixins.sponge.core.json | 2 +- .../level/ServerLevelMixin_Vanilla.java | 54 ++++++++ .../resources/mixins.spongevanilla.core.json | 1 + 14 files changed, 342 insertions(+), 101 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/core/resources/{RegistryDataLoaderMixin.java => RegistryLoadTaskMixin.java} (83%) create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerLevelMixin_Vanilla.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0ea822fc196..39cc1243c66 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -71,4 +71,4 @@ indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = " shadow = { id = "com.gradleup.shadow", version = "9.0.2" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } -modDevGradle = { id = "net.neoforged.moddev", version = "2.0.123" } +modDevGradle = { id = "net.neoforged.moddev", version = "2.0.141" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d0ad73b6c45..47db5333af7 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6662,10 +6662,18 @@ + + + + + + + + @@ -6793,6 +6801,11 @@ + + + + + @@ -6919,6 +6932,11 @@ + + + + + @@ -7008,6 +7026,17 @@ + + + + + + + + + + + @@ -7032,6 +7061,11 @@ + + + + + @@ -7056,6 +7090,11 @@ + + + + + @@ -7064,6 +7103,16 @@ + + + + + + + + + + @@ -7112,6 +7161,11 @@ + + + + + @@ -7173,6 +7227,11 @@ + + + + + @@ -7298,6 +7357,11 @@ + + + + + @@ -7410,6 +7474,16 @@ + + + + + + + + + + @@ -7418,6 +7492,16 @@ + + + + + + + + + + @@ -7434,6 +7518,16 @@ + + + + + + + + + + @@ -7442,6 +7536,16 @@ + + + + + + + + + + @@ -7458,6 +7562,11 @@ + + + + + @@ -11927,6 +12036,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index f6da24fbfff..4a8e50d35bf 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.11.36-beta +neoForgeVersion=26.1.0.1-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java index 72cf95cded1..64bf9c092dc 100644 --- a/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java +++ b/neoforge/src/accessors/java/org/spongepowered/neoforge/accessor/world/level/block/entity/AbstractFurnaceBlockEntityAccessor_Neo.java @@ -26,12 +26,8 @@ import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; @@ -40,7 +36,7 @@ public interface AbstractFurnaceBlockEntityAccessor_Neo { @Invoker("canBurn") - static boolean invoker$canBurn(final RegistryAccess registryAccess, @Nullable final RecipeHolder var0, final SingleRecipeInput input, final NonNullList var1, final int var2) { + static boolean invoker$canBurn(final NonNullList items, final int maxStackSize, final ItemStack burnResult) { throw new UntransformedInvokerError(); } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java index 1c92a7a560a..07c1932ccf8 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/resources/RegistryDataLoaderMixin_Neo.java @@ -28,53 +28,99 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.RegistryLoadTask; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.DependencySorter; import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor; +import org.spongepowered.common.accessor.resources.RegistryLoadTaskAccessor; import org.spongepowered.common.bridge.core.WritableRegistryBridge; -import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; import org.spongepowered.common.registry.SpongeRegistryHolder; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @Mixin(RegistryDataLoader.class) public class RegistryDataLoaderMixin_Neo { + // NeoForge's lambda$load$2 has a gametest stream() call before the freeze logic. + // We use a @Slice starting after GameTestHooks.isGametestEnabled to skip it and + // target the freeze-step stream() call. Vanilla uses ordinal = 0 with no slice. @SuppressWarnings({"rawtypes", "unchecked"}) - @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;Z)Lnet/minecraft/core/RegistryAccess$Frozen;", - at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) - private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + @WrapOperation(method = "lambda$load$2", + at = @At(value = "INVOKE", target = "Ljava/util/List;stream()Ljava/util/stream/Stream;", ordinal = 0), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/neoforged/fml/ModLoader;postEvent(Lnet/neoforged/bus/api/Event;)V"))) + private static Stream impl$onLoad( + List> instance, Operation original + ) { // TODO: Remote layer - final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - instance.stream() - .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) - .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + final var collect = instance.stream() + .collect(Collectors.groupingBy(l -> { + if (l instanceof RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor accessor) { + return accessor.accessor$getResourceManager(); + } + return ResourceManager.Empty.INSTANCE; + }, Collectors.toSet())); + collect .forEach((k, v) -> { - ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); - lifecycle.processServerRegistries(k, v.stream() - .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! - .map(l -> (Registry) l.accessor$registry())); - v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + final RegistryHolder registryHolder; + if (k == ResourceManager.Empty.INSTANCE) { + // on the client side, we don't have a real resource manager + registryHolder = SpongeCommon.game(); + } else { + registryHolder = (RegistryHolder) k; + } + // Build a combined registry list: new batch registries replace any existing ones + // with the same key (e.g., on re-join, the second load produces fresh registries + // for the same keys that were already in the root from the first load). + final var batchRegistries = v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .map(RegistryLoadTaskAccessor::accessor$registry) + .toList(); + final var batchKeys = batchRegistries.stream() + .map(net.minecraft.core.Registry::key) + .collect(java.util.stream.Collectors.toSet()); + ((SpongeRegistryHolder) registryHolder).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat( + registryHolder.streamRegistries(RegistryRoots.MINECRAFT) + .filter(r -> !batchKeys.contains(((net.minecraft.core.Registry) r).key())), + batchRegistries.stream() + ).toList())); + + // Only fire plugin registry events on the server side (ResourceManager-backed loads). + // Client-side network loads only receive SYNCHRONIZED_REGISTRIES and lack server-only + // registries (placed_feature, configured_feature, etc.) that plugins may declare as + // dependencies, causing freeze validation to fail. + if (k != ResourceManager.Empty.INSTANCE) { + lifecycle.processServerRegistries(registryHolder, v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + } + + v + .stream().map(RegistryLoadTaskAccessor.class::cast) + .forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); }); - List> loaders = new ArrayList<>(instance.size()); + List> loaders = new ArrayList<>(collect.size()); dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); - original.call(Collections.unmodifiableList(loaders), consumer); + return original.call(loaders); } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java index 373d42b3fd6..4f797bb9a4f 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/MinecraftServerMixin_Neo.java @@ -63,13 +63,13 @@ public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } - @ModifyExpressionValue(method = "lambda$reloadResources$30", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$1", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager neo$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$31", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$4", at = @At("TAIL")) public void neo$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java index 45edb4ffa57..2b106c2543a 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/server/ReloadableServerResourcesMixin_Neo.java @@ -30,7 +30,6 @@ import net.minecraft.commands.Commands; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.permissions.PermissionSet; @@ -45,14 +44,22 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Neo { - @WrapOperation(method = "lambda$loadResources$3", at = @At(value = "NEW", - target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;")) + @WrapOperation(method = "lambda$loadResources$2", at = @At(value = "NEW", + target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;Ljava/util/List;)Lnet/minecraft/server/ReloadableServerResources;")) private static ReloadableServerResources impl$onCreateResources( - final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, - final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { - final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); - if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + final LayeredRegistryAccess fullLayers, + final HolderLookup.Provider loadingContext, + final FeatureFlagSet enabledFeatures, + final Commands.CommandSelection commandSelection, + final List postponedTags, + final PermissionSet functionCompilationPermissions, + final List newComponents, + final Operation original, + final @Local(argsOnly = true) ResourceManager resourceManager + ) { + final ReloadableServerResources instance = original.call(fullLayers, loadingContext, enabledFeatures, commandSelection, postponedTags, functionCompilationPermissions, newComponents); + if (instance.getCommands().getDispatcher() instanceof + final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); } return instance; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java index 5cc7735bec8..d7e27a18c78 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/tags/TagLoaderMixin_NeoForge.java @@ -55,13 +55,13 @@ public abstract class TagLoaderMixin_NeoForge implements TagLoaderBridge { return this.bridge$acceptTag(instance, lookup, consumer, original::call, $$1, entry); } - @Inject(method = "lambda$build$6", at = @At("HEAD")) + @Inject(method = "lambda$build$1", at = @At("HEAD")) private void neo$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } - @Inject(method = "lambda$build$6", at = @At("RETURN")) + @Inject(method = "lambda$build$1", at = @At("RETURN")) private void neo$onDoneBuildingTag(final CallbackInfo ci) { this.bridge$buildingTagKey(null); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index d67fc4ca999..418cf108045 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -24,18 +24,18 @@ */ package org.spongepowered.neoforge.mixin.core.world.level.block.entity; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.block.entity.carrier.furnace.FurnaceBlockEntity; @@ -52,14 +52,14 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; +import org.spongepowered.common.event.tracking.phase.general.RecipeContext; import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.mixin.core.world.level.block.entity.BaseContainerBlockEntityMixin; -import org.spongepowered.neoforge.accessor.world.level.block.entity.AbstractFurnaceBlockEntityAccessor_Neo; import java.util.ArrayList; import java.util.Collections; @@ -71,58 +71,95 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // @formatter:off @Shadow protected NonNullList items; - @Shadow int cookingTimer; + @Shadow private int cookingTimer; // @formatter:on + private static RecipeContext switched; private boolean neo$filledWaterBucket; // Tick up and Start - @Redirect(method = "serverTick", + @WrapOperation(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", - ordinal = 1)) + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/NonNullList;ILnet/minecraft/world/item/ItemStack;)Z" + ) + ) private static boolean neo$checkIfCanSmelt( - final RegistryAccess registryAccess, @Nullable final RecipeHolder recipe, final SingleRecipeInput input, - final NonNullList slots, final int maxStackSize, final ServerLevel level, final BlockPos entityPos, - final BlockState state, final AbstractFurnaceBlockEntity entityIn + final NonNullList items, + final int maxStackSize, + final ItemStack burnResult, + final Operation original, + final ServerLevel level, + final BlockPos pos, + final BlockState state, + final AbstractFurnaceBlockEntity entityIn, + final @Local RecipeHolder recipe ) { - if (!AbstractFurnaceBlockEntityAccessor_Neo.invoker$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { + if (!original.call(items, maxStackSize, burnResult)) { return false; } - final var entity = (AbstractFurnaceBlockEntityMixin_Neo) (Object) (entityIn); - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(slots.get(1)); + final var cookingRecipe = recipe.value(); + final var entity = (AbstractFurnaceBlockEntityMixin_Neo) (Object) (entityIn); + final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(items.get(1)); final Cause cause = PhaseTracker.getInstance().currentCause(); + final var identifier = recipe.id().identifier(); + // Prepare a phase stack to capture the recipe in use + final var context = GeneralPhase.State.RECIPE_CRAFTING.createPhaseContext(PhaseTracker.getInstance()) + .recipe(recipe.value()) + .recipeID(identifier) + .furnace(entityIn) + .provideItem(items.get(1)) + .buildAndSwitch(); + switched = context; if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up - final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.getFirst()); + final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } } + @Inject(method = "serverTick", at = @At("RETURN")) + private static void neo$closeRecipeContext( + final ServerLevel level, + final BlockPos pos, final BlockState state, + final AbstractFurnaceBlockEntity entity, + final CallbackInfo ci) { + if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); + } + final var closing = switched; + switched = null; + if (closing != null) { + closing.close(); + } + } + // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) private static int neo$resetCookTimeIfCancelled( final int newCookTime, final int zero, final int totalCookTime, final ServerLevel level, final BlockPos entityPos, final BlockState state, - final AbstractFurnaceBlockEntity entityIn - ) { + final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Neo) (Object) entityIn; - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + // we're in an invariant state + return clampedCookTime; + } + final var fuel = switched.usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = entity.bridge$getCurrentRecipe(); + final var recipe = switched.recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -134,11 +171,10 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB // Finish @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;"), slice = @Slice( - from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) + from = @At(value = "FIELD", target = "Lnet/minecraft/world/item/Items;WET_SPONGE:Lnet/minecraft/world/item/Item;", opcode = Opcodes.GETSTATIC) )) private static void neo$captureBucketFill( - final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput arg3, - final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci ) { final Cause cause = PhaseTracker.getInstance().currentCause(); final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) @@ -148,18 +184,18 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", shift = At.Shift.AFTER)) private static void neo$afterSmeltItem( - final RegistryAccess registryAccess, final RecipeHolder recipe, - final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, - final CallbackInfoReturnable cir + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci ) { - final ItemStack itemIn = slots.get(0); - final ItemStack recipeResult = recipe.value().assemble(input, registryAccess); - final ItemStack itemOut = slots.get(2); + final ItemStack itemIn = items.get(0); + final ItemStack itemOut = items.get(2); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + return; + } final Cause cause = PhaseTracker.getInstance().currentCause(); - final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) - .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); - + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); + final var recipe = switched.recipe(); + final var recipeID = switched.recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); @@ -168,25 +204,25 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final boolean hasFuel = !((AbstractFurnaceBlockEntityMixin_Neo) entity).neo$filledWaterBucket; if (((AbstractFurnaceBlockEntityMixin_Neo) entity).neo$filledWaterBucket) { - transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(slots.get(1)))); + transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(items.get(1)))); } ((AbstractFurnaceBlockEntityMixin_Neo) entity).neo$filledWaterBucket = false; if (itemOut.isEmpty()) { - transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(recipeResult))); - } else if (ItemStack.isSameItemSameComponents(itemOut, recipeResult)) { + transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(result))); + } else if (ItemStack.isSameItemSameComponents(itemOut, result)) { itemOut.shrink(1); final ItemStackSnapshot originalResult = ItemStackUtil.snapshotOf(itemOut); itemOut.grow(1); transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), originalResult, ItemStackUtil.snapshotOf(itemOut))); } - final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); + final Optional fuel = hasFuel && !items.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(items.get(1))) : Optional.empty(); final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); + fuel, Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) recipeID), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { - transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); + transaction.custom().ifPresent(item -> items.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryLoadTaskMixin.java similarity index 83% rename from src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryLoadTaskMixin.java index 1fe07db5263..b673a771ccf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryDataLoaderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/resources/RegistryLoadTaskMixin.java @@ -30,7 +30,6 @@ import net.minecraft.network.chat.ChatTypeDecoration; import net.minecraft.resources.Identifier; import net.minecraft.resources.NetworkRegistryLoadTask; -import net.minecraft.resources.RegistryDataLoader; import net.minecraft.resources.RegistryLoadTask; import net.minecraft.resources.ResourceKey; import org.spongepowered.api.adventure.ChatTypes; @@ -42,24 +41,24 @@ import java.util.Map; -@Mixin(RegistryDataLoader.class) -public class RegistryDataLoaderMixin { +@Mixin(RegistryLoadTask.class) +public class RegistryLoadTaskMixin { @SuppressWarnings("unchecked") - @Inject(method = "lambda$load$3", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/RegistryLoadTask;freezeRegistry(Ljava/util/Map;)Z")) - private static void impl$afterLoadRegistryContents( - Map, Exception> loadingErrors, RegistryLoadTask task, CallbackInfoReturnable cir + @Inject(method = "freezeRegistry", at = @At("HEAD")) + private void impl$beforeFreezeRegistryContents( + Map, Exception> loadingErrors, CallbackInfoReturnable cir ) { - if (task instanceof NetworkRegistryLoadTask) { + final RegistryLoadTask self = (RegistryLoadTask) (Object) this; + if (self instanceof NetworkRegistryLoadTask) { // On the client side, this ought to already be registered through the network return; } - final var registry = ((RegistryLoadTaskAccessor) task).accessor$registry(); + final var registry = ((RegistryLoadTaskAccessor) self).accessor$registry(); if (Registries.CHAT_TYPE.equals(registry.key())) { final ChatTypeDecoration narration = ChatTypeDecoration.withSender("chat.type.text.narrate"); registry.register(ResourceKey.create(registry.key(), (Identifier) (Object) ChatTypes.CUSTOM_CHAT.location()), (E) new ChatType(ChatTypeDecoration.withSender("%s%s"), narration), RegistrationInfo.BUILT_IN); registry.register(ResourceKey.create(registry.key(), (Identifier) (Object) ChatTypes.CUSTOM_MESSAGE.location()), (E) new ChatType(ChatTypeDecoration.teamMessage("%s%s%s"), narration), RegistrationInfo.BUILT_IN); } } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 13676d5ed1b..95cb2069610 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -35,7 +35,6 @@ import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.Registries; -import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundExplodePacket; import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; @@ -44,7 +43,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.players.PlayerList; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Util; @@ -678,16 +676,6 @@ public String toString() { .toString(); } - @Redirect( - method = "advanceWeatherCycle", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V"), - require = 0 // already done in Neo - ) - private void impl$broadcastAllCurrentDimensionOnly(final PlayerList instance, final Packet packet) { - // Weather is per world in Sponge. - instance.broadcastAll(packet, this.shadow$dimension()); - } - @Inject(method = "close", at = @At("HEAD")) private void impl$onClose(final CallbackInfo ci) { this.impl$closed = true; diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index e08c1a9e768..e97eddf179d 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -52,7 +52,7 @@ "network.syncher.EntityDataAccessorMixin", "network.syncher.SynchedEntityData_BuilderMixin", "network.syncher.SynchedEntityDataMixin", - "resources.RegistryDataLoaderMixin", + "resources.RegistryLoadTaskMixin", "server.MinecraftServerMixin", "server.PlayerAdvancementsMixin", "server.ReloadableServerResourcesMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerLevelMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerLevelMixin_Vanilla.java new file mode 100644 index 00000000000..f62ecbbb4e5 --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerLevelMixin_Vanilla.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.server.level; + +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.network.protocol.Packet; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.storage.WritableLevelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ServerLevel.class) +public abstract class ServerLevelMixin_Vanilla extends Level { + + protected ServerLevelMixin_Vanilla(WritableLevelData levelData, ResourceKey dimension, RegistryAccess registryAccess, Holder dimensionTypeRegistration, boolean isClientSide, boolean isDebug, long biomeZoomSeed, int maxChainedNeighborUpdates) { + super(levelData, dimension, registryAccess, dimensionTypeRegistration, isClientSide, isDebug, biomeZoomSeed, maxChainedNeighborUpdates); + } + + @Redirect( + method = "advanceWeatherCycle", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V") + ) + private void vanilla$broadcastAllCurrentDimensionOnly(final PlayerList instance, final Packet packet) { + instance.broadcastAll(packet, this.dimension()); + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 887d035d10a..ae6c5e736f6 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -26,6 +26,7 @@ "server.BootstrapMixin_Vanilla", "server.MinecraftServerMixin_Vanilla", "server.ReloadableServerResourcesMixin_Vanilla", + "server.level.ServerLevelMixin_Vanilla", "server.level.ServerPlayerMixin_Vanilla", "server.network.ServerGamePacketListenerImplMixin_Vanilla", "server.packs.repository.PackRepositoryMixin_Vanilla", From 29c5d88c634c4a46657f526f5143ad3276da0a9c Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 27 Mar 2026 18:35:12 -0700 Subject: [PATCH 496/586] feat(forge): update SpongeForge for Forge 62.0.2 / MC 26.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port SpongeForge from Forge 61.0.6 to 62.0.2, targeting Minecraft 26.1. Migrate build system from ForgeGradle 6.0.35 to 7.0.17 (complete DSL rewrite) and Gradle 9.2.1 to 9.3.0. ForgeGradle 7.x migration: - minecraft.dependency() replaces "minecraft"() dependency syntax - runs { register() } replaces runs { create() } - SlimeLauncher replaces RunConfig system (no genIntellijRuns) - Dedicated minecraftLibsConfig avoids cyclic configuration dependency - macOS client runs require -XstartOnFirstThread for GLFW Forge API changes: - LoadingModList/ModList now use static methods (no .get() singleton) - EntityAttributeCreationEvent uses global BUS field Mixin updates for 26.1 Forge bytecode: - RegistryDataLoaderMixin_Forge: async pipeline, RegistryLoadTask API - ReloadableServerResourcesMixin_Forge: 7-param constructor, lambda $2 - MinecraftServerMixin_Forge: lambda $30/$31 → $1/$4 - TagLoaderMixin_Forge: lambda $6 → $1 - AbstractFurnaceBlockEntityMixin_Forge: RecipeContext pattern, instance methods for canBurn/burn, Items.WET_SPONGE - ForgeHooksMixin_Forge: guard LootModifierManager on early ticks Common fixes (all platforms): - LivingEntityMixin_Damage: @Expression replaces @At("STORE") for boolean shield flag (Forge strips LVT type info) - ServerLevelMixin: @Coerce for weather boolean capture - SpongeWorldManager: use server().registryAccess() for LEVEL_STEM (excluded from Sponge's scoped holder) - SpongeLifecycle: null-guard serviceProvider in establishServerFeatures Signed-off-by: Gabriel Harris-Rouquette --- .gitignore | 2 + forge/build.gradle.kts | 61 +++---- forge/gradle.properties | 2 +- .../ForgeAccessWidenerTransformer.java | 2 +- .../ForgeListenerTransformer.java | 2 +- .../ForgeSuperclassChangeTransformer.java | 2 +- .../launch/plugin/ForgePluginManager.java | 8 +- .../launch/plugin/PluginModContainer.java | 4 +- .../spongepowered/forge/SpongeForgeMod.java | 2 +- .../forge/hook/ForgeWorldHooks.java | 10 ++ .../minecraftforge/ForgeHooksMixin_Forge.java | 63 +++++++ .../RegistryDataLoaderMixin_Forge.java | 83 +++++++--- .../server/MinecraftServerMixin_Forge.java | 4 +- .../ReloadableServerResourcesMixin_Forge.java | 24 ++- .../mixin/core/tags/TagLoaderMixin_Forge.java | 4 +- .../LivingEntityMixin_Forge_Damage.java | 6 - ...AbstractFurnaceBlockEntityMixin_Forge.java | 155 ++++++++++++------ .../resources/mixins.spongeforge.core.json | 1 + gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 115 +++++++++++++ gradle/wrapper/gradle-wrapper.properties | 4 +- .../spongepowered/common/SpongeLifecycle.java | 9 +- .../common/hooks/WorldHooks.java | 8 + .../world/server/SpongeWorldManager.java | 7 +- .../core/server/level/ServerLevelMixin.java | 6 +- .../entity/LivingEntityMixin_Damage.java | 10 +- 26 files changed, 454 insertions(+), 142 deletions(-) create mode 100644 forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/ForgeHooksMixin_Forge.java diff --git a/.gitignore b/.gitignore index 655121643bf..ec8cc3fd6d3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ dist lib out run +## ForgeGradle 7 moves the run configurations to runs instead of run. +runs run_snap /target *.com diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 4dfa304d448..3813a8f2728 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,8 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.minecraftforge.gradle.common.util.RunConfig -import org.gradle.internal.DefaultTaskExecutionRequest import org.spongepowered.gradle.impl.AWToAT -import org.spongepowered.gradle.impl.IdeHelper buildscript { repositories { @@ -37,20 +34,23 @@ val projectUrl: String by project description = "The SpongeAPI implementation for MinecraftForge" version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion, forgeVersion) +val fg = the() + repositories { - maven("https://libraries.minecraft.net/") { - name = "Mojang" - } + minecraft.mavenizer(this) + maven(fg.forgeMaven) + maven(fg.minecraftLibsMaven) maven("https://repo.spongepowered.org/repository/maven-public/") { name = "sponge" } } +// Dedicated configuration for the Forge/Minecraft dependency (replaces old configurations.minecraft from FG 6.x) +val minecraftLibsConfig = configurations.register("minecraftLibs") + // SpongeForge libraries val bootLibrariesConfig = configurations.register("bootLibraries") { - // Ideally we would filter minecraft itself and only keep its dependencies for this layer, - // but I couldn't find a way to do it without breaking ForgeGradle. - extendsFrom(configurations.minecraft.get()) + extendsFrom(minecraftLibsConfig.get()) } val serviceLibrariesConfig = configurations.register("serviceLibraries") val gameLibrariesConfig = configurations.register("gameLibraries") @@ -187,8 +187,11 @@ configurations.testRuntimeOnly { exclude(module = "testplugins") } +val forgeDep = minecraft.dependency("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") + dependencies { - "minecraft"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") + implementation(forgeDep) + minecraftLibsConfig.name(forgeDep) val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) @@ -246,22 +249,24 @@ val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations minecraft { mappings("official", minecraftVersion) accessTransformers.from(atFile) - reobf = false runs { configureEach { - ideaModule("Sponge.SpongeForge.main") - - // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath - main("org.spongepowered.bootstrap.forge.ForgeBootstrap") +// jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath + jvmArgs("-Dmixin.debug=true", "-Dmixin.debug.export=true", "-Dmixin.dumpTargetOnFailure=true") + mainClass.set("org.spongepowered.bootstrap.forge.ForgeBootstrap") args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) environment("MOD_CLASSES", "nop") } - create("client") + register("client") { + if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) { + jvmArgs("-XstartOnFirstThread") + } + } - create("server") { + register("server") { args("--nogui") } } @@ -272,10 +277,12 @@ afterEvaluate { // Configure bootstrap dev val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) - runs.configureEach { - jvmArgs("-Dsponge.dev.root=" + project.rootDir) - jvmArgs("-Dsponge.dev.boot=$bootFileNames") - jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") + runs { + configureEach { + jvmArgs("-Dsponge.dev.root=" + project.rootDir) + jvmArgs("-Dsponge.dev.boot=$bootFileNames") + jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") + } } } } @@ -319,7 +326,7 @@ sourceSets { tasks { withType(JavaExec::class) { - if (group == RunConfig.RUNS_GROUP) { + if (group == "Slime Launcher") { standardInput = System.`in` } } @@ -430,8 +437,8 @@ tasks { testClassesDirs = commonTest.get().output.classesDirs + testSources.get().output.classesDirs val runServer = minecraft.runs.getByName("server") - jvmArgs(runServer.jvmArgs) - jvmArgs("-Dsponge.test.args=" + runServer.args.joinToString(" ")) + jvmArgs(runServer.jvmArgs.get()) + jvmArgs("-Dsponge.test.args=" + runServer.args.get().joinToString(" ")) jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") @@ -458,11 +465,7 @@ tasks { } } -if (IdeHelper.isIdeaSync()) { - afterEvaluate { - gradle.startParameter.taskRequests.add(DefaultTaskExecutionRequest(listOf(":SpongeForge:genIntellijRuns"))) - } -} + publishing { publications { diff --git a/forge/gradle.properties b/forge/gradle.properties index 13366137a4c..5ca1b64bf98 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=61.0.6 +forgeVersion=62.0.2 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java index 9a54cfdc85f..3f378d96a9d 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeAccessWidenerTransformer.java @@ -68,7 +68,7 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { + for (ModFileInfo fileInfo : LoadingModList.getModFiles()) { final SecureJar jar = fileInfo.getFile().getSecureJar(); final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java index 83a6eeed82c..da945cd4d8f 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeListenerTransformer.java @@ -62,7 +62,7 @@ public Set targets() { final Type listenerType = Type.getType(ListenerTransformer.ANNOTATION_DESC); final Set listenerClasses = new HashSet<>(); - for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { + for (ModFileInfo fileInfo : LoadingModList.getModFiles()) { for (ModFileScanData.AnnotationData annotation : fileInfo.getFile().getScanResult().getAnnotations()) { if (listenerType.equals(annotation.annotationType())) { listenerClasses.add(annotation.clazz()); diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java index f7d351d2845..f29fa4ce645 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/transformation/ForgeSuperclassChangeTransformer.java @@ -73,7 +73,7 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (ModFileInfo fileInfo : LoadingModList.get().getModFiles()) { + for (ModFileInfo fileInfo : LoadingModList.getModFiles()) { final SecureJar jar = fileInfo.getFile().getSecureJar(); final Attributes attributes = jar.moduleDataProvider().getManifest().getMainAttributes(); diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java index f3b3d09f01d..b721583cdfb 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java @@ -40,23 +40,23 @@ public final class ForgePluginManager implements SpongePluginManager { @Override public Optional fromInstance(final Object instance) { - return ModList.get().getModContainerByObject(Objects.requireNonNull(instance, "instance")).map(ForgePluginContainer::of); + return ModList.getModContainerByObject(Objects.requireNonNull(instance, "instance")).map(ForgePluginContainer::of); } @Override public Optional plugin(final String id) { - return ModList.get().getModContainerById(Objects.requireNonNull(id, "id")).map(ForgePluginContainer::of); + return ModList.getModContainerById(Objects.requireNonNull(id, "id")).map(ForgePluginContainer::of); } @Override public Collection plugins() { final ImmutableList.Builder builder = ImmutableList.builder(); - ModList.get().forEachModInOrder(mod -> builder.add(ForgePluginContainer.of(mod))); + ModList.forEachModInOrder(mod -> builder.add(ForgePluginContainer.of(mod))); return builder.build(); } @Override public boolean isReady() { - return ModList.get() != null; + return ModList.size() > 0; } } diff --git a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index e20021a86a3..fbe57b8c5b7 100644 --- a/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/launch/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -82,11 +82,11 @@ private void constructPlugin() { final ForgePluginContainer pluginContainer = ForgePluginContainer.of(this); pluginContainer.metadata().dependencies().stream() .filter(d -> d.loadOrder() == PluginDependency.LoadOrder.AFTER) - .flatMap(d -> ModList.get().getModContainerById(d.id()).stream()) + .flatMap(d -> ModList.getModContainerById(d.id()).stream()) .filter(m -> m instanceof PluginModContainer) .forEach(m -> ((PluginModContainer) m).waitForInitialization()); - ModList.get().forEachModInOrder(m -> { + ModList.forEachModInOrder(m -> { if (m instanceof PluginModContainer p && ForgePluginContainer.of(m).metadata().dependencies().stream() .anyMatch(d -> d.id().equals(this.getModId()) && d.loadOrder() == PluginDependency.LoadOrder.BEFORE)) { p.waitForInitialization(); diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index 032d4deedeb..9581949691f 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -64,7 +64,7 @@ public SpongeForgeMod(FMLJavaModLoadingContext ctx) { // modBus: add all FML events with it FMLCommonSetupEvent.getBus(group).addListener(this::onCommonSetup); FMLClientSetupEvent.getBus(group).addListener(this::onClientSetup); - EntityAttributeCreationEvent.getBus(group).addListener(this::onEntityAttributeCreationEvent); + EntityAttributeCreationEvent.BUS.addListener(this::onEntityAttributeCreationEvent); // annotation events, for non-FML things MinecraftForge.EVENT_BUS.register(this); diff --git a/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java b/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java index 2d609eb95c4..0e2ab6f4bf0 100644 --- a/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java +++ b/forge/src/main/java/org/spongepowered/forge/hook/ForgeWorldHooks.java @@ -24,13 +24,18 @@ */ package org.spongepowered.forge.hook; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.LevelStem; import net.minecraftforge.event.level.LevelEvent; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.hooks.WorldHooks; public class ForgeWorldHooks implements WorldHooks { @@ -67,4 +72,9 @@ public void preUnloadWorld(final ServerLevel world) { LevelEvent.Unload.BUS.post(new LevelEvent.Unload(world)); world.getServer().markWorldsDirty(); } + + @Override + public Registry earlyRegistryAccess(ResourceKey> levelStem) { + return SpongeCommon.server().registryAccess().lookupOrThrow(Registries.LEVEL_STEM); + } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/ForgeHooksMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/ForgeHooksMixin_Forge.java new file mode 100644 index 00000000000..a6e7c4467da --- /dev/null +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/ForgeHooksMixin_Forge.java @@ -0,0 +1,63 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.mixin.core.minecraftforge; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.loot.LootModifierManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Collections; + +@Mixin(ForgeHooks.class) +public abstract class ForgeHooksMixin_Forge { + + // Forge's LootModifierManager is initialized during resource reload (AddReloadListenerEvent). + // On an integrated server's first tick, resources may not have loaded yet, + // causing ForgeInternalHandler.getLootModifierManager() to throw ISE. + // Guard by wrapping the call and returning an empty modifier list if unavailable. + @WrapOperation(method = "modifyLoot", at = @At(value = "INVOKE", + target = "Lnet/minecraftforge/common/ForgeInternalHandler;getLootModifierManager()Lnet/minecraftforge/common/loot/LootModifierManager;", + remap = false), remap = false) + private static LootModifierManager forge$guardLootModifierManager(final Operation original) { + try { + return original.call(); + } catch (final IllegalStateException e) { + return null; + } + } + + @WrapOperation(method = "modifyLoot", at = @At(value = "INVOKE", + target = "Lnet/minecraftforge/common/loot/LootModifierManager;getAllLootMods()Ljava/util/Collection;", + remap = false), remap = false) + private static java.util.Collection forge$guardGetAllLootMods(final LootModifierManager instance, final Operation> original) { + if (instance == null) { + return Collections.emptyList(); + } + return original.call(instance); + } +} diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java index 443940799f2..d64cef16ce3 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/resources/RegistryDataLoaderMixin_Forge.java @@ -28,54 +28,97 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.RegistryLoadTask; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.DependencySorter; import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.common.accessor.resources.RegistryDataLoader_LoaderAccessor; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.accessor.resources.RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor; +import org.spongepowered.common.accessor.resources.RegistryLoadTaskAccessor; import org.spongepowered.common.bridge.core.WritableRegistryBridge; -import org.spongepowered.common.bridge.resources.RegistryDataLoader_LoaderBridge; import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.Lifecycle; import org.spongepowered.common.registry.SpongeRegistryDependencyEntry; import org.spongepowered.common.registry.SpongeRegistryHolder; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @Mixin(RegistryDataLoader.class) public class RegistryDataLoaderMixin_Forge { - + // Forge's lambda$load$2 is the freeze-step lambda in the async load pipeline. + // Unlike NeoForge, Forge doesn't have a gametest hook before the freeze logic, + // so we can target stream() ordinal 0 directly with no @Slice. @SuppressWarnings({"rawtypes", "unchecked"}) - @WrapOperation(method = "load(Lnet/minecraft/resources/RegistryDataLoader$LoadingFunction;Ljava/util/List;Ljava/util/List;)Lnet/minecraft/core/RegistryAccess$Frozen;", - at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1)) - private static void impl$onLoad(final List> instance, final Consumer consumer, final Operation original) { + @WrapOperation(method = "lambda$load$2", + at = @At(value = "INVOKE", target = "Ljava/util/List;stream()Ljava/util/stream/Stream;", ordinal = 0)) + private static Stream impl$onLoad( + List> instance, Operation original + ) { // TODO: Remote layer - final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); + final DependencySorter, SpongeRegistryDependencyEntry>> dependencies = new DependencySorter<>(); final Lifecycle lifecycle = Launch.instance().lifecycle(); - instance.stream() - .filter(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder() != null) - .collect(Collectors.groupingBy(l -> ((RegistryDataLoader_LoaderBridge) l).bridge$registryHolder(), Collectors.toSet())) + final var collect = instance.stream() + .collect(Collectors.groupingBy(l -> { + if (l instanceof RegistryDataLoader_ResourceManagerRegistryLoadTaskAccessor accessor) { + return accessor.accessor$getResourceManager(); + } + return ResourceManager.Empty.INSTANCE; + }, Collectors.toSet())); + collect .forEach((k, v) -> { - ((SpongeRegistryHolder) k).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( - (List) Stream.concat(k.streamRegistries(RegistryRoots.MINECRAFT), v.stream().map(RegistryDataLoader_LoaderAccessor::accessor$registry)).toList())); - lifecycle.processServerRegistries(k, v.stream() - .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! - .map(l -> (Registry) l.accessor$registry())); - v.forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), + final RegistryHolder registryHolder; + if (k == ResourceManager.Empty.INSTANCE) { + // on the client side, we don't have a real resource manager + registryHolder = SpongeCommon.game(); + } else { + registryHolder = (RegistryHolder) k; + } + // Build a combined registry list: new batch registries replace any existing ones + // with the same key (e.g., on re-join, the second load produces fresh registries + // for the same keys that were already in the root from the first load). + final var batchRegistries = v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .map(RegistryLoadTaskAccessor::accessor$registry) + .toList(); + final var batchKeys = batchRegistries.stream() + .map(net.minecraft.core.Registry::key) + .collect(java.util.stream.Collectors.toSet()); + ((SpongeRegistryHolder) registryHolder).setRootMinecraftRegistry(new RegistryAccess.ImmutableRegistryAccess( + (List) Stream.concat( + registryHolder.streamRegistries(RegistryRoots.MINECRAFT) + .filter(r -> !batchKeys.contains(((net.minecraft.core.Registry) r).key())), + batchRegistries.stream() + ).toList())); + + // Only fire plugin registry events on the server side (ResourceManager-backed loads). + // Client-side network loads only receive SYNCHRONIZED_REGISTRIES and lack server-only + // registries (placed_feature, configured_feature, etc.) that plugins may declare as + // dependencies, causing freeze validation to fail. + if (k != ResourceManager.Empty.INSTANCE) { + lifecycle.processServerRegistries(registryHolder, v.stream() + .map(RegistryLoadTaskAccessor.class::cast) + .filter(l -> !RegistryDataLoader.DIMENSION_REGISTRIES.contains(l.accessor$data())) // NOTE: DIMENSION_REGISTRIES are special! + .map(l -> (Registry) l.accessor$registry())); + } + + v + .stream().map(RegistryLoadTaskAccessor.class::cast) + .forEach(l -> dependencies.addEntry(((Registry) l.accessor$registry()).type(), new SpongeRegistryDependencyEntry<>(l, ((WritableRegistryBridge) l.accessor$registry()).bridge$pendingDependencies().toList()))); }); - List> loaders = new ArrayList<>(instance.size()); + List> loaders = new ArrayList<>(collect.size()); dependencies.orderByDependencies(($, v) -> loaders.add(v.cookie())); - original.call(Collections.unmodifiableList(loaders), consumer); + return original.call(loaders); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java index 32f53051f12..ca9d9de9e3a 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/MinecraftServerMixin_Forge.java @@ -63,13 +63,13 @@ public long[] getTickTime(ResourceKey dim) { return ((ServerLevelBridge) this.shadow$getLevel(dim)).bridge$recentTickTimes(); } - @ModifyExpressionValue(method = "lambda$reloadResources$30", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) + @ModifyExpressionValue(method = "lambda$reloadResources$1", at = @At(value = "NEW", target = "Lnet/minecraft/server/packs/resources/MultiPackResourceManager;")) private MultiPackResourceManager forge$onReloadResources(final MultiPackResourceManager original) { ((MinecraftServerBridge) this).bridge$reloadServerRegistries((RegistryHolder) original); return original; } - @Inject(method = "lambda$reloadResources$31", at = @At("TAIL")) + @Inject(method = "lambda$reloadResources$4", at = @At("TAIL")) public void forge$onReloadedResources(final Collection $$0x, final @Coerce MinecraftServer_ReloadableResourcesAccessor $$1x, final CallbackInfo ci) { ((MinecraftServerBridge) this).bridge$reloadedServerRegistries(((SpongeRegistryHolder) $$1x.accessor$resourceManager()).registryHolder()); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java index e98b5000234..696e261ee09 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/ReloadableServerResourcesMixin_Forge.java @@ -30,7 +30,6 @@ import net.minecraft.commands.Commands; import net.minecraft.core.HolderLookup; import net.minecraft.core.LayeredRegistryAccess; -import net.minecraft.server.RegistryLayer; import net.minecraft.server.ReloadableServerResources; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.permissions.PermissionSet; @@ -45,15 +44,22 @@ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin_Forge { - @WrapOperation(method = "lambda$loadResources$1", at = @At(value = "NEW", - target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;)Lnet/minecraft/server/ReloadableServerResources;" - )) + @WrapOperation(method = "lambda$loadResources$2", at = @At(value = "NEW", + target = "(Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/core/HolderLookup$Provider;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Ljava/util/List;Lnet/minecraft/server/permissions/PermissionSet;Ljava/util/List;)Lnet/minecraft/server/ReloadableServerResources;")) private static ReloadableServerResources impl$onCreateResources( - final LayeredRegistryAccess $$0, final HolderLookup.Provider $$1, final FeatureFlagSet $$2, - final Commands.CommandSelection $$3, final List $$4, final PermissionSet $$5, - final Operation original, final @Local(argsOnly = true) ResourceManager resourceManager) { - final ReloadableServerResources instance = original.call($$0, $$1, $$2, $$3, $$4, $$5); - if (instance.getCommands().getDispatcher() instanceof final DelegatingCommandDispatcher delegatingCommandDispatcher) { + final LayeredRegistryAccess fullLayers, + final HolderLookup.Provider loadingContext, + final FeatureFlagSet enabledFeatures, + final Commands.CommandSelection commandSelection, + final List postponedTags, + final PermissionSet functionCompilationPermissions, + final List newComponents, + final Operation original, + final @Local(argsOnly = true) ResourceManager resourceManager + ) { + final ReloadableServerResources instance = original.call(fullLayers, loadingContext, enabledFeatures, commandSelection, postponedTags, functionCompilationPermissions, newComponents); + if (instance.getCommands().getDispatcher() instanceof + final DelegatingCommandDispatcher delegatingCommandDispatcher) { delegatingCommandDispatcher.permissionService(((ResourceManagerBridge) resourceManager).bridge$services().permissionService()); } return instance; diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java index 3491bcf0d4c..ae4d761e740 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/tags/TagLoaderMixin_Forge.java @@ -55,13 +55,13 @@ public abstract class TagLoaderMixin_Forge implements TagLoaderBridge { return this.bridge$acceptTag(instance, lookup, consumer, original::call, $$1, entry); } - @Inject(method = "lambda$build$6", at = @At("HEAD")) + @Inject(method = "lambda$build$1", at = @At("HEAD")) private void forge$onStartBuildingTag(final TagEntry.Lookup $$0x, final Map> $$1x, final Identifier $$2x, final @Coerce Object $$3x, final CallbackInfo ci) { this.bridge$buildingTagKey($$2x); } - @Inject(method = "lambda$build$6", at = @At("RETURN")) + @Inject(method = "lambda$build$1", at = @At("RETURN")) private void forge$onDoneBuildingTag(final CallbackInfo ci) { this.bridge$buildingTagKey(null); } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java index 3e983729e50..35e92bf1cd8 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge_Damage.java @@ -25,9 +25,7 @@ package org.spongepowered.forge.mixin.core.world.entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyArg; @@ -38,10 +36,6 @@ @Mixin(LivingEntity.class) public abstract class LivingEntityMixin_Forge_Damage implements TrackedDamageBridge { - //@formatter:off - @Shadow public abstract ItemStack shadow$getUseItem(); - //@formatter:on - @ModifyConstant(method = "actuallyHurt", constant = @Constant(floatValue = 0), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onLivingHurt(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F"))) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 38d46dea6d9..688a43f307f 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -24,14 +24,16 @@ */ package org.spongepowered.forge.mixin.core.world.level.block.entity; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.objectweb.asm.Opcodes; @@ -50,79 +52,115 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.block.entity.AbstractFurnaceBlockEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; +import org.spongepowered.common.event.tracking.phase.general.RecipeContext; import org.spongepowered.common.inventory.adapter.impl.slots.SlotAdapter; import org.spongepowered.common.item.util.ItemStackUtil; +import org.spongepowered.common.mixin.core.world.level.block.entity.BaseContainerBlockEntityMixin; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; -import javax.annotation.Nullable; - @Mixin(AbstractFurnaceBlockEntity.class) -public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractFurnaceBlockEntityBridge { +public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContainerBlockEntityMixin implements AbstractFurnaceBlockEntityBridge { // @formatter:off @Shadow protected NonNullList items; - @Shadow int cookingTimer; - @Shadow private boolean shadow$canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, SingleRecipeInput input, NonNullList slots, int maxStackSize) { - throw new UnsupportedOperationException("Shadowed canBurn"); - } + @Shadow private int cookingTimer; // @formatter:on + private static RecipeContext switched; private boolean forge$filledWaterBucket; // Tick up and Start - @Redirect(method = "serverTick", + @WrapOperation(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", - ordinal = 1)) - private static boolean forge$checkIfCanSmelt(final AbstractFurnaceBlockEntity entityIn, - final RegistryAccess registryAccess, - final RecipeHolder recipe, - final SingleRecipeInput input, - final NonNullList slots, - final int maxStackSize) { - final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) (entityIn); - if (!entity.shadow$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/NonNullList;ILnet/minecraft/world/item/ItemStack;)Z" + ) + ) + private static boolean forge$checkIfCanSmelt( + final AbstractFurnaceBlockEntity instance, + final NonNullList maxResultCount, + final int items, + final ItemStack maxStackSize, + final Operation original, + final ServerLevel level, + final BlockPos pos, + final BlockState state, + final AbstractFurnaceBlockEntity entityIn, + final @Local RecipeHolder recipe + ) { + if (!original.call(instance, maxResultCount, items, maxStackSize)) { return false; } - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(slots.get(1)); + final var cookingRecipe = recipe.value(); + final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) (entityIn); + final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(maxResultCount.get(1)); final Cause cause = PhaseTracker.getInstance().currentCause(); + final var identifier = recipe.id().identifier(); + // Prepare a phase stack to capture the recipe in use + final var context = GeneralPhase.State.RECIPE_CRAFTING.createPhaseContext(PhaseTracker.getInstance()) + .recipe(recipe.value()) + .recipeID(identifier) + .furnace(entityIn) + .provideItem(maxResultCount.get(1)) + .buildAndSwitch(); + switched = context; if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } else { // Tick up - final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.getFirst()); + final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier())); + Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); SpongeCommon.post(event); return !event.isCancelled(); } } + @Inject(method = "serverTick", at = @At("RETURN")) + private static void forge$closeRecipeContext( + final ServerLevel level, + final BlockPos pos, final BlockState state, + final AbstractFurnaceBlockEntity entity, + final CallbackInfo ci) { + if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); + } + final var closing = switched; + switched = null; + if (closing != null) { + closing.close(); + } + } + // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) - private static int forge$resetCookTimeIfCancelled(final int newCookTime, final int zero, final int totalCookTime, - final ServerLevel level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { + private static int forge$resetCookTimeIfCancelled( + final int newCookTime, final int zero, final int totalCookTime, + final ServerLevel level, final BlockPos entityPos, final BlockState state, + final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) entityIn; - final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + // we're in an invariant state + return clampedCookTime; + } + final var fuel = switched.usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = entity.bridge$getCurrentRecipe(); + final var recipe = switched.recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - recipe.map(r -> (CookingRecipe) r.value()), recipe.map(r -> (ResourceKey) (Object) r.id().identifier())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -134,51 +172,62 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // Finish @Inject(method = "burn", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;"), slice = @Slice( - from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) + from = @At(value = "FIELD", target = "Lnet/minecraft/world/item/Items;WET_SPONGE:Lnet/minecraft/world/item/Item;", opcode = Opcodes.GETSTATIC) )) - private void forge$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir) { - this.forge$filledWaterBucket = true; + private void forge$captureBucketFill( + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci + ) { + final Cause cause = PhaseTracker.getInstance().currentCause(); + final FurnaceBlockEntity entity = cause.first(FurnaceBlockEntity.class) + .orElseThrow(() -> new IllegalStateException("Expected to have a FurnaceBlockEntity in the Cause")); + ((AbstractFurnaceBlockEntityMixin_Forge) entity).forge$filledWaterBucket = true; } - @Inject( - method = "burn", - locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) + @Inject(method = "burn", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V", + shift = At.Shift.AFTER + )) private void forge$afterSmeltItem( - final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, - final NonNullList slots, final int maxStackSize, - final CallbackInfoReturnable cir, - final ItemStack itemIn, final ItemStack recipeResult, final ItemStack itemOut + final NonNullList items, final ItemStack inputItemStack, final ItemStack result, final CallbackInfo ci ) { - final FurnaceBlockEntity entity = (FurnaceBlockEntity) this; + final ItemStack itemIn = items.get(0); + final ItemStack itemOut = items.get(2); + if (PhaseTracker.getInstance().getPhaseContext() != switched) { + return; + } + final Cause cause = PhaseTracker.getInstance().currentCause(); + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); + final var recipe = switched.recipe(); + final var recipeID = switched.recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); itemIn.shrink(1); transactions.add(new SlotTransaction(entity.inventory().slot(0).get(), originalSmeltItem, ItemStackUtil.snapshotOf(itemIn))); - final boolean hasFuel = !this.forge$filledWaterBucket; - if (this.forge$filledWaterBucket) { - transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(slots.get(1)))); + final boolean hasFuel = !((AbstractFurnaceBlockEntityMixin_Forge) entity).forge$filledWaterBucket; + if (((AbstractFurnaceBlockEntityMixin_Forge) entity).forge$filledWaterBucket) { + transactions.add(new SlotTransaction(entity.inventory().slot(1).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(items.get(1)))); } - this.forge$filledWaterBucket = false; + ((AbstractFurnaceBlockEntityMixin_Forge) entity).forge$filledWaterBucket = false; if (itemOut.isEmpty()) { - transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(recipeResult))); - } else if (ItemStack.isSameItemSameComponents(itemOut, recipeResult)) { + transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), ItemStackSnapshot.empty(), ItemStackUtil.snapshotOf(result))); + } else if (ItemStack.isSameItemSameComponents(itemOut, result)) { itemOut.shrink(1); final ItemStackSnapshot originalResult = ItemStackUtil.snapshotOf(itemOut); itemOut.grow(1); transactions.add(new SlotTransaction(entity.inventory().slot(2).get(), originalResult, ItemStackUtil.snapshotOf(itemOut))); } - final Optional fuel = hasFuel && !slots.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(slots.get(1))) : Optional.empty(); - final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(PhaseTracker.getInstance().currentCause(), entity, - fuel, Optional.of((CookingRecipe) recipe.value()), Optional.of((ResourceKey) (Object) recipe.id().identifier()), Collections.unmodifiableList(transactions)); + final Optional fuel = hasFuel && !items.get(1).isEmpty() ? Optional.of(ItemStackUtil.snapshotOf(items.get(1))) : Optional.empty(); + final CookingEvent.Finish event = SpongeEventFactory.createCookingEventFinish(cause, entity, + fuel, Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) recipeID), Collections.unmodifiableList(transactions)); SpongeCommon.post(event); for (final SlotTransaction transaction : transactions) { - transaction.custom().ifPresent(item -> slots.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); + transaction.custom().ifPresent(item -> items.set(((SlotAdapter) transaction.slot()).getOrdinal(), ItemStackUtil.fromSnapshotToNative(item))); } } diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index 5a88ce6b7cf..da2c8b76a2c 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -5,6 +5,7 @@ "priority": 1301, "mixins": [ "commands.CommandsMixin_Forge", + "minecraftforge.ForgeHooksMixin_Forge", "minecraftforge.MinecraftForgeMixin_Forge", "minecraftforge.internal.BrandingControlMixin_Forge", "minecraftforge.registries.ForgeRegistryMixin_Forge", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 39cc1243c66..20231adc750 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -70,5 +70,5 @@ blossom = { id = "net.kyori.blossom", version = "2.1.0" } indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = "3.1.3" } shadow = { id = "com.gradleup.shadow", version = "9.0.2" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -forgeGradle = { id = "net.minecraftforge.gradle", version = "6.0.35" } +forgeGradle = { id = "net.minecraftforge.gradle", version = "7.0.17" } modDevGradle = { id = "net.neoforged.moddev", version = "2.0.141" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 47db5333af7..ddba15274ab 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4970,6 +4970,11 @@ + + + + + @@ -5045,6 +5050,11 @@ + + + + + @@ -5224,6 +5234,11 @@ + + + + + @@ -5403,6 +5418,11 @@ + + + + + @@ -5582,6 +5602,11 @@ + + + + + @@ -5745,6 +5770,16 @@ + + + + + + + + + + @@ -5772,6 +5807,11 @@ + + + + + @@ -5959,6 +5999,11 @@ + + + + + @@ -6146,6 +6191,11 @@ + + + + + @@ -6333,6 +6383,11 @@ + + + + + @@ -6368,6 +6423,11 @@ + + + + + @@ -6481,6 +6541,16 @@ + + + + + + + + + + @@ -9429,6 +9499,11 @@ + + + + + @@ -9437,6 +9512,11 @@ + + + + + @@ -9450,6 +9530,11 @@ + + + + + @@ -9458,6 +9543,11 @@ + + + + + @@ -9612,6 +9702,11 @@ + + + + + @@ -9660,6 +9755,11 @@ + + + + + @@ -11085,6 +11185,11 @@ + + + + + @@ -11226,6 +11331,11 @@ + + + + + @@ -11303,6 +11413,11 @@ + + + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8a848873f3a..44ae9537e91 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionSha256Sum=0d585f69da091fc5b2beced877feab55a3064d43b8a1d46aeb07996b0915e0e0 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index a33fc73516a..30b79c2c0e9 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -191,7 +191,14 @@ public void establishServerServices(final ResourceManager resourceManager, final @Override public void establishServerFeatures() { - Sponge.server().serviceProvider().contextService().registerContextCalculator(new SpongeContextCalculator()); + // In 26.1, the service provider may not yet be available during ServerAboutToStartEvent + // on the integrated server path (NeoForge/Forge). The service provider is set in + // MinecraftServer. TAIL from the WorldStem's resource manager, but on integrated + // servers the event can fire before the services propagate. Guard against this. + final var serviceProvider = Sponge.server().serviceProvider(); + if (serviceProvider != null) { + serviceProvider.contextService().registerContextCalculator(new SpongeContextCalculator()); + } // Yes this looks odd but prevents having to do sided lifecycle solely to always point at the Server ((SpongeServer) this.game.server()).getUsernameCache().load(); } diff --git a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java index 78980e4de88..1fd42fb015c 100644 --- a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java @@ -24,9 +24,13 @@ */ package org.spongepowered.common.hooks; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.LevelStem; +import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.event.tracking.PhaseTracker; public interface WorldHooks { @@ -42,4 +46,8 @@ default boolean isRestoringBlocks(final Level world) { default void postLoadWorld(ServerLevel world) { } default void preUnloadWorld(ServerLevel world) { } + + default Registry earlyRegistryAccess(ResourceKey> levelStem) { + return SpongeCommon.vanillaRegistry(levelStem); + } } diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index 20befcaa5c9..4940d2b3cf2 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -652,7 +652,7 @@ private CompletableFuture deleteWorld0(final ResourceKey key) { //After vanilla has detected a new dimension from a data pack it "promotes" it //to the overworld's level data where the level persist even when the data pack is removed. //This forcible removes it from there too. - final Registry levelStemRegistry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM); + final Registry levelStemRegistry = SpongeCommon.server().registryAccess().lookupOrThrow(Registries.LEVEL_STEM); final net.minecraft.resources.ResourceKey levelStemKey = Registries.levelToLevelStem(registryKey); if (levelStemRegistry.containsKey(levelStemKey)) { ((MappedRegistryBridge) levelStemRegistry).bridge$forceRemoveValue(Registries.levelToLevelStem(registryKey)); @@ -721,7 +721,10 @@ public void createNonDefaultLevels() { // Migration from old SpongeData format is handled by FileFixerUpperMixin // which runs BEFORE any ServerLevel is created, preserving UUIDs in // per-dimension data/sponge/registry.dat files. - final Registry registry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM); + // LEVEL_STEM is a dimension registry, loaded separately from worldgen registries. + // It's in the server's composite registryAccess() but NOT in Sponge's scoped holder + // (which explicitly excludes DIMENSION_REGISTRIES during RegistryDataLoader processing). + final Registry registry = PlatformHooks.INSTANCE.getWorldHooks().earlyRegistryAccess(Registries.LEVEL_STEM); for (final LevelStem levelStem : registry) { final ResourceKey worldKey = (ResourceKey) (Object) registry.getKey(levelStem); if (DefaultWorldKeys.DEFAULT.equals(worldKey)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 95cb2069610..a2df32fd26c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -118,6 +118,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -507,12 +508,13 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel return original.call(instance); } + // We need to stick with the local capture and coercion in 26.1 due to Forge stripping the LVT @Inject(method = "advanceWeatherCycle", locals = LocalCapture.CAPTURE_FAILEXCEPTION, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerLevel;oRainLevel:F", shift = At.Shift.BEFORE, ordinal = 1)) - public void impl$onSetWeatherParameters(final CallbackInfo ci, final boolean $$0) { + public void impl$onSetWeatherParameters(final CallbackInfo ci, final @Coerce boolean wasRaining) { final boolean isRaining = this.shadow$isRaining(); - if (this.oRainLevel != this.rainLevel || this.oThunderLevel != this.thunderLevel || $$0 != isRaining) { + if (this.oRainLevel != this.rainLevel || this.oThunderLevel != this.thunderLevel || wasRaining != isRaining) { Weather newWeather = ((ServerWorld) this).properties().weather(); final Cause currentCause = PhaseTracker.getInstance().currentCause(); final Transaction weatherTransaction = new Transaction<>(this.impl$prevWeather, newWeather); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java index fc5ba2de9ca..212b8b7087c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Damage.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.mixin.core.world.entity; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; @@ -45,6 +47,7 @@ import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.api.event.cause.entity.damage.DamageStepTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -134,9 +137,12 @@ public abstract class LivingEntityMixin_Damage extends EntityMixin implements Li this.damage$inventoryChanged = true; } - @ModifyVariable(method = "hurtServer", at = @At("STORE"), slice = @Slice( + // The expression is "vague" due to a Forge bug in 26.1 that it strips the LVT entirely + // leaving us with little options to target the local variable assignment + @Expression("? > 0.0") + @ModifyExpressionValue(method = "hurtServer", at = @At("MIXINEXTRAS:EXPRESSION"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;applyItemBlocking(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)F"), - to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;")) + to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;IS_FREEZING:Lnet/minecraft/tags/TagKey;", opcode = Opcodes.GETSTATIC)) ) private boolean damage$setBlockedFlag(final boolean blocked) { final SpongeDamageTracker tracker = this.damage$tracker(); From 3bd63e14391fda77dd6f3817ac107fc088b89624 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Fri, 27 Mar 2026 20:18:51 -0700 Subject: [PATCH 497/586] refactor(mixins): replace static `RecipeContext` with `ThreadLocal` across platforms Update vanilla, Forge, and NeoForge `AbstractFurnaceBlockEntityMixin` implementations to use `ThreadLocal` instead of a static field to ensure thread safety. Includes associated adjustments to method calls and context handling logic. --- ...AbstractFurnaceBlockEntityMixin_Forge.java | 26 +++++++++---------- .../AbstractFurnaceBlockEntityMixin_Neo.java | 26 +++++++++---------- ...stractFurnaceBlockEntityMixin_Vanilla.java | 26 +++++++++---------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 688a43f307f..07a37b72c40 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -74,7 +74,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContaine @Shadow private int cookingTimer; // @formatter:on - private static RecipeContext switched; + private static final ThreadLocal switched = new ThreadLocal<>(); private boolean forge$filledWaterBucket; // Tick up and Start @@ -112,7 +112,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContaine .furnace(entityIn) .provideItem(maxResultCount.get(1)) .buildAndSwitch(); - switched = context; + switched.set(context); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); @@ -133,11 +133,11 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContaine final BlockPos pos, final BlockState state, final AbstractFurnaceBlockEntity entity, final CallbackInfo ci) { - if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + if (switched.get() != null && PhaseTracker.getInstance().getPhaseContext() != switched.get()) { SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); } - final var closing = switched; - switched = null; + final var closing = switched.get(); + switched.remove(); if (closing != null) { closing.close(); } @@ -151,16 +151,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContaine final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) entityIn; - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { // we're in an invariant state return clampedCookTime; } - final var fuel = switched.usedItem(); + final var fuel = switched.get().usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = switched.recipe(); + final var recipe = switched.get().recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.get().recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -193,14 +193,14 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge extends BaseContaine ) { final ItemStack itemIn = items.get(0); final ItemStack itemOut = items.get(2); - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { return; } final Cause cause = PhaseTracker.getInstance().currentCause(); - final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); - final var recipe = switched.recipe(); - final var recipeID = switched.recipeID(); + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.get().furnace(); + final var recipe = switched.get().recipe(); + final var recipeID = switched.get().recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java index 418cf108045..ec8da3607c9 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Neo.java @@ -74,7 +74,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB @Shadow private int cookingTimer; // @formatter:on - private static RecipeContext switched; + private static final ThreadLocal switched = new ThreadLocal<>(); private boolean neo$filledWaterBucket; // Tick up and Start @@ -111,7 +111,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB .furnace(entityIn) .provideItem(items.get(1)) .buildAndSwitch(); - switched = context; + switched.set(context); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); @@ -132,11 +132,11 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final BlockPos pos, final BlockState state, final AbstractFurnaceBlockEntity entity, final CallbackInfo ci) { - if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + if (switched.get() != null && PhaseTracker.getInstance().getPhaseContext() != switched.get()) { SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); } - final var closing = switched; - switched = null; + final var closing = switched.get(); + switched.remove(); if (closing != null) { closing.close(); } @@ -150,16 +150,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Neo) (Object) entityIn; - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { // we're in an invariant state return clampedCookTime; } - final var fuel = switched.usedItem(); + final var fuel = switched.get().usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = switched.recipe(); + final var recipe = switched.get().recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.get().recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -188,14 +188,14 @@ public abstract class AbstractFurnaceBlockEntityMixin_Neo extends BaseContainerB ) { final ItemStack itemIn = items.get(0); final ItemStack itemOut = items.get(2); - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { return; } final Cause cause = PhaseTracker.getInstance().currentCause(); - final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); - final var recipe = switched.recipe(); - final var recipeID = switched.recipeID(); + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.get().furnace(); + final var recipe = switched.get().recipe(); + final var recipeID = switched.get().recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 712209efaf6..c4a080c52e4 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -74,7 +74,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai @Shadow private int cookingTimer; // @formatter:on - private static RecipeContext switched; + private static final ThreadLocal switched = new ThreadLocal<>(); private boolean vanilla$filledWaterBucket; // Tick up and Start @@ -111,7 +111,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai .furnace(entityIn) .provideItem(items.get(1)) .buildAndSwitch(); - switched = context; + switched.set(context); if (entity.cookingTimer == 0) { // Start final CookingEvent.Start event = SpongeEventFactory.createCookingEventStart(cause, (FurnaceBlockEntity) entityIn, Optional.of(fuel), Optional.of((CookingRecipe) cookingRecipe), Optional.of((ResourceKey) (Object) identifier)); @@ -132,11 +132,11 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final BlockPos pos, final BlockState state, final AbstractFurnaceBlockEntity entity, final CallbackInfo ci) { - if (switched != null && PhaseTracker.getInstance().getPhaseContext() != switched) { + if (switched.get() != null && PhaseTracker.getInstance().getPhaseContext() != switched.get()) { SpongeCommon.logger().warn("Closed a recipe context that wasn't open!"); } - final var closing = switched; - switched = null; + final var closing = switched.get(); + switched.remove(); if (closing != null) { closing.close(); } @@ -150,16 +150,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Vanilla) (Object) entityIn; - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { // we're in an invariant state return clampedCookTime; } - final var fuel = switched.usedItem(); + final var fuel = switched.get().usedItem(); final Cause cause = PhaseTracker.getInstance().currentCause(); - final var recipe = switched.recipe(); + final var recipe = switched.get().recipe(); final ItemStackSnapshot cooking = ItemStackUtil.snapshotOf(entity.items.get(0)); final CookingEvent.Tick event = SpongeEventFactory.createCookingEventTick(cause, (FurnaceBlockEntity) entityIn, cooking, Optional.of(fuel), - Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.recipeID())); + Optional.of((CookingRecipe) recipe), Optional.of((ResourceKey) (Object) switched.get().recipeID())); SpongeCommon.post(event); if (event.isCancelled()) { return entity.cookingTimer; // dont tick down @@ -189,14 +189,14 @@ public abstract class AbstractFurnaceBlockEntityMixin_Vanilla extends BaseContai ) { final ItemStack itemIn = items.get(0); final ItemStack itemOut = items.get(2); - if (PhaseTracker.getInstance().getPhaseContext() != switched) { + if (PhaseTracker.getInstance().getPhaseContext() != switched.get()) { return; } final Cause cause = PhaseTracker.getInstance().currentCause(); - final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.furnace(); - final var recipe = switched.recipe(); - final var recipeID = switched.recipeID(); + final FurnaceBlockEntity entity = (FurnaceBlockEntity) switched.get().furnace(); + final var recipe = switched.get().recipe(); + final var recipeID = switched.get().recipeID(); final List transactions = new ArrayList<>(); itemIn.grow(1); final ItemStackSnapshot originalSmeltItem = ItemStackUtil.snapshotOf(itemIn); From 916b4828b0540837e419312a3c89717ac2754e53 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 28 Mar 2026 11:52:07 -0700 Subject: [PATCH 498/586] fix(forge): remove @OnlyIn annotations and fix test infrastructure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forge 62.0.2's RuntimeDistCleaner no longer supports @OnlyIn on mod classes, throwing UnsupportedOperationException during class loading. This broke registry/datapack loading when deserializing components (AdventureTextComponent) and flattening keybind components (ComponentFlattenerProvider). - AdventureTextComponent: replace @OnlyIn with runtime dist check via clientLocale() helper that catches NoClassDefFoundError on server - ComponentFlattenerProvider: remove @OnlyIn from resolveKeybind(), already guarded by !Launch.instance().dedicatedServer() Test infrastructure fixes for Forge (FG 7.x): - Add testModulesConfig with --module-path for byte-buddy/mockito JPMS - Add --launchTarget forge_userdev_server to test args (FG 7.x no longer includes it automatically in run config args) - Upgrade JaCoCo 0.8.13 → 0.8.14 for official Java 25 support Signed-off-by: Gabriel Harris-Rouquette --- forge/build.gradle.kts | 18 +++++++++++++--- gradle/libs.versions.toml | 2 +- .../adventure/AdventureTextComponent.java | 21 ++++++++++++------- .../adventure/ComponentFlattenerProvider.java | 4 +--- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 3813a8f2728..3003e518e51 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -62,6 +62,8 @@ val gameShadedLibrariesConfig = configurations.register("gameShadedLibraries") val productionExcludedLibrariesConfig = configurations.register("productionExcludedLibraries") +val testModulesConfig = configurations.register("testModules") + // ModLauncher layers val bootLayerConfig = configurations.register("bootLayer") { extendsFrom(bootLibrariesConfig.get()) @@ -174,6 +176,10 @@ val testSources = sourceSets.named("test") { spongeImpl.addDependencyToImplementation(bootstrapMain.get(), this) spongeImpl.addDependencyToImplementation(bootstrapForge.get(), this) + + configurations.named(implementationConfigurationName) { + extendsFrom(testModulesConfig.get()) + } } configurations.configureEach { @@ -233,7 +239,8 @@ dependencies { testImplementation(apiLibs.junit.launcher) testRuntimeOnly(apiLibs.junit.engine) - testImplementation(apiLibs.mockito) + val test = testModulesConfig.name + test(apiLibs.mockito) testRuntimeOnly(libs.jacoco.core) { exclude(group = "org.ow2.asm") @@ -438,8 +445,13 @@ tasks { val runServer = minecraft.runs.getByName("server") jvmArgs(runServer.jvmArgs.get()) - jvmArgs("-Dsponge.test.args=" + runServer.args.get().joinToString(" ")) - jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") + jvmArgs("--module-path=" + testModulesConfig.get().asPath) + jvmArgs("--add-modules=net.bytebuddy.agent,net.bytebuddy") + jvmArgs("-Dsponge.test.args=--launchTarget forge_userdev_server " + runServer.args.get().joinToString(" ")) + // Don't set sponge.jacoco.packages — the JaCoCo agent is disabled + // and Sponge's JacocoTransformer would inject Offline references + // that can't be resolved without the agent runtime. + // jvmArgs("-Dsponge.jacoco.packages=org.spongepowered") jvmArgs("-Djunit.platform.launcher.interceptors.enabled=true") jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") workingDir = layout.buildDirectory.dir("test-run").get().asFile diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 20231adc750..9af7694656c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ guava = "32.1.2-jre" jline = "3.25.1" tinylog = "2.7.0" vineflower = "1.11.1" -jacoco = "0.8.13" +jacoco = "0.8.14" [libraries] # common diff --git a/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java b/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java index a822080efdc..e6e10615035 100644 --- a/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java +++ b/src/main/java/org/spongepowered/common/adventure/AdventureTextComponent.java @@ -28,14 +28,11 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.renderer.ComponentRenderer; -import net.minecraft.client.Minecraft; import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.contents.PlainTextContents; import net.minecraft.util.FormattedCharSequence; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.bridge.adventure.ComponentBridge; @@ -92,10 +89,14 @@ net.minecraft.network.chat.Component deepConverted() { return converted; } - @OnlyIn(Dist.CLIENT) net.minecraft.network.chat.Component deepConvertedLocalized() { + // Client-only: resolve locale from Minecraft settings. + // On the server, fall back to non-localized conversion. + final Locale target = AdventureTextComponent.clientLocale(); + if (target == null) { + return this.deepConverted(); + } net.minecraft.network.chat.Component converted = this.converted; - final Locale target = LocaleCache.getLocale(Minecraft.getInstance().options.languageCode); if (converted == null || this.deepConvertedLocalized != target) { converted = this.converted = this.rendered(target, null).deepConverted(); this.deepConvertedLocalized = target; @@ -103,6 +104,14 @@ net.minecraft.network.chat.Component deepConvertedLocalized() { return converted; } + private static @Nullable Locale clientLocale() { + try { + return LocaleCache.getLocale(net.minecraft.client.Minecraft.getInstance().options.languageCode); + } catch (final NoClassDefFoundError | NullPointerException e) { + return null; + } + } + public net.minecraft.network.chat.@Nullable Component deepConvertedIfPresent() { return this.converted; } @@ -146,13 +155,11 @@ public MutableComponent copy() { return this.deepConverted().copy(); } - @OnlyIn(Dist.CLIENT) @Override public FormattedCharSequence getVisualOrderText() { return this.deepConvertedLocalized().getVisualOrderText(); } - @OnlyIn(Dist.CLIENT) @Override public Optional visit(final StyledContentConsumer visitor, final Style style) { return this.deepConvertedLocalized().visit(visitor, style); diff --git a/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java b/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java index f49e51a4931..283a37c683e 100644 --- a/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java +++ b/src/main/java/org/spongepowered/common/adventure/ComponentFlattenerProvider.java @@ -35,8 +35,6 @@ import net.kyori.adventure.translation.Translator; import net.minecraft.client.KeyMapping; import net.minecraft.locale.Language; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import org.spongepowered.common.accessor.client.KeyMappingAccessor; import org.spongepowered.common.launch.Launch; @@ -105,7 +103,7 @@ final class ComponentFlattenerProvider { INSTANCE = builder.build(); } - @OnlyIn(Dist.CLIENT) + // Client-only: guarded by !Launch.instance().dedicatedServer() in the static initializer private static String resolveKeybind(final KeybindComponent component) { final KeyMapping mapping = KeyMappingAccessor.accessor$ALL().get(component.keybind()); if (mapping != null) { From 8afae81a663d925e952d273531e4b742f9347218 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 29 Mar 2026 23:49:50 +0300 Subject: [PATCH 499/586] Fix command registration Reverted back the change --- .../common/mixin/core/commands/CommandsMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 861612758cb..5a66cf3f3c7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -31,6 +31,7 @@ import net.minecraft.server.commands.AdvancementCommands; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -58,7 +59,7 @@ public abstract class CommandsMixin implements CommandsBridge { return new CommandDispatcher<>(); } final SpongeCommandManager manager = Launch.instance().lifecycle().platformInjector().getInstance(SpongeCommandManager.class); - manager.init(SpongeCommon.game()); + manager.init((RegistryHolder) context); this.impl$commandManager = manager; return new DelegatingCommandDispatcher(manager.getBrigadierRegistrar()); } From 3ffbc7ae640d6dc126aa99171b06261dd5f98612 Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 29 Mar 2026 23:53:25 +0300 Subject: [PATCH 500/586] spotless --- .../spongepowered/common/mixin/core/commands/CommandsMixin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java index 5a66cf3f3c7..6af2d4d8b82 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/CommandsMixin.java @@ -35,7 +35,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.commands.CommandsBridge; import org.spongepowered.common.command.brigadier.dispatcher.DelegatingCommandDispatcher; import org.spongepowered.common.command.manager.SpongeCommandManager; From 99f97627de114b6366d5f48754de399148bb864f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Thu, 2 Apr 2026 21:37:09 -0700 Subject: [PATCH 501/586] feat(minecraft): update to 26.1.1 See: https://minecraft.wiki/w/Java_Edition_26.1.1 --- forge/gradle.properties | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 66 ++++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 5ca1b64bf98..e0f7d7f05e3 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=62.0.2 +forgeVersion=63.0.0 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index afa75153d02..4c7950aea78 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1 +minecraftVersion=26.1.1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ddba15274ab..3bc2e0e6f0b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3582,6 +3582,11 @@ + + + + + @@ -5239,6 +5244,11 @@ + + + + + @@ -5423,6 +5433,11 @@ + + + + + @@ -5607,6 +5622,11 @@ + + + + + @@ -5775,6 +5795,11 @@ + + + + + @@ -6004,6 +6029,11 @@ + + + + + @@ -6196,6 +6226,11 @@ + + + + + @@ -6388,6 +6423,11 @@ + + + + + @@ -7107,6 +7147,17 @@ + + + + + + + + + + + @@ -7136,6 +7187,11 @@ + + + + + @@ -7302,6 +7358,11 @@ + + + + + @@ -7432,6 +7493,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 4a8e50d35bf..4704264d8be 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.1.0.1-beta +neoForgeVersion=26.1.1.1-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 58c601503c1a4b33a184911472ef7974725606d7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 8 Apr 2026 23:44:24 -0700 Subject: [PATCH 502/586] feat(minecraft): update to 26.2-snapshot-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING: - StructureProcessorType collapse — ProcessorType removed, Processor now codec-bearing with parse() factory - DimensionType#infiniburn changed from TagKey to HolderSet CHANGED: - LootData removed; DyeColorUtil rebuilt on ColorCollection.pick(DyeColor) - DripstoneThickness renamed to SpeleothemThickness in vanilla; mixin retargeted - Slime/MagmaCube moved to cubemob subpackage with new AbstractCubeMob parent - MinecraftMixin injection retargeted destroy() → exitWorldAndClose() - DensityFunction.DIRECT_CODEC → DensityFunctions.DIRECT_CODEC - Minecraft.setScreen() → setScreenAndShow() in PluginScreen and TitleScreenMixin_Vanilla REMOVED: - FlyingAnimal marker interface and FlyingAnimalMixin_API files - StructureProcessorTypeMixin_API - SlimeAccessor ADDITION: - SpongeProcessorFactory registered in SpongeFactoryProvider - AbstractCubeMobMixin_API as shared parent for SlimeMixin_API and MagmaCubeMixin_API - SpeleothemThicknessMixin_API replacing DripstoneThicknessMixin_API See: https://minecraft.wiki/w/Java_Edition_26.2-snapshot-1 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../BlockStatePropertiesGenerator.java | 4 +- .../BlockStatePropertyKeysGenerator.java | 4 +- .../world/level/LevelDataRegistries.java | 8 ---- .../world/level/block/BlockRegistries.java | 4 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 44 ++++++++++++++++++ .../world/entity/monster/SlimeAccessor.java | 36 --------------- .../resources/mixins.sponge.accessors.json | 1 - .../block/state/BlockStateDataProvider.java | 2 +- .../data/provider/block/state/WoolData.java | 3 +- .../data/provider/entity/SlimeData.java | 5 +-- .../item/stack/WoolItemStackData.java | 3 +- .../data/provider/world/WorldTypeData.java | 6 ++- .../registry/SpongeFactoryProvider.java | 3 ++ .../loader/VanillaRegistryLoader.java | 5 ++- .../common/util/DyeColorUtil.java | 36 ++++++--------- .../jigsaw/SpongeProcessorFactory.java} | 45 ++++++++++++------- .../chunk/storage/SpongeEntityChunk.java | 3 +- .../world/server/SpongeWorldTypeBuilder.java | 6 ++- .../world/volume/VolumeStreamUtils.java | 13 +++--- .../entity/animal/FlyingAnimalMixin_API.java | 33 -------------- .../AbstractCubeMobMixin_API.java} | 11 +++-- .../{ => cubemob}/MagmaCubeMixin_API.java | 6 +-- .../cubemob/SlimeMixin_API.java} | 9 ++-- .../minecraft/world/level/LevelMixin_API.java | 2 +- .../AbstractFurnaceBlockEntityMixin_API.java | 8 ++-- .../entity/BeaconBlockEntityMixin_API.java | 6 +-- ...java => SpeleothemThicknessMixin_API.java} | 6 +-- .../level/chunk/LevelChunkMixin_API.java | 2 +- .../levelgen/DensityFunctionMixin_API.java | 3 +- .../StructureProcessorMixin_API.java | 37 +++++++++------ .../mixin/core/client/MinecraftMixin.java | 6 +-- .../selector/EntitySelectorParserMixin.java | 2 +- .../projectile/arrow/AbstractArrowMixin.java | 2 +- .../mixin/core/world/item/ItemStackMixin.java | 2 +- .../DedicatedServerMixin_IpForward.java | 2 +- .../server/level/ChunkMapMixin_Tracker.java | 2 +- src/mixins/resources/mixins.sponge.api.json | 10 ++--- .../test/worldgen/StructureTest.java | 10 +++-- .../client/gui/screen/PluginScreen.java | 2 +- .../gui/screens/TitleScreenMixin_Vanilla.java | 2 +- 42 files changed, 195 insertions(+), 203 deletions(-) delete mode 100644 src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SlimeAccessor.java rename src/{mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorTypeMixin_API.java => main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java} (50%) delete mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FlyingAnimalMixin_API.java rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{SlimeMixin_API.java => cubemob/AbstractCubeMobMixin_API.java} (89%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/{ => cubemob}/MagmaCubeMixin_API.java (88%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/{FlyingAnimalMixin_API.java => monster/cubemob/SlimeMixin_API.java} (85%) rename src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/{DripstoneThicknessMixin_API.java => SpeleothemThicknessMixin_API.java} (88%) diff --git a/SpongeAPI b/SpongeAPI index a71b70c1941..2adc06b5838 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a71b70c1941d9a4dd8833ef915ba2d2f4c961e06 +Subproject commit 2adc06b583818eed7c346f230fcf996231440506 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 2e07feb0af8..8fa528f8892 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -48,7 +48,7 @@ import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.IntegerProperty; @@ -148,7 +148,7 @@ static PropertyType ofProperty(final Property prop) { vanillaEnumTypeMapping.put(DoorHingeSide.class, BlockStatePropertiesGenerator.inDataTypePkg("DoorHinge")); vanillaEnumTypeMapping.put(NoteBlockInstrument.class, BlockStatePropertiesGenerator.inDataTypePkg("InstrumentType")); vanillaEnumTypeMapping.put(StairsShape.class, BlockStatePropertiesGenerator.inDataTypePkg("StairShape")); - vanillaEnumTypeMapping.put(DripstoneThickness.class, BlockStatePropertiesGenerator.inDataTypePkg("DripstoneSegment")); + vanillaEnumTypeMapping.put(SpeleothemThickness.class, BlockStatePropertiesGenerator.inDataTypePkg("DripstoneSegment")); vanillaEnumTypeMapping.put(FrontAndTop.class, BlockStatePropertiesGenerator.inDataTypePkg("JigsawBlockOrientation")); vanillaEnumTypeMapping.put(ComparatorMode.class, BlockStatePropertiesGenerator.inDataTypePkg("ComparatorMode")); vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertiesGenerator.inDataTypePkg("TrialSpawnerState")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index c012945d60a..a8545583915 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -49,7 +49,7 @@ import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.IntegerProperty; @@ -146,7 +146,7 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property vanillaEnumTypeMapping.put(DoorHingeSide.class, BlockStatePropertyKeysGenerator.inDataTypePkg("DoorHinge")); vanillaEnumTypeMapping.put(NoteBlockInstrument.class, BlockStatePropertyKeysGenerator.inDataTypePkg("InstrumentType")); vanillaEnumTypeMapping.put(StairsShape.class, BlockStatePropertyKeysGenerator.inDataTypePkg("StairShape")); - vanillaEnumTypeMapping.put(DripstoneThickness.class, BlockStatePropertyKeysGenerator.inDataTypePkg("DripstoneSegment")); + vanillaEnumTypeMapping.put(SpeleothemThickness.class, BlockStatePropertyKeysGenerator.inDataTypePkg("DripstoneSegment")); vanillaEnumTypeMapping.put(FrontAndTop.class, BlockStatePropertyKeysGenerator.inDataTypePkg("JigsawBlockOrientation")); vanillaEnumTypeMapping.put(ComparatorMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("ComparatorMode")); vanillaEnumTypeMapping.put(TrialSpawnerState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("TrialSpawnerState")); diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java index 4f10297e20f..ebd1185f235 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/LevelDataRegistries.java @@ -142,14 +142,6 @@ public static List levelDataRegistries(final Context context) { Registries.PROCESSOR_LIST, $ -> true, RegistryScope.SERVER ), - new RegistryEntriesGenerator<>( - "world.generation.structure.jigsaw", - "ProcessorTypes", - "PROCESSOR_TYPE", - context.relativeClass("world.generation.structure.jigsaw", "ProcessorType"), - Registries.STRUCTURE_PROCESSOR, - $ -> true, RegistryScope.GAME - ), new RegistryEntriesGenerator<>( "world.generation.feature", "PlacedFeatures", diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java index 1a7e8938a0b..6bea11604c9 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java @@ -31,7 +31,7 @@ import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; import net.minecraft.world.level.block.state.properties.CreakingHeartState; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import net.minecraft.world.level.block.state.properties.SideChainPart; @@ -69,7 +69,7 @@ public static List enumRegistries(final Context context) { new EnumEntriesValidator<>( "data.type", "DripstoneSegments", - DripstoneThickness.class, + SpeleothemThickness.class, "getSerializedName", "sponge" ), diff --git a/gradle.properties b/gradle.properties index 4c7950aea78..d9c35d66a6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1.1 +minecraftVersion=26.2-snapshot-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3bc2e0e6f0b..249c41b01e6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -10837,6 +10837,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -11003,6 +11025,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SlimeAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SlimeAccessor.java deleted file mode 100644 index 22edef12b4b..00000000000 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/monster/SlimeAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.accessor.world.entity.monster; - -import net.minecraft.world.entity.monster.Slime; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(Slime.class) -public interface SlimeAccessor { - - @Invoker("setSize") void invoker$setSize(final int size, final boolean resetHealth); - -} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 75037b81f1c..d65e866e657 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -109,7 +109,6 @@ "world.entity.monster.PatrollingMonsterAccessor", "world.entity.monster.PhantomAccessor", "world.entity.monster.RavagerAccessor", - "world.entity.monster.SlimeAccessor", "world.entity.monster.VexAccessor", "world.entity.monster.illager.EvokerAccessor", "world.entity.monster.illager.PillagerAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index c6bd3fc18a1..3a2257ccb70 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -75,7 +75,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DOWN, BlockStateProperties.DOWN); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRAG, BlockStateProperties.DRAG); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIED_GHAST_HYDRATION_LEVELS, BlockStateProperties.DRIED_GHAST_HYDRATION_LEVELS); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIPSTONE_THICKNESS, BlockStateProperties.DRIPSTONE_THICKNESS); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIPSTONE_THICKNESS, BlockStateProperties.SPELEOTHEM_THICKNESS); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DUSTED, BlockStateProperties.DUSTED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.EAST, BlockStateProperties.EAST); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.EAST_REDSTONE, BlockStateProperties.EAST_REDSTONE); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java index a1965961b20..d6c218d3338 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/WoolData.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.data.provider.block.state; -import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.level.block.Block; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.DyeColor; @@ -42,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { .asImmutable(Block.class) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) DyeColorUtil.COLOR_BY_WOOL.get(h)) - .supports(LootData.WOOL_ITEM_BY_DYE::containsValue); + .supports(DyeColorUtil.COLOR_BY_WOOL::containsKey); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/SlimeData.java b/src/main/java/org/spongepowered/common/data/provider/entity/SlimeData.java index 0477f97cded..593101c1cdf 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/SlimeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/SlimeData.java @@ -24,9 +24,8 @@ */ package org.spongepowered.common.data.provider.entity; -import net.minecraft.world.entity.monster.Slime; +import net.minecraft.world.entity.monster.cubemob.Slime; import org.spongepowered.api.data.Keys; -import org.spongepowered.common.accessor.world.entity.monster.SlimeAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; public final class SlimeData { @@ -42,7 +41,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(h -> (double) (0.255F * (float) h.getSize())) .create(Keys.SIZE) .get(h -> h.getSize() - 1) - .set((h, v) -> ((SlimeAccessor) h).invoker$setSize(v + 1, false)); + .set((h, v) -> h.setSize(v + 1, false)); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java index 6ab69a33d37..d4b93d4693c 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/WoolItemStackData.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import org.spongepowered.api.data.Keys; @@ -43,7 +42,7 @@ public static void register(final DataProviderRegistrator registrator) { .asImmutable(ItemStack.class) .create(Keys.DYE_COLOR) .get(h -> (DyeColor) (Object) DyeColorUtil.COLOR_BY_WOOL.get(((BlockItem) h.getItem()).getBlock())) - .supports(h -> h.getItem() instanceof BlockItem && LootData.WOOL_ITEM_BY_DYE.containsValue(((BlockItem) h.getItem()).getBlock())); + .supports(h -> h.getItem() instanceof BlockItem && DyeColorUtil.COLOR_BY_WOOL.containsKey(((BlockItem) h.getItem()).getBlock())); } // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java index dc44611b1c6..cbbcbdde685 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java @@ -24,7 +24,9 @@ */ package org.spongepowered.common.data.provider.world; +import net.minecraft.core.HolderSet; import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.level.block.Block; import net.minecraft.world.attribute.BedRule; import net.minecraft.world.attribute.EnvironmentAttributes; import net.minecraft.world.level.dimension.DimensionType; @@ -67,7 +69,9 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.RESPAWN_ANCHOR_USABLE) .get(d -> d.attributes().applyModifier(EnvironmentAttributes.RESPAWN_ANCHOR_WORKS, false)) .create(Keys.INFINIBURN) - .get(dimensionType -> (Tag) (Object) dimensionType.infiniburn()) + .get(dimensionType -> dimensionType.infiniburn() instanceof HolderSet.Named named + ? (Tag) (Object) named.key() + : null) .create(Keys.WORLD_FLOOR) .get(DimensionType::minY) .create(Keys.HAS_RAIDS) diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index 9fb3feee480..a7c58cdbb52 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -101,6 +101,7 @@ import org.spongepowered.api.world.generation.config.SurfaceRule; import org.spongepowered.api.world.generation.config.flat.LayerConfig; import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPoolElement; +import org.spongepowered.api.world.generation.structure.jigsaw.Processor; import org.spongepowered.api.world.portal.PortalLogic; import org.spongepowered.api.world.schematic.PaletteReference; import org.spongepowered.api.world.server.ServerLocation; @@ -174,6 +175,7 @@ import org.spongepowered.common.world.generation.config.flat.SpongeLayerConfigFactory; import org.spongepowered.common.world.generation.config.noise.SpongeSurfaceRulesFactory; import org.spongepowered.common.world.generation.structure.jigsaw.SpongeJigsawFactory; +import org.spongepowered.common.world.generation.structure.jigsaw.SpongeProcessorFactory; import org.spongepowered.common.world.portal.SpongePortalLogicFactory; import org.spongepowered.common.world.schematic.SpongePaletteReferenceFactory; import org.spongepowered.common.world.server.SpongeServerLocation; @@ -287,6 +289,7 @@ public void registerDefaultFactories() { .registerFactory(DefaultWorldKeys.Factory.class, new SpongeDefaultWorldKeysFactory()) .registerFactory(PositionSource.Factory.class, new SpongePositionSourceFactory()) .registerFactory(JigsawPoolElement.Factory.class, new SpongeJigsawFactory()) + .registerFactory(Processor.Factory.class, new SpongeProcessorFactory()) .registerFactory(ParticleConfig.Factory.class, new SpongeParticleConfigFactory()) .registerFactory(SoundConfig.Factory.class, new SpongeSoundConfigFactory()) .registerFactory(NaturalSpawnCost.Factory.class, new SpongeNaturalSpawnerCostFactory()) diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index aa2f8449fbd..5792a43bf86 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -80,7 +80,7 @@ import net.minecraft.world.level.block.state.properties.ComparatorMode; import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.PistonType; @@ -88,6 +88,7 @@ import net.minecraft.world.level.block.state.properties.RedstoneSide; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; import net.minecraft.world.level.block.state.properties.TestBlockMode; @@ -179,7 +180,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.DIFFICULTY, Difficulty.values()); this.automaticName(RegistryTypes.DYE_COLOR, DyeColor.values()); this.automaticName(RegistryTypes.DOOR_HINGE, DoorHingeSide.values()); - this.automaticName(RegistryTypes.DRIPSTONE_SEGMENT, DripstoneThickness.values()); + this.automaticName(RegistryTypes.DRIPSTONE_SEGMENT, SpeleothemThickness.values()); this.automaticName(RegistryTypes.EQUIPMENT_CONDITION, EquipmentSlotGroup.values()); this.automaticName(RegistryTypes.EQUIPMENT_GROUP, EquipmentSlot.Type.values()); this.automaticName(RegistryTypes.EQUIPMENT_TYPE, EquipmentSlot.values()); diff --git a/src/main/java/org/spongepowered/common/util/DyeColorUtil.java b/src/main/java/org/spongepowered/common/util/DyeColorUtil.java index fa690dafe0b..9d932fcdd55 100644 --- a/src/main/java/org/spongepowered/common/util/DyeColorUtil.java +++ b/src/main/java/org/spongepowered/common/util/DyeColorUtil.java @@ -24,41 +24,31 @@ */ package org.spongepowered.common.util; -import net.minecraft.data.loot.packs.LootData; import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ColorCollection; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; public class DyeColorUtil { - public static final Map COLOR_BY_WOOL = LootData.WOOL_ITEM_BY_DYE.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + public static final Map COLOR_BY_WOOL; - public static Map COLOR_BY_TERRACOTTA = new HashMap<>(); + public static final Map COLOR_BY_TERRACOTTA; static { - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.BLACK_TERRACOTTA, DyeColor.BLACK); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.BLUE_TERRACOTTA, DyeColor.BLUE); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.BROWN_TERRACOTTA, DyeColor.BROWN); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.CYAN_TERRACOTTA, DyeColor.CYAN); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.GRAY_TERRACOTTA, DyeColor.GRAY); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.GREEN_TERRACOTTA, DyeColor.GREEN); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.LIGHT_BLUE_TERRACOTTA, DyeColor.LIGHT_BLUE); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.LIGHT_GRAY_TERRACOTTA, DyeColor.LIGHT_GRAY); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.LIME_TERRACOTTA, DyeColor.LIME); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.MAGENTA_TERRACOTTA, DyeColor.MAGENTA); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.ORANGE_TERRACOTTA, DyeColor.ORANGE); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.PINK_TERRACOTTA, DyeColor.PINK); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.PURPLE_TERRACOTTA, DyeColor.PURPLE); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.RED_TERRACOTTA, DyeColor.RED); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.WHITE_TERRACOTTA, DyeColor.WHITE); - DyeColorUtil.COLOR_BY_TERRACOTTA.put(Blocks.YELLOW_TERRACOTTA, DyeColor.YELLOW); + final Map byWool = new HashMap<>(); + final Map byTerracotta = new HashMap<>(); + final ColorCollection wools = Blocks.WOOL; + final ColorCollection terracottas = Blocks.DYED_TERRACOTTA; + for (final DyeColor color : DyeColor.values()) { + byWool.put(wools.pick(color), color); + byTerracotta.put(terracottas.pick(color), color); + } + COLOR_BY_WOOL = Map.copyOf(byWool); + COLOR_BY_TERRACOTTA = Map.copyOf(byTerracotta); } private DyeColorUtil() { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorTypeMixin_API.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java similarity index 50% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorTypeMixin_API.java rename to src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java index 6a2c6060c27..adae34554b4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorTypeMixin_API.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java @@ -22,37 +22,50 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen.structure.templatesystem; +package org.spongepowered.common.world.generation.structure.jigsaw; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.mojang.serialization.JsonOps; import com.mojang.serialization.MapCodec; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.persistence.DataFormats; import org.spongepowered.api.data.persistence.DataView; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.api.world.generation.structure.jigsaw.Processor; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorType; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.registry.SpongeRegistryHolder; import java.io.IOException; +import java.util.Objects; -@Mixin(StructureProcessorType.class) -public interface StructureProcessorTypeMixin_API

extends ProcessorType { - - // @formatter:off - @Shadow MapCodec

shadow$codec(); - // @formatter:on +public final class SpongeProcessorFactory implements Processor.Factory { @Override - default Processor configure(final DataView dataView) throws IOException { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, SpongeCommon.server().registryAccess()); - final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(dataView)); - final P processor = this.shadow$codec().codec().parse(ops, json).getOrThrow(); + public Processor parse(final RegistryHolder registries, final ResourceKey id, final DataView config) throws IOException { + Objects.requireNonNull(registries, "registries"); + Objects.requireNonNull(id, "id"); + Objects.requireNonNull(config, "config"); + + final SpongeRegistryHolder spongeHolder = (SpongeRegistryHolder) registries; + final HolderLookup.RegistryLookup> lookup = + spongeHolder.lookupOrThrow(Registries.STRUCTURE_PROCESSOR); + + final Identifier identifier = Identifier.fromNamespaceAndPath(id.namespace(), id.value()); + final net.minecraft.resources.ResourceKey> vanillaKey = + net.minecraft.resources.ResourceKey.create(Registries.STRUCTURE_PROCESSOR, identifier); + final MapCodec codec = lookup.get(vanillaKey) + .orElseThrow(() -> new IOException("Unknown structure processor id: " + id)) + .value(); + + final RegistryOps ops = spongeHolder.createSerializationContext(JsonOps.INSTANCE); + final JsonElement json = JsonParser.parseString(DataFormats.JSON.get().write(config)); + final StructureProcessor processor = codec.codec().parse(ops, json).getOrThrow( + message -> new IllegalArgumentException("Failed to parse processor " + id + ": " + message)); return (Processor) processor; } } diff --git a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java index cce6d25e36d..716dd2b5360 100644 --- a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java +++ b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java @@ -25,7 +25,7 @@ package org.spongepowered.common.world.level.chunk.storage; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Tuple; + import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.persistence.DataContainer; @@ -33,6 +33,7 @@ import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.util.AABB; +import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.chunk.EntityChunk; import org.spongepowered.api.world.volume.stream.StreamOptions; import org.spongepowered.api.world.volume.stream.VolumeStream; diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java index 3b417c374a6..a5f5efa8916 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldTypeBuilder.java @@ -113,6 +113,10 @@ public WorldType.Builder from(final WorldType type) { final SpongeDimensionTypes.SpongeDataSection spongeData = new SpongeDimensionTypes.SpongeDataSection(createDragonFight); try { final var clocks = SpongeCommon.vanillaRegistry(Registries.WORLD_CLOCK); + final var blocks = SpongeCommon.vanillaRegistry(Registries.BLOCK); + final HolderSet infiniburnSet = infiniburn == null + ? HolderSet.empty() + : blocks.get(((TagBridge) infiniburn).bridge$asVanillaTag()).map(h -> (HolderSet) h).orElse(HolderSet.empty()); final var attributes = EnvironmentAttributeMap.builder(); attributes.set(EnvironmentAttributes.PIGLINS_ZOMBIFY, !piglinSafe); attributes.set(EnvironmentAttributes.BED_RULE, bedsUsable ? BedRule.CAN_SLEEP_WHEN_DARK : BedRule.EXPLODES); @@ -128,7 +132,7 @@ public WorldType.Builder from(final WorldType type) { floor, height, logicalHeight, - ((TagBridge) infiniburn).bridge$asVanillaTag(), + infiniburnSet, ambientLighting, new DimensionType.MonsterSettings(monsterSpawnLightTest, monsterSpawnBlockLightLimit), DimensionType.Skybox.OVERWORLD, diff --git a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java index b319501bd5f..ed374b62afa 100644 --- a/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java +++ b/src/main/java/org/spongepowered/common/world/volume/VolumeStreamUtils.java @@ -33,9 +33,9 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.ProblemReporter; -import net.minecraft.util.Tuple; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; @@ -58,6 +58,7 @@ import org.spongepowered.api.block.entity.BlockEntity; import org.spongepowered.api.block.entity.BlockEntityArchetype; import org.spongepowered.api.entity.EntityArchetype; +import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.volume.Volume; import org.spongepowered.api.world.volume.game.Region; import org.spongepowered.api.world.volume.stream.StreamOptions; @@ -120,7 +121,7 @@ public static org.spongepowered.api.registry.Registry nativeToSpongeR return (org.spongepowered.api.registry.Registry) registry; } - public static Predicate> entityArchetypePositionFilter(final Vector3i min, final Vector3i max) { + public static Predicate> entityArchetypePositionFilter(final Vector3i min, final Vector3i max) { return VolumeStreamUtils.filterPositions(tuple -> tuple.first().toInt(), min, max); } @@ -253,7 +254,7 @@ public static BiConsumer getOrCloneEnti cloned, () -> String.format( "EntityType[%s] creates a null Entity!", - net.minecraft.world.entity.EntityType.getKey(entity.getType()) + EntityType.getKey(entity.getType()) ) ).load(input); backingVolume.spawnEntity((org.spongepowered.api.entity.Entity) cloned); @@ -623,8 +624,8 @@ private static SpongeVolumeSt // without consideration, assuming the MC variant is always mixed in to implement the API variant. // Then constructs the VolumeElement final Function, VolumeElement> elementGenerator = (tuple) -> { - final Supplier blockEntitySupplier = VolumeStreamUtils.createWeaklyReferencedSupplier((API) tuple.getB(), "Element"); - final Vector3d blockEntityPos = VecHelper.toVector3d(tuple.getA()); + final Supplier blockEntitySupplier = VolumeStreamUtils.createWeaklyReferencedSupplier((API) tuple.second(), "Element"); + final Vector3d blockEntityPos = VecHelper.toVector3d(tuple.first()); return VolumeElement.of(worldSupplier, blockEntitySupplier, blockEntityPos); }; // Fairly trivial, but just acts as a filter and provides the set of filtered references back to the `poses` @@ -668,7 +669,7 @@ private static SpongeVolumeSt final Stream> volumeStreamBacker = filteredPosStream .map(pos -> filteredPositionEntityAccessor.apply(pos, worldSupplier.get())) .filter(Objects::nonNull) - .filter(tuple -> Objects.nonNull(tuple.getB())) + .filter(tuple -> Objects.nonNull(tuple.first())) .map(elementGenerator); return new SpongeVolumeStream<>(volumeStreamBacker, worldSupplier); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FlyingAnimalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FlyingAnimalMixin_API.java deleted file mode 100644 index 0d566309c56..00000000000 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/FlyingAnimalMixin_API.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; - -import net.minecraft.world.entity.animal.FlyingAnimal; -import org.spongepowered.api.entity.Aerial; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(FlyingAnimal.class) -public interface FlyingAnimalMixin_API extends Aerial { -} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SlimeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/AbstractCubeMobMixin_API.java similarity index 89% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SlimeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/AbstractCubeMobMixin_API.java index d856a84805a..f23b15ced43 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/SlimeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/AbstractCubeMobMixin_API.java @@ -22,18 +22,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.cubemob; +import net.minecraft.world.entity.monster.cubemob.AbstractCubeMob; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.entity.living.slime.Slime; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.common.mixin.api.minecraft.world.entity.MobMixin_API; +import org.spongepowered.common.mixin.api.minecraft.world.entity.AgeableMobMixin_API; import java.util.Set; -@Mixin(net.minecraft.world.entity.monster.Slime.class) -public abstract class SlimeMixin_API extends MobMixin_API implements Slime { +@Mixin(AbstractCubeMob.class) +public abstract class AbstractCubeMobMixin_API extends AgeableMobMixin_API { @Override protected Set> api$getVanillaValues() { @@ -44,5 +44,4 @@ public abstract class SlimeMixin_API extends MobMixin_API implements Slime { return values; } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/MagmaCubeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/MagmaCubeMixin_API.java similarity index 88% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/MagmaCubeMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/MagmaCubeMixin_API.java index 201e358d58b..bdb88e2f1ba 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/MagmaCubeMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/MagmaCubeMixin_API.java @@ -22,12 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity.monster; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.cubemob; import org.spongepowered.api.entity.living.slime.MagmaCube; import org.spongepowered.asm.mixin.Mixin; -@Mixin(net.minecraft.world.entity.monster.MagmaCube.class) -public abstract class MagmaCubeMixin_API extends SlimeMixin_API implements MagmaCube { +@Mixin(net.minecraft.world.entity.monster.cubemob.MagmaCube.class) +public abstract class MagmaCubeMixin_API extends AbstractCubeMobMixin_API implements MagmaCube { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/SlimeMixin_API.java similarity index 85% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/SlimeMixin_API.java index 3c61c8a2d3a..d9095d7f370 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/FlyingAnimalMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/monster/cubemob/SlimeMixin_API.java @@ -22,13 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.entity; +package org.spongepowered.common.mixin.api.minecraft.world.entity.monster.cubemob; -import net.minecraft.world.entity.animal.FlyingAnimal; -import org.spongepowered.api.entity.Aerial; +import org.spongepowered.api.entity.living.slime.Slime; import org.spongepowered.asm.mixin.Mixin; -@Mixin(FlyingAnimal.class) -public interface FlyingAnimalMixin_API extends Aerial { +@Mixin(net.minecraft.world.entity.monster.cubemob.Slime.class) +public abstract class SlimeMixin_API extends AbstractCubeMobMixin_API implements Slime { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java index 0b531f48042..960546ec774 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java @@ -32,7 +32,6 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.util.ProblemReporter; -import net.minecraft.util.Tuple; import net.minecraft.world.level.BlockAndLightGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -57,6 +56,7 @@ import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.util.AABB; +import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.HeightTypes; import org.spongepowered.api.world.LightType; import org.spongepowered.api.world.Location; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java index 6daaeeea2f3..66250438b89 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/AbstractFurnaceBlockEntityMixin_API.java @@ -42,10 +42,10 @@ public abstract class AbstractFurnaceBlockEntityMixin_API extends BaseContainerBlockEntityMixin_API implements FurnaceBlockEntity { // @formatter:off - @Shadow int litTimeRemaining; - @Shadow int litTotalTime; - @Shadow int cookingTimer; - @Shadow int cookingTotalTime; + @Shadow private int litTimeRemaining; + @Shadow private int litTotalTime; + @Shadow private int cookingTimer; + @Shadow private int cookingTotalTime; @Shadow protected NonNullList items; // @formatter:on diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BeaconBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BeaconBlockEntityMixin_API.java index a4eee2d4265..2ed2b94ae21 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BeaconBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BeaconBlockEntityMixin_API.java @@ -41,9 +41,9 @@ public abstract class BeaconBlockEntityMixin_API extends BlockEntityMixin_API implements Beacon { // @formatter:off - @Shadow int levels; - @Shadow @Nullable Holder primaryPower; - @Shadow @Nullable Holder secondaryPower; + @Shadow private int levels; + @Shadow private @Nullable Holder primaryPower; + @Shadow private @Nullable Holder secondaryPower; // @formatter:on @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/DripstoneThicknessMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/SpeleothemThicknessMixin_API.java similarity index 88% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/DripstoneThicknessMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/SpeleothemThicknessMixin_API.java index 59f0823a809..58dd924adaf 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/DripstoneThicknessMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/SpeleothemThicknessMixin_API.java @@ -24,11 +24,11 @@ */ package org.spongepowered.common.mixin.api.minecraft.world.level.block.state.properties; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import org.spongepowered.api.data.type.DripstoneSegment; import org.spongepowered.asm.mixin.Mixin; -@Mixin(DripstoneThickness.class) -public abstract class DripstoneThicknessMixin_API implements DripstoneSegment { +@Mixin(SpeleothemThickness.class) +public abstract class SpeleothemThicknessMixin_API implements DripstoneSegment { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java index 7234ed4c606..8e51115c4cb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/chunk/LevelChunkMixin_API.java @@ -28,7 +28,6 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Tuple; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ChunkPos; @@ -59,6 +58,7 @@ import org.spongepowered.api.util.AABB; import org.spongepowered.api.util.PositionOutOfBoundsException; import org.spongepowered.api.util.Ticks; +import org.spongepowered.api.util.Tuple; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.api.world.HeightTypes; import org.spongepowered.api.world.WorldLike; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java index 7962c30de34..b0858f95717 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/DensityFunctionMixin_API.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.api.minecraft.world.level.levelgen; import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.DensityFunctions; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; @@ -65,6 +66,6 @@ default double compute(final int x, final int y, final int z) { @Override default Optional toDataPack(final RegistryHolder registryHolder) { - return DataPackUtil.toDataContainer(registryHolder, DensityFunction.DIRECT_CODEC, (DensityFunction) this); + return DataPackUtil.toDataContainer(registryHolder, DensityFunctions.DIRECT_CODEC, (DensityFunction) this); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorMixin_API.java index c30a3c57d88..9b100459ba5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/levelgen/structure/templatesystem/StructureProcessorMixin_API.java @@ -26,13 +26,14 @@ import com.google.gson.JsonElement; import com.mojang.serialization.JsonOps; -import net.minecraft.resources.RegistryOps; +import com.mojang.serialization.MapCodec; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataFormats; import org.spongepowered.api.world.generation.structure.jigsaw.Processor; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeCommon; @@ -40,25 +41,35 @@ import java.io.IOException; @Mixin(StructureProcessor.class) -public abstract class StructureProcessorMixin_API implements Processor { +public interface StructureProcessorMixin_API extends Processor { // @formatter:off - @Shadow protected abstract

StructureProcessorType

shadow$getType(); + @Shadow MapCodec codec(); // @formatter:on @Override - public ProcessorType type() { - return (ProcessorType) this.shadow$getType(); + @SuppressWarnings({"unchecked", "rawtypes"}) + default ResourceKey type() { + final Identifier api$location = SpongeCommon.server().registryAccess() + .lookupOrThrow(Registries.STRUCTURE_PROCESSOR) + .getKey((MapCodec) this.codec()); + if (api$location == null) { + throw new IllegalStateException("Processor codec is not registered: " + this.codec()); + } + return (ResourceKey) (Object) api$location; } @Override - public DataContainer toContainer() { - final RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, SpongeCommon.server().registryAccess()); - final JsonElement serialized = this.shadow$getType().codec().codec().encodeStart(ops, (StructureProcessor) (Object) this).getOrThrow(); + @SuppressWarnings({"unchecked", "rawtypes"}) + default DataContainer toContainer() { + final MapCodec api$codec = this.codec(); + final JsonElement api$serialized = (JsonElement) api$codec.codec() + .encodeStart(SpongeCommon.server().registryAccess().createSerializationContext(JsonOps.INSTANCE), this) + .getOrThrow(); try { - return DataFormats.JSON.get().read(serialized.toString()); - } catch (IOException e) { - throw new IllegalStateException("Could not read deserialized Processor:\n" + serialized, e); + return DataFormats.JSON.get().read(api$serialized.toString()); + } catch (final IOException e) { + throw new IllegalStateException("Could not read deserialized Processor:\n" + api$serialized, e); } } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index 23d069ba04b..1dd9c81c207 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -100,7 +100,7 @@ public MinecraftMixin(String param0) { this.impl$temporaryIntegratedServer = server; } - @Inject(method = "destroy", at = @At("HEAD")) + @Inject(method = "exitWorldAndClose()V", at = @At("HEAD")) private void impl$callStoppingEngineEvent(CallbackInfo ci) { Launch.instance().lifecycle().callStoppingEngineEvent(this); } @@ -112,8 +112,8 @@ public MinecraftMixin(String param0) { this.singleplayerServer = null; } - @Inject(method = "disconnect", at = @At("TAIL")) - private void impl$nullServerRefAndPhaseTracker(Screen screenIn, boolean keepResourcePacks, CallbackInfo ci) { + @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;ZZ)V", at = @At("TAIL")) + private void impl$nullServerRefAndPhaseTracker(Screen screenIn, boolean keepResourcePacks, boolean stopSound, CallbackInfo ci) { ((MinecraftBridge) this).bridge$setTemporaryIntegratedServer(null); try { PhaseTracker.getServerInstanceExplicitly().setThread(null); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/selector/EntitySelectorParserMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/selector/EntitySelectorParserMixin.java index 1f2aeff13da..24bef2ecac7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/selector/EntitySelectorParserMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/commands/arguments/selector/EntitySelectorParserMixin.java @@ -105,7 +105,7 @@ public abstract class EntitySelectorParserMixin implements EntitySelectorParserB return this.reader; } - @Inject(method = "allowSelectors", at = @At("HEAD"), cancellable = true) + @Inject(method = "allowSelectors(Ljava/lang/Object;)Z", at = @At("HEAD"), cancellable = true) private static void impl$onAllowSelectors(final S $$0, final CallbackInfoReturnable cir) { if ($$0 instanceof final CommandCause cause && cause.hasPermission(Constants.Permissions.SELECTOR_PERMISSION)) { cir.setReturnValue(true); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java index 0cbb1ce6fc6..72564fc5f55 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/arrow/AbstractArrowMixin.java @@ -57,7 +57,7 @@ public abstract class AbstractArrowMixin extends ProjectileMixin implements Abst @Shadow @Nullable private BlockState lastState; @Shadow public abstract void shadow$setCritArrow(boolean critical); - @Shadow public abstract void shadow$setPierceLevel(byte level); + @Shadow protected abstract void shadow$setPierceLevel(byte level); @Shadow protected abstract ItemStack shadow$getPickupItem(); @Shadow protected abstract void resetPiercedEntities(); @Shadow protected abstract void shadow$setInGround(boolean $$0); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java index 9b956c758fa..edb7e765228 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/ItemStackMixin.java @@ -122,7 +122,7 @@ public abstract class ItemStackMixin implements SpongeDataHolderBridge, DataComp } } - @Inject(method = "set", at = @At("RETURN")) + @Inject(method = "set(Lnet/minecraft/core/component/DataComponentType;Ljava/lang/Object;)Ljava/lang/Object;", at = @At("RETURN")) private void impl$onSetCustomData(final DataComponentType type, final T value, final CallbackInfoReturnable cir) { if (type.equals(DataComponents.CUSTOM_DATA)) { this.bridge$clear(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/dedicated/DedicatedServerMixin_IpForward.java b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/dedicated/DedicatedServerMixin_IpForward.java index 0daac1911ad..41a68e38868 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/dedicated/DedicatedServerMixin_IpForward.java +++ b/src/mixins/java/org/spongepowered/common/mixin/ipforward/server/dedicated/DedicatedServerMixin_IpForward.java @@ -42,7 +42,7 @@ public class DedicatedServerMixin_IpForward { @Shadow @Final - static Logger LOGGER; + private static Logger LOGGER; @Inject(method = "initServer", at = @At(value = "INVOKE_STRING", remap = false, target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;)V", args = "ldc=**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java index 2998a1d126e..8560b7f254d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java @@ -47,7 +47,7 @@ @Mixin(ChunkMap.class) public abstract class ChunkMapMixin_Tracker { - @Shadow @Final ServerLevel level; + @Shadow @Final private ServerLevel level; @Redirect(method = "addEntity(Lnet/minecraft/world/entity/Entity;)V", at = @At(value = "NEW", args = "class=java/lang/IllegalStateException", remap = false)) diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index e709ca9aede..56b21e9975d 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -107,7 +107,6 @@ "minecraft.world.entity.EntityMixin_API", "minecraft.world.entity.EntityTypeMixin_API", "minecraft.world.entity.ExperienceOrbMixin_API", - "minecraft.world.entity.FlyingAnimalMixin_API", "minecraft.world.entity.HumanoidArmMixin_API", "minecraft.world.entity.InteractionMixin_API", "minecraft.world.entity.LeashableMixin_API", @@ -156,7 +155,6 @@ "minecraft.world.entity.animal.fish.CodMixin_API", "minecraft.world.entity.animal.cow.CowVariantMixin_API", "minecraft.world.entity.animal.dolphin.DolphinMixin_API", - "minecraft.world.entity.animal.FlyingAnimalMixin_API", "minecraft.world.entity.animal.fox.Fox_VariantMixin_API", "minecraft.world.entity.animal.fox.FoxMixin_API", "minecraft.world.entity.animal.frog.FrogVariantMixin_API", @@ -241,7 +239,8 @@ "minecraft.world.entity.monster.GhastMixin_API", "minecraft.world.entity.monster.GiantMixin_API", "minecraft.world.entity.monster.GuardianMixin_API", - "minecraft.world.entity.monster.MagmaCubeMixin_API", + "minecraft.world.entity.monster.cubemob.AbstractCubeMobMixin_API", + "minecraft.world.entity.monster.cubemob.MagmaCubeMixin_API", "minecraft.world.entity.monster.MonsterMixin_API", "minecraft.world.entity.monster.PatrollingMonsterMixin_API", "minecraft.world.entity.monster.Phantom_AttackPhaseMixin_API", @@ -250,7 +249,7 @@ "minecraft.world.entity.monster.RavagerMixin_API", "minecraft.world.entity.monster.ShulkerMixin_API", "minecraft.world.entity.monster.SilverfishMixin_API", - "minecraft.world.entity.monster.SlimeMixin_API", + "minecraft.world.entity.monster.cubemob.SlimeMixin_API", "minecraft.world.entity.monster.StriderMixin_API", "minecraft.world.entity.monster.VexMixin_API", "minecraft.world.entity.monster.WitchMixin_API", @@ -455,7 +454,7 @@ "minecraft.world.level.block.state.properties.ChestTypeMixin_API", "minecraft.world.level.block.state.properties.ComparatorModeMixin_API", "minecraft.world.level.block.state.properties.DoorHingeSideMixin_API", - "minecraft.world.level.block.state.properties.DripstoneThicknessMixin_API", + "minecraft.world.level.block.state.properties.SpeleothemThicknessMixin_API", "minecraft.world.level.block.state.properties.FrontAndTopMixin_API", "minecraft.world.level.block.state.properties.HalfMixin_API", "minecraft.world.level.block.state.properties.NoteBlockInstrumentMixin_API", @@ -510,7 +509,6 @@ "minecraft.world.level.levelgen.structure.pools.StructureTemplatePoolMixin_API", "minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorListMixin_API", "minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorMixin_API", - "minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorTypeMixin_API", "minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateMixin_API", "minecraft.world.level.material.FluidMixin_API", "minecraft.world.level.material.FluidStateMixin_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java b/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java index 16633b8653d..840756c8bfe 100644 --- a/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/worldgen/StructureTest.java @@ -55,7 +55,7 @@ import org.spongepowered.api.world.generation.structure.jigsaw.JigsawPools; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorList; import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorLists; -import org.spongepowered.api.world.generation.structure.jigsaw.ProcessorTypes; +import org.spongepowered.api.world.generation.structure.jigsaw.Processors; import org.spongepowered.api.world.server.ServerLocation; import java.io.IOException; @@ -248,8 +248,12 @@ private CommandResult listProcessors(final CommandContext ctx, final Parameter.V ctx.sendMessage(Identity.nil(), Component.text("Processor Types:", NamedTextColor.DARK_AQUA)); - ProcessorTypes.registry().streamEntries().filter(e -> invert == e.key().toString().toUpperCase().contains(filter)) - .forEach(e -> ctx.sendMessage(Identity.nil(), Component.text(" - " + e.key(), NamedTextColor.GRAY))); + java.util.stream.Stream.of( + Processors.BLACKSTONE_REPLACE, Processors.BLOCK_AGE, Processors.BLOCK_IGNORE, Processors.BLOCK_ROT, + Processors.CAPPED, Processors.GRAVITY, Processors.JIGSAW_REPLACEMENT, Processors.LAVA_SUBMERGED_BLOCK, + Processors.NOP, Processors.PROTECTED_BLOCKS, Processors.RULE) + .filter(k -> invert == k.toString().toUpperCase().contains(filter)) + .forEach(k -> ctx.sendMessage(Identity.nil(), Component.text(" - " + k, NamedTextColor.GRAY))); return CommandResult.success(); } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java index b6324a6a4ae..c867bcee6f6 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java @@ -97,7 +97,7 @@ protected void init() { // Add the 'Done' button this.addRenderableWidget(Button.builder(Component.translatable(I18n.get("gui.done")), - b -> Minecraft.getInstance().setScreen(this.previousScreen)) + b -> Minecraft.getInstance().setScreenAndShow(this.previousScreen)) .pos(this.width / 2 - 50, this.height - 40) .size(100, 20) .build()); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/gui/screens/TitleScreenMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/gui/screens/TitleScreenMixin_Vanilla.java index 22dcc76be2b..9f51567f48d 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/gui/screens/TitleScreenMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/client/gui/screens/TitleScreenMixin_Vanilla.java @@ -57,7 +57,7 @@ protected TitleScreenMixin_Vanilla(final Component titleIn) { // Plugins Button this.addRenderableWidget(Button.builder(Component.literal("Plugins"), - b -> this.minecraft.setScreen(new PluginScreen(this))) + b -> this.minecraft.setScreenAndShow(new PluginScreen(this))) .pos(this.width / 2 - 100, realmsButton.map(b -> b.getY()).orElse(0)) .size(98, 20) .build()); From 431c42bc5d87a87d59825dc3a75f55c8323a99ad Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 16:54:19 -0700 Subject: [PATCH 503/586] fix(common): bypass scoped holder for LEVEL_STEM registry access --- src/main/java/org/spongepowered/common/hooks/WorldHooks.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java index 1fd42fb015c..132b4bca4d9 100644 --- a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java @@ -48,6 +48,9 @@ default void postLoadWorld(ServerLevel world) { } default void preUnloadWorld(ServerLevel world) { } default Registry earlyRegistryAccess(ResourceKey> levelStem) { - return SpongeCommon.vanillaRegistry(levelStem); + // LEVEL_STEM lives in the server's composite registryAccess() but not in Sponge's scoped + // holder (which excludes DIMENSION_REGISTRIES during RegistryDataLoader processing), so we + // must bypass SpongeCommon.vanillaRegistry() and hit server().registryAccess() directly. + return SpongeCommon.server().registryAccess().lookupOrThrow(levelStem); } } From 0469dc9995afbaa516125028bff03627551afe42 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 17:28:02 -0700 Subject: [PATCH 504/586] feat(minecraft): update to 26.1.2 Signed-off-by: Gabriel Harris-Rouquette --- forge/gradle.properties | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 51 ++++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index e0f7d7f05e3..19b01c841c4 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=63.0.0 +forgeVersion=64.0.1 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle.properties b/gradle.properties index 4c7950aea78..5d4cba47a53 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.1.1 +minecraftVersion=26.1.2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3bc2e0e6f0b..ebcbf89633b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5249,6 +5249,11 @@ + + + + + @@ -5438,6 +5443,11 @@ + + + + + @@ -5627,6 +5637,11 @@ + + + + + @@ -5800,6 +5815,11 @@ + + + + + @@ -6034,6 +6054,11 @@ + + + + + @@ -6231,6 +6256,11 @@ + + + + + @@ -6428,6 +6458,11 @@ + + + + + @@ -7158,6 +7193,17 @@ + + + + + + + + + + + @@ -7192,6 +7238,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 4704264d8be..2f4cc0e84d9 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.1.1.1-beta +neoForgeVersion=26.1.2.7-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 38b385a98309178751d8b680f68f93ca77c81e03 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 17:37:24 -0700 Subject: [PATCH 505/586] fix(mixin): correct shadow return type for CachedUserNameToIdResolver#get The shadow for get(UUID) still declared Optional from the pre-1.21.10 signature. The actual method now returns Optional, causing a ClassCastException at runtime when findById mapped the result through SpongeGameProfile::of. Signed-off-by: Gabriel Harris-Rouquette --- .../minecraft/server/players/GameProfileCacheMixin_API.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java index c109b5c9ea2..8c37e2c95f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/players/GameProfileCacheMixin_API.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; +import net.minecraft.server.players.NameAndId; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.api.profile.GameProfileCache; @@ -57,7 +58,7 @@ public abstract class GameProfileCacheMixin_API implements GameProfileCache { @Shadow @Final @Mutable private final Map profilesByName = new ConcurrentHashMap<>(); @Shadow @Final @Mutable private final Map profilesByUUID = new ConcurrentHashMap<>(); - @Shadow public abstract Optional shadow$get(UUID uniqueId); + @Shadow public abstract Optional shadow$get(UUID uniqueId); @Shadow protected abstract long shadow$getNextOperation(); // @formatter:on From df98cd6644ba655b2eba5abcc3bdd4c1b6fa6757 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 17:54:41 -0700 Subject: [PATCH 506/586] fix(minecraft): follow-up fixes for 26.2-snapshot-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHANGED: - Import ordering fixes (SpeleothemThickness alphabetized across generators) - BlockStateKeys.DRIPSTONE_THICKNESS → SPELEOTHEM_THICKNESS - VanillaRegistryLoader unused SpeleothemThickness import removed - Whitespace/import cleanup in WorldTypeData, SpongeProcessorFactory, SpongeEntityChunk FIX: - WorldHooks.earlyRegistryAccess bypasses SpongeCommon.vanillaRegistry() for LEVEL_STEM See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_1 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../vanilla/generator/BlockStatePropertiesGenerator.java | 2 +- .../vanilla/generator/BlockStatePropertyKeysGenerator.java | 2 +- .../vanilla/generator/world/level/block/BlockRegistries.java | 2 +- .../data/provider/block/state/BlockStateDataProvider.java | 2 +- .../common/data/provider/world/WorldTypeData.java | 2 +- src/main/java/org/spongepowered/common/hooks/WorldHooks.java | 5 ++++- .../common/registry/loader/VanillaRegistryLoader.java | 1 - .../generation/structure/jigsaw/SpongeProcessorFactory.java | 2 +- .../common/world/level/chunk/storage/SpongeEntityChunk.java | 1 - 10 files changed, 11 insertions(+), 10 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 2adc06b5838..375585d25f4 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 2adc06b583818eed7c346f230fcf996231440506 +Subproject commit 375585d25f4e5f0edaf440a05383c97ceea9217b diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java index 8fa528f8892..a0f6566e833 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertiesGenerator.java @@ -48,7 +48,6 @@ import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.IntegerProperty; @@ -60,6 +59,7 @@ import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import net.minecraft.world.level.block.state.properties.SideChainPart; import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; import net.minecraft.world.level.block.state.properties.TestBlockMode; diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index a8545583915..dc6e693eb38 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -49,7 +49,6 @@ import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.IntegerProperty; @@ -61,6 +60,7 @@ import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import net.minecraft.world.level.block.state.properties.SideChainPart; import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.StairsShape; import net.minecraft.world.level.block.state.properties.StructureMode; import net.minecraft.world.level.block.state.properties.TestBlockMode; diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java index 6bea11604c9..8ebfca0004f 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/world/level/block/BlockRegistries.java @@ -31,10 +31,10 @@ import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; import net.minecraft.world.level.block.state.properties.BambooLeaves; import net.minecraft.world.level.block.state.properties.CreakingHeartState; -import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import net.minecraft.world.level.block.state.properties.SideChainPart; +import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.TestBlockMode; import net.minecraft.world.level.block.state.properties.Tilt; import org.spongepowered.vanilla.generator.BlockStateDataProviderGenerator; diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index 3a2257ccb70..a6008a81c34 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -75,7 +75,6 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DOWN, BlockStateProperties.DOWN); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRAG, BlockStateProperties.DRAG); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIED_GHAST_HYDRATION_LEVELS, BlockStateProperties.DRIED_GHAST_HYDRATION_LEVELS); - BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DRIPSTONE_THICKNESS, BlockStateProperties.SPELEOTHEM_THICKNESS); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.DUSTED, BlockStateProperties.DUSTED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.EAST, BlockStateProperties.EAST); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.EAST_REDSTONE, BlockStateProperties.EAST_REDSTONE); @@ -147,6 +146,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SOUTH, BlockStateProperties.SOUTH); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SOUTH_REDSTONE, BlockStateProperties.SOUTH_REDSTONE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SOUTH_WALL, BlockStateProperties.SOUTH_WALL); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.SPELEOTHEM_THICKNESS, BlockStateProperties.SPELEOTHEM_THICKNESS); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.STABILITY_DISTANCE, BlockStateProperties.STABILITY_DISTANCE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.STAGE, BlockStateProperties.STAGE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.STAIRS_SHAPE, BlockStateProperties.STAIRS_SHAPE); diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java index cbbcbdde685..f520c45e1fd 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldTypeData.java @@ -26,9 +26,9 @@ import net.minecraft.core.HolderSet; import net.minecraft.util.valueproviders.IntProvider; -import net.minecraft.world.level.block.Block; import net.minecraft.world.attribute.BedRule; import net.minecraft.world.attribute.EnvironmentAttributes; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.dimension.DimensionType; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockType; diff --git a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java index 1fd42fb015c..132b4bca4d9 100644 --- a/src/main/java/org/spongepowered/common/hooks/WorldHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/WorldHooks.java @@ -48,6 +48,9 @@ default void postLoadWorld(ServerLevel world) { } default void preUnloadWorld(ServerLevel world) { } default Registry earlyRegistryAccess(ResourceKey> levelStem) { - return SpongeCommon.vanillaRegistry(levelStem); + // LEVEL_STEM lives in the server's composite registryAccess() but not in Sponge's scoped + // holder (which excludes DIMENSION_REGISTRIES during RegistryDataLoader processing), so we + // must bypass SpongeCommon.vanillaRegistry() and hit server().registryAccess() directly. + return SpongeCommon.server().registryAccess().lookupOrThrow(levelStem); } } diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 5792a43bf86..5d0eb67b2b2 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -80,7 +80,6 @@ import net.minecraft.world.level.block.state.properties.ComparatorMode; import net.minecraft.world.level.block.state.properties.CreakingHeartState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; -import net.minecraft.world.level.block.state.properties.SpeleothemThickness; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.PistonType; diff --git a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java index adae34554b4..729f4bbd1ca 100644 --- a/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/structure/jigsaw/SpongeProcessorFactory.java @@ -30,8 +30,8 @@ import com.mojang.serialization.MapCodec; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; import net.minecraft.resources.Identifier; +import net.minecraft.resources.RegistryOps; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.persistence.DataFormats; diff --git a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java index 716dd2b5360..6e67938b9db 100644 --- a/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java +++ b/src/main/java/org/spongepowered/common/world/level/chunk/storage/SpongeEntityChunk.java @@ -25,7 +25,6 @@ package org.spongepowered.common.world.level.chunk.storage; import net.minecraft.server.level.ServerLevel; - import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.persistence.DataContainer; From 04fd068c5c2ac46fba2ef88408daffa044276677 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 18:07:55 -0700 Subject: [PATCH 507/586] chore(gradle): update verification Signed-off-by: Gabriel Harris-Rouquette --- gradle/verification-metadata.xml | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 0588af7d814..ecc7c96a5ae 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -10889,23 +10889,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -11077,12 +11101,24 @@ + + + + + + + + + + + + From e6ea5b7132dd80a36719195dc12b7f66d2a1100d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 12 Apr 2026 19:29:09 -0700 Subject: [PATCH 508/586] fix(data): DyeColor bridge for ColorCollection blocks Vanilla 26.2 introduced ColorCollection to bulk-register dye-colored blocks using mapColor(MapColor) instead of mapColor(DyeColor). The existing PropertiesMixin hook never fires, leaving DyeColorBlockBridge unpopulated. ColorCollectionMixin injects at registerBlocks() RETURN to stamp the bridge on all 16 blocks per collection. Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- .../level/block/ColorCollectionMixin.java | 58 +++++++++++++++++++ src/mixins/resources/mixins.sponge.core.json | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java diff --git a/SpongeAPI b/SpongeAPI index 375585d25f4..972e9ee68ae 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 375585d25f4e5f0edaf440a05383c97ceea9217b +Subproject commit 972e9ee68ae5ece2a0f6c800571bb6781881f09e diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java new file mode 100644 index 00000000000..2d5cbf450fa --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java @@ -0,0 +1,58 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.level.block; + +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ColorCollection; +import net.minecraft.world.level.block.state.BlockBehaviour; +import org.apache.commons.lang3.function.TriFunction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.bridge.block.DyeColorBlockBridge; + +import java.util.function.BiFunction; +import java.util.function.Function; + +@Mixin(ColorCollection.class) +public abstract class ColorCollectionMixin { + + @Inject(method = "registerBlocks", at = @At("RETURN")) + private static void impl$stampDyeColor( + final String id, + final TriFunction, BlockBehaviour.Properties, Block> register, + final BiFunction colorBlockFactory, + final Function propertiesSupplier, + final CallbackInfoReturnable> cir + ) { + final ColorCollection collection = cir.getReturnValue(); + for (final DyeColor color : DyeColor.values()) { + ((DyeColorBlockBridge) collection.pick(color)) + .bridge$setDyeColor((org.spongepowered.api.data.type.DyeColor) (Object) color); + } + } +} diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index e97eddf179d..d9c24b6b5cd 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -231,6 +231,7 @@ "world.level.block.BaseFireBlockMixin", "world.level.block.CactusBlockMixin", "world.level.block.CampfireBlockMixin", + "world.level.block.ColorCollectionMixin", "world.level.block.CarvedPumpkinBlockMixin", "world.level.block.CommandBlockMixin", "world.level.block.EndPortalBlockMixin", From 3d339b5dd67c2a4ad4b1663ed73b3749393acd0d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 13 Apr 2026 20:16:16 -0700 Subject: [PATCH 509/586] fix(recipes): handle Neo changed RecipeManager --- .../mixins.spongeforge.core.shared.json | 3 +- .../item/crafting/RecipeManagerMixin_Neo.java | 68 +++++++++++++++++++ .../resources/mixins.spongeneo.core.json | 1 + .../item/crafting/RecipeManagerMixin.java | 30 -------- .../crafting/RecipeManagerMixin_Shared.java | 67 ++++++++++++++++++ .../mixins.spongevanilla.core.shared.json | 3 +- 6 files changed, 140 insertions(+), 32 deletions(-) create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_Neo.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin_Shared.java diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json index 5afc6cf65b6..00b0a290898 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.shared.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.shared.json @@ -6,7 +6,8 @@ "mixins": [ "world.entity.LivingEntityMixin_Shared_Damage", "world.entity.player.PlayerMixin_Shared_Damage", - "world.entity.projectile.FishingHookMixin_Shared" + "world.entity.projectile.FishingHookMixin_Shared", + "world.item.crafting.RecipeManagerMixin_Shared" ], "overwrites": { "conformVisibility": true diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_Neo.java new file mode 100644 index 00000000000..0ab4a8efa59 --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_Neo.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.world.item.crafting; + +import com.google.gson.JsonElement; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import net.minecraft.resources.FileToIdConverter; +import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeManager; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.RegistryHolderLogic; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.function.Consumer; +import java.util.stream.Stream; + +@Mixin(RecipeManager.class) +public abstract class RecipeManagerMixin_Neo { + + @SuppressWarnings("unchecked") + @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/world/item/crafting/RecipeMap;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectoryWithModifier(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;Ljava/util/function/Consumer;)V")) + private void impl$onPrepare(final ResourceManager $$0, final FileToIdConverter $$1, final DynamicOps $$2, final Codec> $$3, + final Map> $$4, final Consumer> $$5, final Operation original) { + SortedMap> result = new TreeMap<>(); + original.call($$0, $$1, $$2, $$3, result, $$5); + final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$0).registryHolder(); + final Registry> registry = (Registry>) (Object) registryHolder.registry(RegistryTypes.RECIPE); + result.forEach((k, v) -> registry.register((org.spongepowered.api.ResourceKey) (Object) k, v)); + Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$0, Stream.of(registry)); + registry.streamEntries().forEach(e -> $$4.put((Identifier) (Object) e.key(), e.value())); + } +} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index 1f6a819a953..effa93814ee 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -37,6 +37,7 @@ "world.entity.projectile.FishingHookMixin_Neo", "world.entity.vehicle.boat.AbstractBoatMixin_Neo", "world.level.ServerExplosionMixin_NeoForge", + "world.item.crafting.RecipeManagerMixin_Neo", "world.level.block.FireBlockMixin_Neo", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" ], diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java index 15907a1612b..6a88a92d0e8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin.java @@ -24,35 +24,18 @@ */ package org.spongepowered.common.mixin.core.world.item.crafting; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import net.minecraft.core.HolderLookup; -import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; -import org.spongepowered.api.registry.Registry; -import org.spongepowered.api.registry.RegistryHolder; -import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.common.launch.Launch; -import org.spongepowered.common.registry.RegistryHolderLogic; -import org.spongepowered.common.registry.SpongeRegistryHolder; - -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.stream.Stream; @Mixin(RecipeManager.class) public abstract class RecipeManagerMixin { @@ -77,17 +60,4 @@ public abstract class RecipeManagerMixin { return parsed; } - @SuppressWarnings("unchecked") - @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/world/item/crafting/RecipeMap;", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V")) - private void impl$onPrepare(final ResourceManager $$0, final FileToIdConverter $$1, final DynamicOps $$2, final Codec> $$3, - final Map> $$4, final Operation original) { - SortedMap> result = new TreeMap<>(); - original.call($$0, $$1, $$2, $$3, result); - final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$0).registryHolder(); - final Registry> registry = (Registry>) (Object) registryHolder.registry(RegistryTypes.RECIPE); - result.forEach((k, v) -> registry.register((org.spongepowered.api.ResourceKey) (Object) k, v)); - Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$0, Stream.of(registry)); - registry.streamEntries().forEach(e -> $$4.put((Identifier) (Object) e.key(), e.value())); - } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin_Shared.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin_Shared.java new file mode 100644 index 00000000000..2601d91e40c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/item/crafting/RecipeManagerMixin_Shared.java @@ -0,0 +1,67 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.world.item.crafting; + +import com.google.gson.JsonElement; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import net.minecraft.resources.FileToIdConverter; +import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeManager; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.registry.RegistryHolderLogic; +import org.spongepowered.common.registry.SpongeRegistryHolder; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.stream.Stream; + +@Mixin(RecipeManager.class) +public abstract class RecipeManagerMixin_Shared { + + @SuppressWarnings("unchecked") + @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/world/item/crafting/RecipeMap;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V")) + private void impl$onPrepare(final ResourceManager $$0, final FileToIdConverter $$1, final DynamicOps $$2, final Codec> $$3, + final Map> $$4, final Operation original) { + SortedMap> result = new TreeMap<>(); + original.call($$0, $$1, $$2, $$3, result); + final RegistryHolderLogic registryHolder = ((SpongeRegistryHolder) $$0).registryHolder(); + final Registry> registry = (Registry>) (Object) registryHolder.registry(RegistryTypes.RECIPE); + result.forEach((k, v) -> registry.register((org.spongepowered.api.ResourceKey) (Object) k, v)); + Launch.instance().lifecycle().processServerRegistries((RegistryHolder) $$0, Stream.of(registry)); + registry.streamEntries().forEach(e -> $$4.put((Identifier) (Object) e.key(), e.value())); + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json index 5afc6cf65b6..00b0a290898 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.shared.json @@ -6,7 +6,8 @@ "mixins": [ "world.entity.LivingEntityMixin_Shared_Damage", "world.entity.player.PlayerMixin_Shared_Damage", - "world.entity.projectile.FishingHookMixin_Shared" + "world.entity.projectile.FishingHookMixin_Shared", + "world.item.crafting.RecipeManagerMixin_Shared" ], "overwrites": { "conformVisibility": true From f77f7620ed3dd8a3bbcae8af29124efe1f211d88 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 13 Apr 2026 20:20:45 -0700 Subject: [PATCH 510/586] feat(minecraft): update to 26.2-snapshot-2 See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_2 --- gradle.properties | 2 +- .../mixin/api/minecraft/world/effect/MobEffectMixin_API.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index d9c35d66a6b..3513127c920 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-1 +minecraftVersion=26.2-snapshot-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/effect/MobEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/effect/MobEffectMixin_API.java index 11c63c2219c..7a0cd508b9b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/effect/MobEffectMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/effect/MobEffectMixin_API.java @@ -39,12 +39,12 @@ public abstract class MobEffectMixin_API implements PotionEffectType { // @formatter:off - @Shadow public abstract boolean shadow$isInstantenous(); + @Shadow public abstract boolean shadow$isInstantaneous(); @Shadow public abstract net.minecraft.network.chat.Component shadow$getDisplayName(); // @formatter:on public boolean potionEffectType$isInstant() { - return this.shadow$isInstantenous(); + return this.shadow$isInstantaneous(); } @Override From f3e5dd55264c9f56e2eea16409a6bd6146d73172 Mon Sep 17 00:00:00 2001 From: Vilperi221 <58680173+Vilsu221@users.noreply.github.com> Date: Tue, 14 Apr 2026 23:54:43 +0300 Subject: [PATCH 511/586] Fix world border issues and cleanup (#4280) * Fix teleport helper * Fix WORLD_BORDER key & remove old per-world border Vanilla now implements per-world world border * Fix world border saving * Apply spotless * Revert SpongeWorldManager & cleanup * Clear legacy world border after load * Improve world border tests --- .../level/storage/ServerLevelDataBridge.java | 10 +++ .../provider/world/WorldPropertiesData.java | 5 +- .../world/server/SpongeWorldManager.java | 1 + .../world/teleport/SpongeTeleportHelper.java | 2 +- .../server/level/ServerLevelMixin_API.java | 2 +- .../core/server/level/ServerLevelMixin.java | 5 +- .../storage/DimensionDataStorageMixin.java | 2 +- .../common/world/border/WorldBorderTest.java | 74 +++++++++++++++++++ 8 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/test/java/org/spongepowered/common/world/border/WorldBorderTest.java diff --git a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java index 9780ca08df2..832f24b3199 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/level/storage/ServerLevelDataBridge.java @@ -38,6 +38,7 @@ import org.spongepowered.api.Sponge; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.bridge.world.level.border.WorldBorderBridge; import org.spongepowered.common.world.server.SpongeServerLevelData; import org.spongepowered.common.world.server.SpongeWorldManager; @@ -127,6 +128,15 @@ public interface ServerLevelDataBridge { return Optional.empty(); } + default @Nullable WorldBorderBridge bridge$worldBorder() { + final ServerLevel level = this.bridge$level(); + if (level != null) { + return (WorldBorderBridge) level.getWorldBorder(); + } + + return null; + } + default void bridge$triggerViewDistanceLogic() { final ServerLevel level = this.bridge$level(); if (level != null) { diff --git a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java index 2969efd9ec0..78f3519d419 100644 --- a/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java +++ b/src/main/java/org/spongepowered/common/data/provider/world/WorldPropertiesData.java @@ -35,7 +35,6 @@ import org.spongepowered.api.entity.living.player.gamemode.GameMode; import org.spongepowered.api.world.SerializationBehavior; import org.spongepowered.api.world.WorldType; -import org.spongepowered.api.world.border.WorldBorder; import org.spongepowered.api.world.difficulty.Difficulty; import org.spongepowered.api.world.generation.config.WorldGenerationConfig; import org.spongepowered.api.world.server.WorldArchetype; @@ -78,8 +77,6 @@ public static void register(final DataProviderRegistrator registrator) { .get(ServerLevelData::isAllowCommands) .create(Keys.INITIALIZED) .get(ServerLevelData::isInitialized) - .create(Keys.WORLD_BORDER) - .get(h -> (WorldBorder) (Object) h.getLegacyWorldBorderSettings().orElse(null)) .create(Keys.WEATHER) .get(SpongeWeather::of) .set(SpongeWeather::apply) @@ -100,6 +97,8 @@ public static void register(final DataProviderRegistrator registrator) { .get(ServerLevelDataBridge::bridge$loadOnStartup) .create(Keys.WORLD_ARCHETYPE_TYPE) .get(h -> (WorldArchetypeType) (Object) h.bridge$levelStem()) + .create(Keys.WORLD_BORDER) + .get(h -> h.bridge$worldBorder().bridge$asImmutable()) .asMutable(PrimaryLevelData.class) .create(Keys.WORLD_DIFFICULTY) .set((h, v) -> h.setDifficulty((net.minecraft.world.Difficulty) (Object) v)) diff --git a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java index bde5675f5aa..bc9366c2314 100644 --- a/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java +++ b/src/main/java/org/spongepowered/common/world/server/SpongeWorldManager.java @@ -933,6 +933,7 @@ private ServerLevel createLevel( // Ensure that the world border is registered. levelData.getLegacyWorldBorderSettings().ifPresent(world.getWorldBorder()::applySettings); + levelData.setLegacyWorldBorderSettings(Optional.empty()); PlatformHooks.INSTANCE.getWorldHooks().postLoadWorld(world); return world; } diff --git a/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java b/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java index 133a5af1c62..8388ba229da 100644 --- a/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java +++ b/src/main/java/org/spongepowered/common/world/teleport/SpongeTeleportHelper.java @@ -73,7 +73,7 @@ public Optional findSafeLocation(ServerLocation location, int he private Stream getBlockLocations(ServerLocation worldLocation, int height, int width) { // We don't want to warp outside of the world border, so we want to check that we're within it. - final WorldBorder.Settings worldBorder = (WorldBorder.Settings) (Object) worldLocation.world().properties().worldBorder(); + final WorldBorder.Settings worldBorder = (WorldBorder.Settings) (Object) worldLocation.world().border(); final double radius = worldBorder.size() / 2.0D; int worldBorderMinX = GenericMath.floor(worldBorder.centerX() - radius); int worldBorderMinZ = GenericMath.floor(worldBorder.centerZ() - radius); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java index 9adc9c0b625..dfce0c9ff0c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/server/level/ServerLevelMixin_API.java @@ -345,7 +345,7 @@ public WorldBorder setBorder(final WorldBorder border) { if (worldBorder == null) { return (WorldBorder) (Object) net.minecraft.world.level.border.WorldBorder.Settings.DEFAULT; } - this.serverLevelData.setLegacyWorldBorderSettings(Optional.of((net.minecraft.world.level.border.WorldBorder.Settings) (Object) border)); + return worldBorder; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 2a3fcf9770e..745a85ebd52 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -63,7 +63,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity; -import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.end.EndDragonFight; @@ -375,9 +374,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel if (behavior != SerializationBehavior.NONE) { original.call(self, flush); - // per-world WorldInfo/WorldBorder/BossBars - final var border = this.getWorldBorder(); - levelData.setLegacyWorldBorderSettings(Optional.of(new WorldBorder.Settings(border))); + // per-world WorldInfo/BossBars if (levelData instanceof WorldData worldData) { worldData.setCustomBossEvents(this.bridge$getBossBarManager().save(SpongeCommon.server().registryAccess())); this.bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), worldData, this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java index 9f440bdaa14..bb5d3a67a99 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/storage/DimensionDataStorageMixin.java @@ -57,7 +57,7 @@ public T readSpongeMapData( DataUtil.syncTagToData(dch); dch.data$setCompound(null); } - return null; + return result; } @Override diff --git a/src/test/java/org/spongepowered/common/world/border/WorldBorderTest.java b/src/test/java/org/spongepowered/common/world/border/WorldBorderTest.java new file mode 100644 index 00000000000..2cc37d67283 --- /dev/null +++ b/src/test/java/org/spongepowered/common/world/border/WorldBorderTest.java @@ -0,0 +1,74 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.world.border; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.world.DefaultWorldKeys; +import org.spongepowered.api.world.border.WorldBorder; +import org.spongepowered.api.world.server.ServerWorld; + +public class WorldBorderTest { + + @Test + public void testBorderIsApplied() { + final ServerWorld world = Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); + final WorldBorder worldBorder = world.border(); + final WorldBorder border = WorldBorder.builder().center(1, 1).initialDiameter(1).build(); + + try { + world.setBorder(border); + + Assertions.assertEquals(border, world.border()); + } finally { + world.setBorder(worldBorder); + } + } + + @Test + public void testBorderIsWorldSpecific() { + final ServerWorld world = Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get(); + final ServerWorld nether = Sponge.server().worldManager().world(DefaultWorldKeys.THE_NETHER).get(); + + final WorldBorder worldBorder = world.border(); + final WorldBorder worldBorderNether = nether.border(); + + final WorldBorder border = WorldBorder.builder().center(1, 1).initialDiameter(1).build(); + final WorldBorder netherBorder = WorldBorder.builder().center(2, 2).initialDiameter(2).build(); + + try { + world.setBorder(border); + nether.setBorder(netherBorder); + + Assertions.assertEquals(border, world.border()); + Assertions.assertEquals(netherBorder, nether.border()); + } finally { + world.setBorder(worldBorder); + nether.setBorder(worldBorderNether); + } + } + +} From 623ff4ea853c984776207d3ce63bd38196b2f8bb Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 15 Apr 2026 19:45:02 -0700 Subject: [PATCH 512/586] feat(minecraft): update to 26.2-snapshot-3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHANGED: - Advancement criterion triggers refactored (CriterionTrigger_ListenerMixin → SimpleCriterionTriggerMixin) - EntityTypeAccessor removed, EntityTypesMixin_Tracker added - BlockEntityTypeMixin_Tracker → BlockEntityTypesMixin_Tracker - BedBlockEntityMixin_API removed (bed no longer a block entity) - AirItemMixin_API added - Generator BlockStateDataProvider targets Sponge impl source set instead of SpongeAPI FIX: - DecoratedPotData, SignItemStackData, BlockTypeItemStackData updated for API changes - ColorCollectionMixin, HumanEntity, SpongeViewableInventoryBuilder compilation fixes See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_3 Signed-off-by: Gabriel Harris-Rouquette --- SpongeAPI | 2 +- generator/build.gradle.kts | 3 +- .../BlockStateDataProviderGenerator.java | 59 +++++++++----- .../vanilla/generator/Context.java | 25 +++++- .../vanilla/generator/GeneratorMain.java | 11 +-- gradle.properties | 2 +- gradle/verification-metadata.xml | 5 ++ .../CriteriaTriggersAccessor.java | 4 +- .../item/AdventureModePredicateAccessor.java | 2 +- .../resources/mixins.sponge.accessors.json | 1 - .../advancement/SpongeAdvancementBuilder.java | 2 +- .../advancement/SpongeCriterionTrigger.java | 42 ++++------ .../criterion/SpongeCriterionBuilder.java | 4 +- .../criterion/SpongeDummyTrigger.java | 6 +- .../criterion/SpongeScoreCriterion.java | 4 +- .../SpongeScoreCriterionBuilder.java | 2 +- .../criterion/SpongeScoreTrigger.java | 6 +- .../block/entity/DecoratedPotData.java | 14 +++- .../block/state/BlockStateDataProvider.java | 12 +-- .../item/stack/BlockTypeItemStackData.java | 2 +- .../item/stack/SignItemStackData.java | 4 +- .../entity/living/human/HumanEntity.java | 5 +- .../SpongeViewableInventoryBuilder.java | 4 +- .../common/util/SpongeCriterionUtil.java | 2 +- .../advancements/AdvancementMixin_API.java | 2 +- .../advancements/CriterionMixin_API.java | 4 +- .../CriterionTriggerMixin_API.java | 2 +- .../EntitySelectorParserMixin_API.java | 2 +- .../api/minecraft/item/AirItemMixin_API.java} | 25 +++--- .../minecraft/item/BlockItemMixin_API.java | 3 +- .../core/advancements/AdvancementMixin.java | 2 +- .../advancements/CriteriaTriggersMixin.java | 4 +- .../core/advancements/CriterionMixin.java | 4 +- ....java => SimpleCriterionTriggerMixin.java} | 77 +++++++++---------- .../core/server/level/ServerLevelMixin.java | 12 +-- .../core/server/level/ServerPlayerMixin.java | 2 +- .../level/block/ColorCollectionMixin.java | 8 +- .../world/entity/EntityTypeMixin_Tracker.java | 18 ----- .../entity/EntityTypesMixin_Tracker.java | 53 +++++++++++++ .../entity/BlockEntityTypeMixin_Tracker.java | 17 ---- .../BlockEntityTypesMixin_Tracker.java} | 35 +++++---- src/mixins/resources/mixins.sponge.api.json | 2 +- src/mixins/resources/mixins.sponge.core.json | 2 +- .../resources/mixins.sponge.tracker.json | 2 + 44 files changed, 282 insertions(+), 217 deletions(-) rename src/{accessors/java/org/spongepowered/common/accessor/world/entity/EntityTypeAccessor.java => mixins/java/org/spongepowered/common/mixin/api/minecraft/item/AirItemMixin_API.java} (63%) rename src/mixins/java/org/spongepowered/common/mixin/core/advancements/{CriterionTrigger_ListenerMixin.java => SimpleCriterionTriggerMixin.java} (66%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypesMixin_Tracker.java rename src/mixins/java/org/spongepowered/common/mixin/{api/minecraft/world/level/block/entity/BedBlockEntityMixin_API.java => tracker/world/level/block/entity/BlockEntityTypesMixin_Tracker.java} (50%) diff --git a/SpongeAPI b/SpongeAPI index 972e9ee68ae..2d153e8bff5 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 972e9ee68ae5ece2a0f6c800571bb6781881f09e +Subproject commit 2d153e8bff54b3a5e52970168635b356337b34de diff --git a/generator/build.gradle.kts b/generator/build.gradle.kts index da7ca6bedc2..47243f5c0d4 100644 --- a/generator/build.gradle.kts +++ b/generator/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { } val apiBase = rootProject.file("SpongeAPI/src/main/java/") +val implBase = rootProject.file("src/main/java/") val temporaryLicenseHeader = project.layout.buildDirectory.file("api-gen-license-header.txt") tasks.register("generateApiData", JavaExec::class) { group = "sponge" @@ -30,7 +31,7 @@ tasks.register("generateApiData", JavaExec::class) { classpath(sourceSets.main.map { it.output }, sourceSets.main.map { it.runtimeClasspath }) mainClass.set("org.spongepowered.vanilla.generator.GeneratorMain") - args(apiBase.canonicalPath, temporaryLicenseHeader.get().asFile.canonicalPath) + args(apiBase.canonicalPath, implBase.canonicalPath, temporaryLicenseHeader.get().asFile.canonicalPath) doFirst { // Write a template-expanded license header to the temporary file diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStateDataProviderGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStateDataProviderGenerator.java index a425ff28353..7c3de34d2d0 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStateDataProviderGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStateDataProviderGenerator.java @@ -24,11 +24,14 @@ */ package org.spongepowered.vanilla.generator; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.Property; +import org.tinylog.Logger; import java.io.IOException; import java.lang.reflect.Field; @@ -37,10 +40,9 @@ import java.util.TreeSet; import java.util.stream.Collectors; -import javax.lang.model.element.Modifier; - /** - * Generates the registration of catalog classes for {@link BlockState} properties. + * Updates the register method of the {@code BlockStateDataProvider} in the Sponge implementation + * source set with the current set of {@link BlockState} properties. */ public class BlockStateDataProviderGenerator implements Generator { @@ -51,25 +53,44 @@ public String name() { @Override public void generate(Context ctx) throws IOException { - final var clazz = Types.utilityClass( - "BlockStateDataProvider", - "" - ); + final var cu = ctx.implCompilationUnit("data.provider.block.state", "BlockStateDataProvider"); + final var primaryType = cu.getPrimaryType() + .orElseThrow(() -> new IllegalStateException("Could not find primary type in BlockStateDataProvider")); + + final var registerMethod = primaryType.getMembers().stream() + .filter(m -> m instanceof MethodDeclaration) + .map(m -> (MethodDeclaration) m) + .filter(m -> m.getNameAsString().equals("register")) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Could not find register method in BlockStateDataProvider")); + + final var body = registerMethod.getBody() + .orElseThrow(() -> new IllegalStateException("register method has no body")); - final var codeBlock = CodeBlock.builder(); + // Collect all non-registerProperty statements (e.g. the trailing registrator.asImmutable block) + final var trailingStatements = body.getStatements().stream() + .filter(stmt -> { + if (stmt instanceof ExpressionStmt es) { + return !es.toString().contains("registerProperty"); + } + return true; + }) + .toList(); + + // Rebuild the body: registerProperty calls first, then trailing statements + final var newBody = new BlockStmt(); for (final String property : this.vanillaProperties()) { - codeBlock.addStatement("BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.$L, BlockStateProperties.$L)", property, property); + newBody.addStatement(StaticJavaParser.parseStatement( + "BlockStateDataProvider.registerProperty(registrator, BlockStateKeys." + property + ", BlockStateProperties." + property + ");" + )); + } + for (final var stmt : trailingStatements) { + newBody.addStatement(stmt.clone()); } - clazz.addMethod(MethodSpec.methodBuilder("register") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addCode(codeBlock.build()) - .build() - ); - - ctx.write("data", clazz.build()); + registerMethod.setBody(newBody); - final var cu = ctx.compilationUnit("data", "BlockStateDataProvider"); + Logger.info("Updated BlockStateDataProvider.register() with {} property registrations", this.vanillaProperties().size()); } private Set vanillaProperties() { diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java index 2fcecf82f13..0ad96749f19 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/Context.java @@ -47,23 +47,30 @@ public final class Context { static final String INDENT = " "; static final String BASE_PACKAGE = "org.spongepowered.api"; + static final String IMPL_BASE_PACKAGE = "org.spongepowered.common"; private final Path outputDirectory; + private final Path implOutputDirectory; private final RegistryAccess registries; private final ReloadableServerResources resources; private final String licenseHeader; private final SourceRoot sourceRoot; + private final SourceRoot implSourceRoot; - Context(final Path outputDirectory, final RegistryAccess registries, final ReloadableServerResources resources, final String licenseHeader) { + Context(final Path outputDirectory, final Path implOutputDirectory, final RegistryAccess registries, final ReloadableServerResources resources, final String licenseHeader) { this.outputDirectory = outputDirectory; + this.implOutputDirectory = implOutputDirectory; this.registries = registries; this.resources = resources; this.licenseHeader = licenseHeader; - this.sourceRoot = new SourceRoot(outputDirectory); - this.sourceRoot.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_16); final var config = new DefaultPrinterConfiguration(); config.addOption(new DefaultConfigurationOption(DefaultPrinterConfiguration.ConfigOption.PRINT_COMMENTS, true)); final var printer = new DefaultPrettyPrinter(config); + this.sourceRoot = new SourceRoot(outputDirectory); + this.sourceRoot.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_16); this.sourceRoot.setPrinter(printer::print); + this.implSourceRoot = new SourceRoot(implOutputDirectory); + this.implSourceRoot.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_16); + this.implSourceRoot.setPrinter(printer::print); } public String gameVersion() { @@ -94,6 +101,17 @@ public CompilationUnit compilationUnit(final String relativePackage, final Strin } } + public CompilationUnit implCompilationUnit(final String relativePackage, final String simpleName) { + final String pkg = relativePackage.isBlank() ? Context.IMPL_BASE_PACKAGE : String.join(".", Context.IMPL_BASE_PACKAGE, relativePackage); + try { + final CompilationUnit unit = this.implSourceRoot.parse(pkg, simpleName + ".java"); + LexicalPreservingPrinter.setup(unit); + return unit; + } catch (Exception e) { + throw new RuntimeException("Failed to parse " + simpleName + ".java", e); + } + } + /** * Write the provided type to a file in the defined base package. * @@ -140,5 +158,6 @@ public void write(final String relativePackage, final TypeSpec spec) throws IOEx */ void complete() { this.sourceRoot.saveAll(StandardCharsets.UTF_8); + this.implSourceRoot.saveAll(StandardCharsets.UTF_8); } } diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java index 5c3b120971b..a0bb52beb13 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/GeneratorMain.java @@ -74,13 +74,13 @@ private GeneratorMain() { /** * The entry point. * - * @param args arguments, expected to be {@code } + * @param args arguments, expected to be {@code } */ public static void main(final String[] args) { Logger.info("Begining bootstrap"); Log.setAdapter(new JavaparserLog()); - if (args.length != 2) { - Logger.error("Invalid arguments. Usage: generator "); + if (args.length != 3) { + Logger.error("Invalid arguments. Usage: generator "); System.exit(1); return; } @@ -91,8 +91,9 @@ public static void main(final String[] args) { // Create a generator context based on arguments final var outputDir = Path.of(args[0]); + final var implOutputDir = Path.of(args[1]); final String licenseHeader; - try (final var reader = Files.newBufferedReader(Path.of(args[1]), StandardCharsets.UTF_8)) { + try (final var reader = Files.newBufferedReader(Path.of(args[2]), StandardCharsets.UTF_8)) { licenseHeader = reader.lines().map(line -> (" * " + line).stripTrailing()).collect(Collectors.joining("\n", "\n", "\n ")); } catch (final IOException ex) { Logger.error("Failed to read license header file!", ex); @@ -101,7 +102,7 @@ public static void main(final String[] args) { } final var dataPacks = GeneratorMain.loadVanillaDatapack(); - final var context = new Context(outputDir, dataPacks.getFirst(), dataPacks.getSecond(), licenseHeader); + final var context = new Context(outputDir, implOutputDir, dataPacks.getFirst(), dataPacks.getSecond(), licenseHeader); Logger.info("Generating data for Minecraft version {}", context.gameVersion()); // Execute every generator diff --git a/gradle.properties b/gradle.properties index 3513127c920..fe856ee9273 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-2 +minecraftVersion=26.2-snapshot-3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ecc7c96a5ae..b483698ef6d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2047,6 +2047,11 @@ + + + + + diff --git a/src/accessors/java/org/spongepowered/common/accessor/advancements/CriteriaTriggersAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/advancements/CriteriaTriggersAccessor.java index d0a55751335..2236ca8c735 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/advancements/CriteriaTriggersAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/advancements/CriteriaTriggersAccessor.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.accessor.advancements; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.triggers.CriteriaTriggers; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.common.UntransformedInvokerError; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java index 7026e5ee36d..e325ffc4287 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java +++ b/src/accessors/java/org/spongepowered/common/accessor/world/item/AdventureModePredicateAccessor.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.accessor.world.item; -import net.minecraft.advancements.criterion.BlockPredicate; +import net.minecraft.advancements.predicates.BlockPredicate; import net.minecraft.world.item.AdventureModePredicate; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index d65e866e657..1890a4bd7ab 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -66,7 +66,6 @@ "world.entity.Display_TextDisplayAccessor", "world.entity.DisplayAccessor", "world.entity.EntityAccessor", - "world.entity.EntityTypeAccessor", "world.entity.ExperienceOrbAccessor", "world.entity.InteractionAccessor", "world.entity.LightningBoltAccessor", diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java index b4705b771cc..9cbc1bfc97f 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeAdvancementBuilder.java @@ -27,7 +27,7 @@ import net.minecraft.advancements.AdvancementRequirements; import net.minecraft.advancements.AdvancementRewards; -import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.triggers.Criterion; import net.minecraft.core.ClientAsset; import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/src/main/java/org/spongepowered/common/advancement/SpongeCriterionTrigger.java b/src/main/java/org/spongepowered/common/advancement/SpongeCriterionTrigger.java index e0274ba1d3c..e9013096422 100644 --- a/src/main/java/org/spongepowered/common/advancement/SpongeCriterionTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/SpongeCriterionTrigger.java @@ -24,15 +24,13 @@ */ package org.spongepowered.common.advancement; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; import com.google.gson.JsonObject; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import io.leangen.geantyref.TypeToken; -import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.triggers.CriterionTrigger; import net.minecraft.server.PlayerAdvancements; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; @@ -51,6 +49,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; @@ -59,7 +58,6 @@ public class SpongeCriterionTrigger implements CriterionTrigger constructor; - private final Multimap listeners = HashMultimap.create(); final @Nullable Consumer eventHandler; private final String name; @@ -88,34 +86,26 @@ public String getName() { return this.name; } - @Override - public void addPlayerListener(final PlayerAdvancements playerAdvancementsIn, final Listener listener) { - this.listeners.put(playerAdvancementsIn, listener); - } - - @Override - public void removePlayerListener(final PlayerAdvancements playerAdvancementsIn, final Listener listener) { - this.listeners.remove(playerAdvancementsIn, listener); - } - - @Override - public void removePlayerListeners(final PlayerAdvancements playerAdvancementsIn) { - this.listeners.removeAll(playerAdvancementsIn); - } - @Override public void bridge$trigger(final ServerPlayer player) { - final PlayerAdvancements playerAdvancements = ((net.minecraft.server.level.ServerPlayer) player).getAdvancements(); + final net.minecraft.server.level.ServerPlayer mcPlayer = (net.minecraft.server.level.ServerPlayer) player; + final PlayerAdvancements playerAdvancements = mcPlayer.getAdvancements(); + final Map map = playerAdvancements.getTriggerMapForType(this); + if (map == null || map.isEmpty()) { + return; + } final Cause cause = PhaseTracker.getInstance().currentCause(); @SuppressWarnings("unchecked") // correct type verified in builder final TypeToken typeToken = (TypeToken) TypeToken.get(this.triggerConfigurationType); - for (final Listener listener : new ArrayList<>(this.listeners.get(playerAdvancements))) { - final var advancement = listener.advancement().value(); - final var advancementKey = (ResourceKey) (Object) listener.advancement().id(); - final AdvancementCriterion advancementCriterion = (AdvancementCriterion) (Object) advancement.criteria().get(listener.criterion()); + for (final var entry : new ArrayList<>(map.entrySet())) { + final PlayerAdvancements.TriggerInstanceKey key = entry.getKey(); + final SpongeFilteredTrigger triggerInstance = entry.getValue(); + final var advancement = key.advancement().value(); + final var advancementKey = (ResourceKey) (Object) key.advancement().id(); + final AdvancementCriterion advancementCriterion = (AdvancementCriterion) (Object) advancement.criteria().get(key.criterion()); final CriterionEvent.Trigger event = SpongeEventFactory.createCriterionEventTrigger(cause, (Advancement) (Object) advancement, advancementKey, advancementCriterion, - typeToken, player, (FilteredTrigger) listener.trigger(), (Trigger) advancementCriterion.type().get(), this.eventHandler == null); + typeToken, player, (FilteredTrigger) triggerInstance, (Trigger) advancementCriterion.type().get(), this.eventHandler == null); if (this.eventHandler != null) { this.eventHandler.accept(event); if (!event.result()) { @@ -124,7 +114,7 @@ public void removePlayerListeners(final PlayerAdvancements playerAdvancementsIn) } SpongeCommon.post(event); if (event.result()) { - listener.run(playerAdvancements); + playerAdvancements.award(key.advancement(), key.criterion()); } } } diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeCriterionBuilder.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeCriterionBuilder.java index 828ff5367e3..0c896960f8b 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeCriterionBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeCriterionBuilder.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.advancement.criterion; -import net.minecraft.advancements.Criterion; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.Criterion; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.common.bridge.advancements.CriterionBridge; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java index 67edf73cbb9..1fef191cd35 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeDummyTrigger.java @@ -26,9 +26,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.advancements.criterion.ContextAwarePredicate; -import net.minecraft.advancements.criterion.EntityPredicate; -import net.minecraft.advancements.criterion.SimpleCriterionTrigger; +import net.minecraft.advancements.predicates.ContextAwarePredicate; +import net.minecraft.advancements.predicates.entity.EntityPredicate; +import net.minecraft.advancements.triggers.SimpleCriterionTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterion.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterion.java index 07a662214e8..9e01ff1a742 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterion.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterion.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.advancement.criterion; -import net.minecraft.advancements.Criterion; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.Criterion; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.advancement.criteria.ScoreAdvancementCriterion; import org.spongepowered.api.advancement.criteria.trigger.FilteredTrigger; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterionBuilder.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterionBuilder.java index e549893269a..d3da6d0c322 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterionBuilder.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreCriterionBuilder.java @@ -25,8 +25,8 @@ package org.spongepowered.common.advancement.criterion; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.spongepowered.api.advancement.criteria.ScoreAdvancementCriterion; import org.spongepowered.common.util.Preconditions; diff --git a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java index dc748afd4ee..9463e33f4a3 100644 --- a/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java +++ b/src/main/java/org/spongepowered/common/advancement/criterion/SpongeScoreTrigger.java @@ -26,9 +26,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.advancements.criterion.ContextAwarePredicate; -import net.minecraft.advancements.criterion.EntityPredicate; -import net.minecraft.advancements.criterion.SimpleCriterionTrigger; +import net.minecraft.advancements.predicates.ContextAwarePredicate; +import net.minecraft.advancements.predicates.entity.EntityPredicate; +import net.minecraft.advancements.triggers.SimpleCriterionTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/DecoratedPotData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/DecoratedPotData.java index 9a91cf6e1fe..0dec24a2483 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/DecoratedPotData.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/DecoratedPotData.java @@ -24,6 +24,8 @@ */ package org.spongepowered.common.data.provider.block.entity; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity; @@ -36,10 +38,19 @@ import org.spongepowered.common.accessor.world.level.block.entity.DecoratedPotBlockEntityAccessor; import org.spongepowered.common.data.provider.DataProviderRegistrator; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; public final class DecoratedPotData { + private static final Set> POTTERY_SHERD_ITEMS; + static { + final Set> set = new HashSet<>(); + DecoratedPotPatterns.itemToPatternMappings((itemKey, patternKey) -> set.add(itemKey)); + POTTERY_SHERD_ITEMS = Set.copyOf(set); + } + public static void register(final DataProviderRegistrator registrator) { // @formatter:off registrator.asMutable(DecoratedPotBlockEntity.class) @@ -67,7 +78,8 @@ static boolean setPotDirection(DecoratedPotBlockEntity h, PotDirection direction h.setChanged(); return true; } - if (DecoratedPotPatterns.getPatternFromItem((Item) v) == null) { + final var itemKey = BuiltInRegistries.ITEM.getResourceKey((Item) v).orElse(null); + if (itemKey == null || !POTTERY_SHERD_ITEMS.contains(itemKey)) { return false; } var current = h.getDecorations(); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index a6008a81c34..8fb4dc75f65 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -164,20 +164,12 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.WEST, BlockStateProperties.WEST); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.WEST_REDSTONE, BlockStateProperties.WEST_REDSTONE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.WEST_WALL, BlockStateProperties.WEST_WALL); - registrator.asImmutable(BlockState.class) - .create(Keys.PUSH_REACTION) - .get(h -> (PushReaction) (Object) h.getPistonPushReaction()); + registrator.asImmutable(BlockState.class).create(Keys.PUSH_REACTION).get(h -> (PushReaction) (Object) h.getPistonPushReaction()); } // @formatter:off private static , V extends Comparable> void registerProperty(final DataProviderRegistrator registrator, final Key> key, final Property property) { - - registrator.asImmutable(BlockState.class) - .create(key) - .supports(bs -> bs.getOptionalValue(property).isPresent()) - .get(bs -> ((org.spongepowered.api.block.BlockState) bs).stateProperty((StateProperty) property).orElse(null)) - .set((bs, v) -> (BlockState) ((org.spongepowered.api.block.BlockState) bs).withStateProperty((StateProperty) property, v).orElse((org.spongepowered.api.block.BlockState) bs)); + registrator.asImmutable(BlockState.class).create(key).supports(bs -> bs.getOptionalValue(property).isPresent()).get(bs -> ((org.spongepowered.api.block.BlockState) bs).stateProperty((StateProperty) property).orElse(null)).set((bs, v) -> (BlockState) ((org.spongepowered.api.block.BlockState) bs).withStateProperty((StateProperty) property, v).orElse((org.spongepowered.api.block.BlockState) bs)); } // @formatter:on - } diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java index c211b0513b3..70d663a2569 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/BlockTypeItemStackData.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.data.provider.item.stack; -import net.minecraft.advancements.criterion.BlockPredicate; +import net.minecraft.advancements.predicates.BlockPredicate; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponentType; diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java index 162d919118f..2bad6745879 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/SignItemStackData.java @@ -31,7 +31,7 @@ import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.TypedEntityData; -import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.BlockEntityTypes; import net.minecraft.world.level.block.entity.SignText; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.Keys; @@ -88,7 +88,7 @@ public static void register(final DataProviderRegistrator registrator) { .resultOrPartial(SpongeCommon.logger()::error) .ifPresent($$1x -> tag.put("front_text", $$1x)); - h.set(DataComponents.BLOCK_ENTITY_DATA, TypedEntityData.of(BlockEntityType.SIGN, tag)); + h.set(DataComponents.BLOCK_ENTITY_DATA, TypedEntityData.of(BlockEntityTypes.SIGN, tag)); }) .delete(h -> h.remove(DataComponents.BLOCK_ENTITY_DATA)); } diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 1e562c7e0d6..5351b9fe901 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -56,6 +56,7 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.PathfinderMob; @@ -310,7 +311,7 @@ protected void tickHeadTurn(final float p_110146_1_) { @Override protected HoverEvent createHoverEvent() { - return new HoverEvent.ShowEntity(new HoverEvent.EntityTooltipInfo(EntityType.PLAYER, this.getUUID(), this.getName())); + return new HoverEvent.ShowEntity(new HoverEvent.EntityTooltipInfo(EntityTypes.PLAYER, this.getUUID(), this.getName())); } private void setProfileName(final net.minecraft.network.chat.@Nullable Component newName) { @@ -515,7 +516,7 @@ public void performRangedAttack(final LivingEntity target, final float distanceF @Override public Packet getAddEntityPacket(ServerEntity $$0) { final ClientboundAddEntityPacket packet = new ClientboundAddEntityPacket(this, $$0); - ((ClientboundAddEntityPacketAccessor) packet).accessor$type(EntityType.PLAYER); + ((ClientboundAddEntityPacketAccessor) packet).accessor$type(EntityTypes.PLAYER); return packet; } } diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java index 479c408fa4b..dc1ad0036b6 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java @@ -25,7 +25,7 @@ package org.spongepowered.common.inventory.custom; import net.minecraft.world.Container; -import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.entity.npc.villager.Villager; import net.minecraft.world.entity.player.Player; @@ -379,7 +379,7 @@ public static Map containerTypeInfo() { SpongeViewableInventoryBuilder.register(ContainerTypes.MERCHANT, ContainerTypeInfo.of(sp -> new DefaultEmptyLens(), 0, 0, (id, i, p, vi) -> { - final Villager merchant = new Villager(EntityType.VILLAGER, p.level()); + final Villager merchant = new Villager(EntityTypes.VILLAGER, p.level()); merchant.setPos(p.position()); merchant.setVillagerData(merchant.getVillagerData().withLevel(5)); return new MerchantMenu(id, i, vi.applyTradeOffers(merchant)); diff --git a/src/main/java/org/spongepowered/common/util/SpongeCriterionUtil.java b/src/main/java/org/spongepowered/common/util/SpongeCriterionUtil.java index 8609d228455..591406b711e 100644 --- a/src/main/java/org/spongepowered/common/util/SpongeCriterionUtil.java +++ b/src/main/java/org/spongepowered/common/util/SpongeCriterionUtil.java @@ -26,7 +26,7 @@ import com.google.common.collect.ImmutableSet; -import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.triggers.Criterion; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; import org.spongepowered.api.advancement.criteria.OperatorCriterion; import org.spongepowered.api.util.Tuple; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java index a2bb2249470..7979b5e7e17 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/AdvancementMixin_API.java @@ -28,8 +28,8 @@ import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementRequirements; import net.minecraft.advancements.AdvancementRewards; -import net.minecraft.advancements.Criterion; import net.minecraft.advancements.DisplayInfo; +import net.minecraft.advancements.triggers.Criterion; import net.minecraft.resources.Identifier; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionMixin_API.java index a60236f044a..cbd75628439 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionMixin_API.java @@ -24,9 +24,9 @@ */ package org.spongepowered.common.mixin.api.minecraft.advancements; -import net.minecraft.advancements.Criterion; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.Criterion; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.spongepowered.api.advancement.criteria.trigger.FilteredTrigger; import org.spongepowered.api.advancement.criteria.trigger.Trigger; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionTriggerMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionTriggerMixin_API.java index 17d1baf379c..2f01614e81f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionTriggerMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/advancements/CriterionTriggerMixin_API.java @@ -24,7 +24,7 @@ */ package org.spongepowered.common.mixin.api.minecraft.advancements; -import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.triggers.CriterionTrigger; import org.spongepowered.api.Sponge; import org.spongepowered.api.advancement.criteria.trigger.FilteredTriggerConfiguration; import org.spongepowered.api.advancement.criteria.trigger.Trigger; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java index 889e363d0ea..4cea7f89332 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java @@ -29,7 +29,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; -import net.minecraft.advancements.criterion.MinMaxBounds; +import net.minecraft.advancements.predicates.MinMaxBounds; import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.commands.arguments.selector.EntitySelectorParser; import net.minecraft.core.registries.Registries; diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityTypeAccessor.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/AirItemMixin_API.java similarity index 63% rename from src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityTypeAccessor.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/AirItemMixin_API.java index 8ef9cbcdcb8..6cbbc805423 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/world/entity/EntityTypeAccessor.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/AirItemMixin_API.java @@ -22,20 +22,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor.world.entity; +package org.spongepowered.common.mixin.api.minecraft.item; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.AirItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Blocks; +import org.spongepowered.api.block.BlockType; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.common.UntransformedAccessorError; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.mixin.api.minecraft.world.item.ItemMixin_API; -@Mixin(EntityType.class) -public interface EntityTypeAccessor { +@Mixin(AirItem.class) +public abstract class AirItemMixin_API extends ItemMixin_API { - @Invoker("register") - static EntityType invoker$register(final String key, final EntityType.Builder builder) { - throw new UntransformedAccessorError(); + @Inject(method = "", at = @At(value = "RETURN")) + private void api$setBlockType(Item.Properties builder, CallbackInfo ci) { + this.api$blockType = (BlockType) Blocks.AIR; } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/BlockItemMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/BlockItemMixin_API.java index 47e4cf772c3..23df0926a70 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/BlockItemMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/item/BlockItemMixin_API.java @@ -24,7 +24,6 @@ */ package org.spongepowered.common.mixin.api.minecraft.item; -import net.minecraft.world.item.AirItem; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -35,7 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.mixin.api.minecraft.world.item.ItemMixin_API; -@Mixin(value = { BlockItem.class, AirItem.class }) +@Mixin(BlockItem.class) public abstract class BlockItemMixin_API extends ItemMixin_API { @Inject(method = "", at = @At(value = "RETURN")) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java index 4cc18f889b7..fdee5b6c67f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/AdvancementMixin.java @@ -31,8 +31,8 @@ import net.minecraft.advancements.AdvancementRequirements; import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.AdvancementType; -import net.minecraft.advancements.Criterion; import net.minecraft.advancements.DisplayInfo; +import net.minecraft.advancements.triggers.Criterion; import net.minecraft.resources.Identifier; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriteriaTriggersMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriteriaTriggersMixin.java index 044b4832a6e..8f7ee2e8ac0 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriteriaTriggersMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriteriaTriggersMixin.java @@ -24,8 +24,8 @@ */ package org.spongepowered.common.mixin.core.advancements; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.triggers.CriteriaTriggers; +import net.minecraft.advancements.triggers.CriterionTrigger; import net.minecraft.core.Registry; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionMixin.java index 72b97c688f5..19d7388d229 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionMixin.java @@ -27,9 +27,9 @@ import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; -import net.minecraft.advancements.Criterion; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.Criterion; +import net.minecraft.advancements.triggers.CriterionTrigger; import net.minecraft.util.ExtraCodecs; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.asm.mixin.Final; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionTrigger_ListenerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/SimpleCriterionTriggerMixin.java similarity index 66% rename from src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionTrigger_ListenerMixin.java rename to src/mixins/java/org/spongepowered/common/mixin/core/advancements/SimpleCriterionTriggerMixin.java index 96f72dc54e4..ee548c29e87 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/advancements/CriterionTrigger_ListenerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/advancements/SimpleCriterionTriggerMixin.java @@ -24,11 +24,13 @@ */ package org.spongepowered.common.mixin.core.advancements; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import io.leangen.geantyref.TypeToken; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.AdvancementProgress; -import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.triggers.SimpleCriterionTrigger; import net.minecraft.server.PlayerAdvancements; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.advancement.criteria.AdvancementCriterion; @@ -41,12 +43,8 @@ import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.advancement.CriterionEvent; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.advancement.SpongeCriterionTrigger; import org.spongepowered.common.advancement.SpongeFilteredTrigger; @@ -56,64 +54,61 @@ import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.hooks.PlatformHooks; -@Mixin(CriterionTrigger.Listener.class) -public abstract class CriterionTrigger_ListenerMixin { - - // @formatter:off - @Shadow @Final private CriterionTriggerInstance trigger; - @Shadow @Final private AdvancementHolder advancement; - @Shadow @Final private String criterion; - // @formatter:on +@Mixin(SimpleCriterionTrigger.class) +public abstract class SimpleCriterionTriggerMixin { @SuppressWarnings({"unchecked", "rawtypes"}) - @Inject(method = "run", at = @At("HEAD"), cancellable = true) - private void impl$callEvents(PlayerAdvancements playerAdvancements, CallbackInfo ci) { - final org.spongepowered.api.advancement.Advancement advancement = (org.spongepowered.api.advancement.Advancement) (Object) this.advancement.value(); - AdvancementCriterion advancementCriterion = (AdvancementCriterion) (Object) this.advancement.value().criteria().get(this.criterion); + @WrapOperation(method = "trigger", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/server/PlayerAdvancements;award(Lnet/minecraft/advancements/AdvancementHolder;Ljava/lang/String;)Z")) + private boolean impl$dispatchCriterionEventThenAward(final PlayerAdvancements playerAdvancements, + final AdvancementHolder holder, final String criterionName, final Operation original) { + final org.spongepowered.api.advancement.Advancement advancement = (org.spongepowered.api.advancement.Advancement) (Object) holder.value(); + AdvancementCriterion advancementCriterion = (AdvancementCriterion) (Object) holder.value().criteria().get(criterionName); final CriterionBridge criterionBridge = (CriterionBridge) advancementCriterion; if (criterionBridge.bridge$getScoreCriterion() != null) { advancementCriterion = criterionBridge.bridge$getScoreCriterion(); } - if (!PlatformHooks.INSTANCE.getGeneralHooks().onServerThread()) { - // Some mods do advancement granting on async threads, and we can't allow for the spam to be thrown. - return; + // Some mods do advancement granting on async threads — don't post events from here, but still allow the award. + return original.call(playerAdvancements, holder, criterionName); } - // Sponge filters are always handled in the trigger method + final ServerPlayer player = ((PlayerAdvancementsBridge) playerAdvancements).bridge$getPlayer(); - if (!(this.trigger instanceof SpongeFilteredTrigger)) { - final FilteredTrigger filteredTrigger = (FilteredTrigger) this.trigger; + final CriterionTriggerInstance instance = holder.value().criteria().get(criterionName).triggerInstance(); + + // Sponge filters are handled in SpongeCriterionTrigger.bridge$trigger; only post here for vanilla/mod triggers. + if (!(instance instanceof SpongeFilteredTrigger)) { + final FilteredTrigger filteredTrigger = (FilteredTrigger) instance; final Trigger triggerType = advancementCriterion.type().orElse(null); if (triggerType instanceof SpongeCriterionTrigger) { final Cause cause = PhaseTracker.getInstance().currentCause(); final TypeToken typeToken = (TypeToken) TypeToken.get(triggerType.configurationType()); final CriterionEvent.Trigger event = SpongeEventFactory.createCriterionEventTrigger(cause, - advancement, (ResourceKey) (Object) this.advancement.id(), advancementCriterion, typeToken, player, filteredTrigger, (Trigger) advancementCriterion.type().get(), true); + advancement, (ResourceKey) (Object) holder.id(), advancementCriterion, typeToken, player, filteredTrigger, + (Trigger) advancementCriterion.type().get(), true); SpongeCommon.post(event); if (!event.result()) { - ci.cancel(); - return; + return false; } } } - PhaseTracker.getInstance().pushCause(this.trigger); - // Handle the score criteria ourselves, with each trigger will - // the score be increased by one. - if (advancementCriterion instanceof ScoreAdvancementCriterion sac) { - final AdvancementProgress progress = playerAdvancements.getOrStartProgress(this.advancement); - final var progressMap = ((AdvancementProgressBridge) progress).bridge$getProgressMap(); - if (progressMap.get(sac.name()) instanceof ScoreCriterionProgress score) { - score.add(1); + + PhaseTracker.getInstance().pushCause(instance); + try { + // Score criteria absorb the award and increment progress instead. + if (advancementCriterion instanceof ScoreAdvancementCriterion sac) { + final AdvancementProgress progress = playerAdvancements.getOrStartProgress(holder); + final var progressMap = ((AdvancementProgressBridge) progress).bridge$getProgressMap(); + if (progressMap.get(sac.name()) instanceof ScoreCriterionProgress score) { + score.add(1); + } + return false; } - ci.cancel(); + return original.call(playerAdvancements, holder, criterionName); + } finally { PhaseTracker.getInstance().popCause(); } } - - @Inject(method = "run", at = @At("RETURN")) - private void impl$popCauseAtEndOfEvent(PlayerAdvancements playerAdvancements, CallbackInfo ci) { - PhaseTracker.getInstance().popCause(); - } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index 89e3e39c0ef..67da08270ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -686,7 +686,7 @@ public String toString() { @Override @SuppressWarnings("unchecked") public E bridge$createEntity(final EntityType type, final Vector3d position, final boolean naturally) throws IllegalArgumentException, IllegalStateException { - if (type == net.minecraft.world.entity.EntityType.PLAYER) { + if (type == net.minecraft.world.entity.EntityTypes.PLAYER) { // Unable to construct these throw new IllegalArgumentException("A Player cannot be created by the API!"); } @@ -697,13 +697,13 @@ public String toString() { final double z = position.z(); final Level thisWorld = (Level) (Object) this; // Not all entities have a single World parameter as their constructor - if (type == net.minecraft.world.entity.EntityType.LIGHTNING_BOLT) { - entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); + if (type == net.minecraft.world.entity.EntityTypes.LIGHTNING_BOLT) { + entity = net.minecraft.world.entity.EntityTypes.LIGHTNING_BOLT.create(thisWorld, EntitySpawnReason.EVENT); entity.snapTo(x, y, z); ((LightningBolt) entity).setVisualOnly(false); } // TODO - archetypes should solve the problem of calling the correct constructor - if (type == net.minecraft.world.entity.EntityType.ENDER_PEARL) { + if (type == net.minecraft.world.entity.EntityTypes.ENDER_PEARL) { final ArmorStand tempEntity = new ArmorStand(thisWorld, x, y, z); tempEntity.setPos(tempEntity.getX(), tempEntity.getY() - tempEntity.getEyeHeight(), tempEntity.getZ()); entity = new ThrownEnderpearl(thisWorld, tempEntity, Items.ENDER_PEARL.getDefaultInstance()); @@ -711,10 +711,10 @@ public String toString() { } // Some entities need to have non-null fields (and the easiest way to // set them is to use the more specialised constructor). - if (type == net.minecraft.world.entity.EntityType.FALLING_BLOCK) { + if (type == net.minecraft.world.entity.EntityTypes.FALLING_BLOCK) { entity = FallingBlockEntityAccessor.invoker$new(thisWorld, x, y, z, Blocks.SAND.defaultBlockState()); } - if (type == net.minecraft.world.entity.EntityType.ITEM) { + if (type == net.minecraft.world.entity.EntityTypes.ITEM) { entity = new ItemEntity(thisWorld, x, y, z, new ItemStack(Blocks.STONE)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 31f8239eb76..b82673c99f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -36,7 +36,7 @@ import com.mojang.datafixers.util.Either; import io.netty.channel.Channel; import net.kyori.adventure.text.Component; -import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.advancements.triggers.CriteriaTriggers; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.ChatType; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java index 2d5cbf450fa..543592a19e3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/ColorCollectionMixin.java @@ -42,10 +42,10 @@ public abstract class ColorCollectionMixin { @Inject(method = "registerBlocks", at = @At("RETURN")) - private static void impl$stampDyeColor( - final String id, - final TriFunction, BlockBehaviour.Properties, Block> register, - final BiFunction colorBlockFactory, + private static void impl$stampDyeColor( + final ColorCollection ids, + final TriFunction, BlockBehaviour.Properties, Block> register, + final BiFunction colorBlockFactory, final Function propertiesSupplier, final CallbackInfoReturnable> cir ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java index b4e1f3b7b37..314ccd6ac74 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypeMixin_Tracker.java @@ -26,11 +26,8 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.EntityType; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.config.tracker.TrackerCategory; @@ -38,21 +35,6 @@ @Mixin(EntityType.class) public abstract class EntityTypeMixin_Tracker implements RegistryBackedTrackableBridge> { - @Redirect(method = "register(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/entity/EntityType$Builder;)Lnet/minecraft/world/entity/EntityType;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Lnet/minecraft/resources/ResourceKey;Ljava/lang/Object;)Ljava/lang/Object;" - ) - ) - private static V impl$initializeTrackerState(final Registry registry, final ResourceKey key, final V toRegister) { - final V registered = Registry.register(registry, key, toRegister); - - final RegistryBackedTrackableBridge> trackableBridge = (RegistryBackedTrackableBridge>) toRegister; - trackableBridge.bridge$refreshTrackerStates(); - - return registered; - } - @Override public TrackerCategory bridge$trackerCategory() { return SpongeGameConfigs.getTracker().get().entity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypesMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypesMixin_Tracker.java new file mode 100644 index 00000000000..ea99675dd9e --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityTypesMixin_Tracker.java @@ -0,0 +1,53 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.tracker.world.entity; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; + +@Mixin(EntityTypes.class) +public abstract class EntityTypesMixin_Tracker { + + @Redirect(method = "register(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/entity/EntityType$Builder;)Lnet/minecraft/world/entity/EntityType;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Lnet/minecraft/resources/ResourceKey;Ljava/lang/Object;)Ljava/lang/Object;" + ) + ) + private static V impl$initializeTrackerState(final Registry registry, final ResourceKey key, final V toRegister) { + final V registered = Registry.register(registry, key, toRegister); + + final RegistryBackedTrackableBridge> trackableBridge = (RegistryBackedTrackableBridge>) toRegister; + trackableBridge.bridge$refreshTrackerStates(); + + return registered; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypeMixin_Tracker.java index ca60ab49727..0ca1c2d58b7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypeMixin_Tracker.java @@ -28,8 +28,6 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.entity.BlockEntityType; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; import org.spongepowered.common.config.SpongeGameConfigs; import org.spongepowered.common.config.tracker.TrackerCategory; @@ -37,21 +35,6 @@ @Mixin(BlockEntityType.class) public abstract class BlockEntityTypeMixin_Tracker implements RegistryBackedTrackableBridge> { - @Redirect(method = "register", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;" - ) - ) - private static Object impl$initializeTrackerState(final Registry registry, final String key, final Object toRegister) { - final Object registered = Registry.register(registry, key, toRegister); - - final RegistryBackedTrackableBridge> trackableBridge = (RegistryBackedTrackableBridge>) toRegister; - trackableBridge.bridge$refreshTrackerStates(); - - return registered; - } - @Override public TrackerCategory bridge$trackerCategory() { return SpongeGameConfigs.getTracker().get().blockEntity; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BedBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypesMixin_Tracker.java similarity index 50% rename from src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BedBlockEntityMixin_API.java rename to src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypesMixin_Tracker.java index fe3bbde4d14..d60af5e6068 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BedBlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/entity/BlockEntityTypesMixin_Tracker.java @@ -22,25 +22,32 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.api.minecraft.world.level.block.entity; +package org.spongepowered.common.mixin.tracker.world.level.block.entity; -import net.minecraft.world.level.block.entity.BedBlockEntity; -import org.spongepowered.api.block.entity.Bed; -import org.spongepowered.api.data.value.Value; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.BlockEntityTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; -import java.util.Set; +@Mixin(BlockEntityTypes.class) +public abstract class BlockEntityTypesMixin_Tracker { -@Mixin(BedBlockEntity.class) -public abstract class BedBlockEntityMixin_API extends BlockEntityMixin_API implements Bed { + @Redirect(method = "register", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/core/Registry;register(Lnet/minecraft/core/Registry;Lnet/minecraft/resources/ResourceKey;Ljava/lang/Object;)Ljava/lang/Object;" + ) + ) + private static Object impl$initializeTrackerState(final Registry registry, final ResourceKey key, final Object toRegister) { + final Object registered = Registry.register(registry, key, toRegister); - @Override - protected Set> api$getVanillaValues() { - final Set> values = super.api$getVanillaValues(); + final RegistryBackedTrackableBridge> trackableBridge = (RegistryBackedTrackableBridge>) toRegister; + trackableBridge.bridge$refreshTrackerStates(); - values.add(this.color().asImmutable()); - - return values; + return registered; } - } diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 56b21e9975d..dd0eda00c23 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -29,6 +29,7 @@ "minecraft.core.RegistryMixin", "minecraft.core.particles.ParticleTypeMixin_API", "minecraft.entity.boss.WitherEntityMixin_API", + "minecraft.item.AirItemMixin_API", "minecraft.item.BlockItemMixin_API", "minecraft.map.MapDecorationMixin_API", "minecraft.map.MapDecorationTypeMixin_API", @@ -406,7 +407,6 @@ "minecraft.world.level.block.entity.BarrelBlockEntityMixin_API", "minecraft.world.level.block.entity.BaseContainerBlockEntityMixin_API", "minecraft.world.level.block.entity.BeaconBlockEntityMixin_API", - "minecraft.world.level.block.entity.BedBlockEntityMixin_API", "minecraft.world.level.block.entity.BeehiveBlockEntityMixin_API", "minecraft.world.level.block.entity.BellBlockEntityMixin_API", "minecraft.world.level.block.entity.BlastFurnaceBlockEntityMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index d9c24b6b5cd..2efe19e792d 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -10,8 +10,8 @@ "advancements.CriteriaTriggersMixin", "advancements.CriterionMixin", "advancements.CriterionProgressMixin", - "advancements.CriterionTrigger_ListenerMixin", "advancements.DisplayInfoMixin", + "advancements.SimpleCriterionTriggerMixin", "adventure.KeyMixin", "adventure.bossbar.HackyBossBarPlatformBridgeMixin", "adventure.chat.SignedMessageMixin", diff --git a/src/mixins/resources/mixins.sponge.tracker.json b/src/mixins/resources/mixins.sponge.tracker.json index 59ec46ccd60..816d2e8fc13 100644 --- a/src/mixins/resources/mixins.sponge.tracker.json +++ b/src/mixins/resources/mixins.sponge.tracker.json @@ -23,6 +23,7 @@ "util.thread.BlockableEventLoopMixin_Tracker", "world.entity.EntityMixin_Tracker", "world.entity.EntityTypeMixin_Tracker", + "world.entity.EntityTypesMixin_Tracker", "world.entity.LivingEntityMixin_Tracker", "world.entity.animal.AnimalMixin_Tracker", "world.entity.item.FallingBlockEntityMixin_Tracker", @@ -41,6 +42,7 @@ "world.level.block.SaplingBlockMixin_Tracker", "world.level.block.entity.BlockEntityMixin_Tracker", "world.level.block.entity.BlockEntityTypeMixin_Tracker", + "world.level.block.entity.BlockEntityTypesMixin_Tracker", "world.level.chunk.ChunkAccessMixin_Tracker", "world.level.chunk.LevelChunk_BoundTickingBlockEntityMixin_Tracker", "world.level.chunk.LevelChunkMixin_Tracker", From 2d94e3aa10e7ebe25287994ec8df187099ef065d Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 21 Apr 2026 20:29:16 -0700 Subject: [PATCH 513/586] fix(registries): fix registry access in early lookups --- .../core/world/level/levelgen/WorldDimensionsMixin.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java index a961a964408..c7cc36cdbe6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/levelgen/WorldDimensionsMixin.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.hooks.PlatformHooks; import java.util.Map; @@ -52,8 +52,7 @@ private Object findOverworldStem(final Map instance, final Object key) { // ends up being a double lookup for all worlds but the overworld but I feel it is a small price to pay vs. a very complicated series // of mixins to remove retrieving the level stem settings solely for all worlds but the overworld if (val == null) { - // Registry.get() returns Optional> in 26.1, not the value directly - return SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM).get((ResourceKey) key) + return PlatformHooks.INSTANCE.getWorldHooks().earlyRegistryAccess(Registries.LEVEL_STEM).get((ResourceKey) key) .map(ref -> (Object) ref.value()).orElse(null); } From 77825b8ed794ae932e244ea1db2b9a4921d31a6a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 21 Apr 2026 21:03:25 -0700 Subject: [PATCH 514/586] feat(minecraft): update to 26.2-snapshot-4 Changes: - SpongeSurfaceRulesFactory needs now a HolderGetter to remain functional - ClientLevelMixin matching change See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_4 --- SpongeAPI | 2 +- gradle.properties | 2 +- .../config/noise/SpongeSurfaceRulesFactory.java | 9 +++++---- .../mixin/core/client/multiplayer/ClientLevelMixin.java | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 2d153e8bff5..b6177b74e5f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 2d153e8bff54b3a5e52970168635b356337b34de +Subproject commit b6177b74e5fc5ba9380d68b190ff6a07ea1ecb80 diff --git a/gradle.properties b/gradle.properties index fe856ee9273..f88a4eb06f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-3 +minecraftVersion=26.2-snapshot-4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java index dcdab39802b..1fb66c83829 100644 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java @@ -36,6 +36,7 @@ import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.generation.config.SurfaceRule; import org.spongepowered.api.world.generation.config.noise.Noise; +import org.spongepowered.common.SpongeCommon; import java.util.Arrays; import java.util.List; @@ -44,17 +45,17 @@ public final class SpongeSurfaceRulesFactory implements SurfaceRule.Factory { @Override public SurfaceRule overworld() { - return (SurfaceRule) SurfaceRuleData.overworld(); + return (SurfaceRule) SurfaceRuleData.overworld(SpongeCommon.vanillaRegistry(Registries.BIOME)); } @Override public SurfaceRule overworldLike(final boolean nearSurface, final boolean bedrockRoof, final boolean bedrockFloor) { - return (SurfaceRule) SurfaceRuleData.overworldLike(nearSurface, bedrockRoof, bedrockFloor); + return (SurfaceRule) SurfaceRuleData.overworldLike(SpongeCommon.vanillaRegistry(Registries.BIOME), nearSurface, bedrockRoof, bedrockFloor); } @Override public SurfaceRule nether() { - return (SurfaceRule) SurfaceRuleData.nether(); + return (SurfaceRule) SurfaceRuleData.nether(SpongeCommon.vanillaRegistry(Registries.BIOME)); } @Override @@ -111,7 +112,7 @@ public SurfaceRule.Condition biome(final List> biomes) final var stream = biomes.stream() .map(r -> net.minecraft.resources.ResourceKey.create(Registries.BIOME, ((Identifier) (Object) r.location()))); final net.minecraft.resources.ResourceKey[] keys = stream.toArray(net.minecraft.resources.ResourceKey[]::new); - return (SurfaceRule.Condition) SurfaceRules.isBiome(keys); + return (SurfaceRule.Condition) SurfaceRules.isBiome(SpongeCommon.vanillaRegistry(Registries.BIOME), keys); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java index 9e7eb7aa85a..f8e946272b7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/multiplayer/ClientLevelMixin.java @@ -26,7 +26,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.extract.LevelExtractor; import net.minecraft.core.Holder; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -43,7 +43,7 @@ public abstract class ClientLevelMixin extends LevelMixin { @Inject(method = "", at = @At("TAIL")) private void impl$onInit( final ClientPacketListener listener, final ClientLevel.ClientLevelData data, final ResourceKey key, - final Holder holder, final int storageRange, final int serverSimulationDistance, final LevelRenderer renderer, final boolean isDebug, + final Holder holder, final int storageRange, final int serverSimulationDistance, final LevelExtractor levelExtractor, final boolean isDebug, final long biomeZoomSeed, final int seaLevel, final CallbackInfo ci) { this.bridge$adjustDimensionLogic(holder.value()); } From 5c66ee5658394da823eb845fe386e287f5da09bc Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 21 Apr 2026 22:04:27 -0700 Subject: [PATCH 515/586] fix(test): there are two DamageEvents now Signed-off-by: Gabriel Harris-Rouquette --- .../org/spongepowered/common/event/entity/DamageEventTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/spongepowered/common/event/entity/DamageEventTest.java b/src/test/java/org/spongepowered/common/event/entity/DamageEventTest.java index be9a5d212bd..84b2763d56d 100644 --- a/src/test/java/org/spongepowered/common/event/entity/DamageEventTest.java +++ b/src/test/java/org/spongepowered/common/event/entity/DamageEventTest.java @@ -63,7 +63,8 @@ public void testDamageEvent() { sheep.damage(15, damageSource); - assertEquals(1, listener.events, "events count"); + // There's a Pre and Post + assertEquals(2, listener.events, "events count"); assertNotNull(listener.lastEvent, "last event"); assertEquals(15, listener.lastEvent.baseDamage(), "base damage"); assertEquals(damageSource, listener.lastEvent.cause().root(), "root cause"); From 138bbfce7996764a7fd096be85a8e1c5ecf4640b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 1 May 2026 15:28:31 +0200 Subject: [PATCH 516/586] Update to Gradle 9.4.1 --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 10 ++++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 45633 -> 46175 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index a71b70c1941..3f74c9fd8e1 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a71b70c1941d9a4dd8833ef915ba2d2f4c961e06 +Subproject commit 3f74c9fd8e15d743a0de2bbec972cca9e4ee25ca diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ad4b7eebe08..6ab35a153b8 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -9845,6 +9845,11 @@ + + + + + @@ -9898,6 +9903,11 @@ + + + + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125fe0768e9a76ee977ac089eb657005e..61285a659d17295f1de7c53e24fdf13ad755c379 100644 GIT binary patch delta 37058 zcmX6@V|1Ne+e~Ae*tTsajcwbu)95rhv2ELpZQG4=VmoP?Ce7F9{eJBG_r2E4wXfMT zGk65KcLv$$fC`j{Vn@qwX{~D|!Rqmyk#lN~X&X|PN-VC(*S{l4u_MT_%(!w!9}$Uk z0n6R(L%pgVFwqG>LG8`I2L|;5AqL>R@p~M3nvbIPkUGU1UNfg*ZauQPW^~muS7cbU zWCOm&P{?3pP$V2-95b*Q&5a|Od0agz$|zeVRaw(<69Dt`P$vnK_x?)RF{A%hm#lzZ zbT~v0z0dy14a)UKF93i-snk18=ABFd0*@^K43{`5*j}zPUAQ8qv88O^WC7Zq?4{Dn zLWPLFj&G@%T0ZTCgZp=4wNj4Z>-V)!;cl-gE*!ST1TN8xuy8WVqL)3Db6tFWm*RwN zf(s!ip{!$Jf4>X=q|k*ap-QvQSP)sE`;txD%lq@&hucckTH#-0RRuVB%ww`jiZ2il zu3u7`QW;Ykm{3!U%CUh~8e8his#r!5ZDDQTC2{l~^PYut5F$)n>V5eAkRtjx2OD1> zQL+SqY>IL+hd}&$#NY1?7m)yg!`CaHSIoXh!Qf4fp4`C6U5D%Dm&u0yy&#CpVT$2D zA0Ma3yi+*q-r;qONYQO|SXi@mTuL#2$}MV;WpGn{!l^rG&n$p>{?*#JoAvAVzEeXy z?Lum**`UpRrBwi%XJ9>-ph>ZQ`}WPAvmOq0kARL19afv!rg%rWld88$2Z@_npO8^D zOHJ2Ljop`Eb}D=2>D3X+WefmjyaN_;#$`I4eY&2ZI{~uurIxt96YQ{jBnRO7PT07m z!wE~L-8<|=;S6Y%nAzzdW>41kA$!>-tR`^i^G2rUh;FK{0 zg7)Q(E2In;J@JsC1sm9;+YUglHA`c z6B8B;QACJbxy0o%n?H^G$&c)?Lc0WQ+PsU)!}P=tyXF!n^KX%LPuNJ|Ju~v7$lq6A zLO5-17J+(ho>BP}62RGt^}eAThhTWwBoT}c6txFgn+IJoQ(LR26eSprJFghhedF~s`c@%03@N!2`okf}SA!*37PctOQ24=@(t z4ISBKKb?)JX-4 zX`a~;x^KSBs9ct{12H_?q(Mg9iF-3Vf&hg707Y-47UfID70W?Ys{tRXCW2cC)jl6a z&mIdD@h&42Hq)H|fNa|FL7el=TXJWz7Yl6pBX|dHv8Ey9*N>suh3=Xw!f?Z$#~h zq)Y6zv;#OR-dK6L?V)QvXY+WoYSgcxgJ_3sfzA+Z_WncBwh+mg<00|g9Wqd@Vhyoo z#YQ96%MA$6(d$CNas&)&-~5qs_185AgU?i9)}R{<;o0f(>nBwY^JlSr)8qkTz#X9Jbcs# z{+WHO2?GY!v%&m=W?t*8IQJ@Y@l~4EuvzaskE-3Qw8L?+mEJGW&zn*)p2l2fzS?Zy zRZ4+qm}{+hqPxmALjn_c$1Ny<{aSFr;Zg6BVl~l9&l$>Wu$@O-Mn>D*ii2#|9j%75 z$66Xkp34)=eCeat7Z~5(;=A)*BTh%V4l%Z#-_?Q5OZpj!rX3^>-AnLKb53sU;i&;P zNC?CL;-H;7Py<_~f}3;nNT1nH5HJP2t1I+DMj2M)?>l<01(SDnF=V5PHNi(MF=PjF z9xsPC5{=F=b8%U#lijvt`NkIx!~DNJib^Tt!BUJX?Xh|M>eK-a5K6(|-hIQJJ46EYNlat(S=u%r z6qtFs6f&k&i2tHjiXel@NJ@1>kQg7sKNcI(!NTTMvbk*PH4`-O4)X^%Dh#7BU+#&(yf<*rw*=^9`tSS4$WI`_ z`wddQEB80@PSzEVpE3FCQ&C2J;Dkh9!@W@@2ciA@ynDGNz>k%vE(p8%j=5Mz<+fth{_d;HF#I zh%$ATX7|24-F)* z2w-wbku05E8E02fSC^Iaa{5@5vqxwRO2sh!Y7|X{ulwd?d7kR8QhPojjH%LMJ8sO? za1^D>E55&9;qEt$q<&Ac3FYm3^^y|(+hi7G7GA+n*QX_%sEOCKh$QZxHN>TVQNY| z@a6piqrhJzymCqK&05xqVbDQ!HNXgq^m;kl60$fN<$_eVepCB#c98#?c*cTQCvT<9 z4n3=8g{9DUxKJ(*lH%TKJ57!<5>yq#eYy6EM>;RH`-gYuM`HLo@4p?P>BoUp`urP%8~+wEBL^oh>qG z1Wy3==DW-y(+yquF+;t;EcUA5eN^HY{e3Z})>ho30?TNm*iv4~kPmA?YK00oc48TR zIF#_jO4f&H=meMCju9~44CG3>^<&xItsWY`CmXx73&}pX!K`lHRBY;a23pEyt?tlE z9V#!a3EQ{J)DLO^y4OLSqBVpB?bHD@krho5W6n`z5)z#~!bn=4tI%n|*^>)SlW5Fa zFFtJ23|y{eF3GSOS@ua^ceD@nM{BHQJT~4szuOg!kUi#PPhu#t1D7Wdkg}eat#{tj zOgSANDX*U9vDKVdI~nPmG$ianUppt(h6Vx1rC#G0ENZK2>G<)fIRuw-9QnhKVl&`o zsvqcc2aY`fIZh@ilwc1{GoJp;RVR}689reN%K$OkPoX|p8T=eUO`ARpn_hoP!-3x% zeH7b&7@pP0$vFC0fVRxONoLd4@J$N7da04+&-ke&j&=GYk^-zrLHawCo zBaN)={nIT)e;7;@N*l&E(rXl7HIWET7{Xpp8b?RgR&tnna@B8vQYBPh*F}ef>cl8; zT7hdZzrq@-isR^3Arw;W35>-4SY{qzI`D~VQWs<523H4IQ!Pl$DEJC266=m|@>5~% zXaS{-GzzO25>|X2C@_?+>=2KVNa!Uwatp(VVv~GPa3f>|cC&{asS#ys!+J931Ey_SGkAp= z7Rsh*@k;>*dXC9iX|9a59s^$q_NETs5N((Yj~vNM;SSLcdc|ywDawl?=Ud*_ZA&Zb z1-~|ixAzyA{1qIWk9nq`|0JXr?a2n4t*}_2Y1P8UVF*y4VeA;`mPeZ#GX_L9lLF0H zsgI_9R5BII`Q~{K^t(Moq@_>LBHQPJ)n?2`vJ?S-VLy69^XFs)+!Jfgdn3lTeH zce27W*9`7B-1@|K_*Hs;6KIVXgdGSxTcZfxsa%b~X-1Hm^NL7Qu3BLV%Cd$w=hw;4 z7fpRa{9B3zLv@?MZM#bid*+Q*-+nXHcPM?zg)4$T$>%qd zO(xvodyWY1#lM%O!?UU+o)l)Ix5zcy2C8V{rLV;wkw6QTHj2Od$9oq40r)(pz-zYQ zNk3PlF=KzL{6|AH-0uHg(7}$Bq^FJLCNY?Kk-s746#5!)7eQ(%*N~V!-bD zNLvx-i%;|qS3~R!_MCBQLp3)N+ye>+0E|ifANRYh1d!IVuURse9f5y-Vp8;FW`f0T zp*7V8YGy*&XyRhZSi@4CS!U$UrEmjtNJh^!qN3U(c2{?-Hy2V1VM!nfjDC%0wlplI zB@$8t=bmfz8+J+ox~Rrey7~f>n5KE6I&| zNNG$Z{wMS_fRG9b=u=8xH4ViKHp>jl48t@-K+pK!F(pT5VuTf>u?TT#)VFL>iZ!>5Obt1~jK1JA->f{T`Fml}F4 zR)Ih1vw<~d_R5QBVG3qQHwYXzt}4quVST4*L@If^z>_vw^^3kL{s5C^NaSHWQo=ku z%K90@HP2g(-gdb>_>*=cSBVYHMJav9qFrYzjzfHJ7_MXthED zO%`)4mmh(cm%5zFaHHdgjV!WK9}NA(UmC99_-#a8|2?07Z{s4`*uMEJDFSW<|e~E^3e7*dh@1lIvBp2|ciEr3f#xfwu zqSN8AMv85}^0BqDxA47Jl2xjn>ky1BpquO-!wETgtSdJB9_*Z<+U2CX|HfK`Oik!o z@b0XR<%u~87MTsj9fk6gUI;a|H(H#<-ch&*>i9(I)V*GOQ*C~$UTr8$0O#{PQP0aa zAHlExs%(@$OLo~fuT6co-FSGs3t-{^ z44{UBDFGmt-{CsmsHHjGkEAh8lOe=fP=v7em@ZWF2zD!}F~XhDPp|>DvnRW0S)$M3 z%fHfUc7N5$E8=H6mRA;=@G@?M+36L?{#ppzWC|aguFF;t7B(=^AGMazaw)}3Zb`De zt(afT?-{?gLciHh?rVPb^%Ulj-EMV3Uq`OZI}Z%TeY46eY0d8&Bpjxs(3<#$fjsdM znnP8d5GPn0gR6Nc6cvGp0Xt_8ORqRtLT~MC%LSNE}M`y^u zd_($==UKwoTPa{#cc4UJ>QGe%b_8@26E&F>v{r~Lb{a(`{K3HNMxGNbfRpKnKkAk3~1BmN}|@XzPaO~R`1-u zg6csZ#YTApEJM>`!YamLpz)5~Tre4FZ#UR-5*=##WkZ4&YA-tL6}cBK3EN#2AFBH( zYmO$5?zv0_X1GXNR;fq6h-;pCeiuD6aBhN>f}LIun1PzqBFaUsXK%r#+})UIx4xQ|NBEmz`AkS_GQ=cPz#DUn_NpXo3@fE z^ibMmO=+(S#&h>tH(@c~mD8gPy`F|t&5CAm=|{AYzECK&je9mN)Cz6@S<;$XG5ZcZ zl!wOhM^?ypfnP4tx%+?UanhMRH>`Yzq)w`s~w z4ME~8x3F&Wd30-9iPo9?`!YS}uJiUc-l$>d^uP(W(vB89`K^9d8TuRmzGxEJzyG{C zV;`3H5^~P1x=wOzZL2uoc;Kh&D5i)xw=*1yjoyY&!~2mWI%S$!w?^Z|R(7dp_)+s5 z17}1jF%&sX7hok52bP>2!{JI z3xv@VrT2^#z}?eq3Om+4sE^j08MO@$UhK99oHJ*`g92!ai~PqzGkOSt&g6f`@`AUp zIm}e4hOx4j>BWzzip;MphS)CD$^z4rkz^Mk5uZOkII*-<)Esk*-|=PDEB}5g4CW#) zG!hkS(!@VF@t*;X9t3?TRk_1nLm!jhFe0mcL{9M=eWv_PO?6(#A75EgNkw1}4_HI6 zl=W*-m(#t#{f|L9JvN6aK}?qa%aq1x*V^>!)^1ZWMkN@HaO=d??hEPQrADLSTsC&j zd9sz{y$#S7;qIA*5J&Zz-f6OWdi#4I2WXhseFJ>?8us`_P@Pr7 z=h`q^a;q`VIw+}B!nK`iB}#k5qJ+dSwuIb5d0=_vc$IUnaWW9J^MJ}nV?Bq6)9}Ny zn`7E>_DUZPz#2ws>SP|Db$Ur`gmBxiXu2(l6jj!#^>up(FW!-S4^h}yv7)MOngL4k zBr&a=i5LJXwO=sSZg9Ls{Sa)@T!-93Z9um5l*Y_3UFZ_`t(%HF_P2_^+^}{e?g000 z@hHy(v2w%C+%R@LR^V3>M1b`4c-l0iWt~a%@4AFAj&r+l<&Z(~&ii49@|QcoG)7pd zy1y$%$W??tn(uGDM1uQST8B-=YcT8j^si9`mp=FVCz7@M01r_DFv|-- zHVQpKB#)2k-?u2EL5jcvWoOVD`a}T4e~_8;=vtSjB(a17;qe&pFsaxH2-%A9BBMHY zdYO>AeR8@DR`9-|6%3MQV=2Ca|D}Ip8|p1$$skcd51Si)4{Ph&hCR_BNZkRZ;nUDi z+~WklGy{L}&9`D_r%S0F#P{sW`w8SyFkD+<2S)zCi9SL>MRt(U^*7r=eI9kX2`{c( zCmKHG9*zU@JNlai-P{Q6XdPp|d+$8bq20J1q7a9B8q$Zkmq{!J7Kv9&-MicMY4SKW zH2^QZSWMKyd09n`*VE$Nz)i6e|4Rxo(@(P*gKs_TbRy6Bb&6D%8;B0hQ z=ZBw8@6hK#`|`Yg6J+k6oZd8i1+VY05*)v{`iqK4aXDovYsf?Uj7!-{#fHOw5-u); z?*1gSIP;Nw3X7PYs`?`?y%NOIF9rUJQ5LN|`p1?(f83D;xGQE2DW_wf9~lOcQ?#r+ zShWVenzYK;C?0QzmkY$PBj@QCYh#Jh6LZ88Wz@^m+psW>ifV4N=`XRx<@9z08vrD1 z3}q>CKPlUkpsx?stGkDy(;o~75Hlyq5-6B0!gtY!zcQJ(-spt;P1fXpO_xq8U(Y2= z@D?-X+0|HHN}nkI8qNN74 z>X7~WprgF3s^AKL6Ee40lr9rDRb;7^o3kFRyp`^E=IXVsUI&=gofe53($%qzmF!p|s$ZV-`L`5wYk(G?j!Ns3rWxNZxRk=xmH^~T zvvf&b#=1OtQZIk=ck}WH~tu3&s)tk|Yo^47?Cw5iFmqeux-TJVk)pQX0&MC?fS?3W>gJ>3idYOOho|8C83{{d z1#eVX^9MSj%{hB@QV)S0R8rl@tx%bTe2RqPW8dbpy#v21VSqR8Dip$o(vf-%aEkKJ z=;iP_bMq13i!5y+wNC_*&4fptzZndywPzphDr}A>2N_!VjPKEZ^yQox)5JoOdyEj zLYCvig+gx5Vj#`3G5+L|3;~xnp^38N3ib)3o^7N(o^Z`e?Z9u0VU=OX6@-Hgj-muJ z3~Qzng3c!lwX94WI}cNL$UO{B#z0bT5uiS*1_yeNUj36)Y|ZBA+6Au;akZ8zn&WuQ zh+o+^X9!?|aM!h#2~p6a*HLyg5HoJ462ATrQ)h|LKk`OvuENZceTeN&)aA&$$8`z` zOL^VJ-8Z&KxZf#7I>%GN)k{u$l<7E4zEDWZBhNF{^|8*0zQ5kjjIz7O)tV`WRjqZG zqN+oKD`fwswG71xR(R&Kili=9_sZtg}Ch{m#fn(0h+ zgxgJk%B+xCq+Fu*z0*RSg;dGW$I5p{nTkOY578RGxO<&ibyD`JcOpuPHU!RA5CYi) zAQlP$Fh|Yp_{0}N4v%K7{HW#*d0waAZ>L?PS(VUrj!S_ZWD1PHLs93|JgIC|?)u2p zuOuuptmB|$nh&A55XT4v5{E{1Dk1O@c?eSLWpC3cx`2FozI~To={eUc*+6hXkxUuY zk~AqPq;QVn(P&$u4x}pM1O2nm(9-_=3`p+GqThH*wYv?!^stdX*$3D zHz3ZD{gtuwK$Z-LNirh2fvqQcanJjwhyTy<_N$c91KoATZKKhTjD1GBIPVWY9vDBK z+D_Bzl{k>!ooTff@^tR8wZE&McKw%Ge!dRbM;z?f+QOw#q~#5izQOuJbRY%+l_G?L zt@J>SEe191?3SD^fv*MAf~cb7UNV=8FftU0|Gvq8+g1KcJVVL=j~)1&|f)G3n({iPuRhprduD$c8@dXxF?B-@bKd#R0puWroqLE zDQ8JB4!hV1*uZCMv!pj;X`MF3){ovWq|dHWa~9|TxW(?NI`DzY*L42!iaN1|j)4vl zHbe-tc*@x@YVp0VRL7CEfC^0P;o_3>ChXB&WrlD)&~C`6lQZ9?)}wYamQPsL=;H~A zPQt9;Z;NqtoLWP6mEF=ahdYBtreitr=J3-f{@I0GLV%6TrX)$=z&-(f;QpxGtEKE6 z=c~S}JRfBVY7mfB=yT}`c^ zYTVhDNGcvoY{t90`3`E+$ssdK244WxN}c_c##%ZI`GMnmPhAaF1AZz!k%wK1j~vUA z^$ZDAGiplV6lrLrc6EhX%WX4+9rOfmB%!}ziqG$0Bzi6EVTUCt<#5^@4|K=$IK1-S z;XO237|4o$b^^9+!F_$$Pt3y)CZKmIIr)gl6TINgFj+2c14D5}vV zwi-*BX+-u?tTumburN}*Lu0d zr!2j_WDUv!{U{Mj=d+Z#EJdt&d_x;|K4+}pkVMvGp#?J3bXU0vvE&9Kb1L+paCVRj zJ5Xf^de}iRjV(`^1iT|LlRT*3Vz2s_8LLijX1)V;0k})dKQc7-_;AY#4;89BFV-=Y zDFFvgwyoM%fu>SS(Je2d4KfM|*IOrVJPyQbUY%Js3rNs5D-L$FyIf3o3hd zEcU+E=NvnpV|0UGV2#Z!o*{J3WQj}@oG4N!dw)3a7nI9l5sYiOX~ooZEX9Y^Sxu(YU*953XqaM(Y=ENV0WOjK?OYs7?x7> zER|68{r?M?Lt^gG!cvL^Er1ToYj2gSbumnmqj)WdWzl3Xyf_Sq;u*_FJj8iaRy6dH zXA!TsETx6}aIb0yPJ?+l)8A%0IUheB?_u`w2q7C-S$XSdeaJ%LsVI_R_ke7UG zTV^z~eccE!E7?HBo1o}S ztMy=fsn0}evMjZvG&On+CP%tY)2@ImNlQ;6&5Z}Xc%fg;2~D9wnVhL0cM>T+zWoDK z-MfPwQ+OU%ycLFbX9I7((T13s>9w(PX@eEU@7_USn5@v`uXYq(%G##Qg1;UW?LLR_ ze*e_s5j-BqlGpTRQPumo(OXj#UB*DP0!{FFL|m)c6s?bJrOBWxX;k3-5EMoNbva9Aj7A3?7nvR)Q`;ododzB{EY6$7`^=H}OHVE>=qhsXZC z4+v9UXHLbP4!5pPeaqBKiy;O{SPDOOjD$1qGW*PJPDdc4S`$*pQ9K)r4-EbEw$hnZ zQ9@^HG$B5n`!e>uY-?)eo&8WEUii>WpOOFD#M*hmBkP)C3bb<;t@o0aF7+_R5PL0# z+<5q*I#cp5+CRx3Q6YE5ou&^##~hBjcw9y&%F2dS2nx7xRAU6SX+XTo3C^+ue!tL5w{edMgkR9pKtb357?|wNfrqQ@9sB zyQEOWBh4dX(JgfS78(J!cb^OVxZ*@nWMG=fm1e6h>MN#7snQb%xkgs=ik6+x#-;Uj zA>gngu^W*{7Ple8p)=^NIUez4iBe%GC0ucfd-^dZ5uu3mk6;rj6ySPMF=b|u>}4Mf zd$7KJM9Dez9*OfA|5-D*??jQqQL`GM?*(`0FMbE?Y) zHNgrRsH_jkMZHK)qOM_S`;QUUkZiNTuKCX=XhDnY;*r_habdUjYL;quM!JrPMsN1n z67FH9iNQm_<($4ny0Dqu53bFC1Y}!=Co<^|lKoW%7@M=GwzFD2Ha|af>T|X9aiA(% zMybmYeuzx2dL0Fm%NLmx^3K4TZX-^^*&o7j4(>DDH)mEBhPIYhiuP?KT2*dbF$5qE zbM%JdYfZj1CtwUu-vY&T-G$aDc9sHdWb{!D$;#{oxX@cjX2-l+4qttAWZA)T=~+_h z3v+_9{h>y@5q3N;{t&k(>^;hE9%JaPA(t`blro3VdZwto9A{)@PqagiLaN zZWD7zZkY!7;}}Q3Jz!eqRk!aL)BIm;5XOH<>z!FDDE>MgP$Jl86 zjs6`6$)(a_87n9{oc9lDf^{RcKk3$EM3>Bsxn8Z{s)o$%zHsf?x$@3vo$jwl*0b61 zilpii)`Gmj{CCq^iG`{BF>nOmRASjBBfzIoMA@W)^F1;U)h)Rwe*3O>?9i9k=ETW+ zF3a;6ZusG>A8?su2+W4_u zEc!3`z7K!8-;QMINL#(A`^v-qN3_RC0x}CtC!`~ql6s-;B&rKid!CTUj!(CU@$_6f zk3KWIn~Q5JkU%q+&>w_}af8ck&gf{&Du2EST z)MPO+pppuf7+T=$4ae0F%38ABQ)ogE0!uP79)`pd6?^ochl|R!W3w>ndH%-N*mtzg z?>5TPC`7`qB`etoW1)eSH-5LPHS*8%CO*F)Q0_GMr)OvX+*g=VtmgjU<3n8G`iZQW zkFziymx zq>n%RJ!jIjKw}Cc4_z;hI+kTZ;AZsI*QJFQ#X=vtK!*(4@AR7$cJCSpI^H8kGAga9 zNY;jWLowTSO4HJv+otAhHH{-}Ii`HSO#Ns(YsON1O~SzRL!HIal8SLpnME#*BpoK* z1bC*HK?_-Tofjjby>LA!p<-7KM+&O=pkjekI|7iX{L4c7k05&|A*=A_P$o+F<%oP>MFc`8$lzm*>q-`&WFA0N#HNkN$ucp zqlS}kJ5ddN{WO{&(YQ!AiEK;dfS)Oyq%U+r6L25fTW9il8ne^p{j8iOKy3bE+upyg za(SKQZq>IaE!JeWa-ZlCsUr;J91KzT#L1JLIEQhqZ~DUtwr7Ev;b?U2OTh@|WlK~G zvPwiF($d)>!CC^UQPe52#66rG(-S?ao!r%&bOd{xew<2toEk)_&^W)2RblmM-0r%X zRf@dWC>t@9Wo=3!QELn=fWh*i#eN=_?LAg8eK|FlbmW9r*M0Vg9l$Y^DM(Hgt>P=r zVEJd#w{{l8nGE&_nBYhD4V?MbdFhOr8sM@K(}B5IpQrx0jRQ)0=K$+B#u8O8tq#gK zuO^N~L!6FZK#4<8eY)Bpcd%W~59EA<=U6pdUe{)_9Sl0BhiAkY!*-_rLZ__WBw{6@ zD?2_qk(Y2iV@Mx9zj%yt-(SjX>&`Bsd}HD0>3yc>&}lCpoA5gEZh>K2GOZ;|FD#$9 zWPQzu#>eYT_q*APHIztjJjWf<^%^VYgoRzs3coINPfO*k~Jt@*(N1EaA~TFZg6?KXI%2f}=a%5Utu zYhD@$%2+T6{W=g(k*~&VzMJ?lJeX1e1?~d7eE4c(LB1kT!!7-ojkEF|I|-TF__jg) z+9-O4ni6|@KMtEJ?x8uGdxBeT8t#1jz~z&Qo!jT5xqh{@T#YCq`ZvIEwIDO%;i=Q1<#D1 zxMm0!E|b^X|2%F3^o|`m;2Ga(NA%|qqFP~h!$nZ zmIQkxUBb;GpV)aD?svU9qs&UhRE}#px>-V?2k92I)ET5mtO``@UDliJ-LPY(Lsg^Rl~n$XkfyFo4iu`mIygd6wyD5P6;+#~ z7tHJz`vM$WSlv@~N+T(GkqNpOlmN)R1tX30l83g|{|#597i|rlCsoT!;S0vWDW!`N zj$n*38nZXg;gav>L(QN&M=1RS^^7Zy4k1};(w#p|cwCI)LZfJm$E#;8kL;2aIJ+#> zto%<$n0gY>D*P)_W5E1RM<6LE0bv*z=yq{eoQmqAGeUfW8H~Sw?Z6`>nP?PjiP_o_ z=!S{<*W3zC5UE+j;AR)GJ4jHUcV~BEU!>W|<3ANV4LF_Q{d0I)!3x1*kqkaQIdMGc z?3Ykax~-it9ui1yu#%7$Qpo8oOIyry1)IXM>yAD{$ZmYTBW#z z;qVqihZibvnpQ?X<|M;bDwL&iO5IMBWSr5XiNO&#Zs0?lU=YZ;&^op5yNNBOX| zu=vEtfE1{WK#vX&NTsLB$~AV;wLD!j1hBuj$>uT~T-EMMShux)uEhedx7;rL)R4z2 zMM>U725EdICWRPqZ46A~bP%N_yRdN)+>h3R)MBgfq|<4BXWTPc`*;TGj5@_S@O_`V z+rQE9O=sca7RFuR4SmZyosK61Vs?I!X6%A$u`g_m*7g$tmKxz+6Q0%4xEt8set!RH z5Y`W6c49Qc$VDOUl2uuFNgUrlCQqR=c#e2}FKk|5cJ!9fhSor~kyS1OlOaN}{JjBh zPAPC$wU~rU9WMJd{$wr(v%pPIhWZA8cC(u^f|Lt(m7+pIHf7mB}u_lcNB(17Z)G&u~xQ{-EaS~UXtTj z3)*De+xD63J>B-0|2^M%`f{If14J8OfCX*+y4qNB_xkvrzd1YW8R!sb-`LkFVs-og zl-Bk^o{l}K<)ZDIZ8r4bQ$jgc=HedF=*|$=V-nS!u#N%)&KEr*kF3Yo_}h^=CAQ6+1zT|M4a^xWm>0Q7>-(i)Ea0hXL-Gy? z>&94pp! zil8m3JuNA*j9f=baF3If;|-q?=+IpQKG#I4u;=i{bAT$V1S1_U;Q0y!Gb zT&LgwbjIkN=rN1^PDBEMbQkOw78LQ(?an(3BQ&vGvc5IWmJd=@oyH^}_{k#cu*lH^ zB4+_z65?^BK2L0BJnEn(2h1h@UYJDxGq)unzK*#=B8-ocy5^su03Z3bsKDm>B)029 z=q~e3UcS)xGd=!C{}h!(W3u+bI9moqTH!@niK-L!{pC21y4?0``XOx6lW&H9kMZ=& zf;7+V0Jix_S{eQhG2#JGYuA29VxSDh88b|sgmacHA(PNaIHe>Mn*Hn^LFM<@hN}RH z^7tps$?sjXoZDgw-Sd=@%=3#9LTL>l*6mudY1a!i7z0GCV4{XhUiv7W3(dIYYzMn< zJKi1Aews)46yqY=dx=hQXHa^^91|!5kk~E1CF*k$j-?j<5IffZ=@e_oe^|z;VsR8d zDc7VvenOf$d3oAt%in><#O1%9~eVriI54dRhC z*xn{KEs+buZGW8tRy_K9jTb4<)g4@W{+2n(kysJzsjDam0Ar!tjCsy+@t? zfQEQe_Cz%gRH%+YVaP7NYuRcvk1p08@r8hMH93EYiPDT(G=AUKVz{XY)x_4k zN=lwwxHD0u&RFzDJt%@885mAAwLFI9l85O z-saX?=>Fh~+2y^Pg~%Uhr(=El!y|2=DRgY4bU9|YD9BQOvVOe+8vwV5U3Kr-DV2=G zF!lErJ{SAH63?ua1r#VNzHZ%Uhj{wYyFm>b<@HM|=$rb5U%sAAW|wgJfsAH&iV-&w-Ol@mU5Gm}#Fc1@~c9)f$;b!om<_G?o9; z^@i@TeT7k1d1l4KaP$_TR8mpt?_$o%^-5wiP&B4qJl|S!)Z`q&wJo}TQE74i|5!Sw z=uEn2vt!$K(y?tjcWm3XZFOwhHad3l_w#=LL5)3Xk6mYVu-4pjUTX*!ucqOT zWfEYLmS62NNRh>2oohQMAd?2GE- z3U72=jE*my1**Qt z&QQqavphe_x`Y+BUg0j5PZE@2Y+wjX%U83bsF04(CfWMIL%Zlap+oxbrQO5A!~pZ8 zKLh=y2}iN`hrc&nfUc(@>kUD&5_14@hwYqBK)N!B`DNiUFCw2=QS_3@#r71^?Z*Sq zkCY*yBn+1(x?(oB3`VEmVsOpxk$W}YB%xZ?q;k_TgT3_vIy|x4AKa7%58v4>|j5H1<)F2)h8Mg$H0}1EHw>ok5H!*O3TfCkY}%7gx>+qjK$85Y_(anx?o?KoHXF=~E?A=sA+u|Pj zWCm4x1Q8cfIGyCi;^506dpK2 zQp3o5#`;RIB5mY&q8yc7jepfR%ms&OrHo=9t;%-byGX_b@={(bh;Te0gX9ZV zb>CFEuc)P!;?ZXS^WA%ZP;M#I7n=M^p*&$IaHDhxq=XBZ8?Uwpk?|(!O_Dxo$a?z! zF8t7#5R}%Tfq+g>{?`aq|CWLk{M1309&jrfE*47E!~^_)2!J-L_}!m0Z}XX{3@(-z zzmM-XT7OqM*lq!SJC2 z_`{{Rr zgMX`~r`;Zf0+`eCvIfWlfRay6ca|bWLK9%%<(#cO0-hY1{zoi8cw)f{bft8Efv}QW z!co|dAPrm^ft*ow?14-IWODgIT76c;^k3gVa`J07rpXkn)&EX^D=)KSh@{q3IL$-3 z$*oljo?}gBph-2L<3b>7ci=kOvkVSC1fQcyurIM+$gE<>a%@YdZ{WVZ18xh%5|;uls1y$aRIEzic$h5B+X6bOowD2hYt2-r)1wz&6fJT zCc<&|n**kA95x8g*-0c8*F`&-=dfeTVlpRk82}_(hjGw2^Jf=ov~^nGYfGIVe&*~1 zqr#m$SNZ`8r0eK1IN~&^R|6MJq$wkszx6e`D&2AftnjLQa>S>K+p^YGht}|-Z~?MW zQ>q%e8Z>w@xUQor`?&<9YHebEH%+}-gAK*fZlx6*!Eqs%2m2-(+p)2@(URiilu3L6 zzNOe|kb$Hh*VuoCLQA|eN~5dUM+VQErMZ*JCdaO1Gq90>qvT4(iW;pd#7J#L8!LX7 zw%O55L11=RB+4JNW>|ig7^-DXumYeV*@QJyhh&{c@tGQ75A5#GSYt|ArZb_WOR!~+ ziEvp-7t$4F11uKCmaf;)!3s2wmMtl!&75L(lq?yNNR4mSmzfc2z%3pu1LPmZG@@4u zmC04GXKcda$cRQBK`tz8yDX6DS1gHjp{ra5+Hus-HKzkrEU}Xo+nHbqjRBSAFtKcx zp(P)>sv>?ll@%DRjhqn~u7PITGY+M=;yN=Xpdx?sDvgL?m}5dAt!XV&NK`D#U34RyWgL_z zKsPMger*zzlBY?CMm8z@^2|Y}PvsOAV%Si)9G(HD*e$0+ju=Hki~xvoV#AZ{0ukE^ z_J!>st6}sEa_cHc7*sp(+7av~@n*8dQMx~dTLerpZB+%4nEL0E zHf8%gy9(HvMqwIS$QNZCjB2YF^Am8-%J(Szq_F8MQXCR#vo9tn@&mVf_#8$o|1iD5 zl6jwvFf&twpV%)!K>(b$(qpi(V`2?Uq>4~~Id*d7FroMvTEys0vuY-en;G488qmco zy=g%$+nM-aDevon{lzWVcF_7e(A+NB6#}3`qBFw=+ZDB6IVam@ z*GpS~E-YfLT+lA)MuyQIJhuz~=W&??6!a2?}iagLN z{R0kMEWD@OR4MMfX)$uBP7aj7bH2@;Q~2`Bvr2mKH~$BJ&Q1PeVLbS#V-BQepM2Zm zwyd=tH5LXNRt~^y0_ODDM#4|O1d-XcqBD3=YYlfqI9kOnHxKdhk@#JbxJY`l#Uxs_ zU4*PHj@gpwE`>=&xN;uGYP?Q_kFZQ3d2zHnuHpo}q>y>>v$bqy;ebJ;8-o~j|>y0!aRqoS7I-?mD*}?+R0N#gIk99Zm6{J zc)6nyBux>7IOkOfJ)FW7-3a*<#dr#MTC0xO`+q9iI2AZix3TJ zyv9KN{$0hSPOKcZFncg3)5sDTpoICgMdR2fSP7Uheno^1)<@5j8CUQHX4x(I6ffJ2 zT+k$7O2T$&IKLLJi}IuFY*2Xw$g+$^F2u(S7ZrYg6AVKF|AoxS#jJ@?VZD_?`wft~ zqa*^A`Vj?SkbMV!CNR~=VfIkrWSpMc|HAMBD;^H?(tSki)VDavQ@&I*R@fTLclQ`) zz6DI~k;VQYTcmFShT{SgtTdYY(HnAzR*6m+gjRlXeAK*|M^{yKGLf%6DB+$pjV4I)Ru;#}W!XZE zrT;G6>ueAGGF7C5K&nB4VbEhZ*hA1Gz8C4_nol}+y`y<0^u|sK;luZC**BU(F#;G~ zw|DdCSg7B70S7o5{V89F2+gO(O9S5ZAu&3t37I#F9j-()olYAYVPR@-pS9w%V%sTx z5Jz@^y;oFPl>A6EgV-B|)8|~b4ghH+(0vPDd?q*ws5$cvD)nUDEMkU8(3G3bx_kk1 zC){bQ>ZM-u@lf!7s2$XHZ)WfMXRfTl=eRrBAL&qMooQ)wJgHgn&wPp2Yd4I=4#2Q3C1DmOi zcif|%-xq7?27Q!j!X1>Ldc2CM@M{nObH*hqF#9Y%)@{-w4d>9{eu(4Dht@co+eIpr z(J(qOORW1y!7FKo;~{H4P}I1v7}>R>KuxiFp>z6z|xPiQ;mP^sPVTMU>HPBv=el{Svn<|Az|zr1ci!)V3U zmC`C!KLOtQf4=5r$+AIRah2*xq~R-2^~^+ZsmRF=bkwqn1=jxAu-8FuKs*yT*YnlR zm3~FlQK z630lFemt5Ob;#TwEd?)JmUx`6KM$QVZ%|$>iVW1-SMT)WE&42XCaNvlq97i&G?rao zgfk}dDSqtK(hsY3t;2e>^<-ol2Ve+S++B7cK|ki~@8eoMIso`CYm0JWQkNnx@rX26ym&Q+%&yI+#NNtp^wMei+m0QXzChw%&vdRJogKe=^%&HALz zQT4+SuZfX}wE}$N|7LMyjbz#x-fg<)KZ(1?>ik6GhGq$QJ`7vo4vk$WMRPYz!af>T zvK@+JB4x{5_fTzxNJs{bdw3e_V%KjLoL;po^%1`2Hw4NX!Qv?OzkH8v#-25Un`{(F zNsIhs$;m_a4NHZiluJl44eFU5?mNKS2u zeISmw$w?eBP!q7)Yh@QNq?^iQ5!g5VFr5i9IDyYVW^9PqQEpaK8ty<8;yHs%Y?CO5 zxYuFv*wb_)jq*rs4PKJ#{`5@&jiMT6v}#oPR8%DIbVV^eNsa1`d(0(TziS}^i-#4Y z{t1An86>!C*R zw_(FQJ*8m7jM3x_W#ZelRJLaz$@sFa{Owq;vG1{A#@ImPR{}a!zJ?hEKG-T4K>(m~ z;|-_CK*k*=qm&OLOZ}C1M=_OWwByu-iJ~h|1=5Q_xJ`I+L-iNUwxl`faLe_QTih@e zHU98lVtiEwk(J|Vy1QeK<|zyXw+T|eXXH7df|g6g$sFm#m?TS48jAO$paiajOq1?U zlQQhJIgc-8GobZ{qH*w%It>O$LjbMJyVT7u6fFCwMMu|2Z31a~d^8?mbsNL>onxS5 z$q7YRL~gKHOWKZVi>Y!hSkxVXXtzXasmeo`malOs424n>f7RuS)!Om7G82m;@utV; z(F+V>Q`^%{%5R$AWuJg_pOA?C0)3BmI3%A6Rxa?^o)%X!_Zlw-Ufe!cPXIgTJ1Ipy zUuYBaLYIu3lB;0|1U8pt^jY%%vGUvC7Oo5YedBMS-e%{zoE~@lI;-;de@PO;faCeq_2k`nhVzf3 zIe6tD&YNe*KX}%Obmtj*!2yavtzseMA4YpBKMaW}Oha!u+0O80wlY+WAh4N3ywrz zvLtU{iN0Vk`L7kDH1DU$YiM=f_pNFWoC$|2eMrRm*!cu$HyHjKpgSvIq%&M@NFMCrDLu3@ zQHmp4#5tm0PFF~`|FSo3zlJw}6zp(|Rrb2`%G$l1ulNU9oO!*6HkOo4tPy8t@6Zd_ zHnv&i<{thI;4!YRay&L`L>{QwqG!g7w-AnJY1sjGtP$Ua6P9ln3Mk!fc?MmL4390X zUIu_KK@r?BS44ozj`nFjY6d8)<6NKP7G(F`UK@`+K+}bm9svnVW4Iy&y`_0|eC9pu z;j56I|8nDPa1OLH+zRL<%|wZyoO+Z;lzn0DaDQu|-O9$$Aa#rTf*F59(sZK z!LWw{SCyIv!bEK2=X1nZ(TfKsC;V>48XPy={NlTW3o?araW779{P?{>r&ok}k@vnc zS$yzPvG!K+ZUCoQ5N{`nv?TWN_TW+yt^#?FFAuib&Eh@U zoX;k8O#=%Z^*Lb*=+7==#n1C(b&Ki+(vzJIq2tU=r0?MGn}`Fno!15hkPAiy827#o@Y)>v`TP4aX8PnjUfn4N zt?}^`doB)}Df_qw9Z$ELUE}j$$6w!7;5lENV}B^{&-DvhM=kkDw)yjaeV5LoQbMAw zsqEgUZN9gIP*=h~JOQr7*Ys&bmpx=IZTWPcfPi)%!f)G!tr9%ytM(HQK_UijoH zUz)C(@#PqUke)_dYra8gQE|!6O^cJoVatDmPxFWN9(8;-Od*r zY7VbF!}$PxZn{XCaD4{;@OXNj z<~xV^+_>p6=HbuSy>$6L7%b!wD+gzFWu(Wo*0_B}@G5Ca6U z28&D4Lc{(7?uD8q-p~O#8wZ&~+Nf-du&7_NC-W`zy;K02&IW?I*9Pj9apVr3nc?b| zTPY1;lg8xLu**&~(Jws?{L{DiNxVUuT!5G$AImf+sxjpqF>%Ky>N|+{cbcZGz!#c2 z_>=OSaoz=^lM0@+!zUv#^GmE^K?*Q<5F3<4v=E;)^hZokbxyPA#3GUPhx)ZQ#zt5H z#j;i`gK^CMj65+hCtpqkn#k zSP86#H?YRR%P>Pcr@?(lMjs^>Hm5a7c`b*U3oFJf;jy2N^m6b(bx>V;eGCvxYOSbSRw%GW=n%0f`i+FpuVyS=uPSxF%f*4E)FzX~6Em_QKorGj?*g6V{ z(c4i)X(MB9MMlD;%abIK7-*AJ1y)LsZjP0EIrGDogmJUd9*g5mrQrgfO zJ2&l41RH<3T}{ZcXH>*JYDGkEs|w6v%4>ldN_Y$%mepwXxWQX4UPhjJH${M9GJmOi zpeyk#pBCHjTo=E$cW%m?Q$<}~X0EcSxvEw&!@IY%D7Gwc#tj}e% z?}E1*DQ)55*3MI(RY#goB1)>@lBuV5Os`wDP}D2yjtg_TuF}o(h4;yNGM}K(1+L>q_Gg#u&*qcNMowqRl%&L~7WVR>Wv2$C7WRj%1 zxtR^CY%W9?hbgzNHrmSYAWj32nWe8?-y1Ejl|qj3ldu+Y!fZ>5dG+_7crr?8Ek8}d zU{+waHRUJnR%nZHM=trW)m81eQ|o?@9;bmZK`y6IN!TI*tB$XB69vB2DI&4_Qt6e4 zGr};NT$O_PhTzf&8V1HHSD`ApJnuurNp+WvCa!@^#W6If7>MTI>{zcg>PDd#sF6%-9fCoYDsw)LU=kc!xm|#x6Cab1gYu} zZ#nSp-Vst_OACV3~7NcIzOliWix=N8{`ZmN|AEPN4n{Xq9t~_Fi%Nx zPsr)l;CpK#nH%?9<%$4YbD|xfjYRy;c|$Z=-3Di(v&Ouhhf`MxheoH{9*rEg{bK76N6$ZZ}RSg+a)5j zOQJNQV#d*;>S~zt@>m+c@|l-;)>+3@_%gLTmRH%5SNu`8sS*WXGVJ5uwq%R4+v-aS z{Pva2xEMz{Q5F^3Fs(*Q`o&rwB*j4l3#}f!F|HgT)C;>u)gkD`llA$bhmhyFaJiicSeOS zH~TiRRd!Cb^~W zCPRIO>u$l4p7s*qwzbTF*dgfWrzY{ECCEdX6b4VCeM10rtDNl&gW=TW2fX}Bk2Pn3 zU|?~$;Y8hly;QyF@z6)F9ffbcfAt0BU@BV6=DF_CL%JP(r`d`|tZyuR90;oy#o(7c zrP%7_&kB^!z5;POlauZOC#*1GwJTZ1C4a$M>hx%sS;}}#U&<$_(9BbWk{ciIr##1w zggaOi{-y@_gc^>SH`x_CQyhi7UI5vp$-d&L)UaX)y#_WX>b3{L_d9dAw6wHgUY@2E z2Y0+Oe~mg0ocDMYby21`)Octcsw@5G8K?IqFL`FzqTlcdfzFZZnZZ7b=Q6Ae<~M^t zBoLKHKxn9r1&@Z);xw_@z-@xOcfYB6`%YpUCiMjH^p3QgMECkoARtR^(yeuA+Fq2| z@eEI*4Xrx%IlMviC@o!d+t}CTv>s~P$h7s^Gg}S!JTD2hDrQ7(N<`W=87M+W1lY@= zux}?3!0ZY6Xczcwu1xQ{QuJ2Maf<&QFrKJ=mIRWxDH;%a_>}pbE`9-d@_1kQj9+uRbs!QlcqFyUE5k>EQrCQT5SzceL?iW@2z@R4bUmk z;VjOe^rdCJGzVI--$8Z;$xpObK&5;pJ@NrIX`9Q4zUgk>z`uo;w`83oRbnIh9Bty0 zWxAGjjp6x@(cxK=Kizo=4G2Fa8ct3p)3=~HZ}nk%ZFNVvjm8NSzHu4V55Pae3i;Xw zw+D9yF^AL7lrN;jelQs!9ni%s#|S9V-Cs;(hdBbr?>3sU(PZ8uO4OU5w9gqnDysoG zk>{0#pOw+4YFuAUi&E%;7BnJ;-)q#Jq7c~!!R0jMRqt<+Ols(`>*v<1nN|=nX(!et zTgf86Pt$5mk4PnEGT^)XVqR4j{xIb@_eaHv&&ArwnOaDGW{S&|9l~63nAh#LA|XTI zsfV_yet#nB_{!x~VL`0|4lMYRDpLSktUHH^>+O#)5X(ktlwtA&tLtN|mY%s-ePsEm z7w0~jW||YKW%Ztq7rG%$6jJHeDin7fBgtF&sYz{CNA%b{i@678+&p{hcMX%3nbP9r z&r#CsnPOe8hoOjirm5f}HAX>HypQ)XsE{9@H0YW|^04L0k%Jy3DrkhNWlduK4k=T( zqZ2|S&lgucZgiJY4dsW^Qry^{?PkTie=jP+!^w?jZ<=4u8nkmtD6w4K8XzsswHv8t zr8dZ0vr!dKrAhfJlIlE(aKs@hV`gn>=8x~h00nIIYOKeaDfmNM=#Wf(=R_F6h(?CxpF|k&`$t_w0B6NG@;B!brwKCmANUy3 z-x${xctf9fsc{Bk%?;*IayYsfgOJAtr$B1^LlPjib!`C6VA4fmGaar-q3&~cAVG*WCImWg~dcc zpEuHY_`W?GtrqQIW|yY*jYK{*9?c{%F3qgrEqyu82pjSP&<1!PI}THv^2%8gu`}35 zVM0GrEzgqHu|50>gmo2v#4vFadpkEyMnOs~47l*8m;1|R;6?vgQh^{~2rff^I0oh| z4w2?+6z6TDZml&ff$-_4oRbXgtm69>$*w5FQ~&7ix}i_+NB>#SQk@Z!{?z`A!x+{` zJ{7wx3&I}9c1sF++kQg4BN`%`Wu?W?+!dUo1HwzB`z@`L50O!`gqXL=h>#BOV7~pJy2naetop^H*4&=oB6SVg~Xd5cjZQ3bAH;9ko{T z*ja^NA_n}SI~T9Y*Ql`>`pb0gg?Y;`fUmWLL|n59#BMZ}C~M%NC$;~kv9yF^d7raG(@*!QJs|en;Jo`Fq3v1p^|p$Z~>+XoBxeb3jO)rqO~e=xj)jS_IJs3 zUY&|&2dXe13MMek(Y-Uq43TWpi};8GbjvXrofLja6uC(=Poy>E-wX#czH`vJT9FQVChF!(NTj9ZQ67AHFHVl z{y^mjlvI_L#+a_!TqVQjW!K(A(!Rnt0>h$09k0O?o?JoiFz*~0Z zU;Rj5w)%=US=Y1q`@6BexhmzeKQ+Nqsu5W85;Bpn`r1Iei`4S(%}gVUwPrU=%sJ>r zDOqzw4g?i7x~&CHo0;i>e}P=UTq3J)SxGUy6d|;w@O4p?byanT~K%O`iY7;TwpPQ}08V(|&fZAQO`y)T=d zSK?!|F!hQ3a_nfAQzSBtHD4@EMR9r4iQe2ct=B8flPrZzb=0|7PLjPyZIPL@x=*&I z<-pa{o;7cAIfcUFSu_LOV=-)X81Gyo-Smx&;XJzr@-Mstzx(BfI@8}QUo{X+F0c$* z+Sv0DjV*4t5s5}wNX4U7qBdXu6toG$3u#Ha62r_7;M~tQB7v8O_NfO`Nw$2tVsBN9 z>sqhY=`&im%)oXcY-6O&uujSIPn8r~huMfvx3(g#b+6!mV3h){HkGz-WUN!k%L`g+ zgj2J(Fbe;3n(~61q^?;lEb@EiCR~XOHR9(qHp2lpjn|WQJKTGCfr=H zEL!FxjkTghLRHSQaCws;SO#89dP&OX2H{+z!73+n_h*j4Rrxz#YHcEDXp@RwT7p_P zD9s&cTEl>3;g|tLUydF!c~uJNg)WQ~R&iF`ND-%}K1IW8-58c)V6CY0`x@Bzd171d zhU*HfJq6-B%C#Ir?2wAFRuFo1!@Vj>QoYI*=B_!UZp*2E9mnj0XbbDE8r7(%l-gBj zE~+P)t*k^>SDI4xpPZSTsfTqQiXsH(D%-03^PEwu2^0XxuOEXu4KwWvNdC<5_qlGIs5Qdv3bTTi#J>VpzQXI3Ed&*vFT(~@N7ibIhArEO>P)vvWXPVv zEEu;3LUBaPXRWDL`7x#pDl>knQl9rEgMmI;`>vIvg3o~PP1Nkb^*68(=7`0?9&NJ* zv3g1^MdSeVZLpE>>skaAM%NG_{3yknSh}{$?BiD0Gnnk=Ia~%lJbA^?8*lr+_YYfm z^<8n;F7Ub>c8l{(%c)1kM7b!RJHTb;PPi2B_vOL*!|ZM%Y`40}1&gT26NeX)Lb?qV zTyBKrMR2z4qA&0eAcWygQZ2?Q_HW^xv(MiR?XUsArkSK6&k+JgCTUwPXHQ_*MbEUv ziIb86l)TJvp9#`6lH3gMJ>A*qGvNH-O9 z1(tmKVR$2MPvUHAU{KmO+0)s_S`TK^-iBqHY&1V2eQ|1}IKERI6(5B-pfvur4<{(j zGav>CX!fdyNO{4Ea}T#1l?6Q_kyhA+77>C=tz_f{*xEjreFZn2qDU%8JkHLK20k`D zK5PNyZ`O|rKRR}X1bw2W8_}6M-l^62rro%q2gK{=>znBEQ&X|`!Je*rM!M&U-!)7( z*2-v~sy?Niu}pnnt!DDTo|Oqdf>Ca=zncQsiMSbY*}tlj$^hWhgnJj*ty3<4Ryu0K z&NMWIS>z(Yzd@tDNvX3qmhm!Zg_n@w6{Tt{$6HNM&+1N&#w}1U(%p14!d&^PHnbob z;zU{O){OD#*ZEm^jE-0;`AXMc=a*emvcg7KMJE)Ao8+gDv;<9RrDBUx?EOUF0x0m3a9f<#+&rc3No#fmV?CTi; zc1664B<@ZlPK^nwzFq-6#Rzei-pK#+ELx^OpdIJJExr4-ZJ96tTtMg8m zNUJpr?T>a~AQH%LocAT{YIuys)`a=_Kj&OKWpk%yYVVa^Pq;!}q5N^|L%@WcAzaMU z#9*#k>?|>h_|k0kfGEE#Lr)BB<5<^_NaA;p9Oyz0-mopDu^rPRu$tVa(iy-}TO|f8 z4>uwoTC2YZ}UYq^`)br5QN``FCnQEuc6Xoct&Kn@kcQ3YefQ zLVPrjE%5Hw{TYzr+7-;D<0)wS#XJyUpzx=*oD4v2Ay$%Asqw=tY2T-^I;=uI6 zA>%qm$O(E$gO?ooK@?SanTw2(Ji)XwCabemvJc=@(t{OD*;#!`STM|wIQ(J z{(4%}4J$@VRWL?Pf?vqE;3v>u>MyMb*XoEHf}}Ucma*-jm3NK_Adt? zY1Jq`@c$idb_Tjr82KB{g@x|rbRI)@o?9l%ika*})K`%X8NLbTrn|;l><@a(ua4go z7T58)5;oE?D`D)mU(%C=$j0F6TuG^W}J&C`ysB_8XaDI7Akh?D%^q$?zpd&A3Bn&ORR{tNzS z*Jvdf6rDC1Z^6Va|AadHO*s2mFCcbJ$s+qr`}4P4B}uplD1*RbDuaP0CN6xW1}E`O z(Q*=Q;)#W8Ar}DY+4gfMIi7uyr}wEQxu^{iZje#W8rY)XcYB6FE8_7e9g$Mxcl;V% z>yls@gDQIVApzg?zU{G}iVl6JCdAHdR57#G#4%Kabxz6U1Y7K_1B=yNwfENEqjXU1 z<;UJz{FxXgm6s?X2f(>GHYI%HPk1MCs0y+HO)!hyUqygV7^(NuO(I_nPo!kIjc)NC6RCgUK~!poQn0~(G2jp z=O|F21_it!h`|F4?mWh$xszZ~kPLjY!kl&IZDujj-*(`kh3mdz*R zn)ueq#~py?rsKEm0ae%A^MwGzmpwSO5f)qL7VyEaC1!Omla6W{V_FUmHXU^Vq?mFv z(I5F2kHgFo9G12lsBoro5hx#+aO1HW&o}OE^H9;y&3Lnbv8t*m`^FwPC>Qc4yTz@V zjo7^96@UK-UhFD*BA|^i$kCBUp79E|15QPx>HF@0ig40JjWPJ>-rms6O zOZDk7+;RaJwL=P|K5*q94g4QnxmaSYaHRl5%y}aeBakKTzuru>(PXi*N?)E@nONzC zBV$d?yzg`&n|UQE=Eb+x7U;S+HYjyQQG~{}tjfh~kWtMytl+asr~PEQg!BugL;bWz zd31m;BB$I=lsoE;_W{>j`W^AxV}*s|1o7Ju(Y89tO?jnXI3uG^kP2SICg(M0f=65% z3}`uw$*z|bAy10*U4ti_rMqE$_OuZ`9zIwWlzzIL{bcC z5)whtJ|I+jB=`LnJFVY=6?``5?1dp3Z{=+LXJR76frH(tYFgi5Y29# zu)&&W5xgf;$S({#*9+|XSH-k+1MM*kC=lYd;K4~8+6i%AjNIS`Vh6PegVsiW@jwH5 z+km3o>&w7;aTY9xo@nY=TzWUYVLWG-;&O_vZXS|lT)c}^OqS^j7{NPz4H>(xZiX;^ z{@oeFe(=V8lYFg_ZOP?XJTiJ@e|?+LUC}R$lYF5)3j}|uJl2~>)y-pi?@L{Tv%Rw~ zE1mZ`KS~zjW)X(`u^!wZzl?gU2toqHRVWbho`aI~?#wt5C|oftB$eeWvnmyr`L~uG z!g!NA7H?igz(XXEJP=Jz?VdU;Zrnv7&wSUEqmLmjY6Xm>g+RW$j`?>;${I*=t6cy zA-y7fxFCDdvP*KftLIUDwL@io?2Sq|d|JQO?n}huwtkSyhPR56#T#Sgnts+k>2%S+ z(AF7^NfcJGgWR2-bu1n|@H#sI+q}~|@IS%1!Faxe9C^lFpl71cG6vKU_`Xibe@n*0hbqB_jN)YNquYMx{cuT20?o}EiMRLCELi1= z{IfK)myzo$Qs5{Uex|FXG*Hv640KWw?LOYu0~bqlR00$m#o(?E6e90O_b+{Gz+Ero_53Ma#P=gXw?; zjN*5M0Le4P#6gpP5v=i=eb^HxEfL?oMj$m-&4WZAiF4{<5>N;wY!C#+Wkjx=%YBx+ z5vzi^zvOIWsYJ&}+w8>QjVmU;^eYobw0)Dd)3~xe1N*s$$}7^y`(T6H>j_%kO!xFW z2h6(Vf~p9;w7o*;QRKS*fQp0MO%DqSv^D9`*PSlZH==ND@w(0$Jl`FCcn`x~PD4&k z!**?#A>mpiP&NmE+J-T_zu4@qdEJ;Pz8fUbY1Pc&WA*x*Cf3A?;0rD!b(!6Z(C3kr zK92rSs;BCtdhS*ySb>oH{KILhx5Z(?KjmLMZ%X zK~N`Vcw-Og-w4mYaFtId0rzbC*$|HAZ+`Ft1Lm@sP%jJs&YMWt2vkfO@;+H$`Bln6 z{_j9xdkKa)9MK?Z3NfA7JaEN(m%3t4lXtz&yk5x6QTrf%sk|iCI9Wh$Wa3G}dD@wp z)Wg`L#^1?*dp}4D2BrVb@-+x9@CITK?3-)F$}*zJkWZ5?(hlSNJLriL4fx0 z-(DLa68XQca}EgpTNV#+?{k?spn_79^SQN{3c|_dv9UCUaAK{<{LR*j4MRkHvnLw# z1~iTXyMRd!oTSX6%{r>XpVUw^6lx_D@~BAPScuH`Fq53_uK@Y zBmr$i8rv`r0>T8zOpF{#R|xl?i2n&GQUOV)D9AuSi$wp^wD1xc0M`Ev`v~1F=oh9= zRu)83)Ir}IXxw6jXQK!m3NF?&f*0?Va}T>7*ja-e!FnV9gkg(}ApAG#gXAgb4vt>9 zJ|*YM>^bM5`&4#j>Sb5I5BT>W%HaI|{=>a?%S;U4{=f3k>Z%;J@_*Al)}HyM|4sYw zqQd(_Dij4zU?~m|!SYr*5Wjdwa3^WVhe$oS7i=mCv#hPD-O?>ttM{3>C5sgiUfSDW z{(_lpqNv_Ej-i|He5G#Pm|VTR}b z+`{k#D?@$&5?&G2$Yr;zx?g8$#6M_Uuxckgp?+S@jpr^3UKY83 zhhiX+WFdOGAH)N8NO9rn~2l-qUf$rtPgwB8QIY$qG#}SI= zcoxg^M&?wdbB_!Fs`6n)8JxJDApiU4C~H9?lB$w50fT}_Bj$2H*i~zkiqA{Zi}^K3 zl~5!eC}<%&ZCRF$*Jh}0iylZH|MXJIKS79lA`z(bK~291ckTN!Oa=OO1b_@cyy5iN zvp&uuWnaZS-}zL4I_W&BMSv_cOsa3To9T%#5Y4Bg1$=1Max5^1~%VNOxHs(f>t`1 zE4vLG=K9{C%XzEYa=+YzutDnt(p?Kcdl7BdXbtDu3mF9wGfggyT)6AyeA9H|mPl<0 zdW2q{I242E|Mvcm)_b!v^F)?Jm+A~y6J`@;Y?TDZ%}1dt)pKCxl7gUMIh?|#lDV!# z{0@H>BK+7WE2g(zhurmf;dsUMVY*?_L1AE+)=J7~V%+V`w!hu|@%tC)g|_*{>-p+H z{h(W&e}1_|GeTkPMV%Ub?zYS%D~HvZQn?`}@06CM^T0_>o0+yitE2z&S&0eAqO&X= zO=2p`uC$V$h{qZ}7pFH>Uyh_uujh=0(pgsn>v?L|P51e<9%v14jSioSoav+|NFKC85-*RYUJ4F2V=U{BrPB875-* z<&xg2Zo;|BYITQb!$?9g2*;E?C%1Ws+)WRP`2Wf}^LVJfK8_C|WNXY2#*!>Ch#~vF zh9m|}W62<-D3T>I8jP)yZkBA>Ns(o2NkS2oWt2&_#=b}4Hz=Mlzg~Gf&-{7M=X>rs z_ntfF+;h+Qyj@bu)9bsuoTALExXvkv0&@=2_G)q*DdwWmfe=%cG?y9mZ0q}lc6_*o zv~ov$)xpr|fJugHEGex)yyI+ICTpx^^2guwGj8h|E^EJN3F71{=@+G|4&toFMu|qM z#Y$ZYOhRxe-v~c)^Gkq=nhDzD2}!~ti9y2sgHd_7(UUs!>B^V4$&_Bd zgvHljzaQx2j>J>1@2j<~VD*Pvv2kK8(`-ed@yfTY5CmLD1YJxU=gQ8E=1@DYpU|uP ziebsAu@46_HT?1+p^Zh%xpLIApIhk05Dbs`%SIBLhA{H>P$-OPIBp2ZgDKq3+c}7>%pN0Q%wkG@ z9m9*?i+!k7NEu$f$0|4q9w@rBLkyo}C=HsMt0d&izawrsE?5dzR(1^@sDQr_CkJLZz*@j7-WLI_)rQN zkUT@H-g2wOP-pzFuTx$9Kw8FW$@eL10d)8=mgg=UX-;EgimkWHj+a+MZl>D8KrhGQ zXbp4E)yFCk0DGn@w$s@Tr<|;*s;a)paV*i^BF1=036l}RJ(Lb{B}<&%NaNaK{Uxan z1E0Y$`;&#URn&$fFR5rBkdlYR$~^~>z?Jqgu1>PGZ5n@8JqC=k}VV3xIcNF^8tqi0^O zRR1s=9DRB5b3&f?iHM?V@2jBe^4**)divXzSHV+Ty?2~JbVKro?$#-QgxzDGM`7tG z3ihG0?#wprM=?^29h}mI7uCxS9;jnc*{Wc}jOl)!JT3kbB$_%e39m&AIbTz&igL!k zYCp@DWzrvKI%sw{6;+*?s7D|fx+S?H4!-FLk?aR@ov`dWOlpDTaqPi&z$sXiQF?e2{&}n>WUHVm^2#9Q-&dl4Dr#Is1^!ZH&VC z5%^Ox;~L6CBslzN7gq7~Z2<^7=2%<{rT!wF2eT+Og%o@)Dk*jXJR$vlch0o%Aj`As+StesU()z#K*|+q4 z`cnBKF{N}f-TlJ%PxHCkdN-N6H+|{56%2Pm<`;#OR~3R|Hsc0gTW!(gzJcqO9(ApyQD{r+AOX$3F*ocz&G(92fr z<;R{>yBif3N1-VnHB^yEY-NYP*h`b)6G(d>VQuHSMkmfE*kx@zeb(I5O1D^Fyp|7c2xtnC^$Vo&4qVyawMcm z_KB6G<8vgN@J=sIM}(Shw1e|9)U7q&>%5}Bnfmona){2Ww?-w)8lJxu$*r99PECBb zVjmkar(D*bA>O!owO8s$(KVsAyMB8msWavT*V5^ zt^3>P1cC(;2FtJ98Bp~TGT$ou7Sy>VkZ*%+D$?S+DXo2bn!1yOJST1@i<1kD%A0B9 z@PNHO)X!AaJL3`&X&fsAKi$&XRB<15=i!EEtJ4?{ zDu}TNd26v^M%5{HAn1MDfVomuquI?W(-7_1I^zgulIbe*l;xrH?|qQQOf#l`a#+~0 zN@elekw!V!m9<~tb(Q?@1;;*)7d?kYRW@3QWz4Nbc8NFky3OPvtqBu0XNSkT~{g=s?s!3dQz^Pp#Ak((m%;zGE@ zwb>T2GeK#K3lbz`1;@Hc%h!tw&yf{(ts=es$~DZt(0ANb@&Wr3xCNf9ja>FbPc$BB zz_)#Qd(or!T_KTZBG8NxS58Xe3Br*&vPn|2EQvFtV#!rb#)*jNB&MKk8jpkNxm9{D z04aFFz&$Ba3^W(GF>E{LO#xDc=Naj~Yah1Wz}fAhb!Kve&vzdtViKf;4RR?$h=Uyd_%)TOykIC1o^P*_xKH&=mO7;Znc&orYt z-0#md55N?kXQW|Rfu>?8{i5XG;9U^wPO&s>m#`^H4R)v6cPj2X({HJLVjXEHtqwH4 zBXyNb7c~g6FCbRtZ@^m_{#`L64bBJ9mH5JT!BunA+7PL1K8bx{IE6o9Oh9>wumFuE zLls*8pRfa%E7519AyEK@r%?J54Pd@R6!3Z~F0g0t|G%}k0F*qnWZ(0Vr<#-kVb5Sx zj0y)J|4a|IXFd)BY40l+oe^;N*?HKW?KKE=VxPdu1ZaK^1uh$j@79%J*Blr)TgpRk zY)U)sT*eG|n4F+pv^|4V5J+iXCM*_z#lK4tusvffD#37{Fy!nXp(Je2u?Yl{-6wj6 zripgYOu(x$Sw`B<7+|>!N2ev^-rENVB)2a!%T$`kutEv8H*WmjOEQ%~6aD+bBE$Ia6HKmv(yM0w NNswbwE82Y!{{uvZmpcFe delta 36446 zcmX6^V`C&-vs}csZQHhO+qRPlC+5U9H`>^?ZJQfwgS*drznnkN)qSd~s&`I*^d0`F zvqc0b{9s1P{qci@fbDj_o)SGZcGOth)FdL8OL)J_BV5J0Bg-Q#0m~a{rympvN!T0C zf*?`EI!3lL^X~80-SxBgn+G;u?F#5HaR;_dDD93ojdlBorJ;?Za5f{_E|uh#06r>^ zY+5|x5bua2nd4?pEqL{ATr-RDb>V^WUGMavPGn{?6EUfrVFqeUqtZa!Iee#Qll5`Z7ED@F=0&DnLuUlzG z21;z=*DT?UdaTs!;LD}w3u8Q@*l2p|?=Gf$}v71vIS2OcFN#*+Vg$V%{n^RTp1=nrWz$&^+rv-HGl8O`D z&J4~UF)9^WbknNUst(V88s$JJ4ml^5)M%*=S|VJ)5>*dFE(T}iZa!8{)oEK3L+=g9 zVWg@xdP($nI8`RO^*DoB{F;oy{7ebsF$cER5_M?n>N7-I;z_2)iD&P=!&C#UjcxQw z$^t-|@b3_qG~-qrv_`%GI=(%JE{aZ=kV*WmC8X4r&vt3GNE=A=vBMf!a%cJ0N>eZ{ zxUrh3%oD>7wP8%?cK3LQmQ^jJ^joB9(6SOcajnlHwx(^-h zm?aY2KWq7tXvqs#bSAfwPiy%a6{FjVKO(V06@kCl1bq zEgQX9a(z|bm-rAH?Y+I@q}ijgG?b*kS>9Btgz@Q(j(qbTyj^id40Bt@x39wW`4sSr zt5Zxdv7qO8&erf~%H0r*Oo}ivAe_m&nALj{lc|p7ZH&SXd+bTc0!h@3L8&p^Aaqn9 zciN$gum8rgxH*o=C!&6))g$8K>i~Bo-K1QBkaXq-;XwP&0z1IO;SqM&#qieXeqij6 z;&B@7N0epS&mQZ%5d#>?J)7VbxpuAT3R?Ze#k zs6$;!M3+;Qh>u8oz0c-U)*8hpUbrBJ^BuwE%_A*qD6uAmxWy%%H&DeVT%#|7{8z=p0SQ3PQj``SJ zCOR{SfrbsZfsB*2D>64ScPlJK6S!M038ub;r&nWnC2pGY+z?|P)vXhHgNIhPC|%_a z%aluo0WYGjzN@FcM`HuJTNl~(?=$Sc=~kA6M;(IE-JDLbWu_^jw(^4JrW4&_Fy zaZC}&GxUK=dKp?Ubk*=bT!{<13hMm$_N^I|PlgZrBqj$*SC9dk)a?~FG|&PV%&=m- z9j#m3b)Be#$SCZM*pP-HemT<6t1pm*$y7UJ%kJ-|jd~a@G=9cEx&nk~>zQM_FE@%m z%H2miDn$y?8Rg9=1Fl`C`DeIK2)_RA7}kE5JAfEipj5oZ2vDZg+d=bC&ryAZXRkVs zTVj&C#*M4iR!|2ZUBjq4DbAYY_+}blzLl;t^0_;NWaW-l#%5aF0xd!XO3UtF-|3vU z`g#AxmRh6iF12|?5`^iq+7asw)F8K$>%~8jbTVr}t zj~4ipd4oOt1lg|RP3M+3?*^rE1E0jwJv>_PEa9Etlv}u8dSSrHUE-u9h365> zh~HpnZz?6X`x;klw<=+pnf)@xCX-{0X>>`lt5}h9Nr-7D$!Om#q2Oh9?S0WV#5nbu zkEr8X@_&MQMT~O{!;tO6i(;{0o^g7EVoW>*$5ws$Br7^OmW1gXy`c*L;&J(mq)_hr z7XnZiC$#$G;Udj(Uf6Q13&2kohN4d#D#cHU|3i%J686=Ow0XaY*Cr*73Mg>xzRMgd-Ra^;(#gGxi+9Osx$W+ zdtcw1K*BTjTDq}oNUpU+j1<<9IVKcM1{?mnUYTvo!|X+LV`D*@8eCEzRH6!+eQr5x zW4i(#292HQ->?5VZou%CUFGMuZy-oe0husJ5r-ZCkqSo#5*vk2vf{|XrRy+)Qvbn* z&SYa2#D;V_tcLG_$Yktc$;t{VY-{4UUfH!qyS!{rSix>zbd)q&Tb=h-u(JWk|5z35 zU8eD$zGSd7QWfc$%)ZZkzUy3Z{k$9d3jmu976-4@@AfNwT-%Kx$U~|StE0yvga?K= z(`EoTA)4kyHTooMn5-RY+fzWwlB{`XEc{pEcJo=mOwV z7ciKK8^uBme0PDg^)yyd+a7!q!L*qgVkqS z1sZ>xko}h4nuL<)Ct(#(H77D05dZ-!LDBpcTPUDQUG{BhpPldA$D z;Iocs%8g;0$CrdPN>k1oM_8m2UC`Z@%t@`zE9y)2pw2ln<9dCVRh3747F{(U%NFE( z)PwdMR6Vmj;ECDP@(GN=bu|#e=|}+ug^9vAF*yPidjVsMp+zv)+VJ{A%*Wei@$Cl& zXaqN|W_+Vvxl(mzF#OkqZAAMHz8~E1BXbm@>(}5B1jX{iw)day@IcXlGUxso zC4hwRKo0pmHJ3LvgA4O{=Ts3L8~PRu50C2iM7fTIAU~*|s_m#!8_UIsNRfcva&t(R zEllPL-UR#2-bB&q#9^0gGr7^E#f(1(;&&fniGjb4=5MG7K#6=!G{D!&+wtEc@eE?< zco*G2bA|d*6o|~*zH8wL{JkafaJ|HUqA6!cZ7D05sKGJDK0RY|lm$;L zv`)Clv4ak|Nx0LX^N%Ig>i7j#vF+85h_2~OQn zn8m(~zvErL&)v97SB(HMj}of;JZYW4eeV}GK$8Y~f=W(>oTlv%W#=x@TtU>v(H#V)f+n%pHFfSQ zCIOzuwv!DmG?HZ_wR?orW2Zgaj6?(s*z}5-ku!!b}wM&Ofo8TDWxNO(Qv== z&{tJ>DBa$Ce&A9Ie&x6G`%>oot;wsc;C3R_xVGT-$1vJfDL>%s1ES~g!1z6`zD0aK z(~N5;#dD6=Yo_X(w9LZ^h%-z6G@I{4|LEeFHYM`VFG{h_4Du2Ab$65IqKXlOhukbF zjLt}w;&{SR^8!%Xt&|Z!?Gz-0-p*45`!hosHZlffg4@H{W?Slp{S_`+e}5v2S?7w( zUY`qo2|cy94dlLroiPTOAwb&ryK+4+>{|20kaEAKQR(-8wawB!&5+y?WbTN`4)Ez% zDxpVBsf_XQ08egbW5wNuMw@C!o+0`0qEmqom4w!K|{KmKAOdrm30Ay*3VA#BVy#L9p|)sbtW@nJ=ZtF~rJ za&>-VXNK-0=jPLu@@gkL*AK%S?@|d({l@+gPI#O z3q}q}boAWP*R*y_YbIru2#DzEL(Dvtd*A(U!BUj9oTU@C0{LF^`{$ly=el0c814YR zl@A!b)b)H7-YVESyK0U$Hy38$R~KgFZZzN%tmm@n)zXjtft9=wnjK+4glnLk+{*t0 z0a%v_=M5^i;-7Hxo~bj9_36^6+9Lh6gLTL2KSC@ydo)bX17p3W0=1Kh;r$#+s6=M8PmMFu&o%(Y}V4*?HEPbOp0~w)vey-x9uUeQS=03H?rq3d^z_Z;YP_nsh4R31ET_^tqS17VZ^=sT%BYl;!p7bB=T6q@E&b)qRYUj?;s7kP z*rPi#1=K%=5y9HQt$f9~5H!b1qx*Ez%yQm$jITM!ccedZe`z%xG@$7fzuu4u1AOD4 ztOXp-zmPwi^w87l6Nbq3l${AM3rTF@xD_3|TwXS8izrA+1io%$h zxt6R{IC80fM!j2#&A@eqfi(&xC_)t{!&*Y5e_>syTgijW>p9R#zt4b7qAu0WVDEnF z(Q87qK2gu<4XXUel4oN@{>2w45Q?V!_A{~(6^goxXEbK$&Q$6H;y;v`i2tkvWs$i9 zFj7-ps5!qYJA>O>r@5$(i%XGPN!1|{CB22qwG8~O>mYB?4gIIW<@FKTw321Md=p5% zwSyfmk@f_w<^1tG;Z5Vd|2q?J_>H2z_vZD`jQ>M<%GKYH3*22|$#b!|67%Zk!hWu{ z8(W7KQmCvk^fe62wTtG0XIS^2R6ETaz}j9aZPIyA!P>hJ>jVx6bZ~I6Fqm>i`<0Vq zj=X#AVjt7o&nzbiWz7Ro5H8Y=7Jc(DIw++>8zK6rN{S`wRiu^F?q#nNY+Okdn@sH8 zheEx@q8cr}ajak*mb~2R7KW$Cf8#psw|j@OcGF6U28Nx)p5y4n#>95^MGbcj7^e?n z>2i{{NG<5wVBhMSqq*eW^LxrZOW)=j$kMX+xw^UaL=K%p6XDmv3a&RNjL4^l1D}J! zLB5m6hqLDpoQ9=Q^GN|RyA5ePy$~yEZ!)Xk<^mWRZlB>~?D}GDNh2jTNqaWXz`Mli z+a&LIC7cMij2{Z}bTr+5i=W5<-qqP}GtmtN5p9-*s^8Gzm>MHU74Kr$WSX7$(qO7W z8N5qV#-+yMHRV>aVugl4NCc({1w}BzeX783jA#z-7VJHgZt*;*!f>}txyCOJ7M?W9 z3B^oRwpkNZYgcy1SMyIg7Ot+={1daj^!(It&SLJ~xd{j*T)}EkI1-Kkw(g{$U}vC& zs8=+GXT^A&*1Jxsc>);4Enf_Dr_rnp2XBL@GA-mWjT9@~R>s&lDrTP?)zH4x=Q z$}Xqyk$1Rxnz`u_b)n6eMc?T9La;<&zOw8K>6HT{LP@?NIx561k*}w)%lIF>u>}r? zmj6ixGT{Ff7(5Upl@ee9iOOEF>lYUp`h>_RF}PYqtXh*wvKrV?@6=k3om}U3%2jMa z<(=pYW;V@ZFXCx@C67YLJZ>doK<=|euI2H{pFG5Gvq39x*A9-1?K_>&h$rPFe->fO zwu3NBr76f-NYn$8B&0eeA~%U5SsmV;fP0&Vk+%wEdN_PHzgGc@UdPcTl4T1HEj!9J z*8>c8W>ISid+_fq7 zcUvl1H4n3|hE@Y;)bhvkSKsGxGz$*5AJr1$n}2rJ6S__Amam-)t_=&qXV1Y^6wdPr zn`8UgJ*{lT{L<}R1Mn`JHs-Zycg#a+PQ;h9fUK;whY09%`$txgu?hTk;-%f0Z&!hbrq|BwF_EEkm=#79E_a6}PC@w2 zT3$aB8g_rTDjdGqJ3JJ>s9xS1PIT&6FSU4RthDfob6n$Va z&tVP&l$o4<*f)$^38}H~EaG2ZX#AS9U3&@M>XQ$VMvTmcO z9}$62i+<6#60R=s9IAg}fFDj+dxn@tQl!^qI?ZLfC_U8IU4-ALbo7lI*t$lb=09OU za4@wCvmSqRFl+wR%lLm$9+BswSBlyEi9%Va zDF$Qstq*L03y&J^SnG7Wao63Y-O<1M5Jo+&z?(OhYhX#fg^BB&1=6o|y< zi&A0+l6wAeBuJ=Zu2L*e5S*+^Ja|4fBYN<0g-ylGTr(a-JGHrNHeEu3ftTGK{v)BpoLI z){J6JSrpB!7V0ec?Cju6NkGMum#7iHIlT7fP379_eNQICLE%L{B_mutHQM z5#<8IMMy&0ITA6k31l9AP#uYGxjr}OC?yjnZT`xfG$O|jnaNszvSew+HxCpzjmj%U1IniG zoeF&>D%;2EYZJMx^qecg+Ixt1mkN9cRvmoX$88(O&BOo*fTTv_n~F=mNammbKW>P3 z78k*wKqg=_O^S4Cq5M+wn+2uh1&lbX8TQ)yFzFF zLPT-w@%)?aQqt8k8iy2dpY=r)6dWn&_l1Pz?F_JdE!XCotC!jB?ow*M6`Oe&d&og^P8Wz_(~g%ABiPj2dy^w zI*lfi8ewt9-v}-PzK0n8cF+TCppcP%D{0d$)PbwH`@DnUd6I^?YxiGQKQ*=ddHvJ% z=tK5F){K0oRGer=y!=`}Ku~RSD#&m!l@l#VEk_?yl!b&dr7XcMxH_d(xr!I4%9VD6G20A(9X)m$%>Q7V2OfnWE<>^EFIO zvjbw1xtVX0;Xg?v-R9_bwO*xD4DOE38TO`~>~prF;+Lo((GapvVO`VG;LAM)waxx@ zhpClgW_rvwI3GG<;VY$+K@OAD;p{meS#99uv*p^k2!ddt0hmVatrbavej@HS=w)C6 zaR_5*U2m^jO*ASqr}3xQRM1t?&00bkTIsFoC$ExKFvdIet5$FOxN9~Fc@5}GXgV|J z`Qko5x3{+&LYp8so@SQZa^O5N$`lsVu*j#7`sZU%v@t`?7qra?PtPu}r7BE_KbgRW zkr>k1Wsx=60s2g%rRp+ibT#KB)u%cN+S{0!Me?LWMJ3`I|s0Q)viU!(=*$s zQKZI#qOJiZHe`8OW9Gx*mJ}?isskWy;A%Q#4R>a4vzRnp31#a6)C5)`ep#!0b`8`M z`qXhlyAt-QJy6tQslmX2f$JI`sw4IUr)A=x^PI&ApwEfvh;-IqoJA7`gT$Q+G=(d0b#u?#on4l1;Nhkv9(IyLZ?=GD zZ`kwe+f$f&itE7d^Rz2t85lo7%H}gHHR#okzpWX(2c*j%e7ZC z-Ayn*9XP-~K!830C)vV#WI32nB?iM^(`p@MO%uBCC5`vR2JN35)I2~x(p|!Rgs+Fo zfV?vDLM8|94je3Z3a=b6Io*hxN^Mg|dbaHcD2d@q4}Zv$jcLQRC&4Yv`Qel8y&p4s zfMIS08uXF_UzVLo+Zkl^X0%Fl#IdGtl1TWR$@DDJr(Fh^@H46^FQe%_8#nM-TFf2n zw9q`QPABf#Q(0E3%oVhS*{eoj^uuY<#ItNvuBF_)YBS<;k!qBnPUNEBO}TU>YtDE8 zbE~mYyEFpsb~&B zWKksvM&?v?Q!N%c7XwNp_3#2lV}m9jv%pR5jO0oEBwq3kl>85y?pkQ^j=(kCmU`YGw{|xGGwk2+~sPMn*J0iT9%i9YX_NRcBmrKnI=k|TN zoM@T(e41ti_L;6Ok9^jMt=7s6^CKf=!v}M8f=~fR-%S%#CB`Oia4Uzge*iP$kL1a#ZnY#- zOAJSOMAFstC#HrKhi}$I}Eet0?VQ3fSVxaZT_4nDZ|r?<(!6jsD3)@Pj~0#mTo9(G9iKNxurA?c!6%8(kLp zBW01MP|KCz%Bm-KplgvmN&J?nQ*7MU{XUu>3)u^{A3Ya&cFG)L4*-+E&9eygME4g} zdMGRl0}L%TfB!i=W2gF=d}S3pAM|(Zv@l7=x6mzghN;tX~6wT*R>-}-8L%YetL?v!ExrO`cYyicx8oFA*{YxP%r=W!j`8nAGFe^>XFAhbtW1f3&^BrvbR^}=cR}|Fa`g$9^TEF? z8sbZzD;Nq{9&DL8h(2``KC8&kUQW^Jm1xn8Xjp|s)!I6!D}W>=c4#v3TzCkM{XYBs z1pCFZnzorHBZEz0nbyrm6Kq-*=J;cyN{-*ILB_NwR=Ks6HQrER(;@NDUeiplFz#l} z@HdcO+exTm&$mLuB+b-%=#T><8@?}qn4;#^2%EuK4m#_J$e98tg-a$d+;;Jt8CsnW z0u4e7uh`keGC+_`W$$PmJIX9PZ^9Axj|BW@BFfP%h^_`J4|At-wkX=hDr_HBjt~6V z%r;uD?}YB6g!n`JF0hfC5YD|<>jUH&nw<_~44 zBV3rD2tUpB(C)~SAaM^1SQucrrS6tUV<`F=nWt~)F#yu(W?o@uEEe-)rk$>#-YlyT z8t^ndVTJ6`L)_2A5DcxPl3MFNI#>k%6JuD71|agSEPK zwGdypG$Z1cENa6xJ|9?|o3M<|AY$wa8 z^85Lrh+VDk31Q<%!NQzdKCU0D(1%@}JL6QRJ6Ws{ICT6xHHJ(50Z&}3&JuKpKx zPJyNQO`~q8wr7~?r(eW-eEstR^r=A|%=@7{5e9xqYd%8j=l|42Bf4R<5U_9GRG|L1 z%@6X50G1k?YzW)k6T`}}LYksqgpm4T!NrB0xG7rBP7nL!RFLWk_YGSUf`bWnB_mgY zc{$VWGhHo@FaCa@3L(<|U_7{0zd76bL@GC(+Wwrj!^Yi4V3D%g>`^ ziCT9#N$rKuqh1ie6*o6t9oMIgZmKTC8PslE0j^z_!2lDmYciqvdQC z?qb7t49g)oT{*qcR)+$b#9-$u+SVdGs+nNRtf+tM6B8)}7sq>&hgIA%$s^^81fKN| zdo(?mXlFaqNY89DhChe4_`||Nyn|j77s<7QmOd95VM{(xO%F{C*Y*>BO46tg)eD)M zYTTCw@nD=g%_5z?gFNfhMp$s*)s(A@5$J=~R09}wW)Z5@_7o&K+gf#7Kl z+TwmUrkdFcx1!bW$|%(VCe-Oqqjn3Skvc3>*T)Ty+vH%Tjci}iP^B9oyh~|A11qKDpyte94^g`x+6c>Lg)2t z9)17q(U6`t66zS;qgCC-m47LQu_gFs23O!L5=t^9D@@W~>YC?{ev=bCisM8C@9D}N z!tEr+{q?>wt}GD+(7$OI_Z$d{D9;ojNLufmScAYtWXj4PlOnM*sZM2FuA=aS6Ob#oM#)U<|t;(yP-s(ft7s)Se$UC6Cp56Fcw6vF!0BV zFmSN{X^GugA_q~6ZT^p4K>A~?{?baGa{`tmBJoI*di|#2r@fNb@z^0a`6xTb}x;%a`_4f zbM>64HQuyO-Ar}g8-)EOFmeQt?t`kC_eDDzD?)`Mlh=s{akvnzd4)EnI^mj!f@{#+ z$$owRk0rI;!xN(X3$(QUZ}&5j{;y#WKngX?0CVL&hXo-d{|z#C&~Rgc(zQU7vVIk@ zNP)Oic`zz^aG}e#9mO=qMN^Zlq*_D(lwfZgB^YEJ-V2qH9lEm-Vgv7=E^pS%kJpP0 z&u^xDNH1>w9~O7SnKDgeywP!_?C}UBDVAXzzZctL8~h|NL7>eN>GQ)$r9yk@X&KODhKyWIs$B{npjPhav69-W6wMnz zQ7tzHZUt*+IG!RGV|G+^Mqa_v+ur*IK(%*&Rm*Q`0nCj+wDW_VLc_6mvzMrXe0}t- zX{J(oueT?L#ZII}M=J_IAFvo-kdUpUv&!!4BOL8ntNlVoCp$=d4Cs%kKQEyg6}{De z?0Jv%I8#KoG(kh0-mpDthm?mOc;z*G-wFOReFMwkh$D>YAKLOzr0Zk*@^kNop7t8X zPvY+ue26_pSnEiwK1Qh4->L6N-%a6~Gc~FO|0~|qGcj@YziCJD|JpFFxGn&3IjvA% z!RsYe}l`1P~1J3n{)W+T1nj_9>RAVfbB3Cf&~RsHa5~kegw=D55rq0Vc!}nS_G^X z-7w)kusRmex=Wxl#=dvU`2*Oem8;aNmdYmCA6fl9^VxrDE55~Z7jvmFCn`G+o+ii* zH(}M*3ToH>#mDg>v>*nHnldvI@hM@0UPMI&PfWy@@9U+(FJDcHEJ4`D&L}lAsGP)E zA~=lwgWZ)en4Lk50P`an(uL|L{Q;HNf{k1dOT5utr>?CTmPGJ{vq9I_p zI7GiWE$s;gljYa-<6c*Og3(I1)X`iQ710+5;V$0aI5n-8Kh7XOkb1jIb+Sok15we* zI<$mQi$}cTF`uQs33U^1@7npu>zDq~*N;I@jD|^LLhek<*1(GY{b(2S%D(IWYCQ7) zHMW%$0Ps7a3M2W;3QS{(?uU}i5}JI6$-I|9$z}Ax3;Z4?W3q( ziQge`a1y9qzQ0oqzWn$>mWe-=^}OA=_3?Rd!TC*eQ}e~i{n5t_IWJMbk~cEmlt0$D zo*{bt5KYb+RG3}28|O+f!;+n-_z?5hW{4&r0LWFjZo|~nR#8exUpM8#gM)|zhBUmK(iav|2lF0vVJxWBq;66 z>;d8;0}6pTG>5KJ#1R+w4bF;)CgRDd4pEJ&kn^nJ*K%tAY5%)Nq<%Dy3#p*D`wes< zO#}JtxTRD5X#~QP;R1|d-`~5sx>`o!su})q9I25NTHQNRWkb)s@)7}yvqW9T6qc%o zs-4cwtxlz%;|#z9`*(;DfS11i`v3-*Nw|v6yPHZ&qx=2OqnJ|Lp`&-rOtop6Sk{Qc zgU_e@?nV&Q01#E8A2le7P1Gag*?Z_HS6^Fu2g#z?B+$6`(H@`+1_z350ka~DW(NvK z>locfpm2Y2?1x*3NaA0D7yfy1eqoeUN;DYkJx`wD9&s(4!H&b&1}Qnm601|yoMB05 zghVOhhm4x#8_9(OtxXlO=u)-76lal?R zQr&=4sYO<83F)jbLX5X8MKsUbCFU4r9Pz-+S$nt5-WF+GEUb8R0fLhw0L;?Gvk~`d zRXkpqUJBO7IycAutgx5klOZEak?tfB9QgLptN1#(1^H6*0E@sUOj~7MU9s`H@ySKO z`KQ?7vVV2RO~cjEO$T7@_vPScLuBd z4!5#;-gNPERB@{-oLG7Xpq1OYVqUkL(vv`aROWFrL|W;JGBVd6j7DB>>BL<>p(Sqz zlCXZ>BO&Jxde}*LPOs4N3W|Xt&mr(u=z2-&H9lWOrg6<&#XVfOlJ`k@`=1M`L+zRf z`Y!JX5Qm|GGMGho*R`sO&{0Az_as7M7#@aXwF~z!?$EVtA!5E0^}Cs~WY;Mq8>W>1 zXE$myl+u&U7k99p_?=|`$$qr}e0;va_YzTHZ`;{TmKvNzZ|Wf{Xb>(>k#`w#Zi&qO zZgXr?=-jmcUn{8te+J{e-;B=kHm>n12`)nfF#fwg`0!!IWV|uiT%Ts<;$mWA64T09 zk2a)Pq~Gl zXUG8Y*+w5`9u5^IjCEXRns)GQ@RDw&U6_&!GUDy9wEd9*e}u!I@Jpe@-=nnki-ki5 zIBwmG2a!;N9HHY2++A=D@925ChoU*LaU8Ydj^ddbaoM|1QGp4_{)NI}r6R)7K&H&h z*+30oP4q&JRi>`9!x*3~?b{@COYodaa&!ot)59NO zT-w0adcmd7%Z^($GGI56xZoJ0GMrh{E;P18F!5yvuMvFOPYQ?{rbe|fkv?@m68NKt z>91eBU9EI-J(brr(gW;zj-`LSLM${UWcrW>67g|-WuQYAg;hGHX735Hsar)sk6UiJ z6U@}FJfdC5{;A7MKxgy;sRc4bteJ*~xSBr|SVR8s_Ev}p*Ti9EXCkT#t^)q7Heq^4N9bv|5 zzZFns^NMma_Zb=!`_I+%|whQ!T#BNEc1w(HvuB_fylfDDKj=uxd^puqK zkc5TAovWy1Z0GU}?&!XlSng21kKMo@{f16q4$n76M+6yIrsOPjY>y0n_{~ z@m+3TA>TAunKrvEXHrwEE+8Kk9UMw8bT3px9;Y6uY106lzuRrKEZ8hdxNq%qkJ<;U zU8Fn1yHBXUdxHye;IVS9F4O#E;~?9AY%O1HsKQWd9WjC z%V3t9wjY>8@=V`AxDtO)U9HrTWt$4Ws8#O6`T<>KRQ4i4I)Sawa4E-UdT~Y<|#)bY^?iZ||K@YjmBbZ15FF*CwcY=g1EwrS9y7_d+JQ(2fVtI(Y2wB5|Y z;hD`a;M_(HHeE}hwC%j+BT$a{+acpRhnPW)$Mhkm2ph!>{+cO!mE4}LRf1!?`owz9 z57a@L+SM^L>Rh#}qQ--zprB3RJtRM=GP|f%uy+a&+qi>yve?4DOJ12Wp@B-2oo1CA z=n5<-b$(qYQs^)IhGD`yAid;9%M~VkRB9Vf&V{YDqSc07zaGqmUIvaddU~@qPmq10;bIjOeoDDW%Ab=VTXu}UhEasG``&tO%H0{&jw0B;E_$2P#{OjY<~-aB%G)7L=Y(;8D3zoe{ZEs^e>3t!GH zxN?vLt;}FJD6fi4ZDFsGh^M8-XwU}9e-s8hpupkzCp>QeH5B372 zwCFq|Iavp7fE6T<$gxh69!u!X9G(&h!}<92t9CncWXFXs-1bCzcXJLNca%eEypb_m zw7;DK=g?+gIcY~(vVGM0Qh$gOjnE#;%M`})s2?;Q>*yG?;MXJ)pnC&H>*JR=&2&lM zgi_Pse*df!0=NH6xHvZTMt%qg-=G1&EZ9WQX_KOb#Zd8EYDi~STC)JFj*ZbYRfo{u za>n6nj3e-2uUNlRozK{oGq6vWZ*6lM;Py6o;j1@Ok4z)^|I{}{@Ra2iLoN@zYAjLN z!@Vv2Rx^+#U689#yMRy1&X0+eI@9Y|!LD3e7k;KEY&TIC|O={*lXTlxe?A>6? z`4mN_%8OTDfOVj?#>i}eWNHVyH+Da>99@J$m`{iNxFOnHI=9~ib(>yoQ|@(pHQ+Mr z4>GJHy5Nad1)1F+Cdg`{?TeE6zgX`qtu)s}SuZKz=i*ox>H|<)n1q8l-y8Qt;a2Q* zJ4(umEJ4eEW=q$PySokKeRQ$_*EUmyyjlzLQ%v}|h4aNFrJb}lc?`r7q{Q|hxAN4| zOe@@<;Pn)xkK;Ac5!?{?a

x=@At#P@*q_%W~j^q>HM5SPsO{wLhFU(R&U23Q_zP zi1K$GWGI}eCOB%6ELCo)?@~N<(Eox3|3OjsgfkzXlV5KDg93k6@ku%XkS~ctqRT6L zt=nrci!0Nb@CE*Ct#$i5Bvv_S#TamHgZ{iATnY2<@=4udPioA}>V>g9X~L=l@>b~^ z;;yj_({GoMj6ws@?gx17w5KZ%hw(!p&3g09yhg>&afr5y(dL2>E`PA(P#XesHp{)< zL}~K}3U{<@VeKMMxmS!aVEV}&rducJSE*s&3N;Ck+wQ8A!c!jo!9j4k@EP8ZHE`sX zemwfKJ9Z8OUC~E#p`BUtAuhV=)t$HL`%a&yxDB7WL*ij@)bB5U2zj}fVF}l@)j;D? z(+hV^&yl;%EnBs)p8-PE#<|Juxt7b=r4I2GFUab|l>l8T!M1}`!1_2dup#aO2aW5C zIRK@X|Al%0{fLBqzFcOQdp%+g0iU!8UXu0S=^D%{pZ>L5EV5(FHrD!(ZU;3fK%%+y z!LCxMmXHBvdL0g0^&`=kur$+hP8gtVLvKmGu!%^VatV zHL@xQ@Ic|t%U-+>m?^AED8p91)%5xCOX-%gof;?GE2M~>gUkNT(R-*Y3V>t-LC;&( z!K$PRexRp9eW$-#qEGxRzX=8g#lH{)x{ebKP zZipia@uYH{QbBVbM;uiItyLD8t{*`f)!WZpN{q+n)^f957#1z8R=T9kdQ&{xEQI{7 z*KZthMykIX0M>Yzk_h>>W8WXpoX-Lx0Iv1mkx36zV$dymTtT13vr2>JIlrnRuC~N4 zJM$xgGz^hDmkbA$Z0(CHyrow$pTccN>U|AQzr=E8s>Nw?n=4^3dq0|62XGRTTZn$i-s(~sfZ`h(9Hub%S{sAk0WJvO?lm~a0_ z(m4ia+BI7^p4iUBwr$(CZ97kriEZ1qGqG*kwteRP&X2pgs%!t+Rd-eQ>R#8*kMk{2 zN=X)>i$j(k2k|Dyw~t{FaO=UC&jolBW=B>!@@^5!Czjg9A5^yq$GGp?abA=6 zgxx7t>^NKaBvjO3<_a-6{64Ym`Xuum^K(B9)O#s=X)2M}zHbmGOC$l&2kZ8U@%#2n8@-iHOe z7^^ShjbE9VHmk%66>C@UoocMU_Yst4j0y0h4){7zIqU?AHhT?SWT=kyqSyh}2v)KK zCH3EGe-J6$22?bg4!lU}u&G8|lA3s#^r^8#izc@wuZD`Ag>u&oIiw1CO2Cg1jx;iI zV1GOR?8a4*#A*fA}%|ZcS*}Gat5cuS?{JYoQ1cgVhSwh$U>t$6Ww5?YEDQXS>uc(3Qasr@yRF>L* zy16I1+Ob-ofJ0ni2?9)z1x&EOrXaw`0+7)|McdLhNr;)94`>8BG@6T>o83G$sF&^B zB(1Ak(8=ah>T%ZjDyp}veYa9q%&WI9ONxG+uVoS>$s_==`j6Y*(=Wa!8>#;^*4t5I zktV73oU>~j`_1-eSF|g!LqJ&i>A#vtgp0a@nn>+0IX3gWA~jN&HZIw6qS+*i5*b@( zvfxx8Qcfq^1LQ$aOr)e)Ubhj8xe0Dcn{vtiV?;EP1u9uWC{vDxRE4pSp(c`N zFf258x`zl@puf3fNH(VP6uPTqOdLvSce=C13R^?0`)K7Y@Z4h*uvV({sRS}_>=HYM zG4jT8X>H(XiA1_;Nu&-?Wi!->C4;Lq?x|=EAF|nx_Ku{D1E__Kr#k%3_z+Z;1xl$Z z0;+A~3e>9eG&=_*+y}xY(tjI3ek*HIi0GBf-5S`E>gF#%YYiRZ_SDW>)g`sq#Qt7} z5g3H7Tbb`r(h?SQP#&C8>7crSb825o$XT{#r*8n0`2Z*A~Jq|N=V7XZ$u+EWXpIbEACgO_C%M|f0(m*cGsbyMJBC+$LHmqm~ zJPJ%bi8;lKZS3)~@=C(QC&y$^M(crgCz#1kA|j>B2o_sMW@!f{8sW`~bq1}uG1IoQ z5GiGK1&&!?S=0|9LEq2vX_31yc!Z5a14P6j-yk3eF0p-1jB=xl&fQi3`B#MjUG0B9eegK=pO8UHebj?gSv3K(^F=PjA3gYx25< zRa0i@386Tf=0Zg4$cuxq*GG;U2v-Ir@`yE1ql7}cJw5kgl?D$V(#Kuq<4BDbkfikp z5@Sxf0))w|N?5rflEtE91_sNwRo0_^1?97P(Jq)sk|o9rTM5shDxF*qs$`}=Z}@*_ zi9fzq%KE23s){us136mHO>S#D`#vSp_WgT-~$C-jSEui zfW6HW%bBanN5PV*WDG|w9PclUFvsz!y9dK;J`wyea}~?ZMo=EAinf7;G@-^lV)__VAND25Kb+lCfE@w0 ziF)cPoz$S932OR)R3W;Y68rNS|f0PXr+~d2eGFUl^+BM;w z;u|PkU;S672a)s7e4sZZE*)ycROthmry-sb{-fuS$E@9FfC2$YYoO*oGj4nrdOls4 z6TG`sREfx^tHt)1?Oo$E_2X?i{^S)wpf)|T0u z_mO)pI=kq{ID=Cy>0O3pnehDPM$rcm2rzpFK9|uZ`j8_K0EdbO0AY%Ilz%iA+@~MK zx1891oRuz!_YC-kFwPej(3-4V5&p^h6=e2J*$mJ6JUGeX6`E@M&Ar z5OrDg;y~%`vh10lK!NJJRO~U*X2USAcdMcTo-^$7R=iiH6B2}otsLhJ{tQn?zjww% zyyJ=iQpO`~o;$j<5II%?xc}YO3lV)H8%HaOdIys41B+S27y>OWZ)P))EfrZ2w-4 zdIOa+5#d?WL6cr~+}JcuYs02A>sIYp>}dA$zk*n!0d24Pf54<4keK9?PNxP1KARN;FSl6y{9%k%7PlXi7MzoKP+SvXO&2k znXf}Z9^udfad|{^jv!z)LX6ZD3mxYj%C5&$O`a2!8}PR#1`0HEYbwjI^tt;9#OGjE@^BZLn$SgSD=yZC`-DbfEI>I{uar4=qF z%~@W{iKQRQJ7hA;yu-#mwh^AY(BSWmrV#kr<_UROtgI=+*jNsPctX76^5 zhg4ZLBFPgCdJ38A#t8Nw3qoqNKQ>Z3gj`hJU?Jps`~l&}1h^c#PM_6+{>uE^kjeC_(0`AM6t;s+sC9WEMU@rkPe zVD>8lHU1mgV}9a0iC?Vf@+RqmtcH9wf^g*ui`ytpaXm>gKbly$9)@o$W>v>j55I;j zl0e2Yy+eGn{)y{p^({wzhGF#r1NzE3+{Os5v(j8zr9o!9p7K@xSLHDG>@(|>yD2EX zPDCvQ?pY1tCjmfe^-!xz@-185Gc5QC$R2r6{`z< zsUek7-1n{U_TmXV5)jl|HxB3p%Hb)w!*})5Lv_)$*nlwZsB&6tc3^y;{nmf21$iRn zaO7H}4vTPMLCRVEHNW$Q&(+h5$+!H&|EY15IyXAX9U79B%%o3T^I+6Pyarkdn1Ewk zA9H&KK{)%25CVS~t+7jM7FIG_(@fLAgg?1P!Z*v*SZ+r0d#oOc}qqjzdi$iK_ z5uZCFY^zj)rakn-y{AZI_`HoA|A+NKw_QmpKZT4466i85j;D>nyNiteJ;OLuqkvXh zlN8>hj4aHA)IbcBf*xYj9|ltmC=xAR<3GOFrBpZT-APJ++hcyw4vES@9LIPpeI4Yj z=YQD{8!enf>jBWH43aRBP2Xd}#Oa21wkdM&=h*2utZVNcF%=7`e~t?wux{8#2Ge}N z0Q}N{w9P6giO{J3SbXdV8!*dgMHAfZz;Fr@iS+6|B zV&!P36MN%z8nQL&F<9v$ML1s_TkkO5mg7=}ga*e-i~H(lYtE9=n#DSlk9ArD0_1>L z3&w>lbg+&R$bhc{$SAUO7Ve>Ji)vZmrWH!TY^mfYaCY=yg^C7XNu~@AD_lVkEp?N) ztXHdc0}ACDwVJu)Xy_0CiMq&OhPb8w&VWX=j4W|EGntCWp5oNlgSH@-=>$fUw|6KSL%;vyr!wq3Lj;|8-{>T52E z-}tAkfU*B%tUDkOoS^5bel(t>od>2m)idZ3&NLnN&rN0~uX^<=yT zVDjE5ojUt6N24!aNSF(pkaMpNI9QvsQ7$g`&>ES+S>x87xR9hPR|2>(6dOa1S9;m zxFR3$43SwWR6&F1{;O*%XWv9C?P$M*C3U3EtiemB_HwN5Re#S_kNn&X?7z*Plg|z} zy8&_5;xNl8(HaU`dd92irO&^$C6A9;gb@6v#(!o_{)JB_*95x5_d4{fQKs}YYld`N zo|zYZUXT?a4O;qoz_;`fhL~6aH;>^@tuXTpmp$^1(fF9GdK`70yK?^hi{9Xm8b?tk`HxYmIWB{SKAbv~$u!l^&Tl(^u()?)F`^z_&`I6%J0Mxo$ z<*Y&{1VhyBf8Z?a2c2~H47|^o_ody37Da5O5==<9+ zK(L!~GjJ5=P+MSLb!mni5>NOv6*9io#t5 zTpEOLN}Y%T94vp~^Ob>?qm%?98`_Gr^lf44SBrl zUvrmpT#Io3<}mt8(s$ab?D32Spl!D25E+&T+I|~<-zB zUBP{sO%e3tqdB;cU)tTB(frPIDFOs*=jOeIxt#d-zh;Wb=U^%r$opo>+g=?w6_u&2 zx}P>~ykpL}$8_r_tMWMDTL`8DKwusJ_Qxvgj-oeL$fT2jAq&w|rwFO2AW)g^rTCe8 zxvHh3*>Q?1SK>SSr9E1WjHmE9IZ8iqTH&aeg(3t2F_KqK+B@<|J@m(%w*Z?ess z*W}6rbGVOSI*O=jfaomViyP?7ua?n_JgThAGcwe~IjHorSF?Q2QpnT+Y#*0_tR9IrxZf4<@eW^o1~7_|p|r5`>+XBK{JT2ge zI=n}dvY1XSk|Ku#L~_H+1xg6pq5i@EQq(hd&8SqI|1918P;-Lhl`Lv!Gv%Z28S2>- zYquq9&%b}5>e*F!8~U{4Pz`h*s*#SnEVuR8tFF z=uA+aT9rK2T)8Au%i-vVTNYNP*0^nnuC(D5alN>(SGd>aL%d`!o_1$uZ1NY$o|COt zb^mE8lUHthr?FN2fz_>d5I!Bhv;S`#(aP&c;)f0dq)Yoh56OWuBLK!n+Z62wAi3e4 zX;zzJH-TB01lLhx*;=2BWWc}$v7}_MMPc~ID|NHQour+#eJun*WpEGXXwNzf;g(TF zrI)T+B_wPE3{6B3T=6b|UIa-IDgK>bKY{gXT?o+gxcT6F!hLg-^}zdh&ieserE~?& zuJ5`u%xYi0V>U$B3Q)d#m+-A>?Jnm#Ci|5Ybi`>#mF054wzA;X|8L)e{i9ljW7&R$ zZpI`r{avCqd306w3DkG5h!xR|CH8;nwI{UYf_21+cVjph2Gf_C2e=~l(n*mG_f^q* zTgQN$IYs1!b%wl^9!ksx_xX;Q5G7d0rVW>wy#sPfzYsfMYh^yQWgn{3)O;Nqvu=U* zsyxb^6gg5IlR`PIYir%GnWRcZf8uSUWrJ}>Ah@5=i}ivtJS8nN!gRrs`>46;F0Gl? z5Qo9jAv9Sd%fVP}AK9FM-qtLX@3@UNFtl&usc6rtFr z*7RZ64KD*gY?8Eo@o2iRUI;DCO~zQnjj$ml>Dk?X;m#D9y6`#%k5+}zv5=K?P^~J# z9<}1lR8_X^LZjarBTWx&1Ybd|7_&|QQkGEbDG2tUpHEG4}M*-Ccgb4OD zrs?DvYj13jBeE-nV}YoX8N@MJu_V0;$37ezqlq#zTo#g#L{M@Jb{L2c63?LxBZ@@R zpq!U0xSP5@B2%MI%gHQ--Zw$2gSAGD$z=&VD6&`)6(JmxCLf3@D%^ZbUawCDbL3hc zzs3Tntc*dX5-cC3PAjE}8n4(+w1roh>l=7}30BQ$ySMZQmMi!7a{i4|qcJm2i=RkO z^o3h6o3++toZ1@#UnL6;>9!uh0pY-~SK+vG#ba{7Yo0>Mxgb09e;_5~cI<0onsYTB zZcKz=n|F50c=A9>=}kzQEIfNY{#hDHD$k)Yq!Uvq z((RXGgc1hTPIm!qh%*o^%ce=jJe-(C=`Hp^8Nf6Lezq8D@xe5f!3(LUH8f>HWu&uw zB2ulJqi(IVcPf>2ONZl7DQT*3ebS~@Z*?Yu&8|{)=T#Y#B&Rlp~k9Q0Fo+m~rR!SNO0iG1a6$C%_#|xLmVV zx|H_crcfv7Dy`_C{m=o5k!G2J6X_1%&kOX{N1DI^8p|y(#KN7;aIY!EG_JXjw_*0U zFCubs*ti1lLHQ~aJ-<8+$cXFa)uf9 z&1N~;Wjg3DqW;y;RRWa0NkuZ5F`|BoS_7_o9k9oBM@`G~v(eXQMG^yse&G*?97mUW zjk|jZat)e2^&}N^C3(APZRz56aHnWyEpvWjIXgEfE)%&-@@(kTZlCYySRY}^QoVn? zAWUdfqx;Zhz-RV{SohDN^qmA?JLVrkhqI7AH~dRvo(<+1UM=&zd_(Sz3H*+BlU}D= z)*iK)i+W?jy7cN*Y-7IqhC52jv6h!Lj#i~)|GCd-g9cMY$Y{4SF-Z2MC=|p4aYvbA z=dY!(M|3zo1xpN4%57RhB`;irPs`kt|8GV}*O^e&L!B#bcK9XvcBUXX{5j@v(1 z!G>nftnHpTof>{Od_Q{0NQ&qC!4W6(ec^iglj0SIt9WXPY~Ph~rSc+qTy=zdNqtMkdWK``BF)S;6d@57A5$OMFJ4RYjukNc4q`Nk$Wod=x)l9{R@7alzr|^GjVfnhVMLvV$o}E-cSBvm&0`^YXAT zQsbHHCinAt?d%eAOjob^UlwOLjg&Kz>!dANNDAgs#JnXM(w82(mKT*5r0i0=i7VbH z*j^A7(KEJGb4PcgfE?C3NtPo9;@}46%uTaIFdrg7;VaFKKvnz+H6#YBSgRde^3}km z=?6oPB|du4i=kne4?a5FURx&tz*!;o;NfJlI7#yQ`vOP2j%0m~BkYZn2Dh)l!ua1N zBTENQsOnPnXX*f@Fo!K7j1z}5f*SoqzAZwArx_gprhwB1Q%wBvub>X*6;D`1*SF@x zwHP}f-Da$BoN#*!Gun=nmGamf-pH^hYJ}+Mj|OVA3d_;#4sV#r;B9LLT6MDF)K(Si z3&AWZeDYBoT=GfXg_#Q6K}A?Q##Nv`Zgg5Gh4o{59B1IxoP+`7%C&vlb9KhB+Cv9(4ii{o1yr08EbqIG>-F&n?K_E4 zj-b#C7F8A_3%3vsj!^HR&KERJK14?Gro}ic=pdMU$P>!cR0Sq@mr+P~k=F5W;W;D# zj|5!k?bmr|=r7)fe%HauS z;B{rogLLFjwL7a~bzpVR(bn0sO)MS2BI6oUCeXC6r-Kw7GVWdQjg59mRjJ6_Ij&9Z zWF==SD!&rPMOAvtZ0lq-hi5W~l)WDkhP1Eb`!vA&xK>E`Ck9h7Qj)zWWj33iv`>&F zh{|d)9I5eA4|7hUnBT-@ZY!CyIjYa6!kOOep;Z8r_GD!9w$5sb68ndTk@???13ri& z!Q&BjR5#^{rE;TDCBvqi%`Mvcc^rMg*?ZjLi|LB(aKctwzW3R&w$WA#=07Th({x~| z9~$8}uX=5mFT06Zf5Er=9JO`{#8m=zh6&;D`vp|H42wQZx*zPtT3t zzwimXBluqs+@WWoQ@Abl1`4nV>`D!(4UR^m8( z&VQ$DSu4Kq>zEjX2TZ3jIwv{n_X@P@aj5^eKmA-mgyMilHAKiu_F~6C4`7-`=OzsI zvKD!vHNsu0S?y7Hi!LpGN{}#pE!;6TX&t+euv;c5m#lmugT6%VuTzHWAS>pViYcT(rdGm+*BUa(PbU+{tbU7)od@(A!n1602M|(S6ZQxP ztF}!k(AM_KQ#l@E!nH!H#Pz1wHAUGbCEJBfJmAppwJExtGCiMx5Q2YlR9?HRA~`gIwbYLG=EPptl*FE^!$1I1{3-QrX8srf&ck`o2j~Vdg4&xj=wHo zLJE`-HRMO5Sxely%XTw5ur=nN?cJ*{ngBW?kDx7TVZoBcnJ|4hc=gvEtqy8mFv6~I zxOoK;(J!azw})(gLeC!$Ur>dSz+UBA_c;#-dlLt7$AvA|KPlR-e@LW~Q_`i3=%q6L z-}!FeQv4Li2JYU1qUqjB+FV?b2?)_6QI?0}Ie*fsZW*Yu{G4p%(rPr=nBUk>*;g16 z5gQ_`)MZMUG3u&s?^?UfSaii7Apny~l^g+cDPn=DA|ZPeCeFSyuQ0)XJ!EP_HxP-f-B^Eegs8<(vMnAtz7hnsJIa|w7#rw@%1{9DXMC8IUN{Og^)~t8Drv)KvKa=rHxi<2J8v@ zk*c&&-p{}~4xy?iXYJ8&{Fb@rn%N?P{w?77_5KdNfa5!<@{#5Z0byZip!f>*U$5x0 z)68V`Z`bMM-}gUeZen|&D8NU1$@53yc&Kx`5}O>8=LTkr2BHdj9N>?1%qQs2|@u2d_&nJ+C}Sx^&mb0GIb1Z-~~dHJ+;C z*t0ho=K@aN`OUd3HfM0+%C&zilatA)n74wQC06N?{WPoeS` z;5iRD>OnZlgZl|~`)wa^kI0RR4{@nA8nP-z+HR<#9DLUM4n3Cp!Zh9*4BD*VH{0w~ zSG!2_$Ac;NUlNee0J!vGBdwn4(epq$rpQ9wLQ&eprOx3Na$ENBy{WyN>n3!`>!OFykOZoAkt3VJeXP#Wv=BT{L6XVT2x<5}u zUm{%E4N(V5wK*pZ)-pBZJ=0Ih``Td7Ml(hA1f-qAFi?YuInvsx{IR1`YiRYFq^VSfE}HqzLa#|+h_ z%ZSah#f`hir$q{xd1Rd04be90x#?3N!2&JC3MvW;GiaCLBt=kGW#@#Pp72&K3Opi= z=U~?8%vB)M)%Mo>JR8`C>k^q7kyC*w)0)bNtBV}OfR0j)#lv)HTR25_?~ds@H%w6r zGj#HPmtg07FuF2R|L>BP!%dF$X^ftPn*A?<6nw8ElJ-0O-#A)wpW3c&cT4rBhZ<0@u^DEp&C7Qs%w-_$;T)ebA=3dOR`F|ISwn?P8HFw@J92l-kJpw^iXr1&<& zfnI0fc<-jPTOce@i$xkVygF1^F2ifKMlB`&a7QU-5A+Fy^=%^4zOj6ES>`b7@=wx( z0!lc=))2SEW<5-+-M-$0#zG)Y zoc7X;du=L_lNXK{y?`55p+s1?HmlpG1mKVCio7<9zAleQY+d75V;N~SoKAiblH;=0 z@=Ei|svPI=MRj7j7vg}@tYVjWS&*-b1LRieRSuJMkrHR_Y27andilqz@DI$z29jJ% z&h)mlc>eM0Uvma7DkXkDIW;DH*L?T11Dds6H8%X`Wgiv%hLT}Sxo>;TXz7M=?~D)_ zrJtp5pvy%?)n5&Ux#St*mM?r=HB((VvVEv{mwv=L_6@S0x*~m4HuQ>0wB`O{0^lHK zr^03WEsrhq1STOkJi%(4wU}J!tPDI>(&Pt|4H5ka4tK?;Ol4ZdOkxn8he4E?EH@u( zKTtlZKinTSLAlCs*HjL4AeRGbemAreR0 zHB1t0`@<=;}tA9y zma)wQ%1L34=N4J$!Y`H^+{#jFq)W>}Z0nn2aexS%c5CzHv-{Q!DD81LadETsc736J z?c|DcRcrl-MdasB=0Z4jg?aLUNMb11t+#Ov4KR59aY(HN^Wt(uGOW>3G1h?oGe8=3SA(xbwjUqM%NlhIdaczd@o`Os``9yip-1t@QXi&w0l+n8$FI#N`mCe}xWlmu6fbFF;w;GLl*84ovNdiEbbee zK7g+=h~bD#^jZbBlrCl zZI1;l4;uB4?WP!E)CyysQ?5pkWmB&Q$%UJjP5$fHh1*I1pwADBKa$WCzrkwTZF^~A zef@;Rte+m$Ll12AtGA%G(Vvf=;M~6+m$jUO0KE|F-M_VrCEHNunR3FrA{=hrwDK{L@$1{Ury zYGp+%?~98lU^n2raSHU$7Zu6f> zY!cSUlsFCYWn%K(p`}Vqv5wN9d4JR^)Z%oq4y*LwAVQbHVk6KESo;|WAU56c0()+Q zv!NVC3D`&qgTNz9gZ@TGPF%!0E3poNGNKNG@%bx3fD7^I)^j`QZ~H=U?-Nc^5u1OA zB%{JM*ph%x$3_nu{_$8%p#sz|!+KF0IH6KI6|}4aJl?52+XFvk9YSOp(3=-hB`n$l zr=TI#>G`E4>=E}i;AW3$-Wpf0V!@Rs-&-Gz#{w8s-h$Z79#5?iEs-k|5#3({<&X?$ z{aEZC0E+IZ_%65iLqZg+wu)~VGei%98XIi}@$fAlaGr*gXepFc2kH4Ul_9=m$HF$p zWqhnztBc=?!eItH*c^V@EN^QVSfng^?&z64D6$KXwaa|9tVj+r{hwye}w(e z68B45;E5rTqW7FVeS!lfGH})}+)s(MD6Q4c0KU#G2cO!5if#|pjX!OVJ!nN?hKr|G zzrrv|bsOG?9TauDb=P&+0kS!Sl!ML{$qODV`CO12n35N6F32!M0VhCH&k1kw# zu+TZ}gtfqkYP;Eb#-5o7W|LXkWSxbYarrB4fq_vxoz%PqfSTqIVxrI76O^w89rGlj z0H7DJQm?;Or0_SY(Vm$R3^G~n-*c4gH0Z~%D#W3bcBv4$K~M+Pd4F_eV+^&T6ax@a zXO)nRKo%ixy%}p_N@8Rb2ROBIu+s`kPMMpSo?%6~a`KnVi*Eijh0wXNg{#*M#n#iI z(=K!fo31-#2$`2#8zj_(C!aMe_D&q;0;)a zfhclp#zucIa6=f5>{Z7KUJ|Ee1Hg7Nfrd9$m4Wr+T(BLx#xG#AYu*0JY%{|dn^X3j z{6N*mO?8lOnBqGsOH$x3Ak$FO$m!2DnRmf6Pzh zBiO&dr8${f%wgj7gQgl%GW7zn@MbEnQ&$p4){}P`#lg9Eg?&2^hU>w*{&kKsgV~>7dQq5X%}zI?bj;9eR+U--z86t+98`CC{zqxO_Y8kkf3nd4V{UB?w-Xl z^~=3WH~_ln!x~*0+6p+I8DKo`TGt5~fKVr&8rN#}$HjT&5~UbFRlphl^A#}$fVLy( z2i9)rEzloiVXXqf8MB8qeB(8vYHd_^j~(K}(qhJp2uR7{mF1gJCdcS2*#S90kvA-j zbJv&2c_|ajr>sB64TE*Uxai-LWKZPri^-8Lb{i;|Nj-Dt5Ys=#1n`E(?qERHt|)oG zGUSoymGJXO1IYed&dARxwfyMgWmNgtCcwK7&dgm*zKKN$vWV_Py_THbj6c3W*>}0a zH}T0zSI)j)n;dc9B}JCD-U1q&ZUj)tyIi{qWp=m+_)p@egxaKPS=OC6Ye-aMrWUD2 z*w(2=s86jpuZwh@05bD>obdBVoOt<#3>@(xb-RvHGMp)=f}HpEwO~`Fho=G*6C4`- z`ERCY%O|U)shpg$^u|3>Ke;P* zAqDjyc0CY{dB2>OtX;U-9Qb+|mmO359LSo*ksAU{|3r|DWk%koQq%OJm5rJ*U&pxg- zVqTR@>)H2e?LqV0Q-^ld?CZEOFKZ%Sxk(y)CF0T>0sAEl96lM()n(d9HuqbABJMKR z1Lc7cCr1(tpI2s7J;jy7uAjYyCZ_H{@~7+F1)+h(h>ix#XfQ4w*|6lBhM?s^y0 z#^qK;%qle+DdUXY8S?r4LqUm|RCo zqRq}jKpQm|sa#fV@+UGlhi-1v>njX&7aFhp1tMHY8mc6xAG!eL{8qwo{8{Ij-aDQJ zUJu+miLcx|57UEM4FM~vq50F|OLAjQkOkE;0 zsVuQFwdfcB9o#bNEb=t*QurPBFSkPi5c@CL8rk_@kdLq*^&a0OfYnk9IJX!IB1+*j zHPAu2;HZcP(lSX5L4$vCtQhtJ*KdZoh6s}wCrxM6I&2_fn@(tpIL}h06SJr^Z}IN> zo0HZ^XI9OwR_559nC+H-ylUxM-;jddPTjDhxOpWf3)d?Yq z(|)S^r?(9i)fGar^LDZ0)fPNv$Bq2dW1s$}F{ssjc<#I+w5;Bq};$?%w9T#pJjOWO& zUQA+)e$_HXna@3N57BdkgY*{2IW@P2%r*Dvha6^3<{dxZH|V?|){uk3Lh~bbt8AQ) ze%msfiu%f$vXGP4lquo~XVwvG$azph7(8e#n|lRjKt}&6f-$)YyIVVM1lkfiYv@PD z(mh3T#L&KO1l+&(UF~c(NP=W*suyYU0tpg^_}iA|LP1ua+8?5kt>62pK|5 zrXoRwd75nc7%sp|>>&Oc!hEUr`s#yuEiua?QAjXE-P{S+Y;3YVkw5Voiat{7mq8+E8VX5vP#4qLI_o!_odl`y4+1i6Aq#6lSTVXIej z#u$<-bKaJT+G8UQrF@u@=5fuIsCl8T0>SmO}#dy{) zZYA@Z_zgHURo+1rf~l&77GMySCaQD6Pz;}F$xLi}JRI52jr<{3o+}|-dPbnAlmgGr z4euV82Q1TqD^@)4*$?Fe@bn=+pDgS-ioekv+JsX3)&|!laEhP!>iHj?4;)WJQ~Mv8 zUF&~zzAQ$BM0-id#Ge!b04O8kF!^(BbA&GlX{lO=ZWV8pDi{(ERD{sY!letlEn6qa zh8N-oL3c2D-=F^^ROPupC~2`bsrF=t4;NpcKw@>|yQW>;u{npROMx~tBT7>y`V~CX zO?^ryY@_#SY1~XfIj>Bj_+?3p{q)TABg`y0?+p@xu#o~kmzdFjkbyl)bKOUFer@c5 z-cropjii|t(uYm5X*HvsevzIm99SZPGSqLIV1#*3arD^**0vJ8hSv!Uj+i*m__*lc z?YHm~kMrK+B_TSX6(G+iZT+)(vi%!pSt@J(9scj_EggRm9cH`UpiX%@y;~Ef1Xvlf;dTK{D|O#n@g{`#)fK+rmMT+x zpNFlTUHjXiwiyRW|27tDS+nVGpAV<*F2K*nQ7sTzUEl5D-azrBdp*d?a~ND3 z4c0oDo#DVkO8dK^gXWZ z<}zF#Vr!OD$K`DS;d~~1tL3&@30fsYZfi@nl9$hkKM=A* zCCD)$zjlw?77IeOWL*b*3zkr^xr zaMc?rYrsFkFU$PYe%fKW$(R0wGf*AvFJU1rB?G|0S9yqlj==>Jot`Pn8k6uSJJUM9g1HyDrg+)Tsz@3b4eNlxXe32+y3kGF zV8-Cnx0?P+iA!8*kckli36X&r`GImppiTfl<}zp9%dUfYNuGcUgMlJOc=Ux&qh@R^3;XeNj^O&{XO;@e>@Nn zp&v>}SaBbVnPP!Nxl!=ib=v|Bw}ZS^YWXwof5fA8x42|#DZCP2{M5Ot4$}`s(nK$h zn0ORx5sJtQONTo=D~Y|EDgsxUBj6d+ZO(lcL#|H%HEb-SB>oEKJq#;g^D@20@Y?Zf2G!R+)H-cO-fi*rZ03m{85FmW z=RiMB2gM^ zOek^uuGAiZ^8{z`JZG^32vhd>cbIH(xQ|QTJ|fyTl4dz7=*b3ys%T+`Bigx=&?ioNFZi zfQHL^gHoveNsK@4o+L8kJ)}JBF{$~8B8r_?tf>Ni$jY{%#c$LF^AJsUi6&4t=T29CL)}3R!)h0w*izEDP|P#(E$+O>$f$T#HH#=M$!zGp>1G|>%cNRZzi;R+tCMF9x&)_9!fs3p zN^9@&P}2T9!G~k|3*KL9ZFAC|ynV?j^f{7IyOt+?e0(CYo(U6V1Wy2p&)(m$s9jSn zy*6fjKW7mmsr@X{s2r=f0lgP8rXon*<>g%6f2KZdZ7y=2rP%6N^|b&{eqc}jc6C2! zOW+IyxpJB5bzy`i^|H{sHcb`Px_D|;zJRVZG#jn-si(s{JEKaT1EWZ(UZ7O(k-<>R zOKx3D__%mub6?}F)t8clz5)?OM@QEB=+F5tBdhb*$(u{VqL9<$7BPTPg7?g^1Bm4Q z!)Ln;2JwBbjpdUEmpJi%D&WaO6TvvT$LJUabRCPMS0F6-mX>eX|DBZ-Xm76`EN|8R zVu>VPrloP3`gwNttXZw09pb)1F@}&%CxuGg2K!lsKE~vIAO@u%(ckjEl_g-YwG)Wr zLPuwJx-Ck7%}bi%lfhiNHEpPvbmV<}=YF@Cvod~%nG~$=D5D>5rb(8(hM1ZIj6OtR zylPqobN|rxF(FD=bLvYI%*N65NN1x$qO7N@3n>go&yG!<2}md@nudu3hSm;46{ZQf z)T>k1YK6h>06!UB~WW(bb_~GDJB%%db+jiyyt$#;Mz;d5>6R zO;`mgm^{F1YPXO*L+B8?K4@uoG)<)g&dMxw97wlsmnIi(a z$h>BMtiGLX_gvIwxh7#9t^uE_Cvb6`;q~;wcH$2Y^;; zOM(yXfHjBQkLf1Um>Trs@^*f2>cGLky8R^v@YB|j8JG`*fSAzgxbtCUgRy70T&NF< z5Hp9|VVP%J`S|&${rcG|(+*RbW4_O|eHy+^1*GvP1e(V|=jn#~ItyfBJne%tzEukg zU3utYcvchnMt?)i46bb8X2<0x1Mg{XYeEPW>8rVE=X($I10_3_>sFqsmi|1K!qeT< zaX1q2dEc4cI}oJ#N;tr3FD6=2U2y*N!l}*b=_%b;9k{s zV=CaTWnQ0W4`*=`ElPeN#a8ODV`!%=tcm|)Bch;*H#Ua01Ajg=#cwKJ%Py;awr$4_ z9b@n@A@b#VfBjfcQDM9J#q*A*DrNpI{(6|F+_!<^-kj+hjo;0k_Qtuo?;+h@pK&wo zov-4;;yC$J=HS9<$L7jc|5Vf_rBT0Ux!Wzgn#tQZ5we%D?$4v7Y_NHK#z$0RSta<^ z_t@d4#C87zN-FZD^G9(Gxx{^`UBR%&HX+7fGj)&MPpya{O37fIlw|#h3wvCNqIP4p zslsxX$9;50Td*IFy(%`omYAzT{p{KmCZ?FR$~;dXccA-|7WV}}8t`xQ;<{JNoMS#^rG4j(z? z@X~#C9J#B5NmG}rJ!>%%-aS?-^ZBVwc&8_ylj>3bo7rxQ@C)=up7uuqOpjgB88gy( z))rj6h$a3!GETSPaBf88JXey4ic=T&?h6dL+$(#iaAiEoGBZP*=U7hTgr*MK@Ais; zW<$+%0l{IpbOzWn3}EwR$&EZTuGA*8O7at<;fLi!PgJfM@nrt@wqDY{JxZ=jy!;dY zuA6JBB6kW4Hn{||ntU`I*1cP%EBjkBEd^mSZr6R@dOgHeWjwlR+Lvl6YO=GuK?G@n z#Ofy|RhLv%OD{uBJ|(9-DQ6gtwgMXRNH>kWIiQJInxEQ-1|Hb~@`8s&%)Q$dV=w;E za(+gNu!?ip-#wvRTRwo;O&dn6y0jo{Q30*`TJ!Nry^V(uElV|=yhA45cY9=d-J(sj zLV4qEy)e#DQk|9Zjlie*Nem2$#3f9AO}}&1C%ayEvP15XW?a=rAi+zGD=5bx(Pblw z_DzM*J6v?ZPcXAbmpqv{t#k%;?Be87373I>VS3uyQ6*A-biShyzPZTRV%nw;Nr-vo zU0B-2{0i68(DK!GQQ*(Jk8UqCjxh|uq@beBlGZ6M2|m(#5yZUS5tV>}lq#&TV-!4A zkvC^lHDV#}Iwz4su$wRuRcPPsOTxitT*&BBr`C<*@L^-if6%+vjbV;rHA$^?oWgT0 zhMqaAn9PIM8Es{GDnVhdP1Guis+M~V{m$GbT+HXZHx{Tm9cUV2E*WyCg*4bDV>LzV zgD@JmdPJ7a8Q0|ks)a?+bxUav;9cPb=(SE`B49+Z=fvw=(QyFsDHl2E=a}kN0ACS& zr}04ukh@<3Fey?K{R^{h};{q=35=e&H=&U30LMO#|I8wAsipaR{(O z!f=a1ZrhVWAnft(1LR_R)V3QY1fsvdF+9;VK)e>vOzKOzh=Hzg5hLYqXD9&{=!>!LZ898_i=%G>uh|4$`&sUG=b&$ z);?@|eEgSe2e_zuoGgzDz=8_rpkM(QRRXw9krMu`!w(L@K4(W91PI09SV`O#d z*(NchyG03s%KayVwEaAQ(2F8)%}T0Nrv7=dU)i%jIwmsy{1oR=Eu7-#t+5k-NfJkYL1N z)(&m2@IfGAY$IfZv%oVIXw>f|8Sp@fvOyflEa-8C6zccF1DId-lch3+1#PCHSVOWZ z4KR{B=xeUX7VStX3k*+}WPw``j`QG=vfTCG^mJshz_!XGoWHK*%}O{2@*ZoWT$SQ3 JWd7DQ`9Hc?h(rJY diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44ae9537e91..8e61ef12590 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=0d585f69da091fc5b2beced877feab55a3064d43b8a1d46aeb07996b0915e0e0 -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip +distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 0e8b6adc84d325252879d9e8ed0870bbb19a4f97 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 1 May 2026 16:07:06 +0200 Subject: [PATCH 517/586] Bump VanillaGradle to 0.3.2 --- gradle/verification-metadata.xml | 5 +++++ settings.gradle.kts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6ab35a153b8..19efb99ce0d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -12162,6 +12162,11 @@ + + + + + diff --git a/settings.gradle.kts b/settings.gradle.kts index 1f4d4bdcae3..fe4b70e7155 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { } } plugins { - id("org.spongepowered.gradle.vanilla") version "0.3.0" + id("org.spongepowered.gradle.vanilla") version "0.3.2" id("implementation-structure") } } From 51ff134e31fc609e3ac79ff04e77ea8a4c441527 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 5 May 2026 05:16:03 -0700 Subject: [PATCH 518/586] feat(minecraft): update to 26.2-snapshot-5 See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_5 --- SpongeAPI | 2 +- .../BlockStatePropertyKeysGenerator.java | 2 + gradle.properties | 2 +- mise.toml | 2 +- .../resources/mixins.sponge.accessors.json | 1 - .../common/adventure/SpongeAdventure.java | 96 ++++++++++++++++++- .../standard/SpongeColorValueParameter.java | 26 ++--- .../block/state/BlockStateDataProvider.java | 1 + .../loader/CommandRegistryLoader.java | 3 +- .../loader/VanillaRegistryLoader.java | 2 + .../scoreboard/SpongeDisplaySlotFactory.java | 8 +- .../EntitySelectorParserMixin_API.java | 26 ----- .../PotentSulfurStateMixin_API.java} | 12 +-- .../worldselection/WorldOpenFlowsMixin.java | 60 ++++++++++++ .../core/server/MinecraftServerMixin.java | 13 ++- .../dedicated/DedicatedServerMixin.java | 4 +- .../core/world/scores/PlayerTeamMixin.java | 12 +-- ...MenuMixin_TrackedMenuBridge_Inventory.java | 7 +- src/mixins/resources/mixins.sponge.api.json | 1 + src/mixins/resources/mixins.sponge.core.json | 1 + 20 files changed, 207 insertions(+), 74 deletions(-) rename src/{accessors/java/org/spongepowered/common/accessor/ChatFormattingAccessor.java => mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/PotentSulfurStateMixin_API.java} (80%) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java diff --git a/SpongeAPI b/SpongeAPI index b6177b74e5f..d39ea7c43e8 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b6177b74e5fc5ba9380d68b190ff6a07ea1ecb80 +Subproject commit d39ea7c43e867efbc074830d15086b3aafdf78ba diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java index dc6e693eb38..66099fbcd7a 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/BlockStatePropertyKeysGenerator.java @@ -54,6 +54,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.PistonType; +import net.minecraft.world.level.block.state.properties.PotentSulfurState; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.block.state.properties.RedstoneSide; @@ -133,6 +134,7 @@ static BlockStatePropertyKeysGenerator.PropertyType ofProperty(final Property static { vanillaEnumTypeMapping.put(StructureMode.class, BlockStatePropertyKeysGenerator.inDataTypePkg("StructureMode")); vanillaEnumTypeMapping.put(PistonType.class, BlockStatePropertyKeysGenerator.inDataTypePkg("PistonType")); + vanillaEnumTypeMapping.put(PotentSulfurState.class, BlockStatePropertyKeysGenerator.inDataTypePkg("PotentSulfurState")); vanillaEnumTypeMapping.put(BambooLeaves.class, BlockStatePropertyKeysGenerator.inDataTypePkg("BambooLeavesType")); vanillaEnumTypeMapping.put(WallSide.class, BlockStatePropertyKeysGenerator.inDataTypePkg("WallConnectionState")); vanillaEnumTypeMapping.put(RailShape.class, BlockStatePropertyKeysGenerator.inDataTypePkg("RailDirection")); diff --git a/gradle.properties b/gradle.properties index f88a4eb06f0..88ca2e2bbb1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-4 +minecraftVersion=26.2-snapshot-5 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/mise.toml b/mise.toml index f3149bc0e27..76843a8e48b 100644 --- a/mise.toml +++ b/mise.toml @@ -1,3 +1,3 @@ [tools] -gradle = "9.2.1" +gradle = "9.3.1" java = "temurin-25" diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 1890a4bd7ab..621e1f6497a 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -8,7 +8,6 @@ "world.level.entity.TransientEntitySectionManagerAccessor" ], "mixins": [ - "ChatFormattingAccessor", "advancements.CriteriaTriggersAccessor", "commands.CommandSourceStackAccessor", "commands.arguments.DimensionArgumentAccessor", diff --git a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java index aea7bbad43b..b3cfa95baf0 100644 --- a/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java +++ b/src/main/java/org/spongepowered/common/adventure/SpongeAdventure.java @@ -105,6 +105,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.component.ResolvableProfile; +import net.minecraft.world.scores.TeamColor; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.jetbrains.annotations.NotNull; @@ -519,15 +520,104 @@ public static ChatFormatting asVanilla(final NamedTextColor color) { return TextColor.color(color.getValue()); } - public static @Nullable TextColor asAdventure(final ChatFormatting formatting) { + public static @Nullable TeamColor asVanillaTeamColor(final @Nullable ChatFormatting formatting) { if (formatting == null) { return null; } - final Integer color = formatting.getColor(); + return switch (formatting) { + case BLACK -> TeamColor.BLACK; + case DARK_BLUE -> TeamColor.DARK_BLUE; + case DARK_GREEN -> TeamColor.DARK_GREEN; + case DARK_AQUA -> TeamColor.DARK_AQUA; + case DARK_RED -> TeamColor.DARK_RED; + case DARK_PURPLE -> TeamColor.DARK_PURPLE; + case GOLD -> TeamColor.GOLD; + case GRAY -> TeamColor.GRAY; + case DARK_GRAY -> TeamColor.DARK_GRAY; + case BLUE -> TeamColor.BLUE; + case GREEN -> TeamColor.GREEN; + case AQUA -> TeamColor.AQUA; + case RED -> TeamColor.RED; + case LIGHT_PURPLE -> TeamColor.LIGHT_PURPLE; + case YELLOW -> TeamColor.YELLOW; + case WHITE -> TeamColor.WHITE; + default -> null; + }; + } + + public static @Nullable TextColor asAdventure(final @Nullable ChatFormatting formatting) { + return SpongeAdventure.asAdventure(SpongeAdventure.asVanillaTeamColor(formatting)); + } + + public static @Nullable TeamColor asVanillaTeamColor(final @Nullable NamedTextColor color) { + if (color == null) { + return null; + } + if (color == NamedTextColor.BLACK) { + return TeamColor.BLACK; + } else if (color == NamedTextColor.DARK_BLUE) { + return TeamColor.DARK_BLUE; + } else if (color == NamedTextColor.DARK_GREEN) { + return TeamColor.DARK_GREEN; + } else if (color == NamedTextColor.DARK_AQUA) { + return TeamColor.DARK_AQUA; + } else if (color == NamedTextColor.DARK_RED) { + return TeamColor.DARK_RED; + } else if (color == NamedTextColor.DARK_PURPLE) { + return TeamColor.DARK_PURPLE; + } else if (color == NamedTextColor.GOLD) { + return TeamColor.GOLD; + } else if (color == NamedTextColor.GRAY) { + return TeamColor.GRAY; + } else if (color == NamedTextColor.DARK_GRAY) { + return TeamColor.DARK_GRAY; + } else if (color == NamedTextColor.BLUE) { + return TeamColor.BLUE; + } else if (color == NamedTextColor.GREEN) { + return TeamColor.GREEN; + } else if (color == NamedTextColor.AQUA) { + return TeamColor.AQUA; + } else if (color == NamedTextColor.RED) { + return TeamColor.RED; + } else if (color == NamedTextColor.LIGHT_PURPLE) { + return TeamColor.LIGHT_PURPLE; + } else if (color == NamedTextColor.YELLOW) { + return TeamColor.YELLOW; + } else if (color == NamedTextColor.WHITE) { + return TeamColor.WHITE; + } + return null; + } + + public static @Nullable TextColor asAdventure(final @Nullable TeamColor color) { if (color == null) { return null; } - return TextColor.color(color); + return TextColor.color(color.rgb()); + } + + public static @Nullable NamedTextColor asAdventureNamed(final @Nullable TeamColor color) { + if (color == null) { + return null; + } + return switch (color) { + case BLACK -> NamedTextColor.BLACK; + case DARK_BLUE -> NamedTextColor.DARK_BLUE; + case DARK_GREEN -> NamedTextColor.DARK_GREEN; + case DARK_AQUA -> NamedTextColor.DARK_AQUA; + case DARK_RED -> NamedTextColor.DARK_RED; + case DARK_PURPLE -> NamedTextColor.DARK_PURPLE; + case GOLD -> NamedTextColor.GOLD; + case GRAY -> NamedTextColor.GRAY; + case DARK_GRAY -> NamedTextColor.DARK_GRAY; + case BLUE -> NamedTextColor.BLUE; + case GREEN -> NamedTextColor.GREEN; + case AQUA -> NamedTextColor.AQUA; + case RED -> NamedTextColor.RED; + case LIGHT_PURPLE -> NamedTextColor.LIGHT_PURPLE; + case YELLOW -> NamedTextColor.YELLOW; + case WHITE -> NamedTextColor.WHITE; + }; } public static @Nullable NamedTextColor asAdventureNamed(final @Nullable ChatFormatting color) { diff --git a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeColorValueParameter.java b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeColorValueParameter.java index 7a4fb9c3001..227c2497441 100644 --- a/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeColorValueParameter.java +++ b/src/main/java/org/spongepowered/common/command/parameter/managed/standard/SpongeColorValueParameter.java @@ -30,8 +30,8 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.kyori.adventure.text.Component; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.arguments.ColorArgument; +import net.minecraft.commands.arguments.TeamColorArgument; +import net.minecraft.world.scores.TeamColor; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.command.CommandCause; @@ -39,12 +39,10 @@ import org.spongepowered.api.command.exception.ArgumentParseException; import org.spongepowered.api.command.parameter.ArgumentReader; import org.spongepowered.api.util.Color; -import org.spongepowered.common.accessor.ChatFormattingAccessor; import org.spongepowered.common.command.SpongeCommandCompletion; import org.spongepowered.common.command.brigadier.argument.ResourceKeyedArgumentValueParser; import org.spongepowered.common.util.Constants; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -67,11 +65,10 @@ public final class SpongeColorValueParameter extends ResourceKeyedArgumentValueP .append(Component.text("* Comma separated RGB color, surrounded by double quotes, with values from 0 to 255 (such as \"0,128,255\")")) .build(); private final static Pattern HEX_CODE = Pattern.compile("(#?)(?[0-9A-Fa-f]{6})"); - private final static Collection CHAT_FORMATTING_NAMES = Arrays.stream(ChatFormatting.values()) - .filter(x -> x.isColor()) - .map(x -> x.getName().toLowerCase(Locale.ROOT)) - .collect(Collectors.toList()); - private final ColorArgument colorArgumentType = ColorArgument.color(); + private final static Collection TEAM_COLOR_NAMES = TeamColor.VALUES.stream() + .map(TeamColor::getSerializedName) + .toList(); + private final TeamColorArgument colorArgumentType = TeamColorArgument.teamColor(); public SpongeColorValueParameter(final ResourceKey key) { super(key); @@ -92,13 +89,8 @@ public CompletableFuture listSuggestions( final ArgumentReader.Immutable state = reader.immutable(); // First, is the argument type giving the correct return type? try { - final ChatFormatting formatting = this.colorArgumentType.parse((StringReader) reader); - final Integer colorCode = ((ChatFormattingAccessor) (Object) formatting).accessor$color(); - if (colorCode != null) { - return Optional.of(Color.ofRgb(colorCode)); - } - // "reset" slips through the net here. - throw reader.createException(Component.text().content(String.format("%s is not a valid color", formatting.getName())).build()); + final TeamColor parsed = this.colorArgumentType.parse((StringReader) reader); + return Optional.of(Color.ofRgb(parsed.rgb())); } catch (final CommandSyntaxException e) { // ignored } @@ -130,7 +122,7 @@ public CompletableFuture listSuggestions( @Override public List complete(final CommandCause context, final String currentInput) { - return SpongeColorValueParameter.CHAT_FORMATTING_NAMES + return SpongeColorValueParameter.TEAM_COLOR_NAMES .stream() .filter(x -> x.startsWith(currentInput.toLowerCase(Locale.ROOT))) .map(SpongeCommandCompletion::new) diff --git a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java index 8fb4dc75f65..e6446c0bf40 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/state/BlockStateDataProvider.java @@ -123,6 +123,7 @@ public static void register(final DataProviderRegistrator registrator) { BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.PERSISTENT, BlockStateProperties.PERSISTENT); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.PICKLES, BlockStateProperties.PICKLES); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.PISTON_TYPE, BlockStateProperties.PISTON_TYPE); + BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.POTENT_SULFUR_STATE, BlockStateProperties.POTENT_SULFUR_STATE); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.POWER, BlockStateProperties.POWER); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.POWERED, BlockStateProperties.POWERED); BlockStateDataProvider.registerProperty(registrator, BlockStateKeys.RAIL_SHAPE, BlockStateProperties.RAIL_SHAPE); diff --git a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java index 11bd01ebfad..176c76c9097 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/CommandRegistryLoader.java @@ -247,7 +247,8 @@ public static RegistryLoader> clientCompletionKey(final C l.add(CommandTreeNodeTypes.BLOCK_PREDICATE, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); l.add(CommandTreeNodeTypes.ITEM_STACK, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); l.add(CommandTreeNodeTypes.ITEM_PREDICATE, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); - l.add(CommandTreeNodeTypes.COLOR, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); + l.add(CommandTreeNodeTypes.TEAM_COLOR, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); + l.add(CommandTreeNodeTypes.HEX_COLOR, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); l.add(CommandTreeNodeTypes.COMPONENT, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); l.add(CommandTreeNodeTypes.MESSAGE, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); l.add(CommandTreeNodeTypes.NBT_COMPOUND_TAG, k -> new SpongeBasicCommandTreeNodeType(k, fn.apply(k))); diff --git a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java index 5d0eb67b2b2..5c2c77c0dc1 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java @@ -83,6 +83,7 @@ import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.block.state.properties.PistonType; +import net.minecraft.world.level.block.state.properties.PotentSulfurState; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.block.state.properties.RedstoneSide; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; @@ -199,6 +200,7 @@ private void loadEnumRegistries() { this.automaticName(RegistryTypes.CHAT_VISIBILITY, ChatVisiblity.values()); this.automaticName(RegistryTypes.PISTON_TYPE, PistonType.values()); this.automaticName(RegistryTypes.PORTION_TYPE, Half.values()); + this.automaticName(RegistryTypes.POTENT_SULFUR_STATE, PotentSulfurState.values()); this.automaticName(RegistryTypes.RAID_STATUS, Raid.RaidStatus.values()); this.automaticName(RegistryTypes.ROTATION, Rotation.values()); this.automaticName(RegistryTypes.RAIL_DIRECTION, RailShape.values()); diff --git a/src/main/java/org/spongepowered/common/scoreboard/SpongeDisplaySlotFactory.java b/src/main/java/org/spongepowered/common/scoreboard/SpongeDisplaySlotFactory.java index 9aed7efe677..e16340cf912 100644 --- a/src/main/java/org/spongepowered/common/scoreboard/SpongeDisplaySlotFactory.java +++ b/src/main/java/org/spongepowered/common/scoreboard/SpongeDisplaySlotFactory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.scoreboard; import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.world.scores.TeamColor; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.scoreboard.displayslot.DisplaySlot; import org.spongepowered.common.adventure.SpongeAdventure; @@ -36,8 +37,11 @@ public final class SpongeDisplaySlotFactory implements DisplaySlot.Factory { @Override @NonNull public Optional findByTeamColor(final @NonNull NamedTextColor color) { - var displaySlot = net.minecraft.world.scores.DisplaySlot.teamColorToSlot(SpongeAdventure.asVanilla(color)); - return Optional.ofNullable(displaySlot).map(DisplaySlot.class::cast); + final TeamColor teamColor = SpongeAdventure.asVanillaTeamColor(color); + if (teamColor == null) { + return Optional.empty(); + } + return Optional.of((DisplaySlot) (Object) teamColor.displaySlot()); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java index 4cea7f89332..ef4d0024d43 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/commands/arguments/selector/EntitySelectorParserMixin_API.java @@ -100,22 +100,9 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Shadow private int startPosition; @Shadow @Nullable private UUID entityUUID; @Shadow private BiFunction, CompletableFuture> suggestions; - @Shadow private boolean hasNameEquals; - @Shadow private boolean hasNameNotEquals; - @Shadow private boolean isLimited; - @Shadow private boolean isSorted; - @Shadow private boolean hasGamemodeEquals; - @Shadow private boolean hasGamemodeNotEquals; - @Shadow private boolean hasTeamEquals; - @Shadow private boolean hasTeamNotEquals; @Shadow private net.minecraft.world.entity.@Nullable EntityType type; - @Shadow private boolean typeInverse; - @Shadow private boolean hasScores; - @Shadow private boolean hasAdvancements; @Shadow private boolean usesSelectors; - @Shadow public abstract void shadow$setLimited(boolean value); - @Shadow public abstract void shadow$setSorted(boolean value); @Shadow public abstract void shadow$setX(double xIn); @Shadow public abstract void shadow$setY(double yIn); @Shadow public abstract void shadow$setZ(double zIn); @@ -159,7 +146,6 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Override public Selector.@NonNull Builder limit(final int limit) { this.maxResults = limit; - this.shadow$setLimited(limit != Integer.MAX_VALUE); return this; } @@ -210,7 +196,6 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder @Override public Selector.@NonNull Builder sortAlgorithm(final @NonNull SelectorSortAlgorithm algorithm) { org.spongepowered.common.util.Preconditions.checkArgument(algorithm instanceof SpongeSelectorSortAlgorithm, "Must be a SpongeSelectorSortAlgorithm"); - this.shadow$setSorted(true); this.order = ((SpongeSelectorSortAlgorithm) algorithm).getSortAlgorithm(); return this; } @@ -444,18 +429,7 @@ public abstract class EntitySelectorParserMixin_API implements Selector.Builder this.playerName = null; this.startPosition = 0; this.entityUUID = null; - this.hasNameEquals = false; - this.hasNameNotEquals = false; - this.isLimited = false; - this.isSorted = false; - this.hasGamemodeEquals = false; - this.hasGamemodeNotEquals = false; - this.hasTeamEquals = false; - this.hasTeamNotEquals = false; this.type = null; - this.typeInverse = false; - this.hasScores = false; - this.hasAdvancements = false; this.usesSelectors = false; this.reader.setCursor(0); this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; diff --git a/src/accessors/java/org/spongepowered/common/accessor/ChatFormattingAccessor.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/PotentSulfurStateMixin_API.java similarity index 80% rename from src/accessors/java/org/spongepowered/common/accessor/ChatFormattingAccessor.java rename to src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/PotentSulfurStateMixin_API.java index db438fb6508..97152fdcbaa 100644 --- a/src/accessors/java/org/spongepowered/common/accessor/ChatFormattingAccessor.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/PotentSulfurStateMixin_API.java @@ -22,16 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.accessor; +package org.spongepowered.common.mixin.api.minecraft.world.level.block.state.properties; -import net.minecraft.ChatFormatting; -import org.checkerframework.checker.nullness.qual.Nullable; +import net.minecraft.world.level.block.state.properties.PotentSulfurState; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ChatFormatting.class) -public interface ChatFormattingAccessor { - - @Accessor("color") @Nullable Integer accessor$color(); +@Mixin(PotentSulfurState.class) +public abstract class PotentSulfurStateMixin_API implements org.spongepowered.api.data.type.PotentSulfurState { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java new file mode 100644 index 00000000000..4c72120839a --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.core.client.gui.screens.worldselection; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.datafixers.util.Pair; +import net.minecraft.client.gui.screens.worldselection.WorldOpenFlows; +import net.minecraft.server.WorldLoader; +import net.minecraft.server.packs.resources.CloseableResourceManager; +import net.minecraft.server.permissions.PermissionLevel; +import net.minecraft.world.level.WorldDataConfiguration; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.common.launch.Launch; + +@Mixin(WorldOpenFlows.class) +public abstract class WorldOpenFlowsMixin { + + /** + * The integrated-server "create new world" path constructs a fresh + * {@link CloseableResourceManager} via {@link WorldLoader.PackConfig#createResourceManager()} + * outside of {@link WorldLoader#load} — bypassing {@code WorldLoaderMixin}'s + * {@code establishServerServices} hook. Without it the resource manager that ends up + * in the {@link net.minecraft.server.WorldStem} has no service provider attached, + * and {@code MinecraftServerMixin#impl$onInit} stores {@code null} into the server's + * {@code impl$serviceProvider}, which subsequently NPEs at login time. + */ + @WrapOperation(method = "createLevelFromExistingSettings", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$PackConfig;createResourceManager()Lcom/mojang/datafixers/util/Pair;")) + private Pair impl$establishIntegratedServerServices( + final WorldLoader.PackConfig packConfig, final Operation> original + ) { + final Pair pair = original.call(packConfig); + Launch.instance().lifecycle().establishServerServices(pair.getSecond(), PermissionLevel.ALL); + return pair; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 236b08f1f87..98904805a6a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -42,6 +42,7 @@ import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.LevelLoadListener; +import net.minecraft.server.notifications.NotificationManager; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.players.PlayerList; @@ -199,7 +200,8 @@ public Subject subject() { private void impl$setThreadOnServerPhaseTracker( Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, WorldStem worldStem, Optional gameRules, Proxy proxy, DataFixer fixerUpper, Services services, - LevelLoadListener levelLoadListener, boolean propagatesCrashes, CallbackInfo ci + LevelLoadListener levelLoadListener, boolean propagatesCrashes, + NotificationManager notificationManager, CallbackInfo ci ) { try { PhaseTracker.getServerInstanceExplicitly().setThread(serverThread); @@ -527,7 +529,14 @@ public String toString() { @Inject(method = "", at = @At("TAIL")) public void impl$onInit(final CallbackInfo ci, final @Local(argsOnly = true) WorldStem levelStem) { - this.bridge$reloadedServerRegistries(((SpongeRegistryHolder) levelStem.resourceManager()).registryHolder()); + final SpongeRegistryHolder rmHolder = (SpongeRegistryHolder) levelStem.resourceManager(); + // The integrated server's "create new world" path constructs a fresh resource manager + // in WorldOpenFlows.createLevelFromExistingSettings that bypasses + // ReloadableServerResourcesMixin#impl$onLoadResources, so its RegistryHolderLogic has + // no Minecraft root populated. Seed it from the server's frozen registry access — for + // the dedicated path this is a no-op since the same data was already wired. + rmHolder.setRootMinecraftRegistry(this.shadow$registryAccess()); + this.bridge$reloadedServerRegistries(rmHolder.registryHolder()); this.impl$serviceProvider = ((ResourceManagerBridge) levelStem.resourceManager()).bridge$services(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java index b74ecd8d485..6ce594f360e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/dedicated/DedicatedServerMixin.java @@ -57,7 +57,9 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin { @Inject(method = "", at = @At("TAIL")) private void impl$setServerOnGame( final Thread $$0, final LevelStorageSource.LevelStorageAccess $$1, final PackRepository $$2, final WorldStem $$3, - final Optional $$4, final DedicatedServerSettings $$5, final DataFixer $$6, final Services $$7, final CallbackInfo ci + final Optional $$4, final DedicatedServerSettings $$5, final DataFixer $$6, final Services $$7, + final net.minecraft.server.jsonrpc.ManagementServer $$8, final net.minecraft.server.notifications.NotificationManager $$9, + final CallbackInfo ci ) { $$5.getProperties().serverResourcePackInfo.ifPresent(packInfo -> { try { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/scores/PlayerTeamMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/scores/PlayerTeamMixin.java index 6e46f440fa7..74e2d04db02 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/scores/PlayerTeamMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/scores/PlayerTeamMixin.java @@ -28,10 +28,10 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.minecraft.ChatFormatting; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; +import net.minecraft.world.scores.TeamColor; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; @@ -57,7 +57,7 @@ public abstract class PlayerTeamMixin implements PlayerTeamBridge { // @formatter:off @Shadow @Final @Mutable @Nullable private Scoreboard scoreboard; @Shadow private net.minecraft.network.chat.Component displayName; - @Shadow private ChatFormatting color; + @Shadow private Optional color; @Shadow private net.minecraft.network.chat.Component playerPrefix; @Shadow private net.minecraft.network.chat.Component playerSuffix; @Shadow public abstract Collection getPlayers(); @@ -79,7 +79,7 @@ public abstract class PlayerTeamMixin implements PlayerTeamBridge { this.bridge$displayName = LegacyComponentSerializer.legacySection().deserialize(name); this.bridge$prefix = SpongeAdventure.asAdventure(this.playerPrefix); this.bridge$suffix = SpongeAdventure.asAdventure(this.playerSuffix); - this.bridge$color = SpongeAdventure.asAdventureNamed(this.color); + this.bridge$color = this.color.map(SpongeAdventure::asAdventureNamed).orElse(NamedTextColor.WHITE); } @Redirect( @@ -135,8 +135,8 @@ public abstract class PlayerTeamMixin implements PlayerTeamBridge { } @Inject(method = "setColor", at = @At("RETURN")) - private void impl$trackColorChange(final ChatFormatting color, final CallbackInfo ci) { - this.bridge$color = SpongeAdventure.asAdventureNamed(color); + private void impl$trackColorChange(final Optional color, final CallbackInfo ci) { + this.bridge$color = color.map(SpongeAdventure::asAdventureNamed).orElse(NamedTextColor.WHITE); } @Override @@ -183,7 +183,7 @@ public abstract class PlayerTeamMixin implements PlayerTeamBridge { @Override public void bridge$setColor(final NamedTextColor color) { this.bridge$color = color; - this.color = SpongeAdventure.asVanilla(color); + this.color = Optional.ofNullable(SpongeAdventure.asVanillaTeamColor(color)); this.impl$teamChanged(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java index 155b32b5a54..cccebc2a7e2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/world/inventory/AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory.java @@ -32,7 +32,6 @@ import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.RecipeBookType; -import net.minecraft.world.item.crafting.RecipeType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -43,11 +42,11 @@ public abstract class AbstractFurnaceMenuMixin_TrackedMenuBridge_Inventory { @Inject( - method = "(Lnet/minecraft/world/inventory/MenuType;Lnet/minecraft/world/item/crafting/RecipeType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/inventory/RecipeBookType;ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", + method = "(Lnet/minecraft/world/inventory/MenuType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/inventory/RecipeBookType;ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", at = @At("RETURN")) private void inventory$attachContainerMenu( - final MenuType $$0, final RecipeType $$1, final ResourceKey $$2, - final RecipeBookType $$3, final int $$4, final Inventory inventory, final Container container, final ContainerData $$7, + final MenuType $$0, final ResourceKey $$1, + final RecipeBookType $$2, final int $$3, final Inventory inventory, final Container container, final ContainerData $$6, final CallbackInfo ci) { if (inventory instanceof final TrackedMenuBridge trackedMenu) { trackedMenu.bridge$trackContainerMenu((AbstractContainerMenu) (Object) this); diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index dd0eda00c23..ce91c9f9e8d 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -459,6 +459,7 @@ "minecraft.world.level.block.state.properties.HalfMixin_API", "minecraft.world.level.block.state.properties.NoteBlockInstrumentMixin_API", "minecraft.world.level.block.state.properties.PistonTypeMixin_API", + "minecraft.world.level.block.state.properties.PotentSulfurStateMixin_API", "minecraft.world.level.block.state.properties.RailShapeMixin_API", "minecraft.world.level.block.state.properties.RedstoneSideMixin_API", "minecraft.world.level.block.state.properties.SculkSensorPhaseMixin_API", diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index 2efe19e792d..d7836e8f6cf 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -296,6 +296,7 @@ ], "client": [ "client.MinecraftMixin", + "client.gui.screens.worldselection.WorldOpenFlowsMixin", "client.multiplayer.ClientCommonPacketListenerImplMixin", "client.multiplayer.ClientHandshakePacketListenerImplMixin", "client.multiplayer.ClientLevelMixin", From 9f5a493868452c1a5d2efe8ec1d80d74c87db43e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 10 May 2026 23:41:42 -0700 Subject: [PATCH 519/586] feat(minecraft): update to 26.2-snapshot-6 Changes: - SurfaceRules.noiseCondition split into noiseCondition2d/noiseCondition3d - BlockPos.getCenter/getBottomCenter removed, callers use Vec3 helpers - ArmorSlot is now public, ArmorSlot_Inventory_API switched to @Mixin(class) - LivingEntity.knockback gained DamageSource/damage args, PlayerMixin_Attack sweep retargeted - LevelChunkTicks.pack copies to a sorted ArrayList, LevelChunkTicksMixin iterator target retargeted from Queue to List See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_6 --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 5 +++++ .../generation/config/noise/SpongeSurfaceRulesFactory.java | 2 +- .../common/world/portal/SpongeEndPlatformGenerator.java | 3 ++- .../mixin/core/world/entity/player/PlayerMixin_Attack.java | 6 +++--- .../mixin/core/world/level/block/EndPortalBlockMixin.java | 5 +++-- .../common/mixin/core/world/ticks/LevelChunkTicksMixin.java | 2 +- .../api/world/inventory/ArmorSlot_Inventory_API.java | 3 ++- 9 files changed, 19 insertions(+), 11 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index d39ea7c43e8..a2cb6220da3 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d39ea7c43e867efbc074830d15086b3aafdf78ba +Subproject commit a2cb6220da339f44bb52152cf278257e542b5c07 diff --git a/gradle.properties b/gradle.properties index 88ca2e2bbb1..a06a99801fc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-5 +minecraftVersion=26.2-snapshot-6 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 350745dba82..3215d5635a8 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1840,6 +1840,11 @@ + + + + + diff --git a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java index 1fb66c83829..fef00b3ea2b 100644 --- a/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java +++ b/src/main/java/org/spongepowered/common/world/generation/config/noise/SpongeSurfaceRulesFactory.java @@ -195,7 +195,7 @@ public SurfaceRule.Condition surfaceAbove(final SurfaceRule.VerticalAnchor ancho @Override public SurfaceRule.Condition noiseThreshold(final RegistryReference noise, final double min, final double max) { final net.minecraft.resources.ResourceKey key = net.minecraft.resources.ResourceKey.create(Registries.NOISE, ((Identifier) (Object) noise.location())); - return (SurfaceRule.Condition) SurfaceRules.noiseCondition(key, min, max); + return (SurfaceRule.Condition) SurfaceRules.noiseCondition2d(key, min, max); } // Anchors diff --git a/src/main/java/org/spongepowered/common/world/portal/SpongeEndPlatformGenerator.java b/src/main/java/org/spongepowered/common/world/portal/SpongeEndPlatformGenerator.java index 778a2571374..bd9bac9dc2d 100644 --- a/src/main/java/org/spongepowered/common/world/portal/SpongeEndPlatformGenerator.java +++ b/src/main/java/org/spongepowered/common/world/portal/SpongeEndPlatformGenerator.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.levelgen.feature.EndPlatformFeature; +import net.minecraft.world.phys.Vec3; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.portal.Portal; import org.spongepowered.api.world.portal.PortalLogic; @@ -43,7 +44,7 @@ public final class SpongeEndPlatformGenerator implements PortalLogic.PortalGener @Override public Optional generatePortal(final ServerLocation location, final Axis axis) { final var level = (ServerLevel) location.world(); - final var bottomCenter = VecHelper.toBlockPos(location.blockPosition()).getBottomCenter(); + final var bottomCenter = Vec3.atBottomCenterOf(VecHelper.toBlockPos(location.blockPosition())); EndPlatformFeature.createEndPlatform(level, BlockPos.containing(bottomCenter).below(), true); return Optional.of(new SpongePortal(location, null)); // TODO set portallogic? } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java index 67e6e096eb3..a2f2f028959 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack.java @@ -291,18 +291,18 @@ public abstract class PlayerMixin_Attack extends LivingEntityMixin_Damage implem "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;F)V", // NeoForge changes where this gets invoked in a new method, so we add it as a target "doSweepAttack(Lnet/minecraft/world/entity/Entity;FLnet/minecraft/world/damagesource/DamageSource;FLnet/minecraft/world/phys/AABB;)V" - }, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), slice = @Slice( + }, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDDLnet/minecraft/world/damagesource/DamageSource;F)V"), slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;doPostAttackEffects(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;)V")), require = 1 ) private void sweepAttack$knockbackModifier( - final LivingEntity sweepTarget, double modifier, final double dirX, final double dirZ, final Operation operation) { + final LivingEntity sweepTarget, double modifier, final double dirX, final double dirZ, final DamageSource source, final float damage, final Operation operation) { final SpongeAttackTracker sweepTracker = this.attack$tracker(); if (sweepTracker != null) { modifier = sweepTracker.postEvent().knockbackModifier(); } - operation.call(sweepTarget, modifier, dirX, dirZ); + operation.call(sweepTarget, modifier, dirX, dirZ, source, damage); } @WrapOperation(method = { diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java index 0f985a63a76..944dee0b95f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/block/EndPortalBlockMixin.java @@ -31,6 +31,7 @@ import net.minecraft.world.level.block.EndPortalBlock; import net.minecraft.world.level.levelgen.feature.EndPlatformFeature; import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.phys.Vec3; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.util.Axis; import org.spongepowered.api.world.portal.Portal; @@ -71,7 +72,7 @@ public abstract class EndPortalBlockMixin implements PortalBlockBridge { } final var sharedSpawnPos = toLevel.getRespawnData().pos(); - final var spawnPos = ((net.minecraft.world.entity.Entity) entity).adjustSpawnLocation(toLevel, sharedSpawnPos).getBottomCenter(); + final var spawnPos = Vec3.atBottomCenterOf(((net.minecraft.world.entity.Entity) entity).adjustSpawnLocation(toLevel, sharedSpawnPos)); return ServerLocation.of((ServerWorld) toLevel, VecHelper.toVector3d(spawnPos)); } @@ -90,7 +91,7 @@ public abstract class EndPortalBlockMixin implements PortalBlockBridge { final var level = (ServerLevel) at.world(); // If a target dimension is set assume we always want to generate a portal otherwise we could have used a spawn teleporter if (level.dimension() == Level.END) { - final var bottomCenter = VecHelper.toBlockPos(at.blockPosition()).getBottomCenter(); + final var bottomCenter = Vec3.atBottomCenterOf(VecHelper.toBlockPos(at.blockPosition())); EndPlatformFeature.createEndPlatform(level, BlockPos.containing(bottomCenter).below(), true); return Optional.of(new SpongePortal(at, (PortalLogic) this)); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/LevelChunkTicksMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/LevelChunkTicksMixin.java index 291b3f670e7..0d03d875a25 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/LevelChunkTicksMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/ticks/LevelChunkTicksMixin.java @@ -72,7 +72,7 @@ public abstract class LevelChunkTicksMixin implements LevelChunkTicksBridge> impl$onSaveSkipCancelled(final Iterator> original) { return Iterators.filter(original, t -> ((TickNextTickDataBridge) (Object) t).bridge$internalState() != ScheduledUpdate.State.CANCELLED); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/ArmorSlot_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/ArmorSlot_Inventory_API.java index 08c8b1d6515..9ff6feb1088 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/ArmorSlot_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/inventory/ArmorSlot_Inventory_API.java @@ -24,9 +24,10 @@ */ package org.spongepowered.common.mixin.inventory.api.world.inventory; +import net.minecraft.world.inventory.ArmorSlot; import org.spongepowered.api.item.inventory.slot.EquipmentSlot; import org.spongepowered.asm.mixin.Mixin; -@Mixin(targets = "net/minecraft/world/inventory/ArmorSlot") +@Mixin(ArmorSlot.class) public abstract class ArmorSlot_Inventory_API implements EquipmentSlot { } From 92b99d95c72efff93e8872c453d59e51c25a2474 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 12 May 2026 22:25:34 -0700 Subject: [PATCH 520/586] feat(minecraft): update to 26.2-snapshot-7 See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_7 --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index a2cb6220da3..ec485617723 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit a2cb6220da339f44bb52152cf278257e542b5c07 +Subproject commit ec4856177230d65d9a84fb9e2f639a327d3eb01c diff --git a/gradle.properties b/gradle.properties index a06a99801fc..a0e2ff41057 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-6 +minecraftVersion=26.2-snapshot-7 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3215d5635a8..1fbfcf8fab5 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1816,6 +1816,11 @@ + + + + + @@ -2600,6 +2605,17 @@ + + + + + + + + + + + From ff6072c424886f8b5ee3d8354305d3ad555d3315 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 12 May 2026 22:26:09 -0700 Subject: [PATCH 521/586] feat(blockentity): implement PotentSulfur block entity See: https://minecraft.wiki/w/Potent_Sulfur --- .../entity/BlockEntityDataProviders.java | 1 + .../block/entity/PotentSulfurData.java | 57 +++++++++++++++++++ .../PotentSulfurBlockEntityMixin_API.java | 47 +++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 1 + 4 files changed, 106 insertions(+) create mode 100644 src/main/java/org/spongepowered/common/data/provider/block/entity/PotentSulfurData.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/PotentSulfurBlockEntityMixin_API.java diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/BlockEntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/BlockEntityDataProviders.java index 72644d0343a..cdb6c976eee 100644 --- a/src/main/java/org/spongepowered/common/data/provider/block/entity/BlockEntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/BlockEntityDataProviders.java @@ -42,6 +42,7 @@ public void registerProviders() { LecternData.register(this.registrator); LockableData.register(this.registrator); MobSpawnerData.register(this.registrator); + PotentSulfurData.register(this.registrator); TrialSpawnerDataProvider.register(this.registrator); SignData.register(this.registrator); SkullData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/block/entity/PotentSulfurData.java b/src/main/java/org/spongepowered/common/data/provider/block/entity/PotentSulfurData.java new file mode 100644 index 00000000000..fbffa6fabff --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/block/entity/PotentSulfurData.java @@ -0,0 +1,57 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.block.entity; + +import net.minecraft.world.level.block.entity.PotentSulfurBlockEntity; +import org.spongepowered.api.data.Keys; +import org.spongepowered.common.data.provider.DataProviderRegistrator; +import org.spongepowered.common.util.SpongeTicks; + +public final class PotentSulfurData { + + private PotentSulfurData() { + } + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(PotentSulfurBlockEntity.class) + .create(Keys.ERUPTION_COUNTDOWN) + .get(h -> h.waitingCountdown < 0 ? null : new SpongeTicks(h.waitingCountdown)) + .setAnd((h, v) -> { + if (v.isInfinite()) { + return false; + } + final int ticks = SpongeTicks.toSaturatedIntOrInfinite(v); + if (ticks < 0) { + return false; + } + h.waitingCountdown = ticks; + return true; + }) + .delete(PotentSulfurBlockEntity::resetCountdown); + } + // @formatter:on +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/PotentSulfurBlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/PotentSulfurBlockEntityMixin_API.java new file mode 100644 index 00000000000..8a23483cf04 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/PotentSulfurBlockEntityMixin_API.java @@ -0,0 +1,47 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.level.block.entity; + +import net.minecraft.world.level.block.entity.PotentSulfurBlockEntity; +import org.spongepowered.api.block.entity.PotentSulfur; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Set; + +@Mixin(PotentSulfurBlockEntity.class) +public abstract class PotentSulfurBlockEntityMixin_API extends BlockEntityMixin_API implements PotentSulfur { + + @Shadow public abstract void resetCountdown(); + + @Override + protected Set> api$getVanillaValues() { + final Set> values = super.api$getVanillaValues(); + this.getValue(Keys.ERUPTION_COUNTDOWN).map(Value::asImmutable).ifPresent(values::add); + return values; + } +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index ce91c9f9e8d..2920a551141 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -429,6 +429,7 @@ "minecraft.world.level.block.entity.JigsawBlockEntityMixin_API", "minecraft.world.level.block.entity.JukeboxBlockEntityMixin_API", "minecraft.world.level.block.entity.LecternBlockEntityMixin_API", + "minecraft.world.level.block.entity.PotentSulfurBlockEntityMixin_API", "minecraft.world.level.block.entity.RandomizableContainerBlockEntityMixin_API", "minecraft.world.level.block.entity.SculkSensorBlockEntityMixin_API", "minecraft.world.level.block.entity.ShulkerBoxBlockEntityMixin_API", From ee753effbba17bcdd305e97dd0ba126b86fc9855 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 12 May 2026 22:45:26 -0700 Subject: [PATCH 522/586] fix(client): use replaceEntries() in PluginScreen AbstractSelectionList#children() is an unmodifiable view, so the clear()/addAll() pair crashed the screen on open. Swap to vanilla's public replaceEntries(Collection). Signed-off-by: Gabriel Harris-Rouquette --- .../spongepowered/vanilla/client/gui/screen/PluginScreen.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java index c867bcee6f6..7a7c729e042 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/screen/PluginScreen.java @@ -114,8 +114,7 @@ private void generateEntries(final List metadatas) { return; } - this.selectionList.children().clear(); - this.selectionList.children().addAll(metadatas.stream() + this.selectionList.replaceEntries(metadatas.stream() .map(metadata -> new PluginSelectionList.Entry(this.selectionList, metadata)) .collect(Collectors.toList())); this.selectionList.setSelected(this.selectionList.children().stream().findFirst().orElse(null)); From 83ca5220649f45fadbddfc7aec8c2ae6e57891ab Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 12 May 2026 22:45:36 -0700 Subject: [PATCH 523/586] fix(registry): re-post EngineScoped registry event on integrated create-new path WorldOpenFlows#createLevelFromExistingSettings builds a fresh resource manager outside of WorldLoader#load, so the holder MinecraftServerMixin ends up using had an empty sponge root and engine-scoped lookups from StartingEngineEvent listeners raised ValueNotFoundException. Extend WorldOpenFlowsMixin to also call beginEstablishServerRegistries on the new manager so plugin registrations land on the live holder. Signed-off-by: Gabriel Harris-Rouquette --- .../worldselection/WorldOpenFlowsMixin.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java index 4c72120839a..e66134e6029 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/gui/screens/worldselection/WorldOpenFlowsMixin.java @@ -32,9 +32,11 @@ import net.minecraft.server.packs.resources.CloseableResourceManager; import net.minecraft.server.permissions.PermissionLevel; import net.minecraft.world.level.WorldDataConfiguration; +import org.spongepowered.api.registry.RegistryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.Lifecycle; @Mixin(WorldOpenFlows.class) public abstract class WorldOpenFlowsMixin { @@ -43,10 +45,21 @@ public abstract class WorldOpenFlowsMixin { * The integrated-server "create new world" path constructs a fresh * {@link CloseableResourceManager} via {@link WorldLoader.PackConfig#createResourceManager()} * outside of {@link WorldLoader#load} — bypassing {@code WorldLoaderMixin}'s - * {@code establishServerServices} hook. Without it the resource manager that ends up - * in the {@link net.minecraft.server.WorldStem} has no service provider attached, - * and {@code MinecraftServerMixin#impl$onInit} stores {@code null} into the server's - * {@code impl$serviceProvider}, which subsequently NPEs at login time. + * {@code establishServerServices} and {@code beginEstablishServerRegistries} hooks. + * + *

Without the services hook the resource manager that ends up in the + * {@link net.minecraft.server.WorldStem} has no service provider attached, and + * {@code MinecraftServerMixin#impl$onInit} stores {@code null} into the server's + * {@code impl$serviceProvider}, which subsequently NPEs at login time.

+ * + *

Without the registries hook the new holder has an empty sponge root — + * neither the built-in sponge registries nor any plugin-defined + * {@link org.spongepowered.api.event.lifecycle.RegisterRegistryEvent.EngineScoped} + * registrations are present — so engine-scoped lookups (e.g. from + * {@code StartingEngineEvent} listeners) raise + * {@link org.spongepowered.api.registry.ValueNotFoundException}. Re-posting the + * event here is intentional: plugin handlers register against {@code event.getHolder()}, + * so each holder ends up with its own copy and the discarded #1 holder is harmless.

*/ @WrapOperation(method = "createLevelFromExistingSettings", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$PackConfig;createResourceManager()Lcom/mojang/datafixers/util/Pair;")) @@ -54,7 +67,9 @@ public abstract class WorldOpenFlowsMixin { final WorldLoader.PackConfig packConfig, final Operation> original ) { final Pair pair = original.call(packConfig); - Launch.instance().lifecycle().establishServerServices(pair.getSecond(), PermissionLevel.ALL); + final Lifecycle lifecycle = Launch.instance().lifecycle(); + lifecycle.establishServerServices(pair.getSecond(), PermissionLevel.ALL); + lifecycle.beginEstablishServerRegistries((RegistryHolder) pair.getSecond()); return pair; } } From 217ccc233373587d8c58b180c07d20b1e019e6f8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 12 May 2026 23:09:47 -0700 Subject: [PATCH 524/586] chore(gradle): update verification metadata --- gradle/verification-metadata.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1fbfcf8fab5..99022c2f803 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2606,12 +2606,24 @@
+ + + + + + + + + + + + From 539537584f7be70b798a9a58c43de739887a45c8 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 24 May 2026 16:05:45 -0700 Subject: [PATCH 525/586] feat(minecraft): update content for 26.2-snapshot-8 See: https://minecraft.wiki/w/Java_Edition_26.2_Snapshot_8 --- SpongeAPI | 2 +- gradle.properties | 2 +- gradle/verification-metadata.xml | 126 +++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index ec485617723..08d453d30f6 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit ec4856177230d65d9a84fb9e2f639a327d3eb01c +Subproject commit 08d453d30f69b54f598f8405d9739c8b5e8bb88b diff --git a/gradle.properties b/gradle.properties index a0e2ff41057..12295d588c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-7 +minecraftVersion=26.2-snapshot-8 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 99022c2f803..624d145e613 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -882,6 +882,11 @@ + + + + + @@ -1103,6 +1108,11 @@ + + + + + @@ -1392,6 +1402,11 @@ + + + + + @@ -1671,6 +1686,11 @@ + + + + + @@ -1727,6 +1747,11 @@ + + + + + @@ -2019,6 +2044,11 @@ + + + + + @@ -2280,6 +2310,11 @@ + + + + + @@ -2921,6 +2956,11 @@ + + + + + @@ -2953,6 +2993,11 @@ + + + + + @@ -2961,6 +3006,11 @@ + + + + + @@ -2977,6 +3027,11 @@ + + + + + @@ -3009,6 +3064,11 @@ + + + + + @@ -3041,6 +3101,11 @@ + + + + + @@ -3093,6 +3158,11 @@ + + + + + @@ -3125,6 +3195,11 @@ + + + + + @@ -3157,6 +3232,11 @@ + + + + + @@ -3165,6 +3245,11 @@ + + + + + @@ -3209,6 +3294,14 @@ + + + + + + + + @@ -3220,6 +3313,14 @@ + + + + + + + + @@ -3255,6 +3356,11 @@ + + + + + @@ -8151,6 +8257,11 @@ + + + + + @@ -8765,6 +8876,11 @@ + + + + + @@ -8895,6 +9011,11 @@ + + + + + @@ -8980,6 +9101,11 @@ + + + + + From da996537f3ef8fbc60b4352283f1bced2ec414ca Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 16:43:38 -0700 Subject: [PATCH 526/586] feat(minecraft): update to 26.2-pre-1 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_1 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 8 ++++++++ .../mixin/core/server/level/PlayerSpawnFinderMixin.java | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 12295d588c2..76ae125601f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-snapshot-8 +minecraftVersion=26.2-pre-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 624d145e613..d2be743378e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1846,6 +1846,11 @@ + + + + + @@ -10693,6 +10698,9 @@ + + + diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java index da503e41a34..10493823487 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/PlayerSpawnFinderMixin.java @@ -61,7 +61,7 @@ public abstract class PlayerSpawnFinderMixin { @Shadow @Final private int coprime; @Shadow private static Vec3 fixupSpawnHeight(CollisionGetter level, BlockPos pos) { return null; } - @Shadow @Nullable protected static BlockPos getOverworldRespawnPos(ServerLevel level, int x, int z) { return null; } + @Shadow @Nullable protected static BlockPos getLevelRespawnPos(ServerLevel level, int x, int z) { return null; } @Shadow private static boolean noCollisionNoLiquid(CollisionGetter level, BlockPos pos) { return false; } /** @@ -86,7 +86,7 @@ private void scheduleNext() { final int z = this.spawnSuggestion.getZ() + relZ - this.radius; if (this.scheduleCandidate(x, z, i, () -> { - final BlockPos pos = getOverworldRespawnPos(this.level, x, z); + final BlockPos pos = getLevelRespawnPos(this.level, x, z); return pos != null && noCollisionNoLiquid(this.level, pos) ? Optional.of(Vec3.atBottomCenterOf(pos)) : Optional.empty(); })) { return; From 4e3009e0951a574f0bec0e3723b17b7998131b06 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 16:56:27 -0700 Subject: [PATCH 527/586] feat(minecraft): update to 26.2-pre-2 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 76ae125601f..40f273007b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-1 +minecraftVersion=26.2-pre-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 01d2152748ed88548b0a3976ba2b622a798a1467 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 19:55:25 -0700 Subject: [PATCH 528/586] feat(minecraft): update to 26.2-pre-3 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_3 --- gradle.properties | 2 +- .../org/spongepowered/common/entity/SpongeEntityArchetype.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 40f273007b8..33395a73021 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-2 +minecraftVersion=26.2-pre-3 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java index af6382fa233..2af1f2c692e 100644 --- a/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java +++ b/src/main/java/org/spongepowered/common/entity/SpongeEntityArchetype.java @@ -32,6 +32,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; +import net.minecraft.world.entity.EntitySpawnRequest; import net.minecraft.world.entity.Mob; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -148,7 +149,7 @@ public Optional apply(final ServerLocation compound.put(Constants.Entity.ENTITY_POSITION, pos); compound.remove(Constants.Entity.ENTITY_UUID); - final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, level, EntitySpawnReason.LOAD, e -> { + final @Nullable Entity entity = net.minecraft.world.entity.EntityType.loadEntityRecursive(compound, level, new EntitySpawnRequest(EntitySpawnReason.LOAD, false), e -> { e.snapTo(location.x(), location.y(), location.z()); if (e instanceof Mob mobentity) { mobentity.yHeadRot = mobentity.getYRot(); From b5c8b9ec939dd2be38cd7fea0c86d2f1ab377d9a Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 20:15:45 -0700 Subject: [PATCH 529/586] feat(minecraft): update to 26.2-pre-4 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_4 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 33395a73021..2f4dd0f14a4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-3 +minecraftVersion=26.2-pre-4 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d2be743378e..d9036e723c4 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1851,6 +1851,11 @@ + + + + + From 8f7648851226c313b9fb5ea150a6e905d36efd00 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 20:32:19 -0700 Subject: [PATCH 530/586] feat(minecraft): update to 26.2-pre-5 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_5 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2f4dd0f14a4..5740a49a53d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-4 +minecraftVersion=26.2-pre-5 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From cbe558664a9e1ca650b52b21fb0b9b28c6f622e0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 20:41:41 -0700 Subject: [PATCH 531/586] feat(minecraft): update to 26.2-pre-6 See: https://minecraft.wiki/w/Java_Edition_26.2_Pre-Release_6 --- gradle.properties | 2 +- gradle/verification-metadata.xml | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5740a49a53d..0c66aa2e79d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-5 +minecraftVersion=26.2-pre-6 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d9036e723c4..e0c5cca994a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2971,6 +2971,11 @@ + + + + + @@ -3008,6 +3013,11 @@ + + + + + @@ -3021,6 +3031,11 @@ + + + + + @@ -3042,6 +3057,11 @@ + + + + + @@ -3079,6 +3099,11 @@ + + + + + @@ -3116,6 +3141,11 @@ + + + + + @@ -3173,6 +3203,11 @@ + + + + + @@ -3210,6 +3245,11 @@ + + + + + @@ -3247,6 +3287,11 @@ + + + + + @@ -3260,6 +3305,11 @@ + + + + + @@ -3312,6 +3362,14 @@ + + + + + + + + @@ -3331,6 +3389,14 @@ + + + + + + + + @@ -3371,6 +3437,11 @@ + + + + + From a6a973771de2d377d60bfd67593a9893a0fc5a9e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 20:49:31 -0700 Subject: [PATCH 532/586] feat(minecraft): update to 26.2-rc-1 See: https://minecraft.wiki/w/Java_Edition_26.2_Release_Candidate_1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0c66aa2e79d..a029d9c9401 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-pre-6 +minecraftVersion=26.2-rc-1 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 2719d00342fbb05e9f2d040f177df121ba627bd0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:17:25 -0700 Subject: [PATCH 533/586] feat(minecraft): update to 26.2-rc-2 See: https://minecraft.wiki/w/Java_Edition_26.2_Release_Candidate_2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a029d9c9401..ed7a78ab4c7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-rc-1 +minecraftVersion=26.2-rc-2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 278ef0bfa5354122a64f2dd7f1ad2a63307ca3d0 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:30:09 -0700 Subject: [PATCH 534/586] feat(minecraft): update to 26.2 See: https://minecraft.wiki/w/Java_Edition_26.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ed7a78ab4c7..3b4e495e552 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c mixins.sponge.entityactivation.json,mixins.sponge.exploit.json,mixins.sponge.inventory.json,mixins.sponge.movementcheck.json,\ mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json -minecraftVersion=26.2-rc-2 +minecraftVersion=26.2 recommendedVersion=0-SNAPSHOT org.gradle.dependency.verification.console=verbose From 81229fd1e38ea9b8d206c260b541ec1cf99fd17b Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:31:52 -0700 Subject: [PATCH 535/586] feat(minecraft): update content to 26.2 See: https://minecraft.wiki/w/Java_Edition_26.2 --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 08d453d30f6..42c0e700202 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 08d453d30f69b54f598f8405d9739c8b5e8bb88b +Subproject commit 42c0e70020251ceabc729bfc95d4cbb0d866f445 From 773fa926f1a84cda81c0e64bd1ac3e669dc32660 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:37:29 -0700 Subject: [PATCH 536/586] chore(neoforge): bump to NeoForge 26.1.2.31-beta - neoForgeVersion 26.1.2.7-beta -> 26.1.2.31-beta - gradle 9.2.1 -> 9.3 - refresh dependency verification metadata Signed-off-by: Gabriel Harris-Rouquette --- gradle/verification-metadata.xml | 42 ++++++++++++++++++++++++++++++++ mise.toml | 2 +- neoforge/gradle.properties | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 19efb99ce0d..12078f8d0c3 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2828,6 +2828,11 @@ + + + + + @@ -3587,6 +3592,11 @@ + + + + + @@ -7214,6 +7224,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -7425,6 +7457,11 @@ + + + + + @@ -7560,6 +7597,11 @@ + + + + + diff --git a/mise.toml b/mise.toml index f3149bc0e27..f3a05cff113 100644 --- a/mise.toml +++ b/mise.toml @@ -1,3 +1,3 @@ [tools] -gradle = "9.2.1" +gradle = "9.3" java = "temurin-25" diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 2f4cc0e84d9..9bf88fa5950 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.1.2.7-beta +neoForgeVersion=26.1.2.31-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 4619263347b81fa07b07658c117cb54ad4ca3709 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:37:29 -0700 Subject: [PATCH 537/586] fix(neoforge): target NeoForge's split randomTeleport overload NeoForge moved the LivingEntity#randomTeleport body into a new 5-arg overload taking the consumed ItemStack, leaving the 4-arg method as a forwarder. The shared randomTeleport injections no longer matched on Neo. Split LivingEntityMixin and TeleportRandomlyConsumeEffectMixin into per-platform variants: vanilla/forge target the 4-arg method, neoforge targets the 5-arg overload. Signed-off-by: Gabriel Harris-Rouquette --- .../world/entity/LivingEntityMixin_Forge.java | 57 ++++++++++++++++++ ...eportRandomlyConsumeEffectMixin_Forge.java | 10 ++-- .../resources/mixins.spongeforge.core.json | 1 + .../world/entity/LivingEntityMixin_Neo.java | 60 +++++++++++++++++++ ...eleportRandomlyConsumeEffectMixin_Neo.java | 54 +++++++++++++++++ .../resources/mixins.spongeneo.core.json | 1 + .../core/world/entity/LivingEntityMixin.java | 42 ------------- src/mixins/resources/mixins.sponge.core.json | 1 - .../entity/LivingEntityMixin_Vanilla.java | 56 +++++++++++++++++ ...ortRandomlyConsumeEffectMixin_Vanilla.java | 49 +++++++++++++++ .../resources/mixins.spongevanilla.core.json | 1 + 11 files changed, 284 insertions(+), 48 deletions(-) rename src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java => forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Forge.java (84%) create mode 100644 neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Neo.java create mode 100644 vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Vanilla.java diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java index a91a34fa01e..9e188e58814 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java @@ -24,15 +24,32 @@ */ package org.spongepowered.forge.mixin.core.world.entity; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.api.event.entity.MoveEntityEvent; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.math.vector.Vector3d; @Mixin(value = LivingEntity.class) public abstract class LivingEntityMixin_Forge { + @Unique + @Nullable + private Vector3d forge$preTeleportPosition; + @Inject( method = "updateFallFlying", at = @At( @@ -43,4 +60,44 @@ public abstract class LivingEntityMixin_Forge { ) protected void forge$onElytraUse(final CallbackInfo ci) { } + + @Inject(method = "randomTeleport", at = @At("HEAD")) + private void forge$snapshotPositionBeforeVanillaTeleportLogic(final double x, final double y, final double z, final boolean changeState, + final CallbackInfoReturnable cir) { + final Entity self = (Entity) (Object) this; + this.forge$preTeleportPosition = new Vector3d(self.getX(), self.getY(), self.getZ()); + } + + @Inject(method = "randomTeleport", at = @At(value = "RETURN", ordinal = 0, shift = At.Shift.BY, by = 2), cancellable = true) + private void forge$callMoveEntityEventForTeleport(final double x, final double y, final double z, final boolean changeState, + final CallbackInfoReturnable cir) { + if (!ShouldFire.MOVE_ENTITY_EVENT) { + return; + } + + final Entity self = (Entity) (Object) this; + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.pushCause(this); + + // ENTITY_TELEPORT is our fallback context + if (!frame.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE)) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.ENTITY_TELEPORT); + } + + final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), + (org.spongepowered.api.entity.Entity) this, this.forge$preTeleportPosition, + new Vector3d(self.getX(), self.getY(), self.getZ()), + new Vector3d(x, y, z)); + + if (SpongeCommon.post(event)) { + self.teleportTo(this.forge$preTeleportPosition.x(), this.forge$preTeleportPosition.y(), + this.forge$preTeleportPosition.z()); + cir.setReturnValue(false); + return; + } + + self.teleportTo(event.destinationPosition().x(), event.destinationPosition().y(), + event.destinationPosition().z()); + } + } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Forge.java similarity index 84% rename from src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java rename to forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Forge.java index 44f6a6eb738..045cb37102e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Forge.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.mixin.core.world.item; +package org.spongepowered.forge.mixin.core.world.item; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; @@ -35,15 +35,15 @@ import org.spongepowered.common.event.tracking.PhaseTracker; @Mixin(TeleportRandomlyConsumeEffect.class) -public abstract class TeleportRandomlyConsumeEffectMixin { +public abstract class TeleportRandomlyConsumeEffectMixin_Forge { @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZ)Z")) - private boolean impl$createCauseFrameForTeleport(final LivingEntity entity, final double x, final double y, final double z, - final boolean p_213373_7_) { + private boolean forge$createCauseFrameForTeleport(final LivingEntity entity, final double x, final double y, final double z, + final boolean changeState) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.CHORUS_FRUIT.get()); - return entity.randomTeleport(x, y, z, p_213373_7_); + return entity.randomTeleport(x, y, z, changeState); } } } diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index da2c8b76a2c..e667a285fdf 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -27,6 +27,7 @@ "world.entity.item.ItemEntityMixin_Forge", "world.entity.player.PlayerMixin_Forge_Damage", "world.entity.vehicle.boat.BoatMixin_Forge", + "world.item.TeleportRandomlyConsumeEffectMixin_Forge", "world.level.ServerExplosionMixin_Forge", "world.level.block.FireBlockMixin_Forge", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Forge" diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java index f0ab5d9c54c..87873764d1e 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java @@ -24,15 +24,32 @@ */ package org.spongepowered.neoforge.mixin.core.world.entity; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.api.event.entity.MoveEntityEvent; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.math.vector.Vector3d; @Mixin(value = LivingEntity.class) public abstract class LivingEntityMixin_Neo { + @Unique + @Nullable private Vector3d neo$preTeleportPosition; + @Inject( method = "updateFallFlying", at = @At( @@ -43,4 +60,47 @@ public abstract class LivingEntityMixin_Neo { ) protected void neo$onElytraUse(final CallbackInfo ci) { } + + // Neo PR #3119 (26.1.2.31-beta) split randomTeleport into a 4-arg forwarder and a 5-arg overload that holds the body. + // Inject into the 5-arg overload so the original RETURN+BY 2 anchor still resolves. + @Inject(method = "randomTeleport(DDDZLnet/minecraft/world/item/ItemStack;)Z", at = @At("HEAD")) + private void neo$snapshotPositionBeforeVanillaTeleportLogic(final double x, final double y, final double z, final boolean changeState, + final ItemStack consumedStack, final CallbackInfoReturnable cir) { + final Entity self = (Entity) (Object) this; + this.neo$preTeleportPosition = new Vector3d(self.getX(), self.getY(), self.getZ()); + } + + @Inject(method = "randomTeleport(DDDZLnet/minecraft/world/item/ItemStack;)Z", + at = @At(value = "RETURN", ordinal = 0, shift = At.Shift.BY, by = 2), cancellable = true) + private void neo$callMoveEntityEventForTeleport(final double x, final double y, final double z, final boolean changeState, + final ItemStack consumedStack, final CallbackInfoReturnable cir) { + if (!ShouldFire.MOVE_ENTITY_EVENT) { + return; + } + + final Entity self = (Entity) (Object) this; + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.pushCause(this); + + // ENTITY_TELEPORT is our fallback context + if (!frame.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE)) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.ENTITY_TELEPORT); + } + + final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), + (org.spongepowered.api.entity.Entity) this, this.neo$preTeleportPosition, + new Vector3d(self.getX(), self.getY(), self.getZ()), + new Vector3d(x, y, z)); + + if (SpongeCommon.post(event)) { + self.teleportTo(this.neo$preTeleportPosition.x(), this.neo$preTeleportPosition.y(), + this.neo$preTeleportPosition.z()); + cir.setReturnValue(false); + return; + } + + self.teleportTo(event.destinationPosition().x(), event.destinationPosition().y(), + event.destinationPosition().z()); + } + } } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Neo.java new file mode 100644 index 00000000000..ebdc6e47bfa --- /dev/null +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Neo.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.mixin.core.world.item; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.tracking.PhaseTracker; + +// Neo PR #3119 (26.1.2.31-beta) changed TeleportRandomlyConsumeEffect#apply to call the new +// 5-arg randomTeleport(...,ItemStack) overload directly so it can fire EntityTeleportEvent.ItemConsumption. +// Redirect the 5-arg call here. +@Mixin(TeleportRandomlyConsumeEffect.class) +public abstract class TeleportRandomlyConsumeEffectMixin_Neo { + + @Redirect(method = "apply", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZLnet/minecraft/world/item/ItemStack;)Z")) + private boolean neo$createCauseFrameForTeleport(final LivingEntity entity, final double x, final double y, final double z, + final boolean changeState, final ItemStack consumedStack) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.CHORUS_FRUIT.get()); + + return entity.randomTeleport(x, y, z, changeState, consumedStack); + } + } +} diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index effa93814ee..e1fac839ad5 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -37,6 +37,7 @@ "world.entity.projectile.FishingHookMixin_Neo", "world.entity.vehicle.boat.AbstractBoatMixin_Neo", "world.level.ServerExplosionMixin_NeoForge", + "world.item.TeleportRandomlyConsumeEffectMixin_Neo", "world.item.crafting.RecipeManagerMixin_Neo", "world.level.block.FireBlockMixin_Neo", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Neo" diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index 2b0a1e705fa..9777c6ef4a2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -55,8 +55,6 @@ import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.SpongeEventFactory; import org.spongepowered.api.event.action.SleepingEvent; -import org.spongepowered.api.event.cause.entity.MovementTypes; -import org.spongepowered.api.event.entity.MoveEntityEvent; import org.spongepowered.api.event.item.inventory.UseItemStackEvent; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.util.Ticks; @@ -74,7 +72,6 @@ import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; import org.spongepowered.common.bridge.world.level.LevelBridge; import org.spongepowered.common.entity.living.human.HumanEntity; -import org.spongepowered.common.event.ShouldFire; import org.spongepowered.common.event.SpongeCommonEventFactory; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; @@ -121,7 +118,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt // @formatter:on @Nullable private ItemStack impl$activeItemStackCopy; - @Nullable private Vector3d impl$preTeleportPosition; private int impl$deathEventsPosted; @@ -190,44 +186,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt - @Inject(method = "randomTeleport", at = @At("HEAD")) - private void impl$snapshotPositionBeforeVanillaTeleportLogic(final double x, final double y, final double z, final boolean changeState, - final CallbackInfoReturnable cir) { - this.impl$preTeleportPosition = new Vector3d(this.shadow$getX(), this.shadow$getY(), this.shadow$getZ()); - } - - @Inject(method = "randomTeleport", at = @At(value = "RETURN", ordinal = 0, shift = At.Shift.BY, by = 2), cancellable = true) - private void impl$callMoveEntityEventForTeleport(final double x, final double y, final double z, final boolean changeState, - final CallbackInfoReturnable cir) { - if (!ShouldFire.MOVE_ENTITY_EVENT) { - return; - } - - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { - frame.pushCause(this); - - // ENTITY_TELEPORT is our fallback context - if (!frame.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE)) { - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.ENTITY_TELEPORT); - } - - final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), - (org.spongepowered.api.entity.Entity) this, this.impl$preTeleportPosition, new Vector3d(this.shadow$getX(), this.shadow$getY(), - this.shadow$getZ()), - new Vector3d(x, y, z)); - - if (SpongeCommon.post(event)) { - this.shadow$teleportTo(this.impl$preTeleportPosition.x(), this.impl$preTeleportPosition.y(), - this.impl$preTeleportPosition.z()); - cir.setReturnValue(false); - return; - } - - this.shadow$teleportTo(event.destinationPosition().x(), event.destinationPosition().y(), - event.destinationPosition().z()); - } - } - /** * @author gabizou - January 4th, 2016 * @reason This allows invisiblity to ignore entity collisions. diff --git a/src/mixins/resources/mixins.sponge.core.json b/src/mixins/resources/mixins.sponge.core.json index e97eddf179d..a79eb45f07d 100644 --- a/src/mixins/resources/mixins.sponge.core.json +++ b/src/mixins/resources/mixins.sponge.core.json @@ -210,7 +210,6 @@ "world.item.ItemStackMixin", "world.item.MapItemMixin", "world.item.ServerItemCooldownsMixin", - "world.item.TeleportRandomlyConsumeEffectMixin", "world.item.crafting.AbstractCookingRecipeMixin", "world.item.crafting.IngredientMixin", "world.item.crafting.RecipeManagerMixin", diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla.java index 2e1fe7088ab..085a63ba57f 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/LivingEntityMixin_Vanilla.java @@ -24,15 +24,31 @@ */ package org.spongepowered.vanilla.mixin.core.world.entity; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.api.event.entity.MoveEntityEvent; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.common.SpongeCommon; +import org.spongepowered.common.event.ShouldFire; +import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.math.vector.Vector3d; @Mixin(value = LivingEntity.class) public abstract class LivingEntityMixin_Vanilla extends EntityMixin_Vanilla { + @Unique + @Nullable private Vector3d vanilla$preTeleportPosition; + @Inject( method = "updateFallFlying", at = @At( @@ -44,4 +60,44 @@ public abstract class LivingEntityMixin_Vanilla extends EntityMixin_Vanilla { protected void vanilla$onElytraUse(final CallbackInfo ci) { } + @Inject(method = "randomTeleport", at = @At("HEAD")) + private void vanilla$snapshotPositionBeforeVanillaTeleportLogic(final double x, final double y, final double z, final boolean changeState, + final CallbackInfoReturnable cir) { + final Entity self = (Entity) (Object) this; + this.vanilla$preTeleportPosition = new Vector3d(self.getX(), self.getY(), self.getZ()); + } + + @Inject(method = "randomTeleport", at = @At(value = "RETURN", ordinal = 0, shift = At.Shift.BY, by = 2), cancellable = true) + private void vanilla$callMoveEntityEventForTeleport(final double x, final double y, final double z, final boolean changeState, + final CallbackInfoReturnable cir) { + if (!ShouldFire.MOVE_ENTITY_EVENT) { + return; + } + + final Entity self = (Entity) (Object) this; + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.pushCause(this); + + // ENTITY_TELEPORT is our fallback context + if (!frame.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE)) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.ENTITY_TELEPORT); + } + + final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), + (org.spongepowered.api.entity.Entity) this, this.vanilla$preTeleportPosition, + new Vector3d(self.getX(), self.getY(), self.getZ()), + new Vector3d(x, y, z)); + + if (SpongeCommon.post(event)) { + self.teleportTo(this.vanilla$preTeleportPosition.x(), this.vanilla$preTeleportPosition.y(), + this.vanilla$preTeleportPosition.z()); + cir.setReturnValue(false); + return; + } + + self.teleportTo(event.destinationPosition().x(), event.destinationPosition().y(), + event.destinationPosition().z()); + } + } + } diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Vanilla.java new file mode 100644 index 00000000000..a2fdc00715b --- /dev/null +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/item/TeleportRandomlyConsumeEffectMixin_Vanilla.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.mixin.core.world.item; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.EventContextKeys; +import org.spongepowered.api.event.cause.entity.MovementTypes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.common.event.tracking.PhaseTracker; + +@Mixin(TeleportRandomlyConsumeEffect.class) +public abstract class TeleportRandomlyConsumeEffectMixin_Vanilla { + + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZ)Z")) + private boolean vanilla$createCauseFrameForTeleport(final LivingEntity entity, final double x, final double y, final double z, + final boolean changeState) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.CHORUS_FRUIT.get()); + + return entity.randomTeleport(x, y, z, changeState); + } + } +} diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index ae6c5e736f6..84dfe17085b 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -41,6 +41,7 @@ "world.entity.player.PlayerMixin_Vanilla_Damage", "world.entity.vehicle.boat.AbstractBoatMixin_Vanilla", "world.level.ServerExplosionMixin_Vanilla", + "world.item.TeleportRandomlyConsumeEffectMixin_Vanilla", "world.level.block.FireBlockMixin_Vanilla", "world.level.block.entity.AbstractFurnaceBlockEntityMixin_Vanilla", "world.level.storage.LevelStorageSourceMixin_Vanilla" From 4a2d17b6cd8f89c51668bc3b9b2ddc2c70d854da Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:37:29 -0700 Subject: [PATCH 538/586] fix(tracker): defer entities added off-thread by buggy mods Mods adding entities through ServerLevel#addFreshEntity during async feature placement (instead of WorldGenLevel) crash the entity section manager's main-thread invariant. Capture such off-thread adds into the async entity queue and guard PersistentEntitySectionManager against off-thread access. Signed-off-by: Gabriel Harris-Rouquette --- .../common/event/tracking/PhaseTracker.java | 10 +++++++++ .../PersistentEntitySectionManagerMixin.java | 9 ++++++++ .../level/ServerLevelMixin_Tracker.java | 21 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index 7e3cf86e528..b5708d57cf6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -96,6 +96,16 @@ public final class PhaseTracker implements CauseStackManager { private static final PhaseTracker SERVER = new PhaseTracker(); public static final Logger LOGGER = LogManager.getLogger(PhaseTracker.class); static final CopyOnWriteArrayList ASYNC_CAPTURED_ENTITIES = new CopyOnWriteArrayList<>(); + + /** + * Queue an entity that was offered to a main-thread-only entity addition API from an + * off-thread context (typically a worldgen worker invoking {@code ServerLevel#addFreshEntity} + * directly instead of going through the {@code WorldGenLevel} it was given). The per-tick + * drain task in {@link #init()} re-adds these on the main thread under a forced spawn cause. + */ + public static void captureAsyncEntity(final net.minecraft.world.entity.Entity entity) { + PhaseTracker.ASYNC_CAPTURED_ENTITIES.add(entity); + } private static final Map SPINOFF_TRACKERS = new MapMaker().weakKeys().concurrencyLevel(8).makeMap(); private static final boolean DEBUG_CAUSE_FRAMES = Boolean.parseBoolean(System.getProperty("sponge.debugcauseframes", "false")); private static final String INITIAL_POOL_SIZE_PROPERTY = "sponge.cause.initialFramePoolSize"; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java index f3b9c8b2fb3..6ac4883ddfc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java @@ -56,6 +56,15 @@ public class PersistentEntitySectionManagerMixin { final EntityAccess entity, final boolean callCreateCallback, final CallbackInfoReturnable cir ) { + // Section manager additions outside the main thread are an API misuse (vanilla worldgen + // routes entities through WorldGenRegion#addFreshEntity, which is chunk-scoped). If we + // somehow get here off-thread anyway (e.g. a buggy mod calling ServerLevel#addFreshEntity + // from a worldgen worker), skip the construct event rather than tripping the cause-stack + // main-thread guard. Other Sponge entity mixins (ItemEntityMixin, EntityMixin_Tracker, + // ServerLevelMixin_Tracker, ...) follow the same pattern. + if (!PhaseTracker.getWorldInstance().onSidedThread()) { + return; + } if (!(entity instanceof final EntityBridge bridge)) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index b18c9d61811..81c1d3b6e5c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -789,4 +789,25 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } } + /** + * Salvage for buggy-mod-async-world-adding-entities: some mods (e.g. Aether II's + * MoaNestFeature) call {@link ServerLevel#addFreshEntity(Entity)} directly from a + * worldgen worker thread instead of going through the {@link net.minecraft.world.level.WorldGenLevel} + * (concretely {@link net.minecraft.server.level.WorldGenRegion#addFreshEntity}) they were given. + * + *

The vanilla call chain ({@code ServerLevel#addFreshEntity} → + * {@code PersistentEntitySectionManager#addEntity}) is main-thread-only and races without + * Sponge in the picture. Rather than crash worldgen, capture the entity via + * {@link PhaseTracker#captureAsyncEntity(Entity)} so the per-tick drain task on the main + * thread can re-add it via the proper path. The boolean return is optimistic, mirroring how + * {@code WorldGenRegion#addFreshEntity} unconditionally returns {@code true}.

+ */ + @Inject(method = "addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z", at = @At("HEAD"), cancellable = true) + private void tracker$deferBuggyModAsyncWorldAddingEntities(final Entity entity, final CallbackInfoReturnable cir) { + if (!PhaseTracker.getWorldInstance((ServerLevel) (Object) this).onSidedThread()) { + PhaseTracker.captureAsyncEntity(entity); + cir.setReturnValue(true); + } + } + } From 7c1fd8315565ff4f332adf98e62269fa19ff0dd1 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Tue, 16 Jun 2026 21:37:30 -0700 Subject: [PATCH 539/586] fix(neoforge): adapt to BreakBlockEvent rename NeoForge renamed BlockEvent.BreakEvent to BreakBlockEvent and moved it to the event.level.block package. Signed-off-by: Gabriel Harris-Rouquette --- .../core/api/event/block/ChangeBlockEvent_AllMixin_Neo.java | 4 ++-- .../neoforge/event/world/BlockEvent_BreakEventMixin_Neo.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Neo.java index b3d32099da6..21ba5afdabb 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/api/event/block/ChangeBlockEvent_AllMixin_Neo.java @@ -28,7 +28,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.bus.api.Event; -import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.event.level.block.BreakBlockEvent; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.transaction.BlockTransaction; import org.spongepowered.api.block.transaction.Operation; @@ -54,7 +54,7 @@ public interface ChangeBlockEvent_AllMixin_Neo extends SpongeEventBridge_Neo { final List forgeEvents = new ArrayList<>(); for (final BlockTransaction transaction : thisEvent.transactions()) { if (player != null && transaction.operation() == breakOp) { - forgeEvents.add(new BlockEvent.BreakEvent((Level) thisEvent.world(), + forgeEvents.add(new BreakBlockEvent((Level) thisEvent.world(), VecHelper.toBlockPos(transaction.original().position()), (BlockState) transaction.original().state(), player)); } diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/world/BlockEvent_BreakEventMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/world/BlockEvent_BreakEventMixin_Neo.java index ceec4ae8c05..cef5f076936 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/world/BlockEvent_BreakEventMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/neoforge/event/world/BlockEvent_BreakEventMixin_Neo.java @@ -26,7 +26,7 @@ import net.minecraft.world.level.LevelAccessor; import net.neoforged.bus.api.ICancellableEvent; -import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.event.level.block.BreakBlockEvent; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.block.BlockTypes; @@ -44,7 +44,7 @@ import java.util.Collections; -@Mixin(value = BlockEvent.BreakEvent.class, remap = false) +@Mixin(value = BreakBlockEvent.class, remap = false) public abstract class BlockEvent_BreakEventMixin_Neo extends BlockEventMixin_Neo implements NeoEventBridge_Neo, ICancellableEvent { @Override From 17a3c5fda9ac2682e4503539101537a1afe6e5e9 Mon Sep 17 00:00:00 2001 From: Aapo Katila <81980535+abola2@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:36:15 +0300 Subject: [PATCH 540/586] Change world border timeToTargetDiameter to ticks (#4295) * change WorldBorder timeToTargetDiameter to ticks * Update SpongeAPI for CI * fix infinite ticks * fix logic issues * cleanup * fix infinity ticks * cleanup * fix warning time --- SpongeAPI | 2 +- .../common/util/SpongeTicks.java | 15 ++++++++++ .../border/SpongeWorldBorderBuilder.java | 28 ++++++++----------- .../border/WorldBorderMixin_Settings_API.java | 11 ++++---- .../world/level/border/WorldBorderMixin.java | 10 +++---- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 70c01f5be0f..e01d9a59805 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 70c01f5be0f779353d44c1c14bdedcecc4e978fc +Subproject commit e01d9a59805dded81d1c8d32c8f33bfe81868d21 diff --git a/src/main/java/org/spongepowered/common/util/SpongeTicks.java b/src/main/java/org/spongepowered/common/util/SpongeTicks.java index bfe21863604..d3db1aca012 100644 --- a/src/main/java/org/spongepowered/common/util/SpongeTicks.java +++ b/src/main/java/org/spongepowered/common/util/SpongeTicks.java @@ -109,6 +109,21 @@ public static int toSaturatedIntOrInfinite(final Ticks ticks, final int infinite return (int) ticksValue; } + public static long toSaturatedLongOrInfinite(final Ticks ticks) { + return SpongeTicks.toSaturatedLongOrInfinite(ticks, Constants.TickConversions.INFINITE_TICKS); + } + + public static long toSaturatedLongOrInfinite(final Ticks ticks, final long infiniteTicksMarker) { + if (ticks.isInfinite()) { + return infiniteTicksMarker; + } + long ticksValue = ticks.ticks(); + if (infiniteTicksMarker > 0 && ticksValue >= infiniteTicksMarker) { + ticksValue = infiniteTicksMarker - 1; + } + return ticksValue; + } + public static Ticks ticksOrInfinite(final long ticks) { return SpongeTicks.ticksOrInfinite(ticks, Constants.TickConversions.INFINITE_TICKS); } diff --git a/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java b/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java index 80e3318f7eb..64505ca9ed6 100644 --- a/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java +++ b/src/main/java/org/spongepowered/common/world/border/SpongeWorldBorderBuilder.java @@ -24,20 +24,20 @@ */ package org.spongepowered.common.world.border; +import org.spongepowered.api.util.Ticks; import org.spongepowered.api.world.border.WorldBorder; import org.spongepowered.common.accessor.world.level.border.WorldBorder_SettingsAccessor; import org.spongepowered.common.bridge.world.level.border.WorldBorderBridge; +import org.spongepowered.common.util.SpongeTicks; import org.spongepowered.math.vector.Vector2d; -import java.time.Duration; - public final class SpongeWorldBorderBuilder implements WorldBorder.Builder { private double diameter = -1; private double initialDiameter = -1; - private Duration time = Duration.ZERO; + private Ticks time = Ticks.zero(); private Vector2d center = Vector2d.ZERO; //use a default value otherwise null is used - private Duration warningTime = Duration.ZERO; + private Ticks warningTime = Ticks.zero(); private double warningDistance; private double safeZone; private double damagePerBlock; @@ -77,11 +77,8 @@ public WorldBorder.Builder targetDiameter(final double diameter) { } @Override - public WorldBorder.Builder timeToTargetDiameter(final Duration time) { - if (time.isNegative()) { - throw new IllegalArgumentException("time cannot be negative"); - } - this.time = time; + public WorldBorder.Builder timeToTargetDiameter(final Ticks ticks) { + this.time = ticks; return this; } @@ -122,10 +119,7 @@ public WorldBorder.Builder damagePerBlock(final double damagePerBlock) { } @Override - public WorldBorder.Builder warningTime(final Duration warningTime) { - if (warningTime.isNegative()) { - throw new IllegalArgumentException("warning time cannot be negative"); - } + public WorldBorder.Builder warningTime(final Ticks warningTime) { this.warningTime = warningTime; return this; } @@ -151,9 +145,9 @@ public WorldBorder build() throws IllegalStateException { this.damagePerBlock, this.safeZone, (int) this.warningDistance, - (int) this.warningTime.getSeconds(), + SpongeTicks.toSaturatedIntOrInfinite(this.warningTime), this.initialDiameter == -1 ? this.diameter : this.initialDiameter, - this.time.toMillis(), + SpongeTicks.toSaturatedLongOrInfinite(this.time), this.diameter ); } @@ -165,9 +159,9 @@ public WorldBorder.Builder reset() { this.safeZone = 0; this.diameter = -1; this.initialDiameter = -1; - this.time = Duration.ZERO; + this.time = Ticks.zero(); this.warningDistance = 0; - this.warningTime = Duration.ZERO; + this.warningTime = Ticks.zero(); return this; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java index 68985d69c1d..0eebe6ecb3f 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/border/WorldBorderMixin_Settings_API.java @@ -25,14 +25,15 @@ package org.spongepowered.common.mixin.api.minecraft.world.level.border; import net.minecraft.world.level.border.WorldBorder; +import org.spongepowered.api.util.Ticks; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.util.SpongeTicks; import org.spongepowered.math.vector.Vector2d; -import java.time.Duration; @Mixin(WorldBorder.Settings.class) @Implements(@Interface(iface = org.spongepowered.api.world.border.WorldBorder.class, prefix = "api$")) @@ -61,8 +62,8 @@ public double targetDiameter() { } @Override - public Duration timeUntilTargetDiameter() { - return Duration.ofMillis(this.shadow$lerpTime()); + public Ticks timeUntilTargetDiameter() { + return SpongeTicks.ticksOrInfinite(this.shadow$lerpTime()); } @Override @@ -81,8 +82,8 @@ public double diameter() { } @Intrinsic - public Duration api$warningTime() { - return Duration.ofMillis(this.shadow$warningTime()); + public Ticks api$warningTime() { + return SpongeTicks.ticksOrInfinite(this.shadow$warningTime()); } @Override diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java index 9c9e020ec12..9a3f4538307 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/border/WorldBorderMixin.java @@ -39,9 +39,9 @@ import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.level.border.WorldBorderBridge; import org.spongepowered.common.event.tracking.PhaseTracker; +import org.spongepowered.common.util.SpongeTicks; import org.spongepowered.common.world.border.SpongeWorldBorderBuilder; -import java.time.Duration; import java.util.Optional; import java.util.function.Supplier; @@ -83,13 +83,13 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { } @Inject(method = "lerpSizeBetween", at = @At(value = "HEAD"), cancellable = true) - private void impl$onLerping(final double initial, final double target, final long milliseconds, final long delay, final CallbackInfo ci) { + private void impl$onLerping(final double initial, final double target, final long ticks, final long delay, final CallbackInfo ci) { if (this.impl$fireEvent) { final Supplier proposed = () -> new SpongeWorldBorderBuilder().from(this) .initialDiameter(initial) .targetDiameter(target) - .timeToTargetDiameter(Duration.ofMillis(milliseconds)) + .timeToTargetDiameter(SpongeTicks.ticksOrInfinite(ticks)) .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); @@ -141,7 +141,7 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { if (this.impl$fireEvent) { final Supplier proposed = () -> new SpongeWorldBorderBuilder().from(this) - .warningTime(Duration.ofSeconds(warningTime)) + .warningTime(SpongeTicks.ticksOrInfinite(warningTime)) .build(); if (this.impl$suppressOriginalAction(proposed)) { ci.cancel(); @@ -225,7 +225,7 @@ public abstract class WorldBorderMixin implements WorldBorderBridge { // TODO - figure out how to get the appropriate game time ((WorldBorder) (Object) this).lerpSizeBetween(worldBorder.size(), worldBorder.lerpTarget(), worldBorder.lerpTime(), SpongeCommon.server().overworld().getGameTime()); } else { - ((WorldBorder) (Object) this).setSize(worldBorder.size()); + ((WorldBorder) (Object) this).setSize(worldBorder.lerpTime() == -1 ? worldBorder.size() : worldBorder.lerpTarget()); } } From 6b89b83a251f1538aca2754fe93292946ecf928b Mon Sep 17 00:00:00 2001 From: aromaa Date: Sun, 28 Jun 2026 03:10:12 +0300 Subject: [PATCH 541/586] Add missing TestBlockMode mixin --- .../properties/TestBlockModeMixin_API.java | 32 +++++++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 1 + 2 files changed, 33 insertions(+) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/TestBlockModeMixin_API.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/TestBlockModeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/TestBlockModeMixin_API.java new file mode 100644 index 00000000000..36ae2824a06 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/state/properties/TestBlockModeMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.level.block.state.properties; + +import net.minecraft.world.level.block.state.properties.TestBlockMode; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(TestBlockMode.class) +public abstract class TestBlockModeMixin_API implements org.spongepowered.api.data.type.TestBlockMode { +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 0ac09aad09a..9a45219c85d 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -460,6 +460,7 @@ "minecraft.world.level.block.state.properties.SlabTypeMixin_API", "minecraft.world.level.block.state.properties.StairsShapeMixin_API", "minecraft.world.level.block.state.properties.StructureModeMixin_API", + "minecraft.world.level.block.state.properties.TestBlockModeMixin_API", "minecraft.world.level.block.state.properties.TiltMixin_API", "minecraft.world.level.block.state.properties.WallSideMixin_API", "minecraft.world.level.border.WorldBorderMixin_Settings_API", From eafcbad0c15a6ee25e6e63d3eeb146162ab20c0e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 25 Jul 2026 22:05:15 -0700 Subject: [PATCH 542/586] feat(forge/neoforge): update platforms --- forge/gradle.properties | 2 +- .../core/network/ConnectionMixin_Forge.java | 4 +- .../level/ServerExplosionMixin_Forge.java | 11 +- .../level/block/BlockMixin_Forge_Tracker.java | 7 +- .../BlockBehaviorMixin_Forge_Tracker.java | 7 +- .../resources/mixins.spongeforge.core.json | 3 + gradle/verification-metadata.xml | 116 ++++++++++++++++++ neoforge/gradle.properties | 2 +- .../world/entity/LivingEntityMixin_Neo.java | 3 +- .../entity/LivingEntityMixin_Neo_Damage.java | 4 +- .../entity/player/PlayerMixin_Neo_Damage.java | 4 +- .../level/ServerExplosionMixin_NeoForge.java | 11 +- .../ServerPlayerMixin_Inventory_Neo.java | 7 +- .../level/block/BlockMixin_Neo_Tracker.java | 7 +- .../state/BlockBehaviorMixin_Neo_Tracker.java | 7 +- .../resources/mixins.spongeneo.core.json | 3 + .../resources/mixins.spongevanilla.core.json | 3 + 17 files changed, 176 insertions(+), 25 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 19b01c841c4..3c6c60ee9fb 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=64.0.1 +forgeVersion=65.0.9 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java index fa1e4bbdb98..afa83675b9c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/network/ConnectionMixin_Forge.java @@ -39,9 +39,11 @@ @Mixin(Connection.class) public abstract class ConnectionMixin_Forge { + // Forge 26.2 adds a second addListener call (packet logger) right after this one — pin to the first. @WrapOperation(method = "doSendPacket", at = @At( value = "INVOKE", target = "Lio/netty/channel/ChannelFuture;addListener(Lio/netty/util/concurrent/GenericFutureListener;)Lio/netty/channel/ChannelFuture;", + ordinal = 0, remap = false )) public ChannelFuture impl$onPacketSent( @@ -56,6 +58,6 @@ public abstract class ConnectionMixin_Forge { } }); } - return original.call(instance, listener); + return original.call(instance, genericFutureListener); } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java index 9ac4759c2cf..119f0f25cae 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/ServerExplosionMixin_Forge.java @@ -49,7 +49,6 @@ import org.spongepowered.common.util.VecHelper; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -75,14 +74,16 @@ public abstract class ServerExplosionMixin_Forge { @Redirect(method = "hurtEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) private List forge$throwEventToFilterEntitiesOnHurt(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + // Forge hands this list to ForgeEventFactory.onExplosionDetonate where mods may mutate it, + // so every list returned here must be mutable. final List entities; if (this.impl$shouldDamageEntities) { // filter out invulnerable entities before event entities = instance.getEntities(sourceEntity, aabb).stream() .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) - .toList(); + .collect(Collectors.toCollection(ArrayList::new)); } else { - entities = Collections.emptyList(); + entities = new ArrayList<>(); } if (ShouldFire.EXPLOSION_EVENT_DETONATE) { @@ -93,13 +94,13 @@ public abstract class ServerExplosionMixin_Forge { final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); if (SpongeCommon.post(event)) { this.impl$affectedBlocks.clear(); // no blocks affected - return Collections.emptyList(); // no entities affected + return new ArrayList<>(); // no entities affected } if (this.shadow$interactsWithBlocks()) { this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); } if (this.impl$shouldDamageEntities) { - return event.entities().stream().map(Entity.class::cast).toList(); + return event.entities().stream().map(Entity.class::cast).collect(Collectors.toCollection(ArrayList::new)); } } return entities; diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java index 5a85dc8a59c..efa5fa33f4b 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/BlockMixin_Forge_Tracker.java @@ -25,15 +25,18 @@ package org.spongepowered.forge.mixin.tracker.world.level.block; -import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootTable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; import org.spongepowered.forge.mixin.tracker.world.level.block.state.BlockBehaviorMixin_Forge_Tracker; +import java.util.Optional; + @Mixin(Block.class) public abstract class BlockMixin_Forge_Tracker extends BlockBehaviorMixin_Forge_Tracker implements RegistryBackedTrackableBridge { @@ -42,7 +45,7 @@ public abstract class BlockMixin_Forge_Tracker extends BlockBehaviorMixin_Forge_ //@formatter:on @Override - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable>> cir) { // TODO Not the best check but the tracker options only matter during block ticks... if (this.isRandomlyTicking(this.defaultBlockState())) { this.bridge$refreshTrackerStates(); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java index fbc5f1cb190..a6d52a3eb16 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java @@ -25,15 +25,18 @@ package org.spongepowered.forge.mixin.tracker.world.level.block.state; -import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootTable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Optional; + @Mixin(BlockBehaviour.class) public abstract class BlockBehaviorMixin_Forge_Tracker { @Shadow protected abstract boolean isRandomlyTicking(BlockState $$0); @@ -46,6 +49,6 @@ public abstract class BlockBehaviorMixin_Forge_Tracker { remap = false ) ) - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable>> cir) { } } diff --git a/forge/src/mixins/resources/mixins.spongeforge.core.json b/forge/src/mixins/resources/mixins.spongeforge.core.json index e667a285fdf..f88f70fb92d 100644 --- a/forge/src/mixins/resources/mixins.spongeforge.core.json +++ b/forge/src/mixins/resources/mixins.spongeforge.core.json @@ -3,6 +3,9 @@ "parent": "mixins.sponge.parent.json", "package": "org.spongepowered.forge.mixin.core", "priority": 1301, + "injectors": { + "maxShiftBy": 3 + }, "mixins": [ "commands.CommandsMixin_Forge", "minecraftforge.ForgeHooksMixin_Forge", diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 789538b8348..07e70496436 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2863,6 +2863,11 @@
+ + + + + @@ -2887,6 +2892,11 @@ + + + + + @@ -4978,6 +4988,11 @@ + + + + + @@ -5223,6 +5238,11 @@ + + + + + @@ -5303,6 +5323,11 @@ + + + + + @@ -5497,6 +5522,11 @@ + + + + + @@ -5691,6 +5721,11 @@ + + + + + @@ -5885,6 +5920,11 @@ + + + + + @@ -6063,6 +6103,11 @@ + + + + + @@ -6302,6 +6347,11 @@ + + + + + @@ -6504,6 +6554,11 @@ + + + + + @@ -6706,6 +6761,11 @@ + + + + + @@ -6792,6 +6852,11 @@ + + + + + @@ -7482,6 +7547,17 @@ + + + + + + + + + + + @@ -7521,6 +7597,11 @@ + + + + + @@ -7568,6 +7649,11 @@ + + + + + @@ -11650,6 +11736,11 @@ + + + + + @@ -11724,6 +11815,11 @@ + + + + + @@ -11793,6 +11889,11 @@ + + + + + @@ -11875,6 +11976,11 @@ + + + + + @@ -11944,6 +12050,11 @@ + + + + + @@ -12743,6 +12854,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 9bf88fa5950..2155d02fb99 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.1.2.31-beta +neoForgeVersion=26.2.0.32-beta mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java index 87873764d1e..6ee51db2d4d 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo.java @@ -50,11 +50,12 @@ public abstract class LivingEntityMixin_Neo { @Unique @Nullable private Vector3d neo$preTeleportPosition; + // Neo 26.2 replaced the vanilla hurtAndBreak call with its IItemStackExtension glide-damage hook. @Inject( method = "updateFallFlying", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", + target = "Lnet/minecraft/world/item/ItemStack;onGlideDamage(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", shift = At.Shift.AFTER ) ) diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java index 053b1c6767d..4dbbf866d4a 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/LivingEntityMixin_Neo_Damage.java @@ -70,7 +70,9 @@ public abstract class LivingEntityMixin_Neo_Damage implements TrackedDamageBridg return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } - @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( + // Neo 26.2 reuses the dmg parameter as the post-absorption damage (no separate local anymore), + // mirroring vanilla — target the parameter like LivingEntityMixin_Vanilla_Damage does. + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;"))) private float damage$firePostEvent_Living(final float damage) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java index a0c6b8c7cc6..b6ce129e2d1 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/entity/player/PlayerMixin_Neo_Damage.java @@ -62,7 +62,9 @@ public abstract class PlayerMixin_Neo_Damage extends LivingEntityMixin_Neo_Damag return tracker == null || !tracker.isSkipped(DamageStepTypes.ABSORPTION); } - @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), ordinal = 3, slice = @Slice( + // Neo 26.2 reuses the dmg parameter as the post-absorption damage; the old float ordinal 3 + // (absorbedDamage) is never loaded inside this slice anymore — target the parameter instead. + @ModifyVariable(method = "actuallyHurt", at = @At("LOAD"), argsOnly = true, slice = @Slice( from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;I)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))) private float damage$firePostEvent_Player(final float damage) { diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java index 73ca288cc9b..167f6f922ba 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/core/world/level/ServerExplosionMixin_NeoForge.java @@ -49,7 +49,6 @@ import org.spongepowered.common.util.VecHelper; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -76,14 +75,16 @@ public abstract class ServerExplosionMixin_NeoForge { @Redirect(method = "hurtEntities(Ljava/util/List;)V", at = @At(value = "INVOKE", target = "net/minecraft/server/level/ServerLevel.getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) private List neo$throwEventForHurtEntities(final ServerLevel instance, final Entity sourceEntity, final AABB aabb) { + // NeoForge hands this list to EventHooks.onExplosionDetonate where mods may mutate it, + // so every list returned here must be mutable. final List entities; if (this.impl$shouldDamageEntities) { // filter out invulnerable entities before event entities = instance.getEntities(sourceEntity, aabb).stream() .filter(e -> !e.ignoreExplosion((net.minecraft.world.level.Explosion) this)) - .toList(); + .collect(Collectors.toCollection(ArrayList::new)); } else { - entities = Collections.emptyList(); + entities = new ArrayList<>(); } if (ShouldFire.EXPLOSION_EVENT_DETONATE) { @@ -94,13 +95,13 @@ public abstract class ServerExplosionMixin_NeoForge { final ExplosionEvent.Detonate event = SpongeEventFactory.createExplosionEventDetonate(cause, apiBlockPositions, apiEntities, (Explosion) this, apiWorld); if (SpongeCommon.post(event)) { this.impl$affectedBlocks.clear(); // no blocks affected - return Collections.emptyList(); // no entities affected + return new ArrayList<>(); // no entities affected } if (this.shadow$interactsWithBlocks()) { this.impl$affectedBlocks = event.affectedLocations().stream().map(VecHelper::toBlockPos).collect(Collectors.toList()); } if (this.impl$shouldDamageEntities) { - return event.entities().stream().map(Entity.class::cast).toList(); + return event.entities().stream().map(Entity.class::cast).collect(Collectors.toCollection(ArrayList::new)); } } return entities; diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java index a36159a7dbf..3e6a4de8927 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory_Neo.java @@ -77,7 +77,12 @@ public abstract class ServerPlayerMixin_Inventory_Neo extends PlayerMixin_Inven this.inventory$menuProvider = menuProvider; } - @Inject(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;closeContainer()V", shift = At.Shift.AFTER), cancellable = true) + // Neo 26.2 splits the close path on MenuProvider#shouldTriggerClientSideContainerClosingOnOpen, + // so a cancelled close must be detected after either branch. + @Inject(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", at = { + @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;closeContainer()V", shift = At.Shift.AFTER), + @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;doCloseContainer()V", shift = At.Shift.AFTER) + }, cancellable = true) private void impl$openMenuCloseCancelled(final CallbackInfoReturnable cir) { if (this.containerMenu != this.inventoryMenu) { cir.setReturnValue(OptionalInt.empty()); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java index dece1a48c8e..1cb67b86be0 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/BlockMixin_Neo_Tracker.java @@ -25,15 +25,18 @@ package org.spongepowered.neoforge.mixin.tracker.world.level.block; -import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootTable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.common.bridge.RegistryBackedTrackableBridge; import org.spongepowered.neoforge.mixin.tracker.world.level.block.state.BlockBehaviorMixin_Neo_Tracker; +import java.util.Optional; + @Mixin(Block.class) public abstract class BlockMixin_Neo_Tracker extends BlockBehaviorMixin_Neo_Tracker implements RegistryBackedTrackableBridge { @@ -42,7 +45,7 @@ public abstract class BlockMixin_Neo_Tracker extends BlockBehaviorMixin_Neo_Trac //@formatter:on @Override - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable>> cir) { // TODO Not the best check but the tracker options only matter during block ticks... if (this.isRandomlyTicking(this.defaultBlockState())) { this.bridge$refreshTrackerStates(); diff --git a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java index b708e30d113..116444b172f 100644 --- a/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java +++ b/neoforge/src/mixins/java/org/spongepowered/neoforge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Neo_Tracker.java @@ -25,15 +25,18 @@ package org.spongepowered.neoforge.mixin.tracker.world.level.block.state; -import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootTable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Optional; + @Mixin(BlockBehaviour.class) public abstract class BlockBehaviorMixin_Neo_Tracker { @Shadow protected abstract boolean isRandomlyTicking(BlockState $$0); @@ -46,6 +49,6 @@ public abstract class BlockBehaviorMixin_Neo_Tracker { remap = false ) ) - protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable cir) { + protected void forgeTracker$initializeTrackingState(CallbackInfoReturnable>> cir) { } } diff --git a/neoforge/src/mixins/resources/mixins.spongeneo.core.json b/neoforge/src/mixins/resources/mixins.spongeneo.core.json index e1fac839ad5..43418efdf07 100644 --- a/neoforge/src/mixins/resources/mixins.spongeneo.core.json +++ b/neoforge/src/mixins/resources/mixins.spongeneo.core.json @@ -3,6 +3,9 @@ "parent": "mixins.sponge.parent.json", "package": "org.spongepowered.neoforge.mixin.core", "priority": 1301, + "injectors": { + "maxShiftBy": 3 + }, "mixins": [ "api.event.EventMixin_Neo", "api.event.block.ChangeBlockEvent_AllMixin_Neo", diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 84dfe17085b..778d3c7fd45 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -3,6 +3,9 @@ "parent": "mixins.sponge.parent.json", "package": "org.spongepowered.vanilla.mixin.core", "priority": 1301, + "injectors": { + "maxShiftBy": 3 + }, "client": [ "client.ClientBrandRetrieverMixin_Vanilla", "client.MinecraftMixin_Vanilla", From 1943038958ac61c7dcb2c1016e6c23f24f1820c6 Mon Sep 17 00:00:00 2001 From: AlexandreArcil Date: Fri, 27 Feb 2026 18:05:23 +0100 Subject: [PATCH 543/586] fix pardon command --- .../common/service/server/ban/SpongeBanService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java b/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java index 4b160a73533..44f31b05e82 100644 --- a/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java +++ b/src/main/java/org/spongepowered/common/service/server/ban/SpongeBanService.java @@ -157,7 +157,7 @@ public CompletableFuture remove(final Ban ban) { .thenApplyAsync(user -> { Sponge.eventManager().post(SpongeEventFactory.createPardonUserEvent(PhaseTracker.getInstance().currentCause(), (Ban.Profile) ban, user)); - UserListUtil.removeEntry(this.getUserBanList(), SpongeGameProfile.toMcProfile(((Ban.Profile) ban).profile())); + UserListUtil.removeEntry(this.getUserBanList(), SpongeGameProfile.toNameAndId(((Ban.Profile) ban).profile())); return true; }, ((MinecraftServerBridge) SpongeCommon.server()).bridge$spongeMainThreadExecutor()); } else if (ban.type().equals(BanTypes.IP.get())) { From b5323af26824cd12962a22639e5c34b2f7890fff Mon Sep 17 00:00:00 2001 From: Aapo Katila <81980535+abola2@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:58:30 +0300 Subject: [PATCH 544/586] Add IS_SADDLED to strider (#4282) --- .../provider/entity/EntityDataProviders.java | 1 + .../data/provider/entity/StriderData.java | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/main/java/org/spongepowered/common/data/provider/entity/StriderData.java diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index a73ad5946fc..397f528d03d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -181,6 +181,7 @@ public void registerProviders() { SlimeData.register(this.registrator); SpellcastingIllagerData.register(this.registrator); SpiderData.register(this.registrator); + StriderData.register(this.registrator); TadpoleData.register(this.registrator); TameableData.register(this.registrator); ThrowableItemProjectileData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/StriderData.java b/src/main/java/org/spongepowered/common/data/provider/entity/StriderData.java new file mode 100644 index 00000000000..d8c4a45656e --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/StriderData.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.data.provider.entity; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.monster.Strider; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.spongepowered.api.data.Keys; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public final class StriderData { + + private StriderData() { + } + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(Strider.class) + .create(Keys.IS_SADDLED) + .get(Strider::isSaddled) + .set((h, v) -> { + if (v) { + h.setItemSlot(EquipmentSlot.SADDLE, new ItemStack(Items.SADDLE)); + } else { + h.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY); + } + }); + } + // @formatter:on +} From ce43b02a23ad4a06f3c4e48d889cd70389023b72 Mon Sep 17 00:00:00 2001 From: Aapo Katila <81980535+abola2@users.noreply.github.com> Date: Tue, 4 Aug 2026 21:00:13 +0300 Subject: [PATCH 545/586] Add happy ghast implementation (#4283) --- .../entity/animal/HappyGhastMixin_API.java | 32 +++++++++++++++++++ src/mixins/resources/mixins.sponge.api.json | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java new file mode 100644 index 00000000000..b271e0f74a8 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java @@ -0,0 +1,32 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.entity.animal; + +import org.spongepowered.api.entity.living.animal.HappyGhast; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(net.minecraft.world.entity.animal.HappyGhast.class) +public abstract class HappyGhastMixin_API implements HappyGhast { +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 9a45219c85d..d03826b6fa0 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -159,6 +159,7 @@ "minecraft.world.entity.animal.Fox_VariantMixin_API", "minecraft.world.entity.animal.FoxMixin_API", "minecraft.world.entity.animal.FrogVariantMixin_API", + "minecraft.world.entity.animal.HappyGhastMixin_API", "minecraft.world.entity.animal.IronGolemMixin_API", "minecraft.world.entity.animal.MushroomCow_MushroomTypeMixin_API", "minecraft.world.entity.animal.MushroomCowMixin_API", @@ -389,10 +390,10 @@ "minecraft.world.level.biome.MobSpawnSettings_MobSpawnCostMixin_API", "minecraft.world.level.biome.MultiNoiseBiomeSourceMixin_API", "minecraft.world.level.biome.TheEndBiomeSourceMixin_API", + "minecraft.world.level.block.CopperGolemStatueBlock_PoseMixin_API", "minecraft.world.level.block.MirrorMixin_API", "minecraft.world.level.block.PortalMixin_API", "minecraft.world.level.block.RotationMixin_API", - "minecraft.world.level.block.CopperGolemStatueBlock_PoseMixin_API", "minecraft.world.level.block.WeatheringCopper_WeatherStateMixin_API", "minecraft.world.level.block.entity.AbstractFurnaceBlockEntityMixin_API", "minecraft.world.level.block.entity.BannerBlockEntityMixin_API", From 4fb28b4a8ad3347973e2eed204c4647dec3bcc13 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 4 Aug 2026 20:06:00 +0200 Subject: [PATCH 546/586] Apply spotless --- .../api/minecraft/world/entity/animal/HappyGhastMixin_API.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java index b271e0f74a8..75856347247 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/animal/HappyGhastMixin_API.java @@ -1,5 +1,5 @@ /* - * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * This file is part of Sponge, licensed under the MIT License (MIT). * * Copyright (c) SpongePowered * Copyright (c) contributors From 133e08a65490c4ab3d938b82933e07de45afde13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Sun, 9 Aug 2026 17:12:34 +0300 Subject: [PATCH 547/586] Add keys related to minecraft:equippable data component (#4298) --- SpongeAPI | 2 +- .../item/stack/ArmorItemStackData.java | 290 ++++++++++++++++-- .../common/data/key/KeysTest.java | 49 +-- 3 files changed, 302 insertions(+), 39 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 1f58ca7d3f0..656efea1273 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 1f58ca7d3f0e4e940f54dd59d56cf876aad6795d +Subproject commit 656efea127396c6f7f336f342fdfb6e9d0e3aea6 diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java index c39fe7b1e24..9c6cacd5697 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ArmorItemStackData.java @@ -24,22 +24,32 @@ */ package org.spongepowered.common.data.provider.item.stack; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.Identifier; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ItemAttributeModifiers; +import net.minecraft.world.item.equipment.EquipmentAsset; +import net.minecraft.world.item.equipment.EquipmentAssets; import net.minecraft.world.item.equipment.Equippable; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.api.item.recipe.smithing.ArmorTrim; import org.spongepowered.api.registry.RegistryEntry; import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.common.data.provider.DataProviderRegistrator; -import java.util.function.Function; +import java.util.Optional; +import java.util.stream.Collectors; public final class ArmorItemStackData { @@ -50,6 +60,49 @@ private ArmorItemStackData() { public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(ItemStack.class) + .create(Keys.ALLOWED_ENTITIES) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null || equippable.allowedEntities().isEmpty()) { + return null; + } + return equippable.allowedEntities().get().stream() + .map(Holder::value) + .map(e -> (EntityType) e) + .collect(Collectors.toSet()); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + final HolderSet> holderSet = HolderSet.direct( + e -> BuiltInRegistries.ENTITY_TYPE.wrapAsHolder((net.minecraft.world.entity.EntityType) e), + v + ); + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setAllowedEntities(holderSet).build()); + return true; + }) + .deleteAnd(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, new Equippable( + equippable.slot(), + equippable.equipSound(), + equippable.assetId(), + equippable.cameraOverlay(), + Optional.empty(), + equippable.dispensable(), + equippable.swappable(), + equippable.damageOnHurt(), + equippable.equipOnInteract(), + equippable.canBeSheared(), + equippable.shearingSound() + )); + return true; + }) .create(Keys.ARMOR_MATERIAL) .get(h -> { final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); @@ -62,7 +115,37 @@ public static void register(final DataProviderRegistrator registrator) { .map(RegistryEntry::value) .orElse(null); }) - .supports(isArmorItem()) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + final ResourceKey key = RegistryTypes.ARMOR_MATERIAL.get().valueKey(v); + final net.minecraft.resources.ResourceKey assetKey = + net.minecraft.resources.ResourceKey.create(EquipmentAssets.ROOT_ID, (Identifier) (Object) key); + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setAsset(assetKey).build()); + return true; + }) + .deleteAnd(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, new Equippable( + equippable.slot(), + equippable.equipSound(), + Optional.empty(), + equippable.cameraOverlay(), + equippable.allowedEntities(), + equippable.dispensable(), + equippable.swappable(), + equippable.damageOnHurt(), + equippable.equipOnInteract(), + equippable.canBeSheared(), + equippable.shearingSound() + )); + return true; + }) .create(Keys.ARMOR_TRIM) .get(h -> { final net.minecraft.world.item.equipment.trim.@Nullable ArmorTrim trim = h.get(DataComponents.TRIM); @@ -79,7 +162,58 @@ public static void register(final DataProviderRegistrator registrator) { h.set(DataComponents.TRIM, (net.minecraft.world.item.equipment.trim.ArmorTrim) (Object) v); }) .delete(h -> h.remove(DataComponents.TRIM)) - .supports(isArmorItem()) + .create(Keys.CAMERA_OVERLAY) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null || equippable.cameraOverlay().isEmpty()) { + return null; + } + return (ResourceKey) (Object) equippable.cameraOverlay().get(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setCameraOverlay((Identifier) (Object) v).build()); + return true; + }) + .deleteAnd(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, new Equippable( + equippable.slot(), + equippable.equipSound(), + equippable.assetId(), + Optional.empty(), + equippable.allowedEntities(), + equippable.dispensable(), + equippable.swappable(), + equippable.damageOnHurt(), + equippable.equipOnInteract(), + equippable.canBeSheared(), + equippable.shearingSound() + )); + return true; + }) + .create(Keys.CAN_BE_SHEARED) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return equippable.canBeSheared(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setCanBeSheared(v).build()); + return true; + }) .create(Keys.DAMAGE_ABSORPTION) .get(h -> { final @Nullable ItemAttributeModifiers modifiersContainer = h.get(DataComponents.ATTRIBUTE_MODIFIERS); @@ -92,32 +226,148 @@ public static void register(final DataProviderRegistrator registrator) { .map(e -> e.modifier().amount()) .orElse(null); }) - .supports(isArmorItem()) + .create(Keys.DAMAGE_ON_HURT) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return equippable.damageOnHurt(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setDamageOnHurt(v).build()); + return true; + }) + .create(Keys.EQUIP_ON_INTERACT) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return equippable.equipOnInteract(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setEquipOnInteract(v).build()); + return true; + }) + .create(Keys.EQUIP_SOUND) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return (SoundType) (Object) equippable.equipSound().value(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setEquipSound(Holder.direct((SoundEvent) (Object) v)).build()); + return true; + }) .create(Keys.EQUIPMENT_TYPE) .get(h -> { final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); if (equippable == null) { return null; } - return (EquipmentType) (Object) equippable.slot(); }) - .supports(isArmorItem()); + .set((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + final EquipmentSlot slot = (EquipmentSlot) (Object) v; + if (equippable == null) { + h.set(DataComponents.EQUIPPABLE, Equippable.builder(slot).build()); + return; + } + h.set(DataComponents.EQUIPPABLE, new Equippable( + slot, + equippable.equipSound(), + equippable.assetId(), + equippable.cameraOverlay(), + equippable.allowedEntities(), + equippable.dispensable(), + equippable.swappable(), + equippable.damageOnHurt(), + equippable.equipOnInteract(), + equippable.canBeSheared(), + equippable.shearingSound() + )); + }) + .delete(h -> h.remove(DataComponents.EQUIPPABLE)) + .create(Keys.IS_DISPENSABLE) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return equippable.dispensable(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setDispensable(v).build()); + return true; + }) + .create(Keys.IS_SWAPPABLE) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return equippable.swappable(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setSwappable(v).build()); + return true; + }) + .create(Keys.SHEARING_SOUND) + .get(h -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return null; + } + return (SoundType) (Object) equippable.shearingSound().value(); + }) + .setAnd((h, v) -> { + final @Nullable Equippable equippable = h.get(DataComponents.EQUIPPABLE); + if (equippable == null) { + return false; + } + h.set(DataComponents.EQUIPPABLE, ArmorItemStackData.asBuilder(equippable).setShearingSound(Holder.direct((SoundEvent) (Object) v)).build()); + return true; + }); } // @formatter:on - private static @NonNull Function isArmorItem() { - return h -> { - final var components = h.getItem().components(); - final @Nullable Integer stackSize = components.get(DataComponents.MAX_STACK_SIZE); - if (stackSize == null) { - return false; - } - return components.has(DataComponents.EQUIPPABLE) - && components.has(DataComponents.ENCHANTABLE) - && components.has(DataComponents.MAX_DAMAGE) - && components.has(DataComponents.MAX_STACK_SIZE) - && (1 == stackSize); - }; + private static Equippable.Builder asBuilder(final Equippable equippable) { + final Equippable.Builder builder = Equippable.builder(equippable.slot()) + .setEquipSound(equippable.equipSound()) + .setDispensable(equippable.dispensable()) + .setSwappable(equippable.swappable()) + .setDamageOnHurt(equippable.damageOnHurt()) + .setEquipOnInteract(equippable.equipOnInteract()) + .setCanBeSheared(equippable.canBeSheared()) + .setShearingSound(equippable.shearingSound()); + equippable.assetId().ifPresent(builder::setAsset); + equippable.cameraOverlay().ifPresent(builder::setCameraOverlay); + equippable.allowedEntities().ifPresent(builder::setAllowedEntities); + return builder; } + } diff --git a/src/test/java/org/spongepowered/common/data/key/KeysTest.java b/src/test/java/org/spongepowered/common/data/key/KeysTest.java index 5a7f8a4ac9f..2d9883e1099 100644 --- a/src/test/java/org/spongepowered/common/data/key/KeysTest.java +++ b/src/test/java/org/spongepowered/common/data/key/KeysTest.java @@ -25,11 +25,13 @@ package org.spongepowered.common.data.key; import io.leangen.geantyref.GenericTypeReflector; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.ResourceKeyed; import org.spongepowered.api.data.Key; import org.spongepowered.api.data.Keys; @@ -37,13 +39,16 @@ import org.spongepowered.api.data.type.ShieldItemDamageFunction; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.effect.sound.SoundTypes; +import org.spongepowered.api.entity.EntityTypes; import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.api.item.ItemTypes; import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; import org.spongepowered.api.tag.DamageTypeTags; import org.spongepowered.api.util.Ticks; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; @@ -52,35 +57,45 @@ public class KeysTest { private static Stream testSingleKeys() { return Stream.of( - Arguments.of(Keys.WEAPON_DAMAGE_PER_ATTACK, 5), - Arguments.of(Keys.DISABLE_SHIELD_TICKS, Ticks.of(10)), - Arguments.of(Keys.SHIELD_DEPLOY_TICKS, Ticks.of(15)), - Arguments.of(Keys.DISABLE_SHIELD_TICKS_SCALE, 2.5), + Arguments.of(Keys.WEAPON_DAMAGE_PER_ATTACK, 5, null), + Arguments.of(Keys.DISABLE_SHIELD_TICKS, Ticks.of(10), null), + Arguments.of(Keys.SHIELD_DEPLOY_TICKS, Ticks.of(15), null), + Arguments.of(Keys.DISABLE_SHIELD_TICKS_SCALE, 2.5, null), Arguments.of(Keys.SHIELD_DAMAGE_REDUCTIONS, List.of(ShieldDamageReduction.of(ShieldDamageReduction.MultiplyAdd.builder() .horizontalBlockingAngle(45) .constantReduction(2) .fractionalReduction(0.5) .damageTypes(Set.of(DamageTypes.ARROW.get(), DamageTypes.PLAYER_ATTACK.get())) - .build()))), + .build())), null), Arguments.of(Keys.SHIELD_ITEM_DAMAGE_FUNCTION, ShieldItemDamageFunction.of(ShieldItemDamageFunction.MultiplyAdd.builder() .constantDamage(5) .fractionalDamage(2) .minAttackDamage(2.5) - .build())), - Arguments.of(Keys.SHIELD_BLOCK_SOUND, SoundTypes.ENTITY_SHULKER_HURT.get()), - Arguments.of(Keys.SHIELD_DISABLE_SOUND, SoundTypes.ENTITY_ENDER_DRAGON_DEATH.get()) + .build()), null), + Arguments.of(Keys.SHIELD_BLOCK_SOUND, SoundTypes.ENTITY_SHULKER_HURT.get(), null), + Arguments.of(Keys.SHIELD_DISABLE_SOUND, SoundTypes.ENTITY_ENDER_DRAGON_DEATH.get(), null), + Arguments.of(Keys.ALLOWED_ENTITIES, Set.of(EntityTypes.PLAYER.get(), EntityTypes.ZOMBIE.get()), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.CAMERA_OVERLAY, ResourceKey.minecraft("textures/misc/pumpkinblur.png"), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.CAN_BE_SHEARED, true, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.DAMAGE_ON_HURT, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.EQUIP_ON_INTERACT, true, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.EQUIP_SOUND, SoundTypes.ITEM_ARMOR_EQUIP_DIAMOND.get(), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.EQUIPMENT_TYPE, EquipmentTypes.HEAD.get(), null), + Arguments.of(Keys.IS_DISPENSABLE, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.IS_SWAPPABLE, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), + Arguments.of(Keys.SHEARING_SOUND, SoundTypes.ENTITY_SHEEP_SHEAR.get(), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)) ); } @MethodSource @ParameterizedTest - void testSingleKeys(Key k, Object value) { - testSingleKeyUnchecked(k, value); + void testSingleKeys(Key k, Object value, @Nullable ItemStack baseStack) { + testSingleKeyUnchecked(k, value, baseStack); } @Test void testBypassDamageTag() { - testSingleKey(Keys.BYPASS_DAMAGE_TAG, DamageTypeTags.BYPASSES_ARMOR, ResourceKeyed::key); + testSingleKey(Keys.BYPASS_DAMAGE_TAG, DamageTypeTags.BYPASSES_ARMOR, ResourceKeyed::key, null); } @Test @@ -104,19 +119,17 @@ void testAllWeaponKeys() { } @SuppressWarnings("unchecked") - private static > void testSingleKeyUnchecked(Key k, Object value) { + private static > void testSingleKeyUnchecked(Key k, Object value, @Nullable ItemStack baseStack) { if (!GenericTypeReflector.isSuperType(k.elementType(), value.getClass())) { throw new IllegalArgumentException("Invalid value type for key " + k.key() + ": " + value.getClass().getName()); } - testSingleKey((Key) k, (T) value, a -> a); + testSingleKey((Key) k, (T) value, a -> a, baseStack); } - private static > void testSingleKey(Key k, T value, Function equalityExtractor) { - final var stack = ItemStack.builder() - .itemType(ItemTypes.DIAMOND_SWORD) - .add(k, value) - .build(); + private static > void testSingleKey(Key k, T value, Function equalityExtractor, @Nullable ItemStack baseStack) { + final ItemStack stack = Objects.requireNonNullElseGet(baseStack, () -> ItemStack.of(ItemTypes.DIAMOND_SWORD)); + stack.offer(k, value); Assertions.assertEquals(equalityExtractor.apply(value), equalityExtractor.apply(stack.require(k)), () -> "retrieved value is not equal " + "to the original for " + k.key().asString()); From 51b4dc4934ca2d4fb1b640ebbdcdd2d8b6db0c4b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 9 Aug 2026 21:49:22 +0200 Subject: [PATCH 548/586] Move KeysTest into ItemStackDataTest --- .../common/data/ItemStackDataTest.java | 56 +++++++ .../common/data/key/KeysTest.java | 138 ------------------ 2 files changed, 56 insertions(+), 138 deletions(-) delete mode 100644 src/test/java/org/spongepowered/common/data/key/KeysTest.java diff --git a/src/test/java/org/spongepowered/common/data/ItemStackDataTest.java b/src/test/java/org/spongepowered/common/data/ItemStackDataTest.java index 31230513dc1..6c81b99b093 100644 --- a/src/test/java/org/spongepowered/common/data/ItemStackDataTest.java +++ b/src/test/java/org/spongepowered/common/data/ItemStackDataTest.java @@ -29,13 +29,19 @@ import net.kyori.adventure.text.format.TextDecoration; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.ArmorMaterials; import org.spongepowered.api.data.type.DyeColors; import org.spongepowered.api.data.type.ItemTiers; import org.spongepowered.api.data.type.NotePitches; +import org.spongepowered.api.data.type.ShieldDamageReduction; +import org.spongepowered.api.data.type.ShieldItemDamageFunction; +import org.spongepowered.api.effect.sound.SoundTypes; import org.spongepowered.api.effect.sound.music.MusicDiscs; +import org.spongepowered.api.entity.EntityTypes; +import org.spongepowered.api.event.cause.entity.damage.DamageTypes; import org.spongepowered.api.fluid.FluidStackSnapshot; import org.spongepowered.api.fluid.FluidTypes; import org.spongepowered.api.item.ItemRarities; @@ -43,11 +49,13 @@ import org.spongepowered.api.item.enchantment.Enchantment; import org.spongepowered.api.item.enchantment.EnchantmentTypes; import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; import org.spongepowered.api.item.potion.PotionTypes; import org.spongepowered.api.item.recipe.smithing.ArmorTrim; import org.spongepowered.api.item.recipe.smithing.TrimMaterials; import org.spongepowered.api.item.recipe.smithing.TrimPatterns; import org.spongepowered.api.util.Color; +import org.spongepowered.api.util.Ticks; import java.util.Arrays; import java.util.HashSet; @@ -56,6 +64,54 @@ public final class ItemStackDataTest { + @Test + public void testWeapon() { + final ItemStack weapon = ItemStack.of(ItemTypes.DIAMOND_SWORD); + DataTest.checkOfferData(weapon, Keys.WEAPON_DAMAGE_PER_ATTACK, 5); + DataTest.checkOfferData(weapon, Keys.DISABLE_SHIELD_TICKS, Ticks.of(10)); + } + + @Test + public void testShield() { + final ItemStack shield = ItemStack.of(ItemTypes.SHIELD); + DataTest.checkOfferData(shield, Keys.SHIELD_DEPLOY_TICKS, Ticks.of(15)); + DataTest.checkOfferData(shield, Keys.DISABLE_SHIELD_TICKS_SCALE, 2.5); + DataTest.checkOfferData(shield, Keys.SHIELD_DAMAGE_REDUCTIONS, List.of( + ShieldDamageReduction.of(ShieldDamageReduction.MultiplyAdd.builder() + .horizontalBlockingAngle(45) + .constantReduction(2) + .fractionalReduction(0.5) + .damageTypes(Set.of(DamageTypes.ARROW.get(), DamageTypes.PLAYER_ATTACK.get())) + .build() + ) + )); + DataTest.checkOfferData(shield, Keys.SHIELD_ITEM_DAMAGE_FUNCTION, ShieldItemDamageFunction.of( + ShieldItemDamageFunction.MultiplyAdd.builder() + .constantDamage(5) + .fractionalDamage(2) + .minAttackDamage(2.5) + .build() + ) + ); + DataTest.checkOfferData(shield, Keys.SHIELD_BLOCK_SOUND, SoundTypes.ENTITY_SHULKER_HURT.get()); + DataTest.checkOfferData(shield, Keys.SHIELD_DISABLE_SOUND, SoundTypes.ENTITY_ENDER_DRAGON_DEATH.get()); + } + + @Test + public void testEquippable() { + final ItemStack armor = ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE); + DataTest.checkOfferData(armor, Keys.ALLOWED_ENTITIES, Set.of(EntityTypes.PLAYER.get(), EntityTypes.ZOMBIE.get())); + DataTest.checkOfferData(armor, Keys.CAMERA_OVERLAY, ResourceKey.minecraft("textures/misc/pumpkinblur.png")); + DataTest.checkOfferData(armor, Keys.CAN_BE_SHEARED, true); + DataTest.checkOfferData(armor, Keys.DAMAGE_ON_HURT, false); + DataTest.checkOfferData(armor, Keys.EQUIP_ON_INTERACT, true); + DataTest.checkOfferData(armor, Keys.EQUIP_SOUND, SoundTypes.ITEM_ARMOR_EQUIP_DIAMOND.get()); + DataTest.checkOfferData(armor, Keys.EQUIPMENT_TYPE, EquipmentTypes.HEAD.get()); + DataTest.checkOfferData(armor, Keys.IS_DISPENSABLE, false); + DataTest.checkOfferData(armor, Keys.IS_SWAPPABLE, false); + DataTest.checkOfferData(armor, Keys.SHEARING_SOUND, SoundTypes.ENTITY_SHEEP_SHEAR.get()); + } + @Test public void testEnchantments() { final ItemStack goldenApple = ItemStack.of(ItemTypes.ENCHANTED_GOLDEN_APPLE); diff --git a/src/test/java/org/spongepowered/common/data/key/KeysTest.java b/src/test/java/org/spongepowered/common/data/key/KeysTest.java deleted file mode 100644 index 2d9883e1099..00000000000 --- a/src/test/java/org/spongepowered/common/data/key/KeysTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.data.key; - -import io.leangen.geantyref.GenericTypeReflector; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.spongepowered.api.ResourceKey; -import org.spongepowered.api.ResourceKeyed; -import org.spongepowered.api.data.Key; -import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.type.ShieldDamageReduction; -import org.spongepowered.api.data.type.ShieldItemDamageFunction; -import org.spongepowered.api.data.value.Value; -import org.spongepowered.api.effect.sound.SoundTypes; -import org.spongepowered.api.entity.EntityTypes; -import org.spongepowered.api.event.cause.entity.damage.DamageTypes; -import org.spongepowered.api.item.ItemTypes; -import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; -import org.spongepowered.api.tag.DamageTypeTags; -import org.spongepowered.api.util.Ticks; - -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Stream; - -public class KeysTest { - - private static Stream testSingleKeys() { - return Stream.of( - Arguments.of(Keys.WEAPON_DAMAGE_PER_ATTACK, 5, null), - Arguments.of(Keys.DISABLE_SHIELD_TICKS, Ticks.of(10), null), - Arguments.of(Keys.SHIELD_DEPLOY_TICKS, Ticks.of(15), null), - Arguments.of(Keys.DISABLE_SHIELD_TICKS_SCALE, 2.5, null), - Arguments.of(Keys.SHIELD_DAMAGE_REDUCTIONS, List.of(ShieldDamageReduction.of(ShieldDamageReduction.MultiplyAdd.builder() - .horizontalBlockingAngle(45) - .constantReduction(2) - .fractionalReduction(0.5) - .damageTypes(Set.of(DamageTypes.ARROW.get(), DamageTypes.PLAYER_ATTACK.get())) - .build())), null), - Arguments.of(Keys.SHIELD_ITEM_DAMAGE_FUNCTION, ShieldItemDamageFunction.of(ShieldItemDamageFunction.MultiplyAdd.builder() - .constantDamage(5) - .fractionalDamage(2) - .minAttackDamage(2.5) - .build()), null), - Arguments.of(Keys.SHIELD_BLOCK_SOUND, SoundTypes.ENTITY_SHULKER_HURT.get(), null), - Arguments.of(Keys.SHIELD_DISABLE_SOUND, SoundTypes.ENTITY_ENDER_DRAGON_DEATH.get(), null), - Arguments.of(Keys.ALLOWED_ENTITIES, Set.of(EntityTypes.PLAYER.get(), EntityTypes.ZOMBIE.get()), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.CAMERA_OVERLAY, ResourceKey.minecraft("textures/misc/pumpkinblur.png"), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.CAN_BE_SHEARED, true, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.DAMAGE_ON_HURT, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.EQUIP_ON_INTERACT, true, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.EQUIP_SOUND, SoundTypes.ITEM_ARMOR_EQUIP_DIAMOND.get(), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.EQUIPMENT_TYPE, EquipmentTypes.HEAD.get(), null), - Arguments.of(Keys.IS_DISPENSABLE, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.IS_SWAPPABLE, false, ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)), - Arguments.of(Keys.SHEARING_SOUND, SoundTypes.ENTITY_SHEEP_SHEAR.get(), ItemStack.of(ItemTypes.DIAMOND_CHESTPLATE)) - ); - } - - @MethodSource - @ParameterizedTest - void testSingleKeys(Key k, Object value, @Nullable ItemStack baseStack) { - testSingleKeyUnchecked(k, value, baseStack); - } - - @Test - void testBypassDamageTag() { - testSingleKey(Keys.BYPASS_DAMAGE_TAG, DamageTypeTags.BYPASSES_ARMOR, ResourceKeyed::key, null); - } - - @Test - void testAllWeaponKeys() { - final var stack = ItemStack.builder() - .itemType(ItemTypes.DIAMOND_SWORD) - .add(Keys.WEAPON_DAMAGE_PER_ATTACK, 5) - .add(Keys.DISABLE_SHIELD_TICKS, Ticks.of(5)) - .build(); - - Assertions.assertEquals(5, stack.require(Keys.WEAPON_DAMAGE_PER_ATTACK)); - Assertions.assertEquals(Ticks.of(5), stack.require(Keys.DISABLE_SHIELD_TICKS)); - - stack.remove(Keys.DISABLE_SHIELD_TICKS); - Assertions.assertEquals(5, stack.require(Keys.WEAPON_DAMAGE_PER_ATTACK)); - - stack.remove(Keys.WEAPON_DAMAGE_PER_ATTACK); - - Assertions.assertNull(stack.getOrNull(Keys.WEAPON_DAMAGE_PER_ATTACK)); - Assertions.assertNull(stack.getOrNull(Keys.DISABLE_SHIELD_TICKS)); - } - - @SuppressWarnings("unchecked") - private static > void testSingleKeyUnchecked(Key k, Object value, @Nullable ItemStack baseStack) { - if (!GenericTypeReflector.isSuperType(k.elementType(), value.getClass())) { - throw new IllegalArgumentException("Invalid value type for key " + k.key() + ": " + value.getClass().getName()); - } - - testSingleKey((Key) k, (T) value, a -> a, baseStack); - } - - private static > void testSingleKey(Key k, T value, Function equalityExtractor, @Nullable ItemStack baseStack) { - final ItemStack stack = Objects.requireNonNullElseGet(baseStack, () -> ItemStack.of(ItemTypes.DIAMOND_SWORD)); - stack.offer(k, value); - - Assertions.assertEquals(equalityExtractor.apply(value), equalityExtractor.apply(stack.require(k)), () -> "retrieved value is not equal " + - "to the original for " + k.key().asString()); - } - -} From 15767920620ba17d2b6950ac051eda7271e6e77a Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 10 Jun 2026 22:54:24 +0200 Subject: [PATCH 549/586] Refactor plugin-spi API: - Support recursive locators so that Sponge locators can find plugin services. Before that the SPI was unusable by plugins. - Split language service into reader and loader services. - Allow multiple metadata files (e.g. extra file for tests). Impl: - Factorize code into SpongeCommon. This harmonizes the behavior of our SPI across different platforms. - Connect plugin-spi services to platform mod discovery services. Files discovered by Neo locators can be read by Sponge readers and vice versa. - @Plugin annotation is no longer required. - Less dark magic is involved. --- SpongeAPI | 2 +- .../moddiscovery/SpongeForgeModLocator.java | 102 ------- .../locator/EnvironmentPluginLocator.java | 69 ----- .../locator/PluginsDirectoryLocator.java | 76 ------ .../discovery}/AbstractModProvider.java | 2 +- .../discovery}/PluginFileParser.java | 89 +++---- .../SpongeForgeDependencyLocator.java | 7 +- .../mod/discovery/SpongeForgeModLocator.java | 137 ++++++++++ .../discovery}/library/Log4JLogger.java | 2 +- .../PluginDependencyConfigurable.java | 7 +- .../metadata/PluginFileConfigurable.java | 64 ++--- .../metadata/PluginMetadataConfigurable.java | 11 +- .../applaunch/plugin/ForgePluginPlatform.java | 62 ++--- .../discovery/ForgePluginDiscovery.java | 77 ++++++ .../plugin/discovery}/PluginJarMetadata.java | 61 ++--- .../discovery}/SecureJarPluginResource.java | 81 +++--- ...forge.forgespi.locating.IDependencyLocator | 2 +- ...necraftforge.forgespi.locating.IModLocator | 4 +- ...red.plugin.discovery.PluginResourceLocator | 1 + .../provider/JavaPluginLanguageProvider.java | 126 --------- .../lang/provider/SpongeLanguageProvider.java | 84 ++++++ ...rge.forgespi.language.IModLanguageProvider | 2 +- .../launch/plugin/ForgePluginContainer.java | 30 +-- .../launch/plugin/ForgePluginManager.java | 7 +- .../plugin/PluginMetadataConverter.java | 34 +-- .../launch/plugin/PluginModContainer.java | 86 +++--- .../locator/EnvironmentPluginLocator.java | 71 ----- .../locator/PluginsDirectoryLocator.java | 53 ---- .../moddiscovery/reader/PluginFileParser.java | 89 ------- .../mod/discovery/PluginFileReader.java | 70 +++++ .../discovery/SpongeLanguageLoader.java} | 38 +-- .../SpongeNeoDependencyLocator.java | 4 +- .../discovery}/SpongeNeoModLocator.java | 80 +++--- .../discovery}/library/Log4JLogger.java | 2 +- .../PluginDependencyConfigurable.java | 7 +- .../metadata/PluginFileConfigurable.java | 73 ++--- .../metadata/PluginMetadataConfigurable.java | 11 +- .../metadata/PluginMixinConfigurable.java | 2 +- ...inPlatform.java => NeoPluginPlatform.java} | 60 ++--- .../discovery/JarContentsPluginResource.java | 108 ++++++++ .../plugin/discovery/NeoPluginDiscovery.java | 74 ++++++ ...ed.neoforgespi.language.IModLanguageLoader | 2 +- ...ed.neoforgespi.locating.IDependencyLocator | 2 +- ...forgespi.locating.IModFileCandidateLocator | 4 +- ...forged.neoforgespi.locating.IModFileReader | 2 +- ...red.plugin.discovery.PluginResourceLocator | 1 + .../launch/plugin/NeoPluginContainer.java | 37 +-- .../launch/plugin/NeoPluginManager.java | 10 +- .../plugin/PluginMetadataConverter.java | 34 +-- .../launch/plugin/PluginModContainer.java | 74 +++--- .../common/applaunch/AppLaunch.java | 11 +- .../metadata/PluginMetadataFixer.java | 80 ------ .../applaunch/plugin/PluginPlatform.java | 93 ++++++- .../plugin/PluginPlatformConstants.java | 5 +- .../applaunch/plugin/PluginServiceLoader.java | 67 +++++ .../plugin/discovery/PluginDiscovery.java | 249 ++++++++++++++++++ .../discovery/SpongeJVMPluginResource.java | 26 +- .../SpongePropertyResourceLocator.java | 48 +--- .../spongepowered/common/SpongeLifecycle.java | 11 +- .../common/command/sponge/SpongeCommand.java | 4 +- .../spongepowered/common/launch/Launch.java | 9 +- .../launch/plugin/SpongePluginContainer.java | 25 +- .../plugin/loader}/JavaPluginLoader.java | 49 ++-- .../launch/plugin/loader/PluginCandidate.java | 23 +- .../plugin/loader/PluginCandidateFactory.java | 62 +++++ .../launch/plugin/loader/VersionChecker.java | 51 ++++ .../org.spongepowered.plugin.PluginLoader | 1 + .../plugin/JavaPluginLanguageService.java | 70 ----- .../plugin/VanillaPluginPlatform.java | 211 ++------------- .../plugin/VanillaTransformationService.java | 120 +++------ .../discovery/MinecraftMetadataReader.java | 66 +++++ .../plugin/discovery/PluginJarMetadata.java | 80 ++++++ .../discovery/SecureJarPluginResource.java | 100 +++++++ .../SpongeVanillaResourceLocator.java | 66 +++++ .../discovery/VanillaPluginDiscovery.java | 77 ++++++ .../VanillaAccessWidenerTransformer.java | 29 +- .../VanillaSuperclassChangeTransformer.java | 29 +- ...spongepowered.plugin.PluginLanguageService | 1 - ...owered.plugin.PluginResourceLocatorService | 1 - ...ered.plugin.discovery.PluginMetadataReader | 1 + ...red.plugin.discovery.PluginResourceLocator | 2 + .../client/gui/widget/MetadataPanel.java | 7 +- .../vanilla/launch/VanillaBootstrap.java | 3 +- .../vanilla/launch/VanillaLaunch.java | 21 +- .../plugin/VanillaDummyPluginContainer.java | 19 +- .../plugin/VanillaJavaPluginContainer.java | 57 ---- .../launch/plugin/VanillaPluginManager.java | 68 ++--- .../plugin/resolver/DependencyResolver.java | 26 +- .../plugin/resolver/ResolutionResult.java | 2 +- .../server/packs/PluginRepositorySource.java | 8 +- 90 files changed, 2091 insertions(+), 1920 deletions(-) delete mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java delete mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java delete mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading/moddiscovery => mod/discovery}/AbstractModProvider.java (98%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading/moddiscovery => mod/discovery}/PluginFileParser.java (62%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading/moddiscovery => mod/discovery}/SpongeForgeDependencyLocator.java (94%) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading/moddiscovery => mod/discovery}/library/Log4JLogger.java (96%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading => mod}/metadata/PluginDependencyConfigurable.java (90%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading => mod}/metadata/PluginFileConfigurable.java (61%) rename forge/src/applaunch/java/org/spongepowered/forge/applaunch/{loading => mod}/metadata/PluginMetadataConfigurable.java (88%) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/ForgePluginDiscovery.java rename {vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource => forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery}/PluginJarMetadata.java (55%) rename {vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource => forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery}/SecureJarPluginResource.java (54%) create mode 100644 forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator delete mode 100644 forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java create mode 100644 forge/src/lang/java/org/spongepowered/forge/lang/provider/SpongeLanguageProvider.java delete mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java delete mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java delete mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{plugin/JavaPluginLanguageProvider.java => mod/discovery/SpongeLanguageLoader.java} (57%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading/moddiscovery => mod/discovery}/SpongeNeoDependencyLocator.java (96%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading/moddiscovery => mod/discovery}/SpongeNeoModLocator.java (65%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading/moddiscovery => mod/discovery}/library/Log4JLogger.java (96%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading => mod}/metadata/PluginDependencyConfigurable.java (91%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading => mod}/metadata/PluginFileConfigurable.java (59%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading => mod}/metadata/PluginMetadataConfigurable.java (88%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{loading => mod}/metadata/PluginMixinConfigurable.java (96%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/{NeoForgePluginPlatform.java => NeoPluginPlatform.java} (52%) create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java create mode 100644 neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator delete mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/metadata/PluginMetadataFixer.java create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ResourceType.java => src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongeJVMPluginResource.java (59%) rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java => src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java (53%) rename {vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin => src/main/java/org/spongepowered/common/launch/plugin/loader}/JavaPluginLoader.java (52%) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java => src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidate.java (63%) create mode 100644 src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java create mode 100644 src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java create mode 100644 src/main/resources/META-INF/services/org.spongepowered.plugin.PluginLoader delete mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/JavaPluginLanguageService.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/PluginJarMetadata.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SpongeVanillaResourceLocator.java create mode 100644 vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/VanillaPluginDiscovery.java delete mode 100644 vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginLanguageService delete mode 100644 vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService create mode 100644 vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader create mode 100644 vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator delete mode 100644 vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaJavaPluginContainer.java diff --git a/SpongeAPI b/SpongeAPI index 656efea1273..b08258c147f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 656efea127396c6f7f336f342fdfb6e9d0e3aea6 +Subproject commit b08258c147f8411218ba1e60b28249de48bca979 diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java deleted file mode 100644 index 841f97069a7..00000000000 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.applaunch.loading.moddiscovery; - -import com.google.common.collect.ImmutableMap; -import cpw.mods.modlauncher.Environment; -import cpw.mods.modlauncher.Launcher; -import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.forgespi.locating.IModLocator; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.forge.applaunch.plugin.ForgePluginPlatform; - -import java.io.File; -import java.net.URI; -import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Stream; - -public final class SpongeForgeModLocator extends AbstractModProvider implements IModLocator { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public List scanMods() { - if (!FMLEnvironment.production) { - final List resources = new ArrayList<>(); - final String resourcesProp = System.getProperty("sponge.resources"); - if (resourcesProp != null) { - for (final String entry : resourcesProp.split(File.pathSeparator)) { - if (entry.isBlank()) { - continue; - } - - final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); - resources.add(new ModFileOrException(PluginFileParser.newModFile(this, true, paths), null)); - } - } - return resources; - } - - try { - URL rootJar = SpongeForgeModLocator.class.getProtectionDomain().getCodeSource().getLocation(); - FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar - return Files.list(fs.getPath("jars")) - .filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar")) - .map(path -> { - try { - URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); - final Map env = ImmutableMap.of("packagePath", path); - FileSystem jijFS = FileSystems.newFileSystem(jij, env); - return jijFS.getPath("/"); // root of the archive to load - } catch (Exception e) { - throw new RuntimeException(e); - } - }).map((path -> new ModFileOrException(PluginFileParser.newModFile(this, false, path), null))).toList(); - } catch (Exception e) { - LOGGER.error("Failed to scan mod candidates", e); - } - - return List.of(); - } - - @Override - public String name() { - return "spongeforge"; - } - - @Override - public void initArguments(Map arguments) { - final Environment env = Launcher.INSTANCE.environment(); - ForgePluginPlatform.bootstrap(env); - } -} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java deleted file mode 100644 index a76911d39dd..00000000000 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; - -import net.minecraftforge.forgespi.locating.IModLocator; -import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; -import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Stream; - -public final class EnvironmentPluginLocator extends AbstractModProvider implements IModLocator { - - @Override - public List scanMods() { - final List modFiles = new ArrayList<>(); - for (final Path[] paths : EnvironmentPluginLocator.getPluginsPaths()) { - modFiles.add(new ModFileOrException(PluginFileParser.newModFile(this, false, paths), null)); - } - return modFiles; - } - - @Override - public String name() { - return "environment plugin"; - } - - private static List getPluginsPaths() { - final String env = System.getenv("SPONGE_PLUGINS"); - if (env == null) { - return Collections.emptyList(); - } - - List plugins = new ArrayList<>(); - for (final String entry : env.split(";")) { - if (entry.isBlank()) { - continue; - } - plugins.add(Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new)); - } - - return plugins; - } -} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java deleted file mode 100644 index e0ed9845745..00000000000 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; - -import cpw.mods.modlauncher.api.LamdbaExceptionUtils; -import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; -import net.minecraftforge.fml.loading.StringUtils; -import net.minecraftforge.fml.loading.moddiscovery.ModFile; -import net.minecraftforge.forgespi.locating.IModLocator; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; -import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Stream; - -public final class PluginsDirectoryLocator extends AbstractModProvider implements IModLocator { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public List scanMods() { - final List pluginDirectories = AppLaunch.pluginPlatform().pluginDirectories(); - - final List modFiles = new ArrayList<>(); - - for (final Path pluginDirectory : pluginDirectories) { - PluginsDirectoryLocator.LOGGER.debug("Scanning plugins directory '{}' for plugins", pluginDirectory); - this.scanForPluginsIn(pluginDirectory).map((f) -> new ModFileOrException(f, null)).forEach(modFiles::add); - } - - return modFiles; - } - - @SuppressWarnings("UnstableApiUsage") - private Stream scanForPluginsIn(final Path pluginsDirectory) { - final List excluded = ModDirTransformerDiscoverer.allExcluded(); - return LamdbaExceptionUtils.uncheck(() -> Files.list(pluginsDirectory)) - .filter((p) -> !excluded.contains(p) && StringUtils.toLowerCase(p.getFileName().toString()).endsWith(".jar")) - .sorted(Comparator.comparing((path) -> StringUtils.toLowerCase(path.getFileName().toString()))) - .map((p) -> PluginFileParser.newModFile(this, false, p)) - .filter(ModFile::identifyMods); - } - - @Override - public String name() { - return "plugins directory"; - } -} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/AbstractModProvider.java similarity index 98% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/AbstractModProvider.java index 5b71dde2099..7836e9ea878 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/AbstractModProvider.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.moddiscovery; +package org.spongepowered.forge.applaunch.mod.discovery; import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.forgespi.locating.IModFile; diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java similarity index 62% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java index f63dfb7c498..e18de88e664 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.moddiscovery; +package org.spongepowered.forge.applaunch.mod.discovery; import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; @@ -34,17 +34,12 @@ import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.locating.IModFile; import net.minecraftforge.forgespi.locating.IModProvider; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.applaunch.metadata.PluginMetadataFixer; -import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; -import org.spongepowered.forge.applaunch.loading.metadata.PluginFileConfigurable; -import org.spongepowered.plugin.metadata.builtin.MetadataContainer; -import org.spongepowered.plugin.metadata.builtin.MetadataParser; - -import java.io.Reader; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.forge.applaunch.mod.metadata.PluginFileConfigurable; +import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; + import java.lang.reflect.Constructor; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -64,36 +59,16 @@ public final class PluginFileParser { } } - private static IModFileInfo parsePluginFileInfo(final IModFile iModFile) { - final ModFile modFile = (ModFile) iModFile; - AppLaunch.logger().debug("Considering plugin file candidate {}", modFile.getFilePath()); - - final Path metadataFile = modFile.findResource(PluginPlatformConstants.METADATA_FILE_LOCATION); - if (Files.notExists(metadataFile)) { - AppLaunch.logger().debug("Plugin file '{}' is missing a 'sponge_plugins.json' metadata file in META-INF", modFile); - return null; - } - - try { - final MetadataContainer container; - try (final Reader reader = Files.newBufferedReader(metadataFile, StandardCharsets.UTF_8)) { - container = MetadataParser.read(reader); - } - - final PluginFileConfigurable config = new PluginFileConfigurable(PluginMetadataFixer.fixPluginIds(container)); - return new ModFileInfo(modFile, config, (info) -> {}, List.of()); - } catch (final Exception e) { - AppLaunch.logger().warn("Could not read metadata for plugin file '{}'", modFile, e); - return null; - } + private static IModFileInfo parsePluginFileInfo(final IModFile file, final PluginFileConfigurable config) { + return new ModFileInfo((ModFile) file, config, (info) -> {}, List.of()); } - private static IModFileInfo parseModFileInfo(final IModFile iModFile) { - return ModFileParser.modsTomlParser(iModFile); + private static IModFileInfo parseModFileInfo(final IModFile file) { + return ModFileParser.modsTomlParser(file); } - private static IModFileInfo parseLibraryFileInfo(final IModFile iModFile) { - return DummyModProvider.INSTANCE.manifestParser(iModFile); + private static IModFileInfo parseLibraryFileInfo(final IModFile file) { + return DummyModProvider.INSTANCE.manifestParser(file); } private static ModJarMetadata newModJarMetadata() { @@ -109,13 +84,30 @@ private static boolean useModJarMetadata(final SecureJar jar) { if (data.findFile(PluginFileParser.MODULE_INFO).isPresent()) { return false; } - return data.findFile(PluginFileParser.MODS_TOML).isPresent() || data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent(); + return data.findFile(PluginFileParser.MODS_TOML).isPresent(); + } + + public static ModFile newPluginFile(final IModProvider provider, final PluginDiscovery.Candidate candidate) { + final SecureJarPluginResource resource = (SecureJarPluginResource) candidate.resource(); + final SecureJar jar = resource.pluginJar(candidate.metadata().getFirst()); + final PluginFileConfigurable config = new PluginFileConfigurable(resource, candidate.metadata()); + + return new ModFile(jar, provider, file -> parsePluginFileInfo(file, config), "MOD"); + } + + public static @Nullable ModFile newModFile(final IModProvider provider, SecureJarPluginResource resource) { + final ModJarMetadata mjm = newModJarMetadata(); + final SecureJar jar = PluginFileParser.useModJarMetadata(resource.jar()) ? resource.modJar(mjm) : resource.jar(); + return PluginFileParser.newModFile(provider, mjm, jar); } - public static ModFile newModFile(final IModProvider provider, boolean allowUnknown, final Path... paths) { + public static @Nullable ModFile newModFile(final IModProvider provider, final Path... paths) { final ModJarMetadata mjm = newModJarMetadata(); - final SecureJar jar = SecureJar.from(j -> useModJarMetadata(j) ? mjm : JarMetadata.from(j, paths), paths); + final SecureJar jar = SecureJar.from(j -> PluginFileParser.useModJarMetadata(j) ? mjm : JarMetadata.from(j, paths), paths); + return PluginFileParser.newModFile(provider, mjm, jar); + } + private static @Nullable ModFile newModFile(final IModProvider provider, final ModJarMetadata mjm, final SecureJar jar) { final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); final String type = data.getManifest().getMainAttributes().getValue("FMLModType"); @@ -125,22 +117,15 @@ public static ModFile newModFile(final IModProvider provider, boolean allowUnkno return modFile; } - if (data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent()) { - ModFile modFile = new ModFile(jar, provider, PluginFileParser::parsePluginFileInfo, type == null ? "MOD" : type); - mjm.setModFile(modFile); - return modFile; - } - - if (!allowUnknown && type == null) { - throw new IllegalArgumentException("Unknown mod file type"); + if (type == null) { + return null; } - return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, type == null ? "GAMELIBRARY" : type); + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, type); } - public static ModFile newLibraryFile(final IModProvider provider, final Path... paths) { - final SecureJar jar = SecureJar.from(paths); - return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, "GAMELIBRARY"); + public static ModFile newLibraryFile(final IModProvider provider, final boolean game, final SecureJar jar) { + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, game ? "GAMELIBRARY" : "LIBRARY"); } private static class DummyModProvider extends AbstractModProvider { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java similarity index 94% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java index c063b7ae7a6..ca6dcdb2705 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java @@ -22,8 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.moddiscovery; +package org.spongepowered.forge.applaunch.mod.discovery; +import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.forgespi.locating.IDependencyLocator; import net.minecraftforge.forgespi.locating.IModFile; @@ -31,7 +32,7 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.plugin.PluginPlatform; -import org.spongepowered.forge.applaunch.loading.moddiscovery.library.Log4JLogger; +import org.spongepowered.forge.applaunch.mod.discovery.library.Log4JLogger; import org.spongepowered.libs.LibraryManager; import java.nio.file.Path; @@ -65,7 +66,7 @@ public List scanMods(final Iterable loadedMods) { for (final LibraryManager.Library library : libraryManager.getAll("main")) { final Path path = library.file(); SpongeForgeDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - modFiles.add(PluginFileParser.newLibraryFile(this, path)); + modFiles.add(PluginFileParser.newLibraryFile(this, true, SecureJar.from(path))); } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java new file mode 100644 index 00000000000..3ab62dbd3bc --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java @@ -0,0 +1,137 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.mod.discovery; + +import com.google.common.collect.ImmutableMap; +import net.minecraftforge.fml.loading.FMLEnvironment; +import net.minecraftforge.forgespi.locating.IModFile; +import net.minecraftforge.forgespi.locating.IModLocator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.forge.applaunch.plugin.ForgePluginPlatform; +import org.spongepowered.forge.applaunch.plugin.discovery.ForgePluginDiscovery; +import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; + +import java.net.URI; +import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.*; + +public final class SpongeForgeModLocator extends AbstractModProvider implements IModLocator { + private static final Logger LOGGER = LogManager.getLogger(); + + private @MonotonicNonNull ForgePluginDiscovery discovery; + + @Override + public String name() { + return "spongeforge"; + } + + @Override + public void initArguments(Map arguments) { + this.discovery = AppLaunch.bootstrap(ForgePluginPlatform::new).discovery(); + } + + @Override + public List scanMods() { + this.discovery.discoverPluginResources(); + + final List mods = new ArrayList<>(); + + for (final PluginDiscovery.Candidate candidate : this.discovery.candidates()) { + if (candidate.resource() instanceof SecureJarPluginResource resource) { + candidate.readMetadata(); + + // attempt to load as mod or plugin + IModFile modFile; + if (candidate.pluginFound()) { + modFile = PluginFileParser.newPluginFile(this, candidate); + } else { + modFile = PluginFileParser.newModFile(this, resource); + if (modFile != null) { + candidate.setModFound(); + } + } + + if (modFile == null) { + // determine fallback type + switch (candidate.loading()) { + case IGNORED: + candidate.logResult(); + continue; + case LIBRARY: + modFile = PluginFileParser.newLibraryFile(this, false, resource.jar()); + break; + case GAME_LIBRARY: + modFile = PluginFileParser.newLibraryFile(this, true, resource.jar()); + break; + } + } + + mods.add(new ModFileOrException(modFile, null)); + } + + // TODO else: Forge can only loads jar mods, do we make a dummy jar? + + candidate.logResult(); + } + + this.discovery.logMetadataWarnings(); + + if (!FMLEnvironment.production) { + return mods; + } + + try { + URL rootJar = SpongeForgeModLocator.class.getProtectionDomain().getCodeSource().getLocation(); + FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar + Files.list(fs.getPath("jars")) + .filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar")) + .map(path -> { + try { + URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); + final Map env = ImmutableMap.of("packagePath", path); + FileSystem jijFS = FileSystems.newFileSystem(jij, env); + return jijFS.getPath("/"); // root of the archive to load + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .map((path) -> PluginFileParser.newModFile(this, path)) + .filter(Objects::nonNull) + .map((modFile -> new ModFileOrException(modFile, null))) + .forEach(mods::add); + } catch (Exception e) { + LOGGER.error("Failed to scan embedded mod candidates", e); + } + + return mods; + } +} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/library/Log4JLogger.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/library/Log4JLogger.java similarity index 96% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/library/Log4JLogger.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/library/Log4JLogger.java index 31f7369862f..ab372157887 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/library/Log4JLogger.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/library/Log4JLogger.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.moddiscovery.library; +package org.spongepowered.forge.applaunch.mod.discovery.library; import org.spongepowered.libs.Logger; diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginDependencyConfigurable.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java similarity index 90% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginDependencyConfigurable.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java index 5ddd35637a4..d6bb24ccb44 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginDependencyConfigurable.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java @@ -22,11 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.metadata; +package org.spongepowered.forge.applaunch.mod.metadata; import net.minecraftforge.forgespi.language.IConfigurable; import net.minecraftforge.forgespi.language.IModInfo; -import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginDependency; import java.util.Collections; @@ -36,11 +35,9 @@ // ModVersion public final class PluginDependencyConfigurable implements IConfigurable { - private final PluginMetadata metadata; private final PluginDependency dependency; - public PluginDependencyConfigurable(final PluginMetadata metadata, final PluginDependency dependency) { - this.metadata = metadata; + public PluginDependencyConfigurable(final PluginDependency dependency) { this.dependency = dependency; } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginFileConfigurable.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java similarity index 61% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginFileConfigurable.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java index ee1c28f4e0a..f09095d83c0 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginFileConfigurable.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -22,26 +22,25 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.metadata; +package org.spongepowered.forge.applaunch.mod.metadata; import net.minecraftforge.forgespi.language.IConfigurable; +import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import org.spongepowered.plugin.metadata.builtin.MetadataContainer; -import org.spongepowered.plugin.metadata.model.PluginDependency; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; // ModFileInfo public final class PluginFileConfigurable implements IConfigurable { + private final Map plugins = new LinkedHashMap<>(); + private final PluginResource resource; - private final MetadataContainer container; - - public PluginFileConfigurable(final MetadataContainer container) { - this.container = container; + public PluginFileConfigurable(final PluginResource resource, final Collection plugins) { + for (final PluginMetadata plugin : plugins) { + this.plugins.put(plugin.id(), plugin); + } + this.resource = resource; } @SuppressWarnings("unchecked") @@ -56,27 +55,32 @@ public Optional getConfigElement(final String... key) { return Optional.empty(); } + if ("spongeResource".equals(query)) { + return Optional.of((T) this.resource); + } + if ("modLoader".equals(query)) { - return (Optional) Optional.of(this.container.loader().name()); + return Optional.of((T) "sponge"); } if ("loaderVersion".equals(query)) { - return (Optional) Optional.of(this.container.loader().version().toString()); + return Optional.of((T) "*"); } if ("license".equals(query)) { - return (Optional) Optional.of(this.container.license()); + return Optional.of((T) this.plugins.values().stream() + .map(m -> m.container().license()).distinct().collect(Collectors.joining(", "))); } if (key.length == 2) { final String plugin = key[1]; - final PluginMetadata metadata = this.container.metadata(plugin).orElse(null); + final PluginMetadata metadata = this.plugins.get(plugin); if (metadata == null) { return Optional.empty(); } if ("modproperties".equals(query)) { - return (Optional) Optional.of(metadata.properties()); + return Optional.of((T) metadata.properties()); } } @@ -95,38 +99,21 @@ public List getConfigList(final String... key) { } if ("mods".equals(query)) { - final Set metadataById = this.container.metadata(); - if (metadataById.isEmpty()) { - return Collections.emptyList(); - } - - final List metadataConfigurables = new ArrayList<>(); - metadataById.forEach((metadata) -> metadataConfigurables.add(new PluginMetadataConfigurable(metadata))); - return metadataConfigurables; + return this.plugins.values().stream().map(PluginMetadataConfigurable::new).toList(); } if (key.length != 2) { return Collections.emptyList(); } - final String plugin = key[1]; - final PluginMetadata metadata = this.container.metadata(plugin).orElse(null); + final String pluginId = key[1]; + final PluginMetadata metadata = this.plugins.get(pluginId); if (metadata == null) { return Collections.emptyList(); } if ("dependencies".equals(query)) { - final Set dependencies = metadata.dependencies(); - if (dependencies.isEmpty()) { - return Collections.emptyList(); - } - - final List depConfigurables = new ArrayList<>(); - for (final PluginDependency dependency : dependencies) { - depConfigurables.add(new PluginDependencyConfigurable(metadata, dependency)); - } - - return depConfigurables; + return metadata.dependencies().stream().map(PluginDependencyConfigurable::new).toList(); } return Collections.emptyList(); @@ -136,7 +123,6 @@ private int requiredConfigElements(final String query) { if ("dependencies".equals(query) || "modproperties".equals(query)) { return 2; } - return 1; } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginMetadataConfigurable.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginMetadataConfigurable.java similarity index 88% rename from forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginMetadataConfigurable.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginMetadataConfigurable.java index 95584102d07..50b2371082e 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/metadata/PluginMetadataConfigurable.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginMetadataConfigurable.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.applaunch.loading.metadata; +package org.spongepowered.forge.applaunch.mod.metadata; import net.minecraftforge.forgespi.language.IConfigurable; import org.spongepowered.plugin.metadata.PluginMetadata; @@ -32,13 +32,7 @@ import java.util.Optional; // ModInfo -public final class PluginMetadataConfigurable implements IConfigurable { - - private final PluginMetadata metadata; - - public PluginMetadataConfigurable(final PluginMetadata metadata) { - this.metadata = metadata; - } +public record PluginMetadataConfigurable(PluginMetadata metadata) implements IConfigurable { @SuppressWarnings("unchecked") @Override @@ -53,6 +47,7 @@ public Optional getConfigElement(final String... key) { case "displayName" -> (Optional) this.metadata.name(); case "description" -> (Optional) this.metadata.description(); case "displayTest" -> Optional.of((T) "IGNORE_SERVER_VERSION"); + case "spongeMetadata" -> Optional.of((T) this.metadata); default -> Optional.empty(); }; } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java index a622afd05a7..a1fe3600c31 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java @@ -24,63 +24,31 @@ */ package org.spongepowered.forge.applaunch.plugin; -import cpw.mods.modlauncher.Environment; +import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IEnvironment; import net.minecraftforge.fml.loading.FMLPaths; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.applaunch.config.LaunchConfig; -import org.spongepowered.common.applaunch.config.TokenReplacement; import org.spongepowered.common.applaunch.plugin.PluginPlatform; +import org.spongepowered.forge.applaunch.plugin.discovery.ForgePluginDiscovery; +import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -public final class ForgePluginPlatform implements PluginPlatform { +public final class ForgePluginPlatform extends PluginPlatform { private static final List closeCallbacks = new ArrayList<>(); - private static volatile boolean bootstrapped; + private final ForgePluginDiscovery discovery; - private final Environment environment; - private final LaunchConfig config; - private final TokenReplacement tokens; - private final List pluginDirectories; - - public static synchronized void bootstrap(final Environment environment) { - if (ForgePluginPlatform.bootstrapped) { - return; - } - ForgePluginPlatform.bootstrapped = true; - final ForgePluginPlatform platform; - try { - platform = new ForgePluginPlatform(environment); - } catch (final IOException e) { - throw new RuntimeException(e); - } - AppLaunch.setPluginPlatform(platform); - } - - private ForgePluginPlatform(final Environment environment) throws IOException { - this.environment = environment; - this.config = LaunchConfig.load(this.baseDirectory(), true); - - this.tokens = new TokenReplacement(); - this.tokens.register("BASE_DIR", this.baseDirectory()); - this.tokens.register("CONFIG_DIR", this.configDirectory()); - this.tokens.register("MODS_DIR", FMLPaths.MODSDIR.get()); - - final Path additionalPluginsDirectory = Path.of(this.tokens.replace(this.config.additionalPluginsDirectory())); - Files.createDirectories(additionalPluginsDirectory); - this.pluginDirectories = List.of(FMLPaths.MODSDIR.get(), additionalPluginsDirectory); + public ForgePluginPlatform() { + this.discovery = new ForgePluginDiscovery(this.environment()); } @Override public String version() { - return this.environment.getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev"); + return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev"); } - @Override public boolean vanilla() { return false; @@ -97,18 +65,18 @@ public Path configDirectory() { } @Override - public LaunchConfig config() { - return this.config; + public Path modsDirectory() { + return FMLPaths.MODSDIR.get(); } @Override - public TokenReplacement tokens() { - return this.tokens; + public ForgePluginDiscovery discovery() { + return this.discovery; } @Override - public List pluginDirectories() { - return this.pluginDirectories; + public JVMPluginResource create(final Path[] paths) { + return new SecureJarPluginResource(paths); } @Override diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/ForgePluginDiscovery.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/ForgePluginDiscovery.java new file mode 100644 index 00000000000..d35873407ac --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/ForgePluginDiscovery.java @@ -0,0 +1,77 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.plugin.discovery; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.securemodules.SecureModuleClassLoader; +import net.minecraftforge.securemodules.SecureModuleFinder; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; +import org.spongepowered.plugin.Environment; + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +public class ForgePluginDiscovery extends PluginDiscovery { + private ModuleLayer currentLayer; + private ClassLoader currentLoader; + + public ForgePluginDiscovery(Environment environment) { + super(environment); + this.currentLayer = getClass().getModule().getLayer(); + this.currentLoader = getClass().getClassLoader(); + } + + @Override + protected ServiceLoader newServiceLoader(final Class serviceClass) { + return ServiceLoader.load(this.currentLayer, serviceClass); + } + + @Override + protected void appendDiscoveryServices(final List resources, final int batch) { + final ModuleLayer parentLayer = this.currentLayer; + final ClassLoader parentLoader = this.currentLoader; + + final List jars = new ArrayList<>(); + final List moduleNames = new ArrayList<>(); + + for (final SpongeJVMPluginResource resource : resources) { + final SecureJar jar = ((SecureJarPluginResource) resource).jar(); + jars.add(jar); + moduleNames.add(jar.name()); + } + + final Configuration config = parentLayer.configuration().resolveAndBind(SecureModuleFinder.of(jars), ModuleFinder.of(), moduleNames); + final ClassLoader loader = new SecureModuleClassLoader("SPONGE-DISCOVERY-BATCH-" + batch, null, config, List.of(parentLayer), List.of(parentLoader)); + + this.currentLayer = this.currentLayer.defineModulesWithOneLoader(config, loader); + this.currentLoader = loader; + + this.environment.logger().debug("Built new service layer {} on top of {}.", loader.getName(), parentLoader.getName()); + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/PluginJarMetadata.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/PluginJarMetadata.java similarity index 55% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/PluginJarMetadata.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/PluginJarMetadata.java index 82b71be1464..d60eb3eff57 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/PluginJarMetadata.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/PluginJarMetadata.java @@ -22,11 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch.plugin.resource; +package org.spongepowered.forge.applaunch.plugin.discovery; import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.plugin.metadata.PluginMetadata; import java.lang.module.ModuleDescriptor; @@ -35,71 +34,47 @@ import java.util.Arrays; public class PluginJarMetadata implements JarMetadata { - private final SecureJar jar; - private final Path[] paths; - - private boolean initialized = false; - private ModuleDescriptor descriptor; + private final ModuleDescriptor descriptor; public PluginJarMetadata(final SecureJar jar, final Path[] paths) { - this.jar = jar; - this.paths = paths; - } - - public void init(final PluginMetadata plugin) { - if (this.initialized) { - throw new IllegalStateException("Metadata already initialized"); - } - this.initialized = true; - if (plugin == null) { - if (this.jar.moduleDataProvider().findFile("module-info.class").isEmpty() - && Arrays.stream(this.paths).allMatch(Files::isDirectory)) { - this.descriptor = PluginJarMetadata.createDescriptor(this.jar, this.jar.getPackages() - .stream() - .sorted() - .findFirst() - .orElseThrow(), null); - } else { - this.descriptor = JarMetadata.from(this.jar, this.paths).descriptor(); - } - } else { - this.descriptor = PluginJarMetadata.createDescriptor(this.jar, plugin.id().replace('-', '_'), plugin.version().toString()); - } + this.descriptor = PluginJarMetadata.standardDescriptor(jar, paths); } - private void checkInitialized() { - if (!this.initialized) { - throw new IllegalStateException("Metadata not initialized"); - } + public PluginJarMetadata(final SecureJar jar, final PluginMetadata plugin) { + this.descriptor = PluginJarMetadata.pluginDescriptor(jar, plugin); } @Override public String name() { - this.checkInitialized(); return this.descriptor.name(); } @Override public String version() { - this.checkInitialized(); return this.descriptor.rawVersion().orElse(null); } @Override public ModuleDescriptor descriptor() { - this.checkInitialized(); return this.descriptor; } - private static ModuleDescriptor createDescriptor(final SecureJar jar, final String name, final @Nullable String version) { - final ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(name) - .packages(jar.getPackages()); - if (version != null) { - builder.version(version); + private static ModuleDescriptor pluginDescriptor(final SecureJar jar, final PluginMetadata plugin) { + return PluginJarMetadata.descriptorBuilder(jar, plugin.id()).version(plugin.version().toString()).build(); + } + + private static ModuleDescriptor standardDescriptor(final SecureJar jar, final Path[] paths) { + if (jar.moduleDataProvider().findFile("module-info.class").isEmpty() && Arrays.stream(paths).allMatch(Files::isDirectory)) { + return PluginJarMetadata.descriptorBuilder(jar, jar.getPackages().stream().sorted().findFirst().orElseThrow()).build(); } + return JarMetadata.from(jar, paths).descriptor(); + } + + private static ModuleDescriptor.Builder descriptorBuilder(final SecureJar jar, final String name) { + final ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(name).packages(jar.getPackages()); jar.getProviders().stream() .filter(p -> !p.providers().isEmpty()) .forEach(p -> builder.provides(p.serviceName(), p.providers())); - return builder.build(); + return builder; } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/SecureJarPluginResource.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java similarity index 54% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/SecureJarPluginResource.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java index 62f42cc0dff..2397b22120e 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/resource/SecureJarPluginResource.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -22,54 +22,45 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch.plugin.resource; +package org.spongepowered.forge.applaunch.plugin.discovery; -import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import org.spongepowered.vanilla.applaunch.plugin.ResourceType; +import net.minecraftforge.fml.loading.moddiscovery.ModJarMetadata; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; +import java.lang.module.ModuleDescriptor; +import java.net.URI; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.Arrays; import java.util.Objects; +import java.util.Optional; import java.util.jar.Manifest; -public final class SecureJarPluginResource implements JVMPluginResource { - private final String locator; +public final class SecureJarPluginResource implements SpongeJVMPluginResource { + private final Path[] paths; private final SecureJar jar; - private PluginJarMetadata pluginJarMetadata; - private List candidates; - - public SecureJarPluginResource(final String locator, final Path[] paths) { - Objects.requireNonNull(locator, "locator"); + public SecureJarPluginResource(final Path[] paths) { Objects.requireNonNull(paths, "paths"); - if (paths.length == 0) { throw new IllegalArgumentException("Need at least one path"); } + this.paths = paths; + this.jar = SecureJar.from(jar -> new PluginJarMetadata(jar, paths), paths); + } - this.locator = locator; - this.jar = SecureJar.from(jar -> { - if (ResourceType.of(jar) == ResourceType.PLUGIN) { - this.pluginJarMetadata = new PluginJarMetadata(jar, paths); - this.candidates = new ArrayList<>(); - return this.pluginJarMetadata; - } - return JarMetadata.from(jar, paths); - }, paths); + public SecureJar jar() { + return this.jar; } - @Override - public String locator() { - return this.locator; + public SecureJar pluginJar(final PluginMetadata metadata) { + return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.paths); } - public SecureJar jar() { - return this.jar; + @SuppressWarnings("UnstableApiUsage") + public SecureJar modJar(final ModJarMetadata metadata) { + return SecureJar.from(jar -> metadata, this.paths); } @Override @@ -78,25 +69,18 @@ public Path path() { } @Override - public Manifest manifest() { - return this.jar.moduleDataProvider().getManifest(); + public Optional locateResource(final String path) { + return this.jar.moduleDataProvider().findFile(path); } @Override - public Path resourcesRoot() { - return this.jar.getRootPath(); - } - - public void addCandidates(Collection candidates) { - if (this.candidates != null) { - this.candidates.addAll(candidates); - } + public Manifest manifest() { + return this.jar.moduleDataProvider().getManifest(); } - public void init() { - if (this.pluginJarMetadata != null) { - this.pluginJarMetadata.init(this.candidates.isEmpty() ? null : this.candidates.get(0).metadata()); - } + @Override + public ModuleDescriptor module() { + return this.jar.moduleDataProvider().descriptor(); } @Override @@ -107,19 +91,16 @@ public boolean equals(Object obj) { if (!(obj instanceof SecureJarPluginResource that)) { return false; } - return this.locator.equals(that.locator) && this.jar.equals(that.jar); + return Arrays.equals(this.paths, that.paths); } @Override public int hashCode() { - return Objects.hash(this.locator, this.jar); + return Arrays.hashCode(this.paths); } @Override public String toString() { - return "SecureJarPluginResource[" + - "locator=" + this.locator + ", " + - "jar=" + this.jar + ']'; + return "SecureJarPluginResource[paths=" + Arrays.toString(this.paths) + "]"; } - } diff --git a/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IDependencyLocator b/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IDependencyLocator index 97ede6493ca..9e40bc73290 100644 --- a/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IDependencyLocator +++ b/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IDependencyLocator @@ -1 +1 @@ -org.spongepowered.forge.applaunch.loading.moddiscovery.SpongeForgeDependencyLocator \ No newline at end of file +org.spongepowered.forge.applaunch.mod.discovery.SpongeForgeDependencyLocator \ No newline at end of file diff --git a/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator b/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator index ad02e10d0d0..7274186d124 100644 --- a/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator +++ b/forge/src/applaunch/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator @@ -1,3 +1 @@ -org.spongepowered.forge.applaunch.loading.moddiscovery.SpongeForgeModLocator -org.spongepowered.forge.applaunch.loading.moddiscovery.locator.EnvironmentPluginLocator -org.spongepowered.forge.applaunch.loading.moddiscovery.locator.PluginsDirectoryLocator \ No newline at end of file +org.spongepowered.forge.applaunch.mod.discovery.SpongeForgeModLocator diff --git a/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator new file mode 100644 index 00000000000..93a6e7f4172 --- /dev/null +++ b/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -0,0 +1 @@ +org.spongepowered.common.applaunch.plugin.discovery.SpongePropertyResourceLocator diff --git a/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java b/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java deleted file mode 100644 index 5b5b7af6e68..00000000000 --- a/forge/src/lang/java/org/spongepowered/forge/lang/provider/JavaPluginLanguageProvider.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge.lang.provider; - -import cpw.mods.modlauncher.api.LamdbaExceptionUtils; -import net.minecraftforge.fml.Logging; -import net.minecraftforge.fml.ModLoadingStage; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLanguageProvider; -import net.minecraftforge.forgespi.language.IModInfo; -import net.minecraftforge.forgespi.language.IModLanguageProvider; -import net.minecraftforge.forgespi.language.ModFileScanData; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.objectweb.asm.Type; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -public final class JavaPluginLanguageProvider extends FMLJavaModLanguageProvider { - - private static final Type PLUGIN_ANNOTATION = Type.getType("Lorg/spongepowered/plugin/builtin/jvm/Plugin;"); - - private final Logger logger; - - public JavaPluginLanguageProvider() { - this.logger = LogManager.getLogger(); - } - - @Override - public String name() { - return "java_plain"; - } - - @Override - public Consumer getFileVisitor() { - return scanResult -> { - final Map modTargetMap = scanResult.getAnnotations().stream() - .filter(ad -> ad.annotationType().equals(JavaPluginLanguageProvider.PLUGIN_ANNOTATION)) - .peek(ad -> this.logger.debug(Logging.SCAN, "Found @Plugin class {} with id {}", ad.clazz().getClassName(), ad.annotationData().get("value"))) - .map(ad -> new PluginTarget(ad.clazz().getClassName(), JavaPluginLanguageProvider.fixPluginId((String) ad.annotationData().get("value")))) - .collect(Collectors.toMap(PluginTarget::getPlugin, Function.identity(), (a,b)->a)); - scanResult.addLanguageLoader(modTargetMap); - }; - } - - private static String fixPluginId(final String id) { - return id.replace('-', '_'); - } - - private static final class PluginTarget implements IModLanguageProvider.IModLanguageLoader { - - private final Logger logger; - private final String className; - private final String plugin; - - private PluginTarget(final String className, final String plugin) { - this.logger = LogManager.getLogger(); - this.className = className; - this.plugin = plugin; - } - - @Override - public T loadMod(final IModInfo info, final ModFileScanData modFileScanData, final ModuleLayer gameLayer) { - // The following is adapted from FMLJavaModLanguageProvider.FMLModTarget - - // This language class is loaded in the system level classloader - before the game even starts - // So we must treat container construction as an arms length operation, and load the container - // in the classloader of the game - the context classloader is appropriate here. - try { - final Class pluginContainer = Class.forName( - "org.spongepowered.forge.launch.plugin.PluginModContainer", true, Thread.currentThread().getContextClassLoader()); - this.logger.debug(Logging.LOADING, "Loading PluginModContainer from classloader {} - got {}", Thread.currentThread().getContextClassLoader(), pluginContainer.getClassLoader()); - final Constructor constructor = pluginContainer.getConstructor(IModInfo.class, String.class, ModFileScanData.class, ModuleLayer.class); - return (T) constructor.newInstance(info, className, modFileScanData, gameLayer); - } - // ALL exception handling has to be done through the classloader, because we're loaded in the wrong context, so any classes we just blind load will be in the wrong - // class loading context. Funky but works. - catch (final InvocationTargetException e) { - this.logger.fatal(Logging.LOADING, "Failed to build plugin", e); - final Class mle = (Class) LamdbaExceptionUtils.uncheck(()->Class.forName("net.minecraftforge.fml.ModLoadingException", true, Thread.currentThread().getContextClassLoader())); - if (mle.isInstance(e.getTargetException())) { - throw mle.cast(e.getTargetException()); - } else { - final Class mls = (Class) LamdbaExceptionUtils.uncheck(()->Class.forName("net.minecraftforge.fml.ModLoadingStage", true, Thread.currentThread().getContextClassLoader())); - throw LamdbaExceptionUtils.uncheck(()->LamdbaExceptionUtils.uncheck(()->mle.getConstructor(IModInfo.class, mls, String.class, Throwable.class)).newInstance(info, Enum.valueOf(mls, "CONSTRUCT"), "fml.modloading.failedtoloadmodclass", e)); - } - } - catch (final NoSuchMethodException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { - this.logger.fatal(Logging.LOADING,"Unable to load PluginModContainer, excuse me?", e); - final Class mle = (Class)LamdbaExceptionUtils.uncheck(()->Class.forName("net.minecraftforge.fml.ModLoadingException", true, Thread.currentThread().getContextClassLoader())); - final Class mls = (Class) LamdbaExceptionUtils.uncheck(()->Class.forName("net.minecraftforge.fml.ModLoadingStage", true, Thread.currentThread().getContextClassLoader())); - throw LamdbaExceptionUtils.uncheck(()->LamdbaExceptionUtils.uncheck(()->mle.getConstructor(IModInfo.class, mls, String.class, Throwable.class)).newInstance(info, Enum.valueOf(mls, "CONSTRUCT"), "fml.modloading.failedtoloadmodclass", e)); - } - } - - public String getPlugin() { - return this.plugin; - } - } -} diff --git a/forge/src/lang/java/org/spongepowered/forge/lang/provider/SpongeLanguageProvider.java b/forge/src/lang/java/org/spongepowered/forge/lang/provider/SpongeLanguageProvider.java new file mode 100644 index 00000000000..2280157526a --- /dev/null +++ b/forge/src/lang/java/org/spongepowered/forge/lang/provider/SpongeLanguageProvider.java @@ -0,0 +1,84 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.lang.provider; + +import net.minecraftforge.fml.Logging; +import net.minecraftforge.fml.ModLoadingException; +import net.minecraftforge.fml.ModLoadingStage; +import net.minecraftforge.forgespi.language.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +@SuppressWarnings("unchecked") +public final class SpongeLanguageProvider implements IModLanguageProvider { + + @Override + public String name() { + return "sponge"; + } + + @Override + public Consumer getFileVisitor() { + return scanData -> { + final Map targets = (Map) scanData.getTargets(); + for (final IModFileInfo fileInfo : scanData.getIModInfoData()) { + for (final IModInfo modInfo : fileInfo.getMods()) { + targets.put(modInfo.getModId(), SpongeLanguageLoader.INSTANCE); + } + } + }; + } + + @Override + public > void consumeLifecycleEvent(final Supplier consumeEvent) {} + + private static final class SpongeLanguageLoader implements IModLanguageProvider.IModLanguageLoader { + private static final Logger LOGGER = LogManager.getLogger(); + private static final SpongeLanguageLoader INSTANCE = new SpongeLanguageLoader(); + + @Override + public T loadMod(final IModInfo info, final ModFileScanData scanData, final ModuleLayer layer) { + try { + final Module module = layer.findModule("spongeforge").orElseThrow(() -> new NoSuchElementException("Module spongeforge")); + final Class containerClass = Class.forName(module, "org.spongepowered.forge.launch.plugin.PluginModContainer"); + final Constructor constructor = containerClass.getConstructor(IModInfo.class, ModFileScanData.class, ModuleLayer.class); + return (T) constructor.newInstance(info, scanData, layer); + } catch (final InvocationTargetException e) { + SpongeLanguageLoader.LOGGER.fatal(Logging.LOADING, "Failed to build plugin", e); + throw new ModLoadingException(info, ModLoadingStage.CONSTRUCT, "Failed to build plugin", e); + } catch (final Exception e) { + SpongeLanguageLoader.LOGGER.fatal(Logging.LOADING, "Unable to load PluginModContainer", e); + throw new ModLoadingException(info, ModLoadingStage.CONSTRUCT, "Unable to load PluginModContainer", e); + } + } + } +} diff --git a/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.language.IModLanguageProvider b/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.language.IModLanguageProvider index 1f6b5fa2dfd..fd8849eb51b 100644 --- a/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.language.IModLanguageProvider +++ b/forge/src/lang/resources/META-INF/services/net.minecraftforge.forgespi.language.IModLanguageProvider @@ -1 +1 @@ -org.spongepowered.forge.lang.provider.JavaPluginLanguageProvider \ No newline at end of file +org.spongepowered.forge.lang.provider.SpongeLanguageProvider \ No newline at end of file diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java index d4979335e54..1d5e58138a7 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java @@ -25,12 +25,12 @@ package org.spongepowered.forge.launch.plugin; import com.google.common.collect.MapMaker; -import com.google.inject.Injector; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; +import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.common.launch.plugin.SpongePluginContainer; +import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.metadata.PluginMetadata; import java.net.URI; @@ -40,15 +40,17 @@ import java.util.Objects; import java.util.Optional; -public class ForgePluginContainer implements SpongePluginContainer { +@SuppressWarnings("UnstableApiUsage") +public class ForgePluginContainer implements PluginContainer { private final ModContainer modContainer; + private final IModFile modFile; - private Injector injector; private Logger logger; private PluginMetadata pluginMetadata; private ForgePluginContainer(final ModContainer modContainer) { this.modContainer = modContainer; + this.modFile = modContainer.getModInfo().getOwningFile().getFile(); } @Override @@ -69,7 +71,7 @@ public Logger logger() { @Override public Optional locateResource(String relative) { - final Path p = this.modContainer.getModInfo().getOwningFile().getFile().findResource(Objects.requireNonNull(relative, "relative")); + final Path p = this.modFile.findResource(Objects.requireNonNull(relative, "relative")); return Files.exists(p) ? Optional.of(p.toUri()) : Optional.empty(); } @@ -78,18 +80,12 @@ public Object instance() { return this.modContainer.getMod(); } - @Override - public Optional injector() { - return Optional.ofNullable(this.injector); - } - - public void setInjector(final Injector injector) { - this.injector = injector; - } - - private static final Map containers = new MapMaker().weakKeys().makeMap(); + private static final Map mods = new MapMaker().weakKeys().makeMap(); - public static ForgePluginContainer of(final ModContainer modContainer) { - return containers.computeIfAbsent(modContainer, ForgePluginContainer::new); + public static Optional of(final ModContainer modContainer) { + if (modContainer instanceof PluginModContainer plugin) { + return plugin.container(); + } + return Optional.of(ForgePluginContainer.mods.computeIfAbsent(modContainer, ForgePluginContainer::new)); } } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java index f3b3d09f01d..c3ae1d2c9d1 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java @@ -35,23 +35,22 @@ import java.util.Optional; @Singleton -@SuppressWarnings("unchecked") public final class ForgePluginManager implements SpongePluginManager { @Override public Optional fromInstance(final Object instance) { - return ModList.get().getModContainerByObject(Objects.requireNonNull(instance, "instance")).map(ForgePluginContainer::of); + return ModList.get().getModContainerByObject(Objects.requireNonNull(instance, "instance")).flatMap(ForgePluginContainer::of); } @Override public Optional plugin(final String id) { - return ModList.get().getModContainerById(Objects.requireNonNull(id, "id")).map(ForgePluginContainer::of); + return ModList.get().getModContainerById(Objects.requireNonNull(id, "id")).flatMap(ForgePluginContainer::of); } @Override public Collection plugins() { final ImmutableList.Builder builder = ImmutableList.builder(); - ModList.get().forEachModInOrder(mod -> builder.add(ForgePluginContainer.of(mod))); + ModList.get().forEachModInOrder(mod -> ForgePluginContainer.of(mod).ifPresent(builder::add)); return builder.build(); } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java index e854d3d2a2e..d9c6eed0e1d 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java @@ -28,13 +28,13 @@ import net.minecraftforge.forgespi.language.IModInfo; import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginContributor; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginDependency; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginLinks; +import org.spongepowered.plugin.metadata.model.PluginContributor; import org.spongepowered.plugin.metadata.model.PluginDependency; +import org.spongepowered.plugin.metadata.model.PluginLinks; -import java.util.ArrayList; -import java.util.List; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Optional; public final class PluginMetadataConverter { @@ -47,22 +47,22 @@ public static PluginMetadata modToPlugin(final ModInfo info) { .version(info.getVersion().toString()) .description(info.getDescription()) .entrypoint("unknown") - .addContributor(StandardPluginContributor.builder().name(info.getConfigElement("authors").orElse("unknown").toString()).build()) - .links(StandardPluginLinks.builder().issues(info.getOwningFile().getIssueURL()).build()) + .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); - final List dependencies = new ArrayList<>(); - for (final IModInfo.ModVersion dependency : info.getDependencies()) { - final StandardPluginDependency.Builder depBuilder = StandardPluginDependency.builder(); - depBuilder - .id(dependency.getModId()) - .loadOrder(PluginMetadataConverter.orderingToLoad(dependency.getOrdering())) - .version(dependency.getVersionRange().toString()); + try { + final URL issueURL = info.getOwningFile().getIssueURL(); + builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); + } catch (URISyntaxException ignored) {} - dependencies.add(depBuilder.build()); + for (final IModInfo.ModVersion dependency : info.getDependencies()) { + builder.addDependency(new PluginDependency( + dependency.getModId(), + dependency.getVersionRange(), + PluginMetadataConverter.orderingToLoad(dependency.getOrdering()), + false + )); } - - builder.dependencies(dependencies); return builder.build(); } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index e20021a86a3..aa37cf1e883 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -24,7 +24,6 @@ */ package org.spongepowered.forge.launch.plugin; -import com.google.inject.Injector; import net.minecraftforge.eventbus.api.bus.BusGroup; import net.minecraftforge.eventbus.api.bus.EventBus; import net.minecraftforge.fml.Logging; @@ -35,102 +34,105 @@ import net.minecraftforge.fml.config.IConfigEvent; import net.minecraftforge.fml.event.IModBusEvent; import net.minecraftforge.fml.javafmlmod.AutomaticEventSubscriber; +import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.api.Sponge; -import org.spongepowered.common.inject.plugin.PluginGuice; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.common.launch.Launch; +import org.spongepowered.common.launch.plugin.loader.PluginCandidate; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginDependency; +import java.util.Optional; import java.util.concurrent.CountDownLatch; -// Spongified FMLModContainer public final class PluginModContainer extends ModContainer { private static final Logger LOGGER = LogManager.getLogger(); - private final ModFileScanData scanResults; - private final BusGroup eventBusGroup; - private Object modInstance; - private final Class modClass; + private final PluginCandidate candidate; + private final Module module; + + private final ModFileScanData scanData; + private final BusGroup busGroup; private final CountDownLatch initializationLock; - public PluginModContainer(IModInfo info, String className, ModFileScanData modFileScanResults, ModuleLayer gameLayer) { + private @MonotonicNonNull PluginContainer container; + + public PluginModContainer(final IModInfo info, final ModFileScanData scanData, final ModuleLayer layer) { super(info); - LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", className); - this.scanResults = modFileScanResults; + LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", info.getModId()); + this.scanData = scanData; this.activityMap.put(ModLoadingStage.CONSTRUCT, this::constructPlugin); - this.eventBusGroup = BusGroup.create("modBusFor" + info.getModId()); + this.busGroup = BusGroup.create("modBusFor" + info.getModId()); this.contextExtension = () -> null; this.initializationLock = new CountDownLatch(1); - try { - Module module = gameLayer.findModule(info.getOwningFile().moduleName()).orElseThrow(); - modClass = Class.forName(module, className); - LOGGER.trace(Logging.LOADING, "Loaded modclass {} with {}", modClass.getName(), modClass.getClassLoader()); - } catch (Throwable e) { - LOGGER.error(Logging.LOADING, "Failed to load class {}", className, e); - throw new ModLoadingException(info, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmodclass", e); - } + final PluginResource resource = info.getOwningFile().getConfig().getConfigElement("spongeResource").get(); + final PluginMetadata metadata = info.getConfig().getConfigElement("spongeMetadata").get(); + this.candidate = Launch.instance().pluginFactory().create(resource, metadata); + this.module = layer.findModule(PluginModContainer.getModuleName(info.getOwningFile())).orElseThrow(); + } + + private static String getModuleName(final IModFileInfo fileInfo) { + return fileInfo.getMods().isEmpty() ? fileInfo.getFile().getSecureJar().name() : fileInfo.getMods().getFirst().getModId(); } private void constructPlugin() { try { - LOGGER.trace(Logging.LOADING, "Loading plugin instance {} of type {}", getModId(), this.modClass.getName()); + LOGGER.trace(Logging.LOADING, "Loading plugin container {}", getModId()); - final ForgePluginContainer pluginContainer = ForgePluginContainer.of(this); - pluginContainer.metadata().dependencies().stream() + this.candidate.metadata().dependencies().stream() .filter(d -> d.loadOrder() == PluginDependency.LoadOrder.AFTER) .flatMap(d -> ModList.get().getModContainerById(d.id()).stream()) .filter(m -> m instanceof PluginModContainer) .forEach(m -> ((PluginModContainer) m).waitForInitialization()); ModList.get().forEachModInOrder(m -> { - if (m instanceof PluginModContainer p && ForgePluginContainer.of(m).metadata().dependencies().stream() + if (m instanceof PluginModContainer p && p.candidate.metadata().dependencies().stream() .anyMatch(d -> d.id().equals(this.getModId()) && d.loadOrder() == PluginDependency.LoadOrder.BEFORE)) { p.waitForInitialization(); } }); - final Injector pluginInjector = PluginGuice.create(pluginContainer, this.modClass, Launch.instance().lifecycle().platformInjector()); - this.modInstance = pluginInjector.getInstance(this.modClass); - pluginContainer.setInjector(pluginInjector); - Sponge.eventManager().registerListeners(pluginContainer, this.modInstance); - - LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), this.modClass.getName()); + this.container = this.candidate.load(); + LOGGER.trace(Logging.LOADING, "Loaded plugin container {}", getModId()); this.initializationLock.countDown(); - } catch (Throwable e) { - LOGGER.error(Logging.LOADING, "Failed to create plugin instance. PluginID: {}, class {}", getModId(), this.modClass.getName(), e); - throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, this.modClass); + } catch (Exception e) { + LOGGER.error(Logging.LOADING, "Failed to create plugin container {}.", getModId(), e); + throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e); } try { LOGGER.trace(Logging.LOADING, "Injecting Automatic event subscribers for {}", getModId()); - AutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.getClassLoader()); + AutomaticEventSubscriber.inject(this, this.scanData, this.module.getClassLoader()); LOGGER.trace(Logging.LOADING, "Completed Automatic event subscribers for {}", getModId()); } catch (Throwable e) { - LOGGER.error(Logging.LOADING, "Failed to register automatic subscribers. PluginID: {}, class {}", getModId(), this.modClass.getName(), e); - throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, this.modClass); + LOGGER.error(Logging.LOADING, "Failed to register automatic subscribers. ModID: {}", getModId(), e); + throw new ModLoadingException(this.modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e); } } @Override public boolean matches(Object mod) { - return mod == this.modInstance; + return mod == this.container.instance(); } @Override public Object getMod() { - return this.modInstance; + return this.container.instance(); } + @SuppressWarnings("unchecked") @Override protected void acceptEvent(final T e) { try { LOGGER.trace(Logging.LOADING, "Firing event for modid {} : {}", this.getModId(), e); - IModBusEvent.getBus(this.eventBusGroup, (Class) e.getClass()).post(e); + IModBusEvent.getBus(this.busGroup, (Class) e.getClass()).post(e); LOGGER.trace(Logging.LOADING, "Fired event for modid {} : {}", this.getModId(), e); } catch (Throwable t) { LOGGER.error(Logging.LOADING, "Caught exception during event {} dispatch for modid {}", e, this.getModId(), t); @@ -140,7 +142,11 @@ protected void acceptEvent(final T e) { @Override public void dispatchConfigEvent(final IConfigEvent event) { - EventBus.create(this.eventBusGroup, event.self().getClass()).post(event.self()); + EventBus.create(this.busGroup, event.self().getClass()).post(event.self()); + } + + public Optional container() { + return Optional.ofNullable(this.container); } private void waitForInitialization() { diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java deleted file mode 100644 index 764bcb25fe0..00000000000 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery.locator; - -import net.neoforged.neoforgespi.ILaunchContext; -import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; -import net.neoforged.neoforgespi.locating.IModFileCandidateLocator; -import net.neoforged.neoforgespi.locating.IncompatibleFileReporting; -import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Stream; - -public final class EnvironmentPluginLocator implements IModFileCandidateLocator { - - @Override - public void findCandidates(final ILaunchContext context, final IDiscoveryPipeline pipeline) { - final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); - for (final Path[] paths : EnvironmentPluginLocator.getPluginsPaths()) { - pipeline.addPath(Arrays.asList(paths), attributes, IncompatibleFileReporting.WARN_ON_KNOWN_INCOMPATIBILITY); - } - } - - @Override - public String toString() { - return "environment plugin"; - } - - private static List getPluginsPaths() { - final String env = System.getenv("SPONGE_PLUGINS"); - if (env == null) { - return Collections.emptyList(); - } - - List plugins = new ArrayList<>(); - for (final String entry : env.split(";")) { - if (entry.isBlank()) { - continue; - } - plugins.add(Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new)); - } - - return plugins; - } -} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java deleted file mode 100644 index b6ad0452b43..00000000000 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery.locator; - -import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.fml.loading.moddiscovery.locators.ModsFolderLocator; -import net.neoforged.neoforgespi.ILaunchContext; -import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; -import net.neoforged.neoforgespi.locating.IModFileCandidateLocator; -import org.spongepowered.common.applaunch.AppLaunch; - -import java.nio.file.Path; -import java.util.List; - -public final class PluginsDirectoryLocator implements IModFileCandidateLocator { - - @Override - public void findCandidates(final ILaunchContext context, final IDiscoveryPipeline pipeline) { - final List pluginDirectories = AppLaunch.pluginPlatform().pluginDirectories(); - for (final Path pluginDirectory : pluginDirectories) { - if (pluginDirectory != FMLPaths.MODSDIR.get()) { - new ModsFolderLocator(pluginDirectory, "plugins directory").findCandidates(context, pipeline); - } - } - } - - @Override - public String toString() { - return "plugins directory"; - } -} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java deleted file mode 100644 index 846eb87582c..00000000000 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileParser.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader; - -import net.neoforged.fml.jarcontents.JarContents; -import net.neoforged.fml.jarcontents.JarResource; -import net.neoforged.fml.loading.moddiscovery.ModFile; -import net.neoforged.fml.loading.moddiscovery.ModFileInfo; -import net.neoforged.fml.loading.moddiscovery.ModJarMetadata; -import net.neoforged.neoforgespi.language.IModFileInfo; -import net.neoforged.neoforgespi.locating.IModFile; -import net.neoforged.neoforgespi.locating.InvalidModFileException; -import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.applaunch.metadata.PluginMetadataFixer; -import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; -import org.spongepowered.neoforge.applaunch.loading.metadata.PluginFileConfigurable; -import org.spongepowered.plugin.metadata.builtin.MetadataContainer; -import org.spongepowered.plugin.metadata.builtin.MetadataParser; - -import java.io.Reader; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Optional; - -public final class PluginFileParser { - - @SuppressWarnings("UnstableApiUsage") - private static IModFileInfo parsePluginMetadata(final IModFile modFile) throws InvalidModFileException { - final JarResource metadataFile = modFile.getContents().get(PluginPlatformConstants.METADATA_FILE_LOCATION); - if (metadataFile == null) { - throw new InvalidModFileException("Plugin metadata not found", modFile.getModFileInfo()); - } - - try { - final MetadataContainer container; - try (final Reader reader = metadataFile.bufferedReader(StandardCharsets.UTF_8)) { - container = MetadataParser.read(reader); - } - - final PluginFileConfigurable config = new PluginFileConfigurable(PluginMetadataFixer.fixPluginIds(container), modFile.getContents().getManifest()); - return new ModFileInfo((ModFile) modFile, config, (info) -> {}, List.of()); - } catch (final Exception e) { - AppLaunch.logger().warn("Could not read metadata for plugin file '{}'", modFile, e); - throw new InvalidModFileException("Could not read plugin metadata", modFile.getModFileInfo()); - } - } - - public static IModFile newPluginInstance(final JarContents contents, final ModFileDiscoveryAttributes attributes) { - AppLaunch.logger().debug("Considering plugin file candidate {}", contents.getPrimaryPath()); - - final Optional metadataFile = contents.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION); - if (metadataFile.isEmpty()) { - AppLaunch.logger().debug("Plugin file '{}' is missing a 'sponge_plugins.json' metadata file in META-INF", contents.getPrimaryPath()); - return null; - } - - final ModJarMetadata mjm = new ModJarMetadata(); - final IModFile modFile = new ModFile(contents, mjm, PluginFileParser::parsePluginMetadata, attributes); - mjm.setModFile(modFile); - return modFile; - } - - private PluginFileParser() { - } -} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java new file mode 100644 index 00000000000..396b738152c --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java @@ -0,0 +1,70 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.mod.discovery; + +import net.neoforged.fml.jarcontents.JarContents; +import net.neoforged.fml.loading.moddiscovery.ModFile; +import net.neoforged.fml.loading.moddiscovery.ModFileInfo; +import net.neoforged.fml.loading.moddiscovery.ModJarMetadata; +import net.neoforged.neoforgespi.language.IModFileInfo; +import net.neoforged.neoforgespi.locating.IModFile; +import net.neoforged.neoforgespi.locating.IModFileReader; +import net.neoforged.neoforgespi.locating.InvalidModFileException; +import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.neoforge.applaunch.mod.metadata.PluginFileConfigurable; +import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; +import org.spongepowered.plugin.discovery.PluginResource; + +import java.util.List; + +@SuppressWarnings("UnstableApiUsage") +public class PluginFileReader implements IModFileReader { + @Override + public @Nullable IModFile read(final JarContents jar, final ModFileDiscoveryAttributes attributes) { + final PluginResource resource = new JarContentsPluginResource(jar); + final PluginDiscovery.Candidate candidate = AppLaunch.pluginPlatform().discovery().candidate(resource); + candidate.readMetadata(); + if (!candidate.pluginFound()) { + return null; + } + final PluginFileConfigurable config = new PluginFileConfigurable(resource, candidate.metadata()); + final ModJarMetadata mjm = new ModJarMetadata(); + final IModFile modFile = new ModFile(jar, mjm, file -> newModFileInfo(file, config), attributes); + mjm.setModFile(modFile); + return modFile; + } + + @Override + public String toString() { + return "sponge manifest"; + } + + private static IModFileInfo newModFileInfo(final IModFile file, final PluginFileConfigurable config) throws InvalidModFileException { + return new ModFileInfo((ModFile) file, config, (info) -> {}, List.of()); + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java similarity index 57% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java index 1de9c31e1ce..aadde5e3b22 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/JavaPluginLanguageProvider.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.plugin; +package org.spongepowered.neoforge.applaunch.mod.discovery; import net.neoforged.fml.Logging; import net.neoforged.fml.ModContainer; @@ -33,52 +33,32 @@ import net.neoforged.neoforgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.objectweb.asm.Type; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.NoSuchElementException; -public final class JavaPluginLanguageProvider extends BuiltInLanguageLoader { +public final class SpongeLanguageLoader extends BuiltInLanguageLoader { private static final Logger LOGGER = LogManager.getLogger(); - private static final Type PLUGIN_ANNOTATION = Type.getType("Lorg/spongepowered/plugin/builtin/jvm/Plugin;"); @Override public String name() { - return "java_plain"; + return "sponge"; } @Override - public ModContainer loadMod(final IModInfo info, final ModFileScanData modFileScanResults, final ModuleLayer layer) { - final var modClasses = modFileScanResults.getAnnotations().stream() - .filter(ad -> ad.annotationType().equals(JavaPluginLanguageProvider.PLUGIN_ANNOTATION)) - .peek(ad -> LOGGER.debug(Logging.SCAN, "Found @Plugin class {} with id {}", ad.clazz().getClassName(), ad.annotationData().get("value"))) - .filter(data -> JavaPluginLanguageProvider.fixPluginId((String) data.annotationData().get("value")).equals(info.getModId())) - .map(ad -> ad.clazz().getClassName()) - .toList(); - - if (modClasses.size() != 1) { - throw new ModLoadingException(ModLoadingIssue.error("Found {0} plugin entrypoints", modClasses.size())); - } - return JavaPluginLanguageProvider.newPluginModContainer(info, modClasses.get(0), modFileScanResults, layer); - } - - private static ModContainer newPluginModContainer(final IModInfo info, final String className, final ModFileScanData modFileScanData, final ModuleLayer gameLayer) { + public ModContainer loadMod(final IModInfo info, final ModFileScanData scanData, final ModuleLayer layer) { try { - final Module module = gameLayer.findModule("spongeneo").orElseThrow(() -> new NoSuchElementException("Module spongeneo")); + final Module module = layer.findModule("spongeneo").orElseThrow(() -> new NoSuchElementException("Module spongeneo")); final Class containerClass = Class.forName(module, "org.spongepowered.neoforge.launch.plugin.PluginModContainer"); - final Constructor constructor = containerClass.getConstructor(IModInfo.class, String.class, ModFileScanData.class, ModuleLayer.class); - return (ModContainer) constructor.newInstance(info, className, modFileScanData, gameLayer); + final Constructor constructor = containerClass.getConstructor(IModInfo.class, ModFileScanData.class, ModuleLayer.class); + return (ModContainer) constructor.newInstance(info, scanData, layer); } catch (final InvocationTargetException e) { - LOGGER.fatal(Logging.LOADING, "Failed to build plugin", e); + SpongeLanguageLoader.LOGGER.fatal(Logging.LOADING, "Failed to build plugin", e); throw new ModLoadingException(ModLoadingIssue.error("Failed to build plugin")); } catch (final Exception e) { - LOGGER.fatal(Logging.LOADING, "Unable to load PluginModContainer", e); + SpongeLanguageLoader.LOGGER.fatal(Logging.LOADING, "Unable to load PluginModContainer", e); throw new ModLoadingException(ModLoadingIssue.error("Unable to load PluginModContainer")); } } - - private static String fixPluginId(final String id) { - return id.replace('-', '_'); - } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoDependencyLocator.java similarity index 96% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoDependencyLocator.java index 21e9d21d1e3..af1a969c1a1 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoDependencyLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoDependencyLocator.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery; +package org.spongepowered.neoforge.applaunch.mod.discovery; import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; @@ -36,7 +36,7 @@ import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.libs.LibraryManager; -import org.spongepowered.neoforge.applaunch.loading.moddiscovery.library.Log4JLogger; +import org.spongepowered.neoforge.applaunch.mod.discovery.library.Log4JLogger; import java.io.IOException; import java.nio.file.Path; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java similarity index 65% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index 15f591911cc..475b60cd5c4 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -22,9 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery; +package org.spongepowered.neoforge.applaunch.mod.discovery; -import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; @@ -36,10 +35,12 @@ import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.neoforge.applaunch.plugin.NeoForgePluginPlatform; +import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.neoforge.applaunch.plugin.NeoPluginPlatform; +import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; +import org.spongepowered.neoforge.applaunch.plugin.discovery.NeoPluginDiscovery; -import java.io.File; -import java.io.IOException; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; @@ -47,47 +48,66 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; -import java.util.stream.Stream; public final class SpongeNeoModLocator implements IModFileCandidateLocator { private static final Logger LOGGER = LogManager.getLogger(); + private final NeoPluginDiscovery discovery; + public SpongeNeoModLocator() { - NeoForgePluginPlatform.bootstrap(); + this.discovery = AppLaunch.bootstrap(NeoPluginPlatform::new).discovery(); + this.discovery.discoverPluginResources(); } @Override public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) { final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); - if (!FMLEnvironment.isProduction()) { - final String resourcesProp = System.getProperty("sponge.resources"); - if (resourcesProp != null) { - for (final String entry : resourcesProp.split(File.pathSeparator)) { - if (entry.isBlank()) { - continue; - } + for (final PluginDiscovery.Candidate candidate : this.discovery.candidates()) { + if (candidate.resource() instanceof JarContentsPluginResource resource) { + // skip duplicates + if (!context.addLocated(resource.path())) { + candidate.setModFound(); + candidate.logResult(); + continue; + } - final JarContents jarContents; - try { - jarContents = JarContents.ofPaths(Stream.of(entry.split("&")).map(Path::of).toList()); - } catch (IOException e) { - LOGGER.error("Failed to create jar contents from {}", entry, e); - continue; - } + // attempt to load as mod or plugin + IModFile modFile = null; + try { + modFile = pipeline.readModFile(resource.jar(), attributes); + } catch (Exception ignored) {} - IModFile modFile = null; - try { - // attempt to load as mod or plugin - modFile = pipeline.readModFile(jarContents, attributes); - } catch (Exception ignored) {} - if (modFile == null) { - // fallback to game library - modFile = IModFile.create(jarContents, JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes); + if (modFile == null) { + // determine fallback type + IModFile.Type type = null; + switch (candidate.loading()) { + case IGNORED: + candidate.logResult(); + continue; + case LIBRARY: + type = IModFile.Type.LIBRARY; + break; + case GAME_LIBRARY: + type = IModFile.Type.GAMELIBRARY; + break; } - pipeline.addModFile(modFile); + modFile = IModFile.create(resource.jar(), JarModsDotTomlModFileReader::manifestParser, type, attributes); + } else if (!candidate.pluginFound()) { + candidate.setModFound(); } + + pipeline.addModFile(modFile); } + + // TODO else: Neo can only loads jar mods, do we make a dummy jar? + + candidate.logResult(); + } + + this.discovery.logMetadataWarnings(); + + if (!FMLEnvironment.isProduction()) { return; } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/library/Log4JLogger.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/library/Log4JLogger.java similarity index 96% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/library/Log4JLogger.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/library/Log4JLogger.java index efac9b34303..0d5c7c61cc7 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/library/Log4JLogger.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/library/Log4JLogger.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery.library; +package org.spongepowered.neoforge.applaunch.mod.discovery.library; import org.spongepowered.libs.Logger; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginDependencyConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java similarity index 91% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginDependencyConfigurable.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java index 9f0996dce7e..b198266cdce 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginDependencyConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java @@ -22,11 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.metadata; +package org.spongepowered.neoforge.applaunch.mod.metadata; import net.neoforged.neoforgespi.language.IConfigurable; import net.neoforged.neoforgespi.language.IModInfo; -import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginDependency; import java.util.Collections; @@ -36,11 +35,9 @@ // ModVersion public final class PluginDependencyConfigurable implements IConfigurable { - private final PluginMetadata metadata; private final PluginDependency dependency; - public PluginDependencyConfigurable(final PluginMetadata metadata, final PluginDependency dependency) { - this.metadata = metadata; + public PluginDependencyConfigurable(final PluginDependency dependency) { this.dependency = dependency; } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java similarity index 59% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java index a9be2b962f1..40deaa2c37c 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -22,29 +22,25 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.metadata; +package org.spongepowered.neoforge.applaunch.mod.metadata; import net.neoforged.neoforgespi.language.IConfigurable; +import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import org.spongepowered.plugin.metadata.builtin.MetadataContainer; -import org.spongepowered.plugin.metadata.model.PluginDependency; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.jar.Manifest; +import java.util.*; +import java.util.stream.Collectors; // ModFileInfo public final class PluginFileConfigurable implements IConfigurable { + private final Map plugins = new LinkedHashMap<>(); + private final PluginResource resource; - private final MetadataContainer container; - private final Manifest manifest; - - public PluginFileConfigurable(final MetadataContainer container, final Manifest manifest) { - this.container = container; - this.manifest = manifest; + public PluginFileConfigurable(final PluginResource resource, final Collection plugins) { + for (final PluginMetadata plugin : plugins) { + this.plugins.put(plugin.id(), plugin); + } + this.resource = resource; } @SuppressWarnings("unchecked") @@ -59,27 +55,28 @@ public Optional getConfigElement(final String... key) { return Optional.empty(); } - if ("modLoader".equals(query)) { - return (Optional) Optional.of(this.container.loader().name()); + if ("spongeResource".equals(query)) { + return Optional.of((T) this.resource); } - if ("loaderVersion".equals(query)) { - return (Optional) Optional.of(this.container.loader().version().toString()); + if ("modLoader".equals(query)) { + return Optional.of((T) "sponge"); } if ("license".equals(query)) { - return (Optional) Optional.of(this.container.license()); + return Optional.of((T) this.plugins.values().stream() + .map(m -> m.container().license()).distinct().collect(Collectors.joining(", "))); } if (key.length == 2) { final String plugin = key[1]; - final PluginMetadata metadata = this.container.metadata(plugin).orElse(null); + final PluginMetadata metadata = this.plugins.get(plugin); if (metadata == null) { return Optional.empty(); } if ("modproperties".equals(query)) { - return (Optional) Optional.of(metadata.properties()); + return Optional.of((T) metadata.properties()); } } @@ -98,24 +95,17 @@ public List getConfigList(final String... key) { } if ("mods".equals(query)) { - final Set metadataById = this.container.metadata(); - if (metadataById.isEmpty()) { - return Collections.emptyList(); - } - - final List metadataConfigurables = new ArrayList<>(); - metadataById.forEach((metadata) -> metadataConfigurables.add(new PluginMetadataConfigurable(metadata))); - return metadataConfigurables; + return this.plugins.values().stream().map(PluginMetadataConfigurable::new).toList(); } if ("mixins".equals(query)) { - final String mixinConfigs = this.manifest.getMainAttributes().getValue("MixinConfigs"); - if (mixinConfigs == null) { + final Optional mixinConfigs = this.resource.property("MixinConfigs"); + if (mixinConfigs.isEmpty()) { return Collections.emptyList(); } final List mixinConfigurables = new ArrayList<>(); - for (final String config : mixinConfigs.split(",")) { + for (final String config : mixinConfigs.get().split(",")) { mixinConfigurables.add(new PluginMixinConfigurable(config.trim())); } return mixinConfigurables; @@ -125,24 +115,14 @@ public List getConfigList(final String... key) { return Collections.emptyList(); } - final String plugin = key[1]; - final PluginMetadata metadata = this.container.metadata(plugin).orElse(null); + final String pluginId = key[1]; + final PluginMetadata metadata = this.plugins.get(pluginId); if (metadata == null) { return Collections.emptyList(); } if ("dependencies".equals(query)) { - final Set dependencies = metadata.dependencies(); - if (dependencies.isEmpty()) { - return Collections.emptyList(); - } - - final List depConfigurables = new ArrayList<>(); - for (final PluginDependency dependency : dependencies) { - depConfigurables.add(new PluginDependencyConfigurable(metadata, dependency)); - } - - return depConfigurables; + return metadata.dependencies().stream().map(PluginDependencyConfigurable::new).toList(); } return Collections.emptyList(); @@ -152,7 +132,6 @@ private int requiredConfigElements(final String query) { if ("dependencies".equals(query) || "modproperties".equals(query)) { return 2; } - return 1; } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMetadataConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMetadataConfigurable.java similarity index 88% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMetadataConfigurable.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMetadataConfigurable.java index 9baa86ce681..02964711caa 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMetadataConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMetadataConfigurable.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.metadata; +package org.spongepowered.neoforge.applaunch.mod.metadata; import net.neoforged.neoforgespi.language.IConfigurable; import org.spongepowered.plugin.metadata.PluginMetadata; @@ -32,13 +32,7 @@ import java.util.Optional; // ModInfo -public final class PluginMetadataConfigurable implements IConfigurable { - - private final PluginMetadata metadata; - - public PluginMetadataConfigurable(final PluginMetadata metadata) { - this.metadata = metadata; - } +public record PluginMetadataConfigurable(PluginMetadata metadata) implements IConfigurable { @SuppressWarnings("unchecked") @Override @@ -53,6 +47,7 @@ public Optional getConfigElement(final String... key) { case "displayName" -> (Optional) this.metadata.name(); case "description" -> (Optional) this.metadata.description(); case "displayTest" -> Optional.of((T) "IGNORE_SERVER_VERSION"); + case "spongeMetadata" -> Optional.of((T) this.metadata); default -> Optional.empty(); }; } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java similarity index 96% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java index e524434e472..fc9612029c9 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/metadata/PluginMixinConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.metadata; +package org.spongepowered.neoforge.applaunch.mod.metadata; import net.neoforged.neoforgespi.language.IConfigurable; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java similarity index 52% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java index 3c1204b3ea8..a547f7cdd0d 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoForgePluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java @@ -27,51 +27,21 @@ import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.common.NeoForgeVersion; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.common.applaunch.config.LaunchConfig; -import org.spongepowered.common.applaunch.config.TokenReplacement; import org.spongepowered.common.applaunch.plugin.PluginPlatform; +import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; +import org.spongepowered.neoforge.applaunch.plugin.discovery.NeoPluginDiscovery; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; -public final class NeoForgePluginPlatform implements PluginPlatform { +public final class NeoPluginPlatform extends PluginPlatform { + private final NeoPluginDiscovery discovery; - private static volatile boolean bootstrapped; - - private final LaunchConfig config; - private final TokenReplacement tokens; - private final List pluginDirectories; - - public static synchronized void bootstrap() { - if (NeoForgePluginPlatform.bootstrapped) { - return; - } - NeoForgePluginPlatform.bootstrapped = true; - final NeoForgePluginPlatform platform; - try { - platform = new NeoForgePluginPlatform(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - AppLaunch.setPluginPlatform(platform); - } - - private NeoForgePluginPlatform() throws IOException { - this.config = LaunchConfig.load(this.baseDirectory(), true); - - this.tokens = new TokenReplacement(); - this.tokens.register("BASE_DIR", this.baseDirectory()); - this.tokens.register("CONFIG_DIR", this.configDirectory()); - this.tokens.register("MODS_DIR", FMLPaths.MODSDIR.get()); - - final Path additionalPluginsDirectory = Path.of(this.tokens.replace(this.config.additionalPluginsDirectory())); - Files.createDirectories(additionalPluginsDirectory); - this.pluginDirectories = List.of(FMLPaths.MODSDIR.get(), additionalPluginsDirectory); + public NeoPluginPlatform() { + this.discovery = new NeoPluginDiscovery(this.environment()); } + @SuppressWarnings("UnstableApiUsage") @Override public String version() { return NeoForgeVersion.getVersion(); @@ -93,22 +63,22 @@ public Path configDirectory() { } @Override - public LaunchConfig config() { - return this.config; + public Path modsDirectory() { + return FMLPaths.MODSDIR.get(); } @Override - public TokenReplacement tokens() { - return this.tokens; + public NeoPluginDiscovery discovery() { + return this.discovery; } @Override - public List pluginDirectories() { - return this.pluginDirectories; + public JVMPluginResource create(final Path[] paths) { + return new JarContentsPluginResource(paths); } @Override - public void addLoaderCloseCallback(AutoCloseable closeable) { + public void addLoaderCloseCallback(final AutoCloseable closeable) { FMLLoader.getCurrent().addCloseCallback(closeable); } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java new file mode 100644 index 00000000000..67a9d75d70b --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java @@ -0,0 +1,108 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.plugin.discovery; + +import net.neoforged.fml.jarcontents.JarContents; +import net.neoforged.fml.jarmoduleinfo.JarModuleInfo; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor; +import java.net.URI; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.jar.Manifest; + +public final class JarContentsPluginResource implements SpongeJVMPluginResource { + private final Path[] paths; + private final JarContents jar; + + public JarContentsPluginResource(final Path[] paths) { + Objects.requireNonNull(paths, "paths"); + if (paths.length == 0) { + throw new IllegalArgumentException("Need at least one path"); + } + this.paths = paths; + try { + this.jar = JarContents.ofPaths(Arrays.asList(paths)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public JarContentsPluginResource(final JarContents jar) { + Objects.requireNonNull(jar, "jar"); + this.paths = jar.getContentRoots().toArray(new Path[0]); + this.jar = jar; + } + + public JarContents jar() { + return this.jar; + } + + @Override + public Path path() { + return this.jar.getPrimaryPath(); + } + + @Override + public Optional locateResource(String path) { + return this.jar.findFile(path); + } + + @Override + public Manifest manifest() { + return this.jar.getManifest(); + } + + @Override + public ModuleDescriptor module() { + return JarModuleInfo.from(this.jar).createDescriptor(this.jar); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof JarContentsPluginResource that)) { + return false; + } + return Arrays.equals(this.paths, that.paths); + } + + @Override + public int hashCode() { + return Arrays.hashCode(this.paths); + } + + @Override + public String toString() { + return "JarContentsPluginResource[paths=" + Arrays.toString(this.paths) + "]"; + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java new file mode 100644 index 00000000000..cc054cd2488 --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java @@ -0,0 +1,74 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.plugin.discovery; + +import net.neoforged.fml.jarcontents.CompositeJarContents; +import net.neoforged.fml.jarcontents.JarContents; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; +import org.spongepowered.plugin.Environment; + +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +public class NeoPluginDiscovery extends PluginDiscovery { + private ClassLoader currentLoader; + + public NeoPluginDiscovery(Environment environment) { + super(environment); + this.currentLoader = getClass().getClassLoader(); + } + + @Override + protected ServiceLoader newServiceLoader(final Class serviceClass) { + return ServiceLoader.load(serviceClass, this.currentLoader); + } + + @SuppressWarnings("UnstableApiUsage") + @Override + protected void appendDiscoveryServices(final List resources, final int batch) throws Exception { + final ClassLoader parentLoader = this.currentLoader; + + // See FMLLoader#appendLoader + final List rootUrls = new ArrayList<>(resources.size()); + for (final SpongeJVMPluginResource resource : resources) { + final JarContents jar = ((JarContentsPluginResource) resource).jar(); + if (jar instanceof final CompositeJarContents compositeJar && compositeJar.isFiltered()) { + throw new IllegalArgumentException("Cannot use simple URLClassLoader for filtered content " + jar); + } + for (final Path contentRoot : jar.getContentRoots()) { + rootUrls.add(contentRoot.toUri().toURL()); + } + } + + final ClassLoader loader = new URLClassLoader("SPONGE-DISCOVERY-BATCH-" + batch, rootUrls.toArray(URL[]::new), parentLoader); + this.currentLoader = loader; + this.environment.logger().debug("Built new service layer {} on top of {}.", loader.getName(), parentLoader.getName()); + } +} diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader index 135fde603ee..226127c74e5 100644 --- a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.language.IModLanguageLoader @@ -1 +1 @@ -org.spongepowered.neoforge.applaunch.plugin.JavaPluginLanguageProvider +org.spongepowered.neoforge.applaunch.mod.discovery.SpongeLanguageLoader diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator index 386ebb032d7..33c4820c8c1 100644 --- a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator @@ -1 +1 @@ -org.spongepowered.neoforge.applaunch.loading.moddiscovery.SpongeNeoDependencyLocator \ No newline at end of file +org.spongepowered.neoforge.applaunch.mod.discovery.SpongeNeoDependencyLocator \ No newline at end of file diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator index c92ba9dda26..9f21f501e4f 100644 --- a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator @@ -1,3 +1 @@ -org.spongepowered.neoforge.applaunch.loading.moddiscovery.SpongeNeoModLocator -org.spongepowered.neoforge.applaunch.loading.moddiscovery.locator.EnvironmentPluginLocator -org.spongepowered.neoforge.applaunch.loading.moddiscovery.locator.PluginsDirectoryLocator \ No newline at end of file +org.spongepowered.neoforge.applaunch.mod.discovery.SpongeNeoModLocator diff --git a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileReader b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileReader index 58be04367a6..2770e5f95dc 100644 --- a/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileReader +++ b/neoforge/src/applaunch/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileReader @@ -1 +1 @@ -org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader.PluginFileReader \ No newline at end of file +org.spongepowered.neoforge.applaunch.mod.discovery.PluginFileReader \ No newline at end of file diff --git a/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator new file mode 100644 index 00000000000..93a6e7f4172 --- /dev/null +++ b/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -0,0 +1 @@ +org.spongepowered.common.applaunch.plugin.discovery.SpongePropertyResourceLocator diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java index 6448d458d87..31371283ccf 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java @@ -25,12 +25,12 @@ package org.spongepowered.neoforge.launch.plugin; import com.google.common.collect.MapMaker; -import com.google.inject.Injector; import net.neoforged.fml.ModContainer; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.moddiscovery.ModInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.common.launch.plugin.SpongePluginContainer; +import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.metadata.PluginMetadata; import java.net.URI; @@ -38,16 +38,17 @@ import java.util.Objects; import java.util.Optional; -public class NeoPluginContainer implements SpongePluginContainer { +public class NeoPluginContainer implements PluginContainer { private final ModContainer modContainer; + private final JarContents jar; + private final Object instance = new Object(); private Logger logger; private PluginMetadata pluginMetadata; - private Object instance = new Object(); - private Injector injector; private NeoPluginContainer(final ModContainer modContainer) { this.modContainer = modContainer; + this.jar = modContainer.getModInfo().getOwningFile().getFile().getContents(); } @Override @@ -67,8 +68,8 @@ public Logger logger() { } @Override - public Optional locateResource(String relative) { - return this.modContainer.getModInfo().getOwningFile().getFile().getContents().findFile(Objects.requireNonNull(relative, "relative")); + public Optional locateResource(final String relative) { + return this.jar.findFile(Objects.requireNonNull(relative, "relative")); } @Override @@ -76,22 +77,12 @@ public Object instance() { return this.instance; } - public void setInstance(final Object instance) { - this.instance = instance; - } - - @Override - public Optional injector() { - return Optional.ofNullable(this.injector); - } + private static final Map mods = new MapMaker().weakKeys().makeMap(); - public void setInjector(final Injector injector) { - this.injector = injector; - } - - private static final Map containers = new MapMaker().weakKeys().makeMap(); - - public static NeoPluginContainer of(final ModContainer modContainer) { - return containers.computeIfAbsent(modContainer, NeoPluginContainer::new); + public static Optional of(final ModContainer modContainer) { + if (modContainer instanceof PluginModContainer plugin) { + return plugin.container(); + } + return Optional.of(NeoPluginContainer.mods.computeIfAbsent(modContainer, NeoPluginContainer::new)); } } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java index 538ae3e9f4b..4c7c1897549 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java @@ -41,9 +41,9 @@ public final class NeoPluginManager implements SpongePluginManager { @Override public Optional fromInstance(final Object instance) { for (final ModContainer mod : ModList.get().getSortedMods()) { - final NeoPluginContainer plugin = NeoPluginContainer.of(mod); - if (plugin.instance() == instance) { - return Optional.of(plugin); + final Optional plugin = NeoPluginContainer.of(mod); + if (plugin.isPresent() && plugin.get().instance() == instance) { + return plugin; } } return Optional.empty(); @@ -51,13 +51,13 @@ public Optional fromInstance(final Object instance) { @Override public Optional plugin(final String id) { - return ModList.get().getModContainerById(Objects.requireNonNull(id, "id")).map(NeoPluginContainer::of); + return ModList.get().getModContainerById(Objects.requireNonNull(id, "id")).flatMap(NeoPluginContainer::of); } @Override public Collection plugins() { final ImmutableList.Builder builder = ImmutableList.builder(); - ModList.get().forEachModInOrder(mod -> builder.add(NeoPluginContainer.of(mod))); + ModList.get().forEachModInOrder(mod -> NeoPluginContainer.of(mod).ifPresent(builder::add)); return builder.build(); } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java index 4ad12384a0a..34b1983f53e 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java @@ -28,13 +28,13 @@ import net.neoforged.neoforgespi.language.IModInfo; import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginContributor; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginDependency; -import org.spongepowered.plugin.metadata.builtin.model.StandardPluginLinks; +import org.spongepowered.plugin.metadata.model.PluginContributor; import org.spongepowered.plugin.metadata.model.PluginDependency; +import org.spongepowered.plugin.metadata.model.PluginLinks; -import java.util.ArrayList; -import java.util.List; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Optional; public final class PluginMetadataConverter { @@ -46,22 +46,22 @@ public static PluginMetadata modToPlugin(final ModInfo info) { .version(info.getVersion().toString()) .description(info.getDescription()) .entrypoint("unknown") - .addContributor(StandardPluginContributor.builder().name(info.getConfigElement("authors").orElse("unknown").toString()).build()) - .links(StandardPluginLinks.builder().issues(info.getOwningFile().getIssueURL()).build()) + .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); - final List dependencies = new ArrayList<>(); - for (final IModInfo.ModVersion dependency : info.getDependencies()) { - final StandardPluginDependency.Builder depBuilder = StandardPluginDependency.builder(); - depBuilder - .id(dependency.getModId()) - .loadOrder(PluginMetadataConverter.orderingToLoad(dependency.getOrdering())) - .version(dependency.getVersionRange().toString()); + try { + final URL issueURL = info.getOwningFile().getIssueURL(); + builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); + } catch (URISyntaxException ignored) {} - dependencies.add(depBuilder.build()); + for (final IModInfo.ModVersion dependency : info.getDependencies()) { + builder.addDependency(new PluginDependency( + dependency.getModId(), + dependency.getVersionRange(), + PluginMetadataConverter.orderingToLoad(dependency.getOrdering()), + false + )); } - - builder.dependencies(dependencies); return builder.build(); } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java index 585e0129a5e..dc8886ce029 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginModContainer.java @@ -24,7 +24,6 @@ */ package org.spongepowered.neoforge.launch.plugin; -import com.google.inject.Injector; import net.neoforged.bus.EventBusErrorMessage; import net.neoforged.bus.api.BusBuilder; import net.neoforged.bus.api.Event; @@ -32,53 +31,48 @@ import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.Logging; import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.ModLoadingException; import net.neoforged.fml.ModLoadingIssue; import net.neoforged.fml.event.IModBusEvent; import net.neoforged.fml.javafmlmod.AutomaticEventSubscriber; -import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforgespi.language.IModInfo; import net.neoforged.neoforgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.common.inject.plugin.PluginGuice; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.common.launch.Launch; -import org.spongepowered.neoforge.launch.event.NeoEventManager; +import org.spongepowered.common.launch.plugin.loader.PluginCandidate; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; -import java.lang.reflect.InvocationTargetException; +import java.util.Optional; -// Spongified FMLModContainer public final class PluginModContainer extends ModContainer { private static final Logger LOGGER = LogManager.getLogger(); - private final ModFileScanData scanResults; - private final IEventBus eventBus; - private final Class modClass; + private final PluginCandidate candidate; private final Module module; - public PluginModContainer(IModInfo info, String className, ModFileScanData modFileScanResults, ModuleLayer gameLayer) { + private final ModFileScanData scanData; + private final IEventBus eventBus; + + private @MonotonicNonNull PluginContainer container; + + public PluginModContainer(final IModInfo info, final ModFileScanData scanData, final ModuleLayer layer) { super(info); - LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", className); - this.scanResults = modFileScanResults; + LOGGER.debug(Logging.LOADING, "Creating PluginModContainer instance for {}", info.getModId()); + this.scanData = scanData; this.eventBus = BusBuilder.builder() .setExceptionHandler(this::onEventFailed) .markerType(IModBusEvent.class) .allowPerPhasePost() .build(); - this.module = gameLayer.findModule(info.getOwningFile().getFile().getId()).orElseThrow(); - ModLoadingContext context = ModLoadingContext.get(); - try { - context.setActiveContainer(this); - this.modClass = Class.forName(this.module, className); - LOGGER.trace(Logging.LOADING, "Loaded plugin class {} with {}", this.modClass.getName(), this.modClass.getClassLoader()); - } catch (Throwable e) { - LOGGER.error(Logging.LOADING, "Failed to load class {}", className, e); - throw new ModLoadingException(ModLoadingIssue.error("fml.modloadingissue.failedtoloadmodclass").withCause(e).withAffectedMod(info)); - } finally { - context.setActiveContainer(null); - } + final PluginResource resource = info.getOwningFile().getConfig().getConfigElement("spongeResource").get(); + final PluginMetadata metadata = info.getConfig().getConfigElement("spongeMetadata").get(); + this.candidate = Launch.instance().pluginFactory().create(resource, metadata); + this.module = layer.findModule(info.getOwningFile().getFile().getId()).orElseThrow(); } private void onEventFailed(IEventBus iEventBus, Event event, EventListener[] iEventListeners, int i, Throwable throwable) { @@ -88,31 +82,21 @@ private void onEventFailed(IEventBus iEventBus, Event event, EventListener[] iEv @Override protected void constructMod() { try { - LOGGER.trace(Logging.LOADING, "Loading plugin instance {} of type {}", getModId(), this.modClass.getName()); - - final NeoPluginContainer pluginContainer = NeoPluginContainer.of(this); - final Injector pluginInjector = PluginGuice.create(pluginContainer, this.modClass, Launch.instance().lifecycle().platformInjector()); - final Object modInstance = pluginInjector.getInstance(this.modClass); - pluginContainer.setInjector(pluginInjector); - pluginContainer.setInstance(modInstance); - ((NeoEventManager) NeoForge.EVENT_BUS).registerListeners(pluginContainer, modInstance); - - LOGGER.trace(Logging.LOADING, "Loaded plugin instance {} of type {}", getModId(), this.modClass.getName()); - } catch (Throwable e) { - if (e instanceof InvocationTargetException) { - e = e.getCause(); - } - LOGGER.error(Logging.LOADING, "Failed to create plugin instance. PluginID: {}, class {}", getModId(), this.modClass.getName(), e); - throw new ModLoadingException(ModLoadingIssue.error("fml.modloadingissue.failedtoloadmod").withCause(e).withAffectedMod(modInfo)); + LOGGER.trace(Logging.LOADING, "Loading plugin container {}", getModId()); + this.container = this.candidate.load(); + LOGGER.trace(Logging.LOADING, "Loaded plugin container {}", getModId()); + } catch (Exception e) { + LOGGER.error(Logging.LOADING, "Failed to create plugin container {}.", getModId(), e); + throw new ModLoadingException(ModLoadingIssue.error("fml.modloadingissue.failedtoloadmod").withCause(e).withAffectedMod(this.modInfo)); } try { LOGGER.trace(Logging.LOADING, "Injecting Automatic event subscribers for {}", getModId()); - AutomaticEventSubscriber.inject(this, this.scanResults, this.module); + AutomaticEventSubscriber.inject(this, this.scanData, this.module); LOGGER.trace(Logging.LOADING, "Completed Automatic event subscribers for {}", getModId()); } catch (Throwable e) { LOGGER.error(Logging.LOADING, "Failed to register automatic subscribers. ModID: {}", getModId(), e); - throw new ModLoadingException(ModLoadingIssue.error("fml.modloadingissue.failedtoloadmod").withCause(e).withAffectedMod(modInfo)); + throw new ModLoadingException(ModLoadingIssue.error("fml.modloadingissue.failedtoloadmod").withCause(e).withAffectedMod(this.modInfo)); } } @@ -120,4 +104,8 @@ protected void constructMod() { public IEventBus getEventBus() { return this.eventBus; } + + public Optional container() { + return Optional.ofNullable(this.container); + } } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/AppLaunch.java b/src/applaunch/java/org/spongepowered/common/applaunch/AppLaunch.java index 0bd1e86e0c5..dad59f26612 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/AppLaunch.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/AppLaunch.java @@ -28,6 +28,8 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.plugin.PluginPlatform; +import java.util.function.Supplier; + public final class AppLaunch { private static final Logger LOGGER = LogManager.getLogger("app launch"); @@ -37,12 +39,11 @@ public static Logger logger() { return AppLaunch.LOGGER; } - public static

P setPluginPlatform(final PluginPlatform pluginPlatform) { - if (AppLaunch.pluginPlatform != null) { - throw new RuntimeException("The plugin platform cannot be set twice! (Same classloader ?)"); + public static synchronized

P bootstrap(final Supplier

supplier) { + if (AppLaunch.pluginPlatform == null) { + AppLaunch.pluginPlatform = supplier.get(); } - AppLaunch.pluginPlatform = pluginPlatform; - return (P) pluginPlatform; + return (P) AppLaunch.pluginPlatform; } public static

P pluginPlatform() { diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/metadata/PluginMetadataFixer.java b/src/applaunch/java/org/spongepowered/common/applaunch/metadata/PluginMetadataFixer.java deleted file mode 100644 index 620837e2f2d..00000000000 --- a/src/applaunch/java/org/spongepowered/common/applaunch/metadata/PluginMetadataFixer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.common.applaunch.metadata; - -import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; -import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.plugin.metadata.PluginMetadata; -import org.spongepowered.plugin.metadata.builtin.MetadataContainer; -import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class PluginMetadataFixer { - private static final Set invalidPluginIds = new HashSet<>(); - - public static MetadataContainer fixPluginIds(final MetadataContainer container) { - boolean modified = false; - final List metadata = new ArrayList<>(); - - for (final PluginMetadata plugin : container.metadata()) { - final String id = plugin.id(); - if (id.indexOf('-') >= 0) { - final String newId = id.replace('-', '_'); - if (PluginMetadataFixer.invalidPluginIds.add(id)) { - AppLaunch.pluginPlatform().logger().warn("The dash character (-) is no longer supported in plugin ids.\n" + - "Plugin {} will be loaded as {}. If you are the developer of this plugin, please change the id.", id, newId); - } - - final StandardPluginMetadata.Builder pluginBuilder = StandardPluginMetadata.builder() - .from((StandardPluginMetadata) plugin).id(newId).entrypoint(plugin.entrypoint()); - plugin.name().ifPresent(pluginBuilder::name); - plugin.description().ifPresent(pluginBuilder::description); - - metadata.add(pluginBuilder.build()); - modified = true; - } else { - metadata.add((StandardPluginMetadata) plugin); - } - } - - if (!modified) { - return container; - } - - final MetadataContainer.Builder builder = container.toBuilder(); - builder.metadata(metadata); - - try { - return builder.build(); - } catch (InvalidVersionSpecificationException e) { - // This should not happen since we never modify the version. - throw new RuntimeException(e); - } - } -} diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java index 84310a04721..176a86eec8b 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java @@ -28,35 +28,104 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.blackboard.Blackboard; +import org.spongepowered.plugin.blackboard.Keys; +import org.spongepowered.plugin.builtin.StandardEnvironment; +import org.spongepowered.plugin.builtin.jvm.JVMKeys; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -public interface PluginPlatform { - Logger LOGGER = LogManager.getLogger("plugin"); +public abstract class PluginPlatform implements JVMPluginResource.Factory { + public static final Logger LOGGER = LogManager.getLogger("plugin"); - String version(); + private final Environment environment; + private final LaunchConfig config; + private final TokenReplacement tokens; + private final List pluginDirectories; - default Logger logger() { - return LOGGER; + public PluginPlatform() { + this.environment = new StandardEnvironment(PluginPlatform.LOGGER); + + final String version = this.version(); + this.logger().info("SpongePowered PLUGIN Subsystem Version={} Source={}", version, this.getCodeSource()); + + final Path baseDirectory = this.baseDirectory(); + final Path modsDirectory = this.modsDirectory(); + + this.tokens = new TokenReplacement(); + this.tokens.register("BASE_DIR", baseDirectory); + this.tokens.register("CONFIG_DIR", this.configDirectory()); + this.tokens.register("MODS_DIR", modsDirectory); + + final Path additionalPluginsDirectory; + try { + this.config = LaunchConfig.load(baseDirectory, false); + additionalPluginsDirectory = Path.of(this.tokens.replace(this.config.additionalPluginsDirectory())); + Files.createDirectories(additionalPluginsDirectory); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + this.pluginDirectories = List.of(modsDirectory, additionalPluginsDirectory); + + final Blackboard blackboard = this.environment.blackboard(); + blackboard.set(Keys.VERSION, version); + blackboard.set(Keys.BASE_DIRECTORY, baseDirectory); + blackboard.set(Keys.PLUGIN_DIRECTORIES, this.pluginDirectories); + blackboard.set(Keys.METADATA_FILE_PATHS, List.of(PluginPlatformConstants.METADATA_FILE_PATH)); + blackboard.set(JVMKeys.ENVIRONMENT_LOCATOR_VARIABLE_NAME, PluginPlatformConstants.ENVIRONMENT_LOCATOR_VARIABLE_NAME); + blackboard.set(JVMKeys.JVM_PLUGIN_RESOURCE_FACTORY, this); + } + + public final Logger logger() { + return PluginPlatform.LOGGER; } - boolean vanilla(); + public abstract String version(); + + protected String getCodeSource() { + try { + return this.getClass().getProtectionDomain().getCodeSource().getLocation().toString(); + } catch (final Throwable th) { + return "Unknown"; + } + } - Path baseDirectory(); + public abstract boolean vanilla(); - Path configDirectory(); + public abstract Path baseDirectory(); - LaunchConfig config(); + public abstract Path configDirectory(); - TokenReplacement tokens(); + public abstract Path modsDirectory(); - List pluginDirectories(); + public abstract PluginDiscovery discovery(); /** * Adds a callback that will be called once, when the platform loader is about to close. * When the platform loader is closed, no new class can be loaded, so this is the last thing we can do. */ - void addLoaderCloseCallback(AutoCloseable closeable); + public abstract void addLoaderCloseCallback(AutoCloseable closeable); + + public final List pluginDirectories() { + return this.pluginDirectories; + } + + public final LaunchConfig config() { + return this.config; + } + + public final TokenReplacement tokens() { + return this.tokens; + } + public final Environment environment() { + return this.environment; + } } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java index f6ea7f509fd..14330e20648 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java @@ -29,8 +29,7 @@ public final class PluginPlatformConstants { private PluginPlatformConstants() { } - public static final String METADATA_FILE_NAME = "sponge_plugins"; - public static final String METADATA_FILE_NAME_WITH_EXTENSION = PluginPlatformConstants.METADATA_FILE_NAME + ".json"; - public static final String METADATA_FILE_LOCATION = "META-INF/" + PluginPlatformConstants.METADATA_FILE_NAME_WITH_EXTENSION; + public static final String METADATA_FILE_PATH = "META-INF/sponge_plugins.json"; + public static final String ENVIRONMENT_LOCATOR_VARIABLE_NAME = "SPONGE_PLUGINS"; } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java new file mode 100644 index 00000000000..dddd142ea19 --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java @@ -0,0 +1,67 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.plugin; + +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginService; + +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; +import java.util.function.Predicate; + +public abstract class PluginServiceLoader { + protected final Environment environment; + + protected PluginServiceLoader(final Environment environment) { + this.environment = environment; + } + + protected final Map loadServices(final String serviceDescription, final Class serviceClass) { + return this.loadServices(serviceDescription, serviceClass, c -> true); + } + + protected final Map loadServices(final String serviceDescription, final Class serviceClass, final Predicate> filter) { + final Map services = new HashMap<>(); + this.newServiceLoader(serviceClass).stream() + .filter(provider -> filter.test(provider.type())) + .forEach(provider -> { + final T service; + try { + service = provider.get(); + } catch (final ServiceConfigurationError e) { + this.environment.logger().error("Failed to initialize {}: {}", serviceDescription, provider.type().getName(), e); + return; + } + + this.environment.logger().info("Found {} '{}'.", serviceDescription, service.name()); + services.put(service.name(), service); + }); + return services; + } + + protected abstract ServiceLoader newServiceLoader(final Class serviceClass); +} diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java new file mode 100644 index 00000000000..e966582ffde --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -0,0 +1,249 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.plugin.discovery; + +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.spongepowered.common.applaunch.plugin.PluginServiceLoader; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginLoader; +import org.spongepowered.plugin.PluginService; +import org.spongepowered.plugin.discovery.*; +import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.builtin.MetadataParser; + +import java.lang.module.ModuleDescriptor; +import java.util.*; +import java.util.stream.Collectors; + +public abstract class PluginDiscovery extends PluginServiceLoader { + private Map candidates; + private Collection readers; + + protected PluginDiscovery(final Environment environment) { + super(environment); + } + + public final void discoverPluginResources() { + final Map candidates = new HashMap<>(); + final Set> locatorsFound = new HashSet<>(); + + int maxBatches = 10; + final String maxBatchesProp = System.getProperty("sponge.discovery.maxBatches"); + if (maxBatchesProp != null) { + try { + maxBatches = Integer.parseInt(maxBatchesProp); + } catch (final NumberFormatException ignored) {} + } + + int batch = 1; + + while (true) { + this.environment.logger().info("Running plugin locators batch #{} ...", batch); + + final List batchServices = new ArrayList<>(); + + for (final PluginResourceLocator locator : this.loadServices("resource locator", PluginResourceLocator.class, locatorsFound::add).values()) { + final Collection results; + try { + results = locator.locatePluginResources(this.environment); + } catch (final Exception e) { + this.environment.logger().error("Service '{}' failed to locate plugin resources.", locator.name(), e); + continue; + } + this.environment.logger().info("Service '{}' located {} resources.", locator.name(), results.size()); + + for (final PluginResourceLocator.Result result : results) { + Candidate candidate = candidates.get(result.resource()); + if (candidate == null) { + candidate = new Candidate(result.resource(), result.unknownResourceStrategy()); + candidates.put(result.resource(), candidate); + candidate.detectServices(); + if (candidate.locatorFound || candidate.readerFound) { + batchServices.add((SpongeJVMPluginResource) result.resource()); + } + } else { + candidate.unknownResourceStrategy = candidate.unknownResourceStrategy.merge(result.unknownResourceStrategy()); + } + candidate.locators.add(locator); + } + } + + this.environment.logger().info("Found {} new discovery services.", batchServices.size()); + if (batchServices.isEmpty()) { + break; + } + + if (++batch > maxBatches) { + this.environment.logger().warn("Max locator batches reached."); + break; + } + + try { + this.appendDiscoveryServices(batchServices, batch); + } catch (final Exception e) { + this.environment.logger().error("Failed to build new service layer.", e); + break; + } + } + + for (final Candidate candidate : candidates.values()) { + this.environment.logger().debug("Found {} located by [{}] ({}).", candidate.resource, candidate.locatorNames(), candidate.serviceNames()); + } + + final Collection readers = this.loadServices("metadata reader", PluginMetadataReader.class).values(); + + this.candidates = candidates; + this.readers = readers; + } + + protected abstract void appendDiscoveryServices(final List resources, final int batch) throws Exception; + + public final Collection candidates() { + return Collections.unmodifiableCollection(this.candidates.values()); + } + + public final Candidate candidate(final PluginResource resource) { + Candidate candidate = this.candidates.get(resource); + if (candidate == null) { + candidate = new Candidate(resource, UnknownResourceStrategy.IGNORE); + this.candidates.put(resource, candidate); + this.environment.logger().debug("Found {} located by the platform.", resource); + } + return candidate; + } + + public final Collection resources(final ResourceLoading loading) { + return this.candidates.values().stream().filter((c) -> c.loading() == loading).map(Candidate::resource).toList(); + } + + public final void logMetadataWarnings() { + for (final String warning : MetadataParser.warnings()) { + this.environment.logger().warn(warning); + } + } + + public final class Candidate { + private final PluginResource resource; + private final List locators = new ArrayList<>(); + private @MonotonicNonNull UnknownResourceStrategy unknownResourceStrategy; + private final SequencedSet metadata = new LinkedHashSet<>(); + private boolean locatorFound, readerFound, loaderFound, modFound; + + public Candidate(final PluginResource resource, final UnknownResourceStrategy unknownResourceStrategy) { + this.resource = resource; + this.unknownResourceStrategy = unknownResourceStrategy; + } + + public PluginResource resource() { + return this.resource; + } + + private void detectServices() { + if (this.resource instanceof SpongeJVMPluginResource jvmResource) { + final Set services = jvmResource.module().provides().stream().map(ModuleDescriptor.Provides::service).collect(Collectors.toSet()); + this.locatorFound = services.contains(PluginResourceLocator.class.getName()); + this.readerFound = services.contains(PluginMetadataReader.class.getName()); + this.loaderFound = services.contains(PluginLoader.class.getName()); + } + } + + private String serviceNames() { + final StringJoiner joiner = new StringJoiner(", "); + if (this.locatorFound) { + joiner.add("locator"); + } + if (this.readerFound) { + joiner.add("reader"); + } + if (this.loaderFound) { + joiner.add("loader"); + } + return joiner.toString(); + } + + private String locatorNames() { + return this.locators.stream().map(PluginService::name).collect(Collectors.joining(", ")); + } + + public List locators() { + return Collections.unmodifiableList(this.locators); + } + + public void readMetadata() { + this.metadata.clear(); + for (final PluginMetadataReader reader : PluginDiscovery.this.readers) { + try { + this.metadata.addAll(reader.readPluginMetadata(PluginDiscovery.this.environment, this.resource, this.locators())); + } catch (final Exception e) { + PluginDiscovery.this.environment.logger().error("Service '{}' failed to read plugin metadata", reader.name(), e); + } + } + } + + public SequencedSet metadata() { + return Collections.unmodifiableSequencedSet(this.metadata); + } + + public boolean pluginFound() { + return !this.metadata.isEmpty(); + } + + public ResourceLoading loading() { + if (this.pluginFound() || this.loaderFound) { + return ResourceLoading.GAME_LIBRARY; + } + if (this.locatorFound || this.readerFound) { + return ResourceLoading.IGNORED; + } + return this.unknownResourceStrategy.loading(); + } + + public void setModFound() { + this.modFound = true; + } + + public void logResult() { + if (this.pluginFound()) { + PluginDiscovery.this.environment.logger().debug("Found {} metadata in {}.", this.metadata.size(), this.resource); + return; + } + if (this.locatorFound || this.readerFound || this.loaderFound || this.modFound) { + return; + } + + final String result = switch (this.unknownResourceStrategy.loading()) { + case IGNORED -> "ignored"; + case LIBRARY -> "loaded as a standard library"; + case GAME_LIBRARY -> "loaded as a game library"; + }; + + if (this.unknownResourceStrategy.warn()) { + PluginDiscovery.this.environment.logger().warn("The unknown resource {} will be {}.", this.resource, result); + } else { + PluginDiscovery.this.environment.logger().debug("The unknown resource {} will be {}.", this.resource, result); + } + } + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ResourceType.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongeJVMPluginResource.java similarity index 59% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ResourceType.java rename to src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongeJVMPluginResource.java index adeece5a25d..bd25b2d6f0e 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/ResourceType.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongeJVMPluginResource.java @@ -22,29 +22,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch.plugin; +package org.spongepowered.common.applaunch.plugin.discovery; -import cpw.mods.jarhandling.SecureJar; -import org.spongepowered.plugin.PluginResource; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import java.util.Locale; +import java.lang.module.ModuleDescriptor; -public enum ResourceType { - SERVICE, // service layer - LANGUAGE, // plugin layer - PLUGIN; // game layer +public interface SpongeJVMPluginResource extends JVMPluginResource { - public static final String PROPERTY_NAME = "Resource-Type"; - - public static ResourceType of(final PluginResource resource) { - return ResourceType.fromName(resource.property(PROPERTY_NAME).orElse(null)); - } - - public static ResourceType of(final SecureJar jar) { - return ResourceType.fromName(jar.moduleDataProvider().getManifest().getMainAttributes().getValue(PROPERTY_NAME)); - } - - public static ResourceType fromName(final String name) { - return name == null ? ResourceType.PLUGIN : ResourceType.valueOf(name.toUpperCase(Locale.ROOT)); - } + ModuleDescriptor module(); } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java similarity index 53% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java rename to src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java index 19e5d2e8b4e..046dd4108ec 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java @@ -22,23 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.applaunch.plugin.locator; +package org.spongepowered.common.applaunch.plugin.discovery; import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import org.spongepowered.plugin.builtin.jvm.locator.JVMPluginResourceLocatorService; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.discovery.ResourceLoading; +import org.spongepowered.plugin.discovery.UnknownResourceStrategy; import java.io.File; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.Collection; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.stream.Stream; -public final class SpongePropertyLocatorService implements JVMPluginResourceLocatorService { +public final class SpongePropertyResourceLocator implements PluginResourceLocator { @Override public String name() { @@ -46,46 +45,21 @@ public String name() { } @Override - public Set locatePluginResources(final Environment environment) { - environment.logger().info("Locating '{}' resources...", this.name()); - - final Set resources = new HashSet<>(); + public Collection locatePluginResources(final Environment environment) { + final Set resources = new HashSet<>(); final String resourcesProp = System.getProperty("sponge.resources"); if (resourcesProp != null) { + final UnknownResourceStrategy strategy = new UnknownResourceStrategy(false, ResourceLoading.GAME_LIBRARY); + for (final String entry : resourcesProp.split(File.pathSeparator)) { if (entry.isBlank()) { continue; } final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); - resources.add(JVMPluginResource.create(environment, this.name(), paths)); - } - } - - final String fsProp = System.getProperty("sponge.rootJarFS"); - if (fsProp != null) { - try { - final FileSystem fs = FileSystems.getFileSystem(new URI(fsProp)); - final Path spongeMod = newJarInJar(fs.getPath("jars", "spongevanilla-mod.jar")); - resources.add(JVMPluginResource.create(environment, this.name(), spongeMod)); - } catch (final Exception e) { - environment.logger().error("Failed to locate spongevanilla-mod jar."); + resources.add(new Result(JVMPluginResource.create(environment, paths), strategy)); } } - - environment.logger().info("Located [{}] resource(s) for '{}'...", resources.size(), this.name()); - return resources; } - - private static Path newJarInJar(final Path jar) { - try { - URI jij = new URI("jij:" + jar.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); - final Map env = Map.of("packagePath", jar); - FileSystem jijFS = FileSystems.newFileSystem(jij, env); - return jijFS.getPath("/"); // root of the archive to load - } catch (Exception e) { - throw new RuntimeException(e); - } - } } diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index a33fc73516a..709a7c54b63 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -47,7 +47,6 @@ import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.registry.RegistryTypes; -import org.spongepowered.common.applaunch.plugin.DummyPluginContainer; import org.spongepowered.common.bridge.core.WritableRegistryBridge; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.data.SpongeDataManager; @@ -76,7 +75,6 @@ import org.spongepowered.common.world.server.SpongeWorldManager; import org.spongepowered.plugin.PluginContainer; -import java.util.Collection; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @@ -200,7 +198,7 @@ public void establishServerFeatures() { @Override public void callConstructEvent() { - for (final PluginContainer plugin : this.filterInternalPlugins(this.game.pluginManager().plugins())) { + for (final PluginContainer plugin : this.game.pluginManager().plugins()) { ((SpongeEventManager) this.game.eventManager()).postToPlugin(SpongeEventFactory.createConstructPluginEvent(Cause.of(EventContext.empty(), this.game), this.game, plugin), plugin); } @@ -304,13 +302,6 @@ public void setWorldDataConfiguration(final WorldDataConfiguration config) { this.featureFlags = config.enabledFeatures(); } - private Collection filterInternalPlugins(final Collection plugins) { - return plugins - .stream() - .filter(plugin -> !(plugin instanceof DummyPluginContainer)) - .collect(Collectors.toList()); - } - @Override public void establishTags(final ResourceManager resourceManager) { final RegisterTagEventImpl event = new RegisterTagEventImpl(Cause.of(EventContext.empty(), this.game), this.game); diff --git a/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java b/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java index 54082cae6a9..32229c68b34 100644 --- a/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java +++ b/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java @@ -72,7 +72,7 @@ import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginContributor; -import java.net.URL; +import java.net.URI; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collection; @@ -657,7 +657,7 @@ private void appendPluginMeta(final TextComponent.Builder builder, final String this.appendPluginMeta(builder, key, Component.text(value)); } - private void appendPluginMeta(final TextComponent.Builder builder, final String key, final URL value) { + private void appendPluginMeta(final TextComponent.Builder builder, final String key, final URI value) { final String url = value.toString(); this.appendPluginMeta(builder, key, Component.text().content(url).clickEvent(ClickEvent.openUrl(url)) .decoration(TextDecoration.UNDERLINED, true).build()); diff --git a/src/main/java/org/spongepowered/common/launch/Launch.java b/src/main/java/org/spongepowered/common/launch/Launch.java index ab1684504c3..491f78e68ec 100644 --- a/src/main/java/org/spongepowered/common/launch/Launch.java +++ b/src/main/java/org/spongepowered/common/launch/Launch.java @@ -33,6 +33,7 @@ import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.launch.plugin.SpongePluginManager; +import org.spongepowered.common.launch.plugin.loader.PluginCandidateFactory; import org.spongepowered.plugin.PluginContainer; import java.util.ArrayList; @@ -47,6 +48,7 @@ public abstract class Launch { protected final PluginPlatform pluginPlatform; private final Logger logger; private final List launcherPlugins; + private final PluginCandidateFactory pluginFactory; private PluginContainer minecraftPlugin, apiPlugin, commonPlugin; private Lifecycle lifecycle; @@ -54,6 +56,7 @@ protected Launch(final PluginPlatform pluginPlatform) { this.logger = LogManager.getLogger("launch"); this.pluginPlatform = pluginPlatform; this.launcherPlugins = new ArrayList<>(); + this.pluginFactory = new PluginCandidateFactory(pluginPlatform.environment()); } @SuppressWarnings("unchecked") @@ -95,10 +98,14 @@ public final Logger logger() { return this.logger; } - public PluginPlatform pluginPlatform() { + public final PluginPlatform pluginPlatform() { return this.pluginPlatform; } + public final PluginCandidateFactory pluginFactory() { + return this.pluginFactory; + } + public abstract Stage injectionStage(); public final boolean developerEnvironment() { diff --git a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java index 7d6b13b7cda..898beda7b5c 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java @@ -25,11 +25,30 @@ package org.spongepowered.common.launch.plugin; import com.google.inject.Injector; -import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.StandardPluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; import java.util.Optional; -public interface SpongePluginContainer extends PluginContainer { +public class SpongePluginContainer extends StandardPluginContainer { - Optional injector(); + private Injector injector; + + public SpongePluginContainer(final PluginResource resource, final PluginMetadata metadata) { + super(resource, metadata); + } + + @Override + public void initializeInstance(final Object instance) { + super.initializeInstance(instance); + } + + public Optional injector() { + return Optional.ofNullable(this.injector); + } + + public void setInjector(final Injector injector) { + this.injector = injector; + } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/JavaPluginLoader.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java similarity index 52% rename from vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/JavaPluginLoader.java rename to src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java index 432b2e14313..749b71f6641 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/JavaPluginLoader.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java @@ -22,43 +22,44 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.launch.plugin; +package org.spongepowered.common.launch.plugin.loader; import com.google.inject.Injector; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.spongepowered.api.Sponge; import org.spongepowered.common.inject.plugin.PluginGuice; import org.spongepowered.common.launch.Launch; -import org.spongepowered.plugin.Environment; -import org.spongepowered.plugin.InvalidPluginException; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.PluginLoader; +import org.spongepowered.common.launch.plugin.SpongePluginContainer; +import org.spongepowered.plugin.*; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; -public final class JavaPluginLoader implements PluginLoader { - - private final ArtifactVersion version = new DefaultArtifactVersion("1.0"); +public final class JavaPluginLoader implements PluginLoader { + private static final ArtifactVersion version = new DefaultArtifactVersion("1.0"); @Override public ArtifactVersion version() { - return this.version; + return JavaPluginLoader.version; } @Override - public VanillaJavaPluginContainer loadPlugin(final Environment environment, final PluginCandidate candidate, final ClassLoader targetClassLoader) - throws InvalidPluginException { - final VanillaJavaPluginContainer container = new VanillaJavaPluginContainer(candidate); - try { - final String mainClass = container.metadata().entrypoint(); - final Class pluginClass = Class.forName(mainClass, true, targetClassLoader); - - final Injector pluginInjector = PluginGuice.create(container, pluginClass, Launch.instance().lifecycle().platformInjector()); - final Object plugin = pluginInjector.getInstance(pluginClass); - container.setInjector(pluginInjector); - container.initializeInstance(plugin); - return container; - } catch (final Exception ex) { - throw new InvalidPluginException("An error occurred creating an instance of plugin '" + container.metadata().id() + "'!", ex); - } + public String name() { + return "java_plain"; } + @Override + public PluginContainer loadPlugin(Environment environment, PluginResource resource, PluginMetadata metadata) throws Exception { + final SpongePluginContainer container = new SpongePluginContainer(resource, metadata); + final String mainClass = container.metadata().entrypoint(); + final Class pluginClass = Class.forName(mainClass); + + final Injector pluginInjector = PluginGuice.create(container, pluginClass, Launch.instance().lifecycle().platformInjector()); + final Object plugin = pluginInjector.getInstance(pluginClass); + container.setInjector(pluginInjector); + container.initializeInstance(plugin); + + Sponge.eventManager().registerListeners(container, plugin); + return container; + } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidate.java similarity index 63% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java rename to src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidate.java index 3fdc3a181e8..5a0c28af244 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/loading/moddiscovery/reader/PluginFileReader.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidate.java @@ -22,22 +22,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.loading.moddiscovery.reader; +package org.spongepowered.common.launch.plugin.loader; -import net.neoforged.fml.jarcontents.JarContents; -import net.neoforged.neoforgespi.locating.IModFile; -import net.neoforged.neoforgespi.locating.IModFileReader; -import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.PluginLoader; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; -public class PluginFileReader implements IModFileReader { - @Override - public @Nullable IModFile read(final JarContents jar, final ModFileDiscoveryAttributes attributes) { - return PluginFileParser.newPluginInstance(jar, attributes.withReader(this)); - } +public record PluginCandidate(Environment environment, PluginResource resource, PluginMetadata metadata, PluginLoader loader) { - @Override - public String toString() { - return "sponge manifest"; + public PluginContainer load() throws Exception { + return this.loader.loadPlugin(this.environment, this.resource, this.metadata); } } diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java new file mode 100644 index 00000000000..9764eb780ca --- /dev/null +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java @@ -0,0 +1,62 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.launch.plugin.loader; + +import org.spongepowered.common.applaunch.plugin.PluginServiceLoader; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginLoader; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.model.ContainerLoader; + +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.ServiceLoader; + +public final class PluginCandidateFactory extends PluginServiceLoader { + private final Map loaders; + + public PluginCandidateFactory(final Environment environment) { + super(environment); + this.loaders = this.loadServices("plugin loader", PluginLoader.class); + } + + @Override + protected ServiceLoader newServiceLoader(final Class serviceClass) { + return ServiceLoader.load(serviceClass); + } + + public PluginCandidate create(final PluginResource resource, final PluginMetadata metadata) { + final ContainerLoader loaderSpec = metadata.container().loader(); + final PluginLoader loader = this.loaders.get(loaderSpec.name()); + if (loader == null) { + throw new NoSuchElementException("Cannot find loader " + loaderSpec.name()); + } + if (!VersionChecker.check(loaderSpec.version(), loader.version())) { + throw new IllegalArgumentException("Expected loader " + loader.name() + " version " + loaderSpec.version() + " but found " + loaderSpec.version()); + } + return new PluginCandidate(this.environment, resource, metadata, loader); + } +} diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java new file mode 100644 index 00000000000..488898c0f73 --- /dev/null +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java @@ -0,0 +1,51 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.launch.plugin.loader; + +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.VersionRange; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Objects; + +public class VersionChecker { + + public static boolean check(final @Nullable VersionRange requestedVersion, final ArtifactVersion dependencyVersion) { + if (requestedVersion == null || !requestedVersion.hasRestrictions()) { + // we don't care which version + return true; + } + // Maven Artifact version resolution has a bug(?) where VersionRange#containsVersion() + // returns false if there are no restrictions when logically it should be true because + // theoretically all versions are included. Except in our case, the recommended version + // might be populated, yet no restrictions are in the VersionRange object, because we + // want a specific version, which should be a restriction. + // + // Further, VersionRange#hasRestrictions() returns true even if VersionRange#getRestrictions() + // is empty as it accounts for if there is a recommended version. Thus, we have to do the check + // on the recommended version first... which might be null, hence the Objects.equals check. + return Objects.equals(requestedVersion.getRecommendedVersion(), dependencyVersion) || requestedVersion.containsVersion(dependencyVersion); + } +} diff --git a/src/main/resources/META-INF/services/org.spongepowered.plugin.PluginLoader b/src/main/resources/META-INF/services/org.spongepowered.plugin.PluginLoader new file mode 100644 index 00000000000..a4e68ba568b --- /dev/null +++ b/src/main/resources/META-INF/services/org.spongepowered.plugin.PluginLoader @@ -0,0 +1 @@ +org.spongepowered.common.launch.plugin.loader.JavaPluginLoader diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/JavaPluginLanguageService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/JavaPluginLanguageService.java deleted file mode 100644 index 07b026699e3..00000000000 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/JavaPluginLanguageService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.vanilla.applaunch.plugin; - -import org.spongepowered.plugin.Environment; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.plugin.builtin.StandardPluginCandidate; -import org.spongepowered.plugin.builtin.StandardPluginLanguageService; -import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; -import org.spongepowered.plugin.metadata.PluginMetadata; - -import java.io.InputStream; -import java.nio.file.Files; -import java.util.LinkedList; -import java.util.List; - -public final class JavaPluginLanguageService extends StandardPluginLanguageService { - private final static String NAME = "java_plain"; - - @Override - public String name() { - return JavaPluginLanguageService.NAME; - } - - @Override - public String pluginLoader() { - return "org.spongepowered.vanilla.launch.plugin.JavaPluginLoader"; - } - - @Override - public List createPluginCandidates(final Environment environment, final PluginResource resource) throws Exception { - if (resource instanceof JVMPluginResource jvmResource && Files.exists(jvmResource.resourcesRoot().resolve("net/minecraft/server/MinecraftServer.class"))) { - this.logger.debug("Container in path '{}' has been detected as Minecraft.", resource.path()); - - final List candidates = new LinkedList<>(); - try (final InputStream stream = JavaPluginLanguageService.class.getClassLoader().getResourceAsStream("META-INF/minecraft_sponge_plugins.json")) { - for (final PluginMetadata metadata : loadMetadataContainer(environment, stream).metadata()) { - candidates.add(new StandardPluginCandidate(metadata, resource)); - } - } - - return candidates; - } - - return super.createPluginCandidates(environment, resource); - } -} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java index d6c47ff9206..753b2fa0ec1 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java @@ -25,83 +25,33 @@ package org.spongepowered.vanilla.applaunch.plugin; import cpw.mods.modlauncher.Launcher; -import cpw.mods.modlauncher.api.IModuleLayerManager; -import org.spongepowered.common.applaunch.config.LaunchConfig; -import org.spongepowered.common.applaunch.config.TokenReplacement; +import cpw.mods.modlauncher.api.IEnvironment; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.common.applaunch.plugin.PluginPlatform; -import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; -import org.spongepowered.plugin.Environment; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.PluginLanguageService; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.plugin.PluginResourceLocatorService; -import org.spongepowered.plugin.blackboard.Blackboard; -import org.spongepowered.plugin.blackboard.Keys; import org.spongepowered.plugin.builtin.StandardEnvironment; -import org.spongepowered.plugin.builtin.jvm.JVMKeys; -import org.spongepowered.vanilla.applaunch.plugin.resource.SecureJarPluginResource; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; +import org.spongepowered.vanilla.applaunch.plugin.discovery.VanillaPluginDiscovery; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.ServiceConfigurationError; -import java.util.ServiceLoader; -import java.util.Set; -public final class VanillaPluginPlatform implements PluginPlatform { +public final class VanillaPluginPlatform extends PluginPlatform { private static final List closeCallbacks = new ArrayList<>(); - private final Environment environment; - private final LaunchConfig config; - private final TokenReplacement tokens; + private final VanillaPluginDiscovery discovery; + private @MonotonicNonNull Path baseDirectory; - private final Map> locatorServices; - private final Map languageServices; - - private final Map> locatorResources; - private final Map> pluginCandidates; - - public VanillaPluginPlatform(final Path baseDirectory) throws IOException { - this.environment = new StandardEnvironment(); - - final String implVersion = StandardEnvironment.class.getPackage().getImplementationVersion(); - this.setVersion(implVersion == null ? "dev" : implVersion); - - this.setBaseDirectory(baseDirectory); - this.setMetadataFilePath(PluginPlatformConstants.METADATA_FILE_LOCATION); - - this.config = LaunchConfig.load(baseDirectory, false); - - final Path modsDirectory = baseDirectory.resolve("mods"); - this.tokens = new TokenReplacement(); - this.tokens.register("BASE_DIR", baseDirectory); - this.tokens.register("CONFIG_DIR", this.configDirectory()); - this.tokens.register("MODS_DIR", modsDirectory); - - this.locatorServices = new HashMap<>(); - this.languageServices = new HashMap<>(); - this.locatorResources = new HashMap<>(); - this.pluginCandidates = new IdentityHashMap<>(); - - final Path additionalPluginsDirectory = Path.of(this.tokens.replace(this.config.additionalPluginsDirectory())); - Files.createDirectories(additionalPluginsDirectory); - this.setPluginDirectories(List.of(modsDirectory, additionalPluginsDirectory)); + public VanillaPluginPlatform() { + this.discovery = new VanillaPluginDiscovery(this.environment()); } @Override public String version() { - return this.environment.blackboard().get(Keys.VERSION); - } - - private void setVersion(final String version) { - this.environment.blackboard().set(Keys.VERSION, version); + final String implVersion = StandardEnvironment.class.getPackage().getImplementationVersion(); + return implVersion == null ? "dev" : implVersion; } @Override @@ -111,7 +61,10 @@ public boolean vanilla() { @Override public Path baseDirectory() { - return this.environment.blackboard().get(Keys.BASE_DIRECTORY); + if (this.baseDirectory == null) { + this.baseDirectory = Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.GAMEDIR.get()).orElse(Paths.get(".")); + } + return this.baseDirectory; } @Override @@ -120,26 +73,18 @@ public Path configDirectory() { } @Override - public LaunchConfig config() { - return this.config; + public Path modsDirectory() { + return this.baseDirectory().resolve("mods"); } @Override - public TokenReplacement tokens() { - return this.tokens; - } - - private void setBaseDirectory(final Path baseDirectory) { - this.environment.blackboard().set(Keys.BASE_DIRECTORY, baseDirectory); + public VanillaPluginDiscovery discovery() { + return this.discovery; } @Override - public List pluginDirectories() { - return this.environment.blackboard().get(Keys.PLUGIN_DIRECTORIES); - } - - private void setPluginDirectories(final List pluginDirectories) { - this.environment.blackboard().set(Keys.PLUGIN_DIRECTORIES, pluginDirectories); + public JVMPluginResource create(final Path[] paths) { + return new SecureJarPluginResource(paths); } @Override @@ -147,116 +92,6 @@ public void addLoaderCloseCallback(final AutoCloseable closeable) { VanillaPluginPlatform.closeCallbacks.add(closeable); } - public String metadataFilePath() { - return this.environment.blackboard().get(Keys.METADATA_FILE_PATH); - } - - private void setMetadataFilePath(final String metadataFilePath) { - this.environment.blackboard().set(Keys.METADATA_FILE_PATH, metadataFilePath); - } - - public Environment getEnvironment() { - return this.environment; - } - - public Map> getLocatorServices() { - return Collections.unmodifiableMap(this.locatorServices); - } - - public Map getLanguageServices() { - return Collections.unmodifiableMap(this.languageServices); - } - - public Map> getResources() { - return Collections.unmodifiableMap(this.locatorResources); - } - - public Map> getCandidates() { - return Collections.unmodifiableMap(this.pluginCandidates); - } - - public void initializeLanguageServices() { - for (final Map.Entry entry : this.languageServices.entrySet()) { - entry.getValue().initialize(this.environment); - } - } - - public void discoverLocatorServices() { - final Blackboard blackboard = this.environment.blackboard(); - blackboard.set(JVMKeys.ENVIRONMENT_LOCATOR_VARIABLE_NAME, "SPONGE_PLUGINS"); - blackboard.set(JVMKeys.JVM_PLUGIN_RESOURCE_FACTORY, SecureJarPluginResource::new); - - final ModuleLayer serviceLayer = Launcher.INSTANCE.environment().findModuleLayerManager().flatMap(lm -> lm.getLayer(IModuleLayerManager.Layer.SERVICE)).orElseThrow(); - final var serviceLoader = ServiceLoader.load(serviceLayer, PluginResourceLocatorService.class); - - for (final var iter = serviceLoader.iterator(); iter.hasNext(); ) { - final PluginResourceLocatorService next; - - try { - next = iter.next(); - } catch (final ServiceConfigurationError e) { - this.environment.logger().error("Error encountered initializing plugin resource locator!", e); - continue; - } - - this.locatorServices.put(next.name(), next); - } - } - - public void discoverLanguageServices() { - final ModuleLayer pluginLayer = Launcher.INSTANCE.environment().findModuleLayerManager().flatMap(lm -> lm.getLayer(IModuleLayerManager.Layer.PLUGIN)).orElseThrow(); - final var serviceLoader = ServiceLoader.load(pluginLayer, PluginLanguageService.class); - - for (final var iter = serviceLoader.iterator(); iter.hasNext(); ) { - final PluginLanguageService next; - - try { - next = iter.next(); - } catch (final ServiceConfigurationError e) { - this.environment.logger().error("Error encountered initializing plugin language service!", e); - continue; - } - - this.languageServices.put(next.name(), next); - } - } - - public void locatePluginResources() { - for (final Map.Entry> locatorEntry : this.locatorServices.entrySet()) { - final PluginResourceLocatorService locatorService = locatorEntry.getValue(); - final Set resources = locatorService.locatePluginResources(this.environment); - if (!resources.isEmpty()) { - this.locatorResources.put(locatorEntry.getKey(), resources); - } - } - } - - public void createPluginCandidates() { - for (final PluginLanguageService languageService : this.languageServices.values()) { - for (final Set resources : this.locatorResources.values()) { - for (final PluginResource pluginResource : resources) { - if (ResourceType.of(pluginResource) != ResourceType.PLUGIN) { - continue; - } - - try { - final List candidates = languageService.createPluginCandidates(this.environment, pluginResource); - if (candidates.isEmpty()) { - continue; - } - this.pluginCandidates.computeIfAbsent(languageService, k -> new LinkedList<>()).addAll(candidates); - - if (pluginResource instanceof SecureJarPluginResource jarResource) { - jarResource.addCandidates(candidates); - } - } catch (final Exception ex) { - this.environment.logger().error("Failed to create plugin candidates", ex); - } - } - } - } - } - static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { for (final AutoCloseable closeCallback : VanillaPluginPlatform.closeCallbacks) { diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java index c2631356d4c..a8048fd4df9 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java @@ -25,7 +25,6 @@ package org.spongepowered.vanilla.applaunch.plugin; import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IEnvironment; import cpw.mods.modlauncher.api.IModuleLayerManager; import cpw.mods.modlauncher.api.ITransformationService; @@ -35,20 +34,18 @@ import org.fusesource.jansi.AnsiConsole; import org.spongepowered.asm.launch.MixinLaunchPlugin; import org.spongepowered.common.applaunch.AppLaunch; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.vanilla.applaunch.plugin.resource.SecureJarPluginResource; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; import org.spongepowered.vanilla.applaunch.transformation.VanillaAccessWidenerTransformer; import org.spongepowered.vanilla.applaunch.transformation.VanillaSuperclassChangeTransformer; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; public final class VanillaTransformationService implements ITransformationService { - private @MonotonicNonNull VanillaPluginPlatform pluginPlatform; + private @MonotonicNonNull VanillaPluginPlatform platform; @Override public String name() { @@ -58,100 +55,63 @@ public String name() { @Override public void onLoad(final IEnvironment env, final Set otherServices) { AnsiConsole.systemInstall(); - - final Path baseDirectory = env.getProperty(IEnvironment.Keys.GAMEDIR.get()).orElse(Paths.get(".")); - try { - this.pluginPlatform = new VanillaPluginPlatform(baseDirectory); - } catch (IOException e) { - throw new RuntimeException(e); - } - AppLaunch.setPluginPlatform(this.pluginPlatform); - - this.pluginPlatform.logger().info("SpongePowered PLUGIN Subsystem Version={} Source={}", this.pluginPlatform.version(), this.getCodeSource()); - } - - @Override - public void initialize(final IEnvironment environment) { - this.pluginPlatform.initializeLanguageServices(); + this.platform = AppLaunch.bootstrap(VanillaPluginPlatform::new); } @Override - public List beginScanning(final IEnvironment environment) { - this.pluginPlatform.discoverLocatorServices(); - this.pluginPlatform.getLocatorServices().forEach((k, v) -> this.pluginPlatform.logger().info("Plugin resource locator '{}' found.", k)); - - this.pluginPlatform.locatePluginResources(); - - final List languageResources = new ArrayList<>(); - - for (final Set resources : this.pluginPlatform.getResources().values()) { - for (final PluginResource resource : resources) { - if (resource instanceof SecureJarPluginResource secureJarResource) { - if (ResourceType.of(resource) == ResourceType.LANGUAGE) { - languageResources.add(secureJarResource.jar()); - } - } - } - } - - return List.of(new Resource(IModuleLayerManager.Layer.PLUGIN, languageResources)); - } + public void initialize(final IEnvironment environment) {} @Override - public List completeScan(final IModuleLayerManager layerManager) { - this.pluginPlatform.discoverLanguageServices(); - this.pluginPlatform.getLanguageServices().forEach((k, v) -> this.pluginPlatform.logger().info("Plugin language loader '{}' found.", k)); - - this.pluginPlatform.createPluginCandidates(); - - final IEnvironment env = Launcher.INSTANCE.environment(); + public List beginScanning(final IEnvironment env) { final ILaunchPluginService mixin = env.findLaunchPlugin(MixinLaunchPlugin.NAME).orElse(null); - final List gameResources = new ArrayList<>(); + this.platform.discovery().discoverPluginResources(); + + final List libs = new ArrayList<>(); + final List gameLibs = new ArrayList<>(); - for (final Set resources : this.pluginPlatform.getResources().values()) { - for (final PluginResource resource : resources) { - if (resource instanceof SecureJarPluginResource secureJarResource) { - // Build jar metadata from first candidate, or fallback to standard - secureJarResource.init(); + for (final PluginDiscovery.Candidate candidate : this.platform.discovery().candidates()) { + final PluginResource resource = candidate.resource(); + candidate.readMetadata(); - if (ResourceType.of(resource) == ResourceType.PLUGIN) { - gameResources.add(secureJarResource.jar()); + switch (candidate.loading()) { + case IGNORED: + break; + case LIBRARY: + if (resource instanceof SecureJarPluginResource jarResource) { + libs.add(jarResource.jar()); + } + break; + case GAME_LIBRARY: + if (resource instanceof SecureJarPluginResource jarResource) { + gameLibs.add(candidate.pluginFound() ? jarResource.pluginJar(candidate.metadata().getFirst()) : jarResource.jar()); } - } - // Offer jar to the Mixin service - if (mixin != null) { - mixin.offerResource(resource.path(), resource.path().getFileName().toString()); - } + // Offer jar to the Mixin service + if (mixin != null) { + mixin.offerResource(resource.path(), resource.path().getFileName().toString()); + } - // Log warning about plugin using Mixin - if (mixin != null && resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { - if (!VanillaTransformationService.isSponge(resource)) { - this.pluginPlatform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", resource.path()); + // Log warning about plugin using Mixin + if (mixin != null && resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { + if (candidate.metadata().stream().noneMatch(m -> "spongevanilla".equals(m.id()))) { + this.platform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", resource.path()); + } } - } + break; } + + candidate.logResult(); } - return List.of(new Resource(IModuleLayerManager.Layer.GAME, gameResources)); - } + this.platform.discovery().logMetadataWarnings(); - private static boolean isSponge(final PluginResource resource) { - return resource instanceof SecureJarPluginResource secureJarResource && secureJarResource.jar().name().equals("spongevanilla"); + return List.of(new Resource(IModuleLayerManager.Layer.PLUGIN, libs), new Resource(IModuleLayerManager.Layer.GAME, gameLibs)); } @SuppressWarnings("rawtypes") @Override public List transformers() { - return List.of(new VanillaAccessWidenerTransformer(this.pluginPlatform), new VanillaSuperclassChangeTransformer(this.pluginPlatform)); - } - - private String getCodeSource() { - try { - return this.getClass().getProtectionDomain().getCodeSource().getLocation().toString(); - } catch (final Throwable th) { - return "Unknown"; - } + return List.of(new VanillaAccessWidenerTransformer(this.platform.discovery()), new VanillaSuperclassChangeTransformer(this.platform.discovery())); } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java new file mode 100644 index 00000000000..c8406525ecf --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java @@ -0,0 +1,66 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.plugin.discovery; + +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.plugin.discovery.PluginMetadataReader; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.builtin.MetadataParser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; + +public final class MinecraftMetadataReader implements PluginMetadataReader { + + @Override + public String name() { + return "minecraft"; + } + + @Override + public Collection readPluginMetadata(final Environment environment, final PluginResource resource, final List locators) throws Exception { + if (resource instanceof JVMPluginResource && resource.locateResource("net/minecraft/server/MinecraftServer.class").isPresent()) { + environment.logger().debug("Container in path '{}' has been detected as Minecraft.", resource.path()); + + final InputStream input = MinecraftMetadataReader.class.getClassLoader().getResourceAsStream("META-INF/minecraft_sponge_plugins.json"); + if (input == null) { + throw new IOException("Unable to locate Minecraft plugins metadata file"); + } + + try (final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { + return MetadataParser.read(reader).metadata(); + } + } + return List.of(); + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/PluginJarMetadata.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/PluginJarMetadata.java new file mode 100644 index 00000000000..523de9fdb0e --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/PluginJarMetadata.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.plugin.discovery; + +import cpw.mods.jarhandling.JarMetadata; +import cpw.mods.jarhandling.SecureJar; +import org.spongepowered.plugin.metadata.PluginMetadata; + +import java.lang.module.ModuleDescriptor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +public class PluginJarMetadata implements JarMetadata { + private final ModuleDescriptor descriptor; + + public PluginJarMetadata(final SecureJar jar, final Path[] paths) { + this.descriptor = PluginJarMetadata.standardDescriptor(jar, paths); + } + + public PluginJarMetadata(final SecureJar jar, final PluginMetadata plugin) { + this.descriptor = PluginJarMetadata.pluginDescriptor(jar, plugin); + } + + @Override + public String name() { + return this.descriptor.name(); + } + + @Override + public String version() { + return this.descriptor.rawVersion().orElse(null); + } + + @Override + public ModuleDescriptor descriptor() { + return this.descriptor; + } + + private static ModuleDescriptor pluginDescriptor(final SecureJar jar, final PluginMetadata plugin) { + return PluginJarMetadata.descriptorBuilder(jar, plugin.id()).version(plugin.version().toString()).build(); + } + + private static ModuleDescriptor standardDescriptor(final SecureJar jar, final Path[] paths) { + if (jar.moduleDataProvider().findFile("module-info.class").isEmpty() && Arrays.stream(paths).allMatch(Files::isDirectory)) { + return PluginJarMetadata.descriptorBuilder(jar, jar.getPackages().stream().sorted().findFirst().orElseThrow()).build(); + } + return JarMetadata.from(jar, paths).descriptor(); + } + + private static ModuleDescriptor.Builder descriptorBuilder(final SecureJar jar, final String name) { + final ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(name).packages(jar.getPackages()); + jar.getProviders().stream() + .filter(p -> !p.providers().isEmpty()) + .forEach(p -> builder.provides(p.serviceName(), p.providers())); + return builder; + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java new file mode 100644 index 00000000000..fa3222ace14 --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.plugin.discovery; + +import cpw.mods.jarhandling.SecureJar; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; + +import java.lang.module.ModuleDescriptor; +import java.net.URI; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.jar.Manifest; + +public final class SecureJarPluginResource implements SpongeJVMPluginResource { + private final Path[] paths; + private final SecureJar jar; + + public SecureJarPluginResource(final Path[] paths) { + Objects.requireNonNull(paths, "paths"); + if (paths.length == 0) { + throw new IllegalArgumentException("Need at least one path"); + } + this.paths = paths; + this.jar = SecureJar.from(jar -> new PluginJarMetadata(jar, paths), paths); + } + + public SecureJar jar() { + return this.jar; + } + + public SecureJar pluginJar(final PluginMetadata metadata) { + return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.paths); + } + + @Override + public Path path() { + return this.jar.getPrimaryPath(); + } + + @Override + public Optional locateResource(final String path) { + return this.jar.moduleDataProvider().findFile(path); + } + + @Override + public Manifest manifest() { + return this.jar.moduleDataProvider().getManifest(); + } + + @Override + public ModuleDescriptor module() { + return this.jar.moduleDataProvider().descriptor(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof SecureJarPluginResource that)) { + return false; + } + return Arrays.equals(this.paths, that.paths); + } + + @Override + public int hashCode() { + return Arrays.hashCode(this.paths); + } + + @Override + public String toString() { + return "SecureJarPluginResource[paths=" + Arrays.toString(this.paths) + "]"; + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SpongeVanillaResourceLocator.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SpongeVanillaResourceLocator.java new file mode 100644 index 00000000000..d7f0bd87992 --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SpongeVanillaResourceLocator.java @@ -0,0 +1,66 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.plugin.discovery; + +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.discovery.UnknownResourceStrategy; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public final class SpongeVanillaResourceLocator implements PluginResourceLocator { + + @Override + public String name() { + return "spongevanilla"; + } + + @Override + public Collection locatePluginResources(final Environment environment) throws Exception { + final String fsProp = System.getProperty("sponge.rootJarFS"); + if (fsProp == null) { + return List.of(); + } + final FileSystem fs = FileSystems.getFileSystem(new URI(fsProp)); + final Path spongeMod = newJarInJar(fs.getPath("jars", "spongevanilla-mod.jar")); + return List.of(new Result(JVMPluginResource.create(environment, spongeMod), UnknownResourceStrategy.WARN)); + } + + private static Path newJarInJar(final Path jar) throws IOException, URISyntaxException { + URI jij = new URI("jij:" + jar.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); + final Map env = Map.of("packagePath", jar); + FileSystem jijFS = FileSystems.newFileSystem(jij, env); + return jijFS.getPath("/"); // root of the archive to load + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/VanillaPluginDiscovery.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/VanillaPluginDiscovery.java new file mode 100644 index 00000000000..98bd937d291 --- /dev/null +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/VanillaPluginDiscovery.java @@ -0,0 +1,77 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.vanilla.applaunch.plugin.discovery; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.securemodules.SecureModuleClassLoader; +import net.minecraftforge.securemodules.SecureModuleFinder; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; +import org.spongepowered.plugin.Environment; + +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +public class VanillaPluginDiscovery extends PluginDiscovery { + private ModuleLayer currentLayer; + private ClassLoader currentLoader; + + public VanillaPluginDiscovery(Environment environment) { + super(environment); + this.currentLayer = getClass().getModule().getLayer(); + this.currentLoader = getClass().getClassLoader(); + } + + @Override + protected ServiceLoader newServiceLoader(final Class serviceClass) { + return ServiceLoader.load(this.currentLayer, serviceClass); + } + + @Override + protected void appendDiscoveryServices(final List resources, final int batch) { + final ModuleLayer parentLayer = this.currentLayer; + final ClassLoader parentLoader = this.currentLoader; + + final List jars = new ArrayList<>(); + final List moduleNames = new ArrayList<>(); + + for (final SpongeJVMPluginResource resource : resources) { + final SecureJar jar = ((SecureJarPluginResource) resource).jar(); + jars.add(jar); + moduleNames.add(jar.name()); + } + + final Configuration config = parentLayer.configuration().resolveAndBind(SecureModuleFinder.of(jars), ModuleFinder.of(), moduleNames); + final ClassLoader loader = new SecureModuleClassLoader("SPONGE-DISCOVERY-BATCH-" + batch, null, config, List.of(parentLayer), List.of(parentLoader)); + + this.currentLayer = this.currentLayer.defineModulesWithOneLoader(config, loader); + this.currentLoader = loader; + + this.environment.logger().debug("Built new service layer {} on top of {}.", loader.getName(), parentLoader.getName()); + } +} diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java index 58ca2f4e226..ba2ff2f515b 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java @@ -29,9 +29,10 @@ import cpw.mods.modlauncher.api.ITransformerVotingContext; import cpw.mods.modlauncher.api.TransformerVoteResult; import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.applaunch.transformation.AccessWidenerTransformer; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.discovery.ResourceLoading; import java.net.URL; import java.util.*; @@ -40,10 +41,10 @@ public class VanillaAccessWidenerTransformer extends AccessWidenerTransformer implements ITransformer { private static final String[] LABELS = { AccessWidenerTransformer.NAME }; - private final VanillaPluginPlatform pluginPlatform; + private final PluginDiscovery discovery; - public VanillaAccessWidenerTransformer(final VanillaPluginPlatform pluginPlatform) { - this.pluginPlatform = pluginPlatform; + public VanillaAccessWidenerTransformer(final PluginDiscovery discovery) { + this.discovery = discovery; } @Override @@ -69,16 +70,14 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (final Set plugins : this.pluginPlatform.getResources().values()) { - for (final PluginResource plugin : plugins) { - final Optional attribute = plugin.property(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); - if (attribute.isPresent()) { - for (final String path : attribute.get().split(",")) { - try { - resources.add(plugin.locateResource(path).get().toURL()); - } catch (final Exception e) { - LOGGER.warn("Failed to locate access widener {} from {}", path, plugin.path().getFileName(), e); - } + for (final PluginResource plugin : this.discovery.resources(ResourceLoading.GAME_LIBRARY)) { + final Optional attribute = plugin.property(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); + if (attribute.isPresent()) { + for (final String path : attribute.get().split(",")) { + try { + resources.add(plugin.locateResource(path).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate access widener {} from {}", path, plugin.path().getFileName(), e); } } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java index d2d8dd5aede..3a6eb40b982 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java @@ -29,9 +29,10 @@ import cpw.mods.modlauncher.api.ITransformerVotingContext; import cpw.mods.modlauncher.api.TransformerVoteResult; import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.applaunch.transformation.SuperclassChangeTransformer; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.discovery.ResourceLoading; import java.net.URL; import java.util.*; @@ -41,10 +42,10 @@ public class VanillaSuperclassChangeTransformer extends SuperclassChangeTransfor private static final String MIXIN_PLUGIN_REASON = "mixin"; private static final String[] LABELS = { SuperclassChangeTransformer.NAME }; - private final VanillaPluginPlatform pluginPlatform; + private final PluginDiscovery discovery; - public VanillaSuperclassChangeTransformer(final VanillaPluginPlatform pluginPlatform) { - this.pluginPlatform = pluginPlatform; + public VanillaSuperclassChangeTransformer(final PluginDiscovery discovery) { + this.discovery = discovery; } @Override @@ -74,16 +75,14 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (final Set plugins : this.pluginPlatform.getResources().values()) { - for (final PluginResource plugin : plugins) { - final Optional attribute = plugin.property(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); - if (attribute.isPresent()) { - for (final String scPath : attribute.get().split(",")) { - try { - resources.add(plugin.locateResource(scPath).get().toURL()); - } catch (final Exception e) { - LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin.path().getFileName()); - } + for (final PluginResource plugin : this.discovery.resources(ResourceLoading.GAME_LIBRARY)) { + final Optional attribute = plugin.property(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); + if (attribute.isPresent()) { + for (final String scPath : attribute.get().split(",")) { + try { + resources.add(plugin.locateResource(scPath).get().toURL()); + } catch (final Exception e) { + LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin.path().getFileName()); } } } diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginLanguageService b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginLanguageService deleted file mode 100644 index 3e6983f38f8..00000000000 --- a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginLanguageService +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.vanilla.applaunch.plugin.JavaPluginLanguageService \ No newline at end of file diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService deleted file mode 100644 index cf8cd29b6e7..00000000000 --- a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.vanilla.applaunch.plugin.locator.SpongePropertyLocatorService \ No newline at end of file diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader new file mode 100644 index 00000000000..62c4d04f71e --- /dev/null +++ b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader @@ -0,0 +1 @@ +org.spongepowered.vanilla.applaunch.plugin.discovery.MinecraftMetadataReader diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator new file mode 100644 index 00000000000..8bac9b4cf51 --- /dev/null +++ b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -0,0 +1,2 @@ +org.spongepowered.vanilla.applaunch.plugin.discovery.SpongeVanillaResourceLocator +org.spongepowered.common.applaunch.plugin.discovery.SpongePropertyResourceLocator diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 66c37f503b4..31af1ab3ced 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -45,7 +45,6 @@ import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -114,9 +113,9 @@ public void setMetadata(@Nullable final PluginMetadata metadata) { // Resources this.categories.add( new Category("Resources") - .addEntry(new Entry("Homepage", metadata.links().homepage().map(URL::toString).orElse(null))) - .addEntry(new Entry("Issues", metadata.links().issues().map(URL::toString).orElse(null))) - .addEntry(new Entry("Source", metadata.links().source().map(URL::toString).orElse(null)))); + .addEntry(new Entry("Homepage", metadata.links().homepage().map(URI::toString).orElse(null))) + .addEntry(new Entry("Issues", metadata.links().issues().map(URI::toString).orElse(null))) + .addEntry(new Entry("Source", metadata.links().source().map(URI::toString).orElse(null)))); // Other this.categories.add(new Category("Other", diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaBootstrap.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaBootstrap.java index c37b7391c43..a221bcabff4 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaBootstrap.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaBootstrap.java @@ -34,7 +34,6 @@ import org.spongepowered.common.launch.Launch; import org.spongepowered.common.network.channel.SpongeChannelManager; import org.spongepowered.common.network.packet.SpongePacketHandler; -import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; import org.spongepowered.vanilla.launch.plugin.VanillaPluginManager; public final class VanillaBootstrap { @@ -50,7 +49,7 @@ public static void perform(final String engineName, final Runnable engineStart) Launch.instance().setLifecycle(lifecycle); lifecycle.establishFactories(); lifecycle.establishBuilders(); - ((VanillaPluginManager) Launch.instance().pluginManager()).loadPlugins((VanillaPluginPlatform) Launch.instance().pluginPlatform()); + ((VanillaPluginManager) Launch.instance().pluginManager()).loadPlugins(); lifecycle.callConstructEvent(); lifecycle.callRegisterFactoryEvent(); lifecycle.callRegisterBuilderEvent(); diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java index 34de7cbadd3..ad9cca94c8a 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java @@ -29,16 +29,17 @@ import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Stage; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.inject.SpongeCommonModule; import org.spongepowered.common.inject.SpongeModule; import org.spongepowered.common.launch.Launch; import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; import org.spongepowered.vanilla.launch.inject.SpongeVanillaModule; import org.spongepowered.vanilla.launch.plugin.VanillaDummyPluginContainer; import org.spongepowered.vanilla.launch.plugin.VanillaPluginManager; -import java.util.Collection; import java.util.List; import java.util.Set; @@ -52,7 +53,7 @@ public abstract class VanillaLaunch extends Launch { protected VanillaLaunch(final VanillaPluginPlatform pluginPlatform, final Stage injectionStage) { super(pluginPlatform); this.injectionStage = injectionStage; - this.pluginManager = new VanillaPluginManager(); + this.pluginManager = new VanillaPluginManager(this); } @Override @@ -73,11 +74,6 @@ public final PluginContainer platformPlugin() { return this.vanillaPlugin; } - @Override - public final VanillaPluginPlatform pluginPlatform() { - return (VanillaPluginPlatform) this.pluginPlatform; - } - @Override public final VanillaPluginManager pluginManager() { return this.pluginManager; @@ -102,9 +98,12 @@ protected final void launchPlatform(final String[] args) { protected abstract void performBootstrap(final String[] args); protected final void createPlatformPlugins() { - this.pluginPlatform().getCandidates().values().stream().flatMap(Collection::stream) - .filter(plugin -> PLATFORM_IDS.contains(plugin.metadata().id())) - .map(plugin -> new VanillaDummyPluginContainer(plugin, this.logger(), this)) - .forEach(this.pluginManager()::addPlugin); + for (final PluginDiscovery.Candidate candidate : this.pluginPlatform().discovery().candidates()) { + for (final PluginMetadata metadata : candidate.metadata()) { + if (VanillaLaunch.PLATFORM_IDS.contains(metadata.id())) { + this.pluginManager().addPlugin(new VanillaDummyPluginContainer(candidate.resource(), metadata, this)); + } + } + } } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java index e9de757aa15..28cf69a4eed 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java @@ -24,24 +24,15 @@ */ package org.spongepowered.vanilla.launch.plugin; -import com.google.inject.Injector; -import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.plugin.DummyPluginContainer; import org.spongepowered.common.launch.plugin.SpongePluginContainer; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.builtin.StandardPluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; -import java.util.Optional; +public final class VanillaDummyPluginContainer extends SpongePluginContainer implements DummyPluginContainer { -public final class VanillaDummyPluginContainer extends StandardPluginContainer implements SpongePluginContainer, DummyPluginContainer { - - public VanillaDummyPluginContainer(final PluginCandidate candidate, final Logger logger, final Object instance) { - super(candidate, logger); + public VanillaDummyPluginContainer(final PluginResource resource, final PluginMetadata metadata, final Object instance) { + super(resource, metadata); this.initializeInstance(instance); } - - @Override - public Optional injector() { - return Optional.empty(); - } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaJavaPluginContainer.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaJavaPluginContainer.java deleted file mode 100644 index 696596282af..00000000000 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaJavaPluginContainer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.vanilla.launch.plugin; - -import com.google.inject.Injector; -import org.spongepowered.api.Sponge; -import org.spongepowered.common.launch.plugin.SpongePluginContainer; -import org.spongepowered.plugin.PluginCandidate; -import org.spongepowered.plugin.builtin.StandardPluginContainer; - -import java.util.Optional; - -public final class VanillaJavaPluginContainer extends StandardPluginContainer implements SpongePluginContainer { - - private Injector injector; - - public VanillaJavaPluginContainer(final PluginCandidate candidate) { - super(candidate); - } - - @Override - protected void initializeInstance(final Object instance) { - super.initializeInstance(instance); - Sponge.eventManager().registerListeners(this, instance); - } - - @Override - public Optional injector() { - return Optional.ofNullable(this.injector); - } - - public void setInjector(final Injector injector) { - this.injector = injector; - } -} diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java index 319fc0c42a7..2932ff1047c 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java @@ -28,43 +28,33 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.apache.logging.log4j.Level; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.applaunch.plugin.PluginPlatform; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.launch.plugin.SpongePluginManager; +import org.spongepowered.common.launch.plugin.loader.PluginCandidate; import org.spongepowered.common.util.PrettyPrinter; -import org.spongepowered.plugin.InvalidPluginException; -import org.spongepowered.plugin.PluginCandidate; import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.PluginLanguageService; -import org.spongepowered.plugin.PluginLoader; -import org.spongepowered.plugin.PluginResource; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginDependency; -import org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform; import org.spongepowered.vanilla.launch.VanillaLaunch; import org.spongepowered.vanilla.launch.plugin.resolver.DependencyResolver; import org.spongepowered.vanilla.launch.plugin.resolver.ResolutionResult; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @Singleton public final class VanillaPluginManager implements SpongePluginManager { + private final VanillaLaunch launch; private final Map plugins; private final Map instancesToPlugins; private final List sortedPlugins; private final Map containerToResource; private boolean ready = false; - public VanillaPluginManager() { + public VanillaPluginManager(final VanillaLaunch launch) { + this.launch = launch; this.plugins = new Object2ObjectOpenHashMap<>(); this.instancesToPlugins = new IdentityHashMap<>(); this.sortedPlugins = new ArrayList<>(); @@ -86,33 +76,31 @@ public Collection plugins() { return Collections.unmodifiableCollection(this.sortedPlugins); } - public void loadPlugins(final VanillaPluginPlatform platform) { - final Map pluginLanguageLookup = new HashMap<>(); - final Map> pluginLoaders = new HashMap<>(); - - // Initialise the plugin language loaders. - for (final Map.Entry> candidate : platform.getCandidates().entrySet()) { - final PluginLanguageService languageService = candidate.getKey(); - final String loaderClass = languageService.pluginLoader(); - try { - pluginLoaders.put(languageService, (PluginLoader) Class.forName(loaderClass).getConstructor().newInstance()); - } catch (final InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) { - throw new RuntimeException(e); + public void loadPlugins() { + final PluginPlatform platform = this.launch.pluginPlatform(); + + final List prioritizedCandidates = new LinkedList<>(); + final List candidates = new LinkedList<>(); + for (final PluginDiscovery.Candidate resourceCandidate : platform.discovery().candidates()) { + for (final PluginMetadata metadata : resourceCandidate.metadata()) { + final List target = this.plugins.containsKey(metadata.id()) ? prioritizedCandidates : candidates; + try { + target.add(this.launch.pluginFactory().create(resourceCandidate.resource(), metadata)); + } catch (final Exception e) { + platform.logger().error("Cannot create plugin {}.", metadata.id(), e); + } } - candidate.getValue().forEach(x -> pluginLanguageLookup.put(x, languageService)); } // Priority to platform plugins that will already exist here -- meaning the resolver will act upon them first // and if someone decides to give a plugin an ID that is the same as a platform plugin, the resolver will effectively // reject it. - final Set resources = new LinkedHashSet<>(); - pluginLanguageLookup.keySet().stream().filter(x -> this.plugins.containsKey(x.metadata().id())).forEach(resources::add); - resources.addAll(pluginLanguageLookup.keySet()); + candidates.addAll(0, prioritizedCandidates); - final ResolutionResult resolutionResult = DependencyResolver.resolveAndSortCandidates(resources, platform.logger()); + final ResolutionResult resolutionResult = DependencyResolver.resolveAndSortCandidates(candidates, platform.logger()); final Map failedInstances = new HashMap<>(); final Map consequentialFailedInstances = new HashMap<>(); - final ClassLoader launchClassloader = VanillaLaunch.instance().getClass().getClassLoader(); + for (final PluginCandidate candidate : resolutionResult.sortedSuccesses()) { final String id = candidate.metadata().id(); if (id.indexOf('-') >= 0) { @@ -149,13 +137,11 @@ public void loadPlugins(final VanillaPluginPlatform platform) { // If a dependency failed to load, then we should bail on required dependencies too. // This should work fine, we're sorted so all deps should be in place at this stage. if (this.stillValid(candidate, consequentialFailedInstances)) { - final PluginLanguageService languageService = pluginLanguageLookup.get(candidate); - final PluginLoader pluginLoader = pluginLoaders.get(languageService); try { - final PluginContainer container = pluginLoader.loadPlugin(platform.getEnvironment(), candidate, launchClassloader); + final PluginContainer container = candidate.load(); this.addPlugin(container); this.containerToResource.put(container, candidate.resource()); - } catch (final InvalidPluginException e) { + } catch (final Exception e) { failedInstances.put(candidate, "Failed to construct: see stacktrace(s) above this message for details."); platform.logger().error("Failed to construct plugin {}", id, e); } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java index 3d53223bac9..736147410f4 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java @@ -25,11 +25,9 @@ package org.spongepowered.vanilla.launch.plugin.resolver; import org.apache.logging.log4j.Logger; -import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.artifact.versioning.VersionRange; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.util.Tuple; -import org.spongepowered.plugin.PluginCandidate; +import org.spongepowered.common.launch.plugin.loader.PluginCandidate; +import org.spongepowered.common.launch.plugin.loader.VersionChecker; import org.spongepowered.plugin.metadata.model.PluginDependency; import java.util.ArrayList; @@ -40,7 +38,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -83,7 +80,7 @@ public static ResolutionResult resolveAndSortCandidates(final Collection nodes, final ResolutionResult resolutionResult) { for (final Node node : nodes) { if (!node.checked) { diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/ResolutionResult.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/ResolutionResult.java index fb1124b893b..1ce1652bfcd 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/ResolutionResult.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/ResolutionResult.java @@ -27,8 +27,8 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.spongepowered.api.util.Tuple; +import org.spongepowered.common.launch.plugin.loader.PluginCandidate; import org.spongepowered.common.util.PrettyPrinter; -import org.spongepowered.plugin.PluginCandidate; import java.util.Collection; import java.util.HashMap; diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java index 7d2b6972662..a512faf69e9 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java @@ -36,8 +36,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.launch.Launch; import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.PluginResource; -import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; import org.spongepowered.vanilla.bridge.server.packs.repository.PackRepositoryBridge_Vanilla; import org.spongepowered.vanilla.launch.plugin.VanillaPluginManager; @@ -66,8 +66,8 @@ public void loadPacks(final Consumer callback) { final PluginResource resource = pluginManager.resource(pluginContainer); // TODO: provide hook in the resource to return the file system for all resource types? @Nullable Path pluginRoot = null; - if (resource instanceof JVMPluginResource jvmResource) { - pluginRoot = jvmResource.resourcesRoot(); + if (resource instanceof SecureJarPluginResource jarResource) { + pluginRoot = jarResource.jar().getRootPath(); } final PackLocationInfo info = new PackLocationInfo(id, Component.literal(id), PackSource.DEFAULT, Optional.empty()); From ddce1100329f8ee8a927344852c2856c11ff1a88 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 20 Jun 2026 20:43:41 +0200 Subject: [PATCH 550/586] Remove Container and Inheritable from plugin-meta --- .../mod/metadata/PluginFileConfigurable.java | 5 ++- .../plugin/PluginMetadataConverter.java | 39 ++++++++++++++++--- .../mod/metadata/PluginFileConfigurable.java | 5 ++- .../plugin/PluginMetadataConverter.java | 38 +++++++++++++++--- .../plugin/discovery/PluginDiscovery.java | 13 +++++-- .../plugin/loader/PluginCandidateFactory.java | 4 +- .../discovery/MinecraftMetadataReader.java | 2 +- 7 files changed, 84 insertions(+), 22 deletions(-) diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java index f09095d83c0..4b5e39fcff0 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -68,8 +68,9 @@ public Optional getConfigElement(final String... key) { } if ("license".equals(query)) { - return Optional.of((T) this.plugins.values().stream() - .map(m -> m.container().license()).distinct().collect(Collectors.joining(", "))); + final String joinedLicenses = this.plugins.values().stream() + .flatMap(m -> m.license().stream()).distinct().collect(Collectors.joining(", ")); + return Optional.of((T) (joinedLicenses.isEmpty() ? "?" : joinedLicenses)); } if (key.length == 2) { diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java index d9c6eed0e1d..9b30c9c741c 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java @@ -25,28 +25,50 @@ package org.spongepowered.forge.launch.plugin; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; +import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.language.IModInfo; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.builtin.InheritableMetadata; import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; import org.spongepowered.plugin.metadata.model.PluginContributor; import org.spongepowered.plugin.metadata.model.PluginDependency; import org.spongepowered.plugin.metadata.model.PluginLinks; +import org.spongepowered.plugin.metadata.model.PluginLoaderSpecification; import java.net.URISyntaxException; import java.net.URL; +import java.util.List; import java.util.Optional; public final class PluginMetadataConverter { + private static final VersionRange ANY_VERSION; + + static { + try { + ANY_VERSION = VersionRange.createFromVersionSpec("*"); + } catch (InvalidVersionSpecificationException e) { + throw new RuntimeException(e); + } + } @SuppressWarnings("UnstableApiUsage") public static PluginMetadata modToPlugin(final ModInfo info) { - final StandardPluginMetadata.Builder builder = StandardPluginMetadata.builder(); - builder - .id(info.getModId()) + final List loaders = info.getOwningFile().requiredLanguageLoaders(); + final PluginLoaderSpecification loaderSpec; + if (loaders.isEmpty()) { + loaderSpec = new PluginLoaderSpecification("forge", PluginMetadataConverter.ANY_VERSION); + } else { + final VersionRange loaderVersion = loaders.getFirst().acceptedVersions(); + loaderSpec = new PluginLoaderSpecification("forge:" + loaders.getFirst().languageName(), loaderVersion == null ? PluginMetadataConverter.ANY_VERSION : loaderVersion); + } + + final InheritableMetadata.Builder builder = InheritableMetadata.builder() .name(info.getDisplayName()) - .version(info.getVersion().toString()) + .version(info.getVersion()) + .loader(loaderSpec) .description(info.getDescription()) - .entrypoint("unknown") .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); @@ -63,7 +85,12 @@ public static PluginMetadata modToPlugin(final ModInfo info) { false )); } - return builder.build(); + + return StandardPluginMetadata.builder() + .id(info.getModId()) + .entrypoint("unknown") + .override(builder.build()) + .build(); } private static PluginDependency.LoadOrder orderingToLoad(final IModInfo.Ordering ordering) { diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java index 40deaa2c37c..bd499cffe32 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -64,8 +64,9 @@ public Optional getConfigElement(final String... key) { } if ("license".equals(query)) { - return Optional.of((T) this.plugins.values().stream() - .map(m -> m.container().license()).distinct().collect(Collectors.joining(", "))); + final String joinedLicenses = this.plugins.values().stream() + .flatMap(m -> m.license().stream()).distinct().collect(Collectors.joining(", ")); + return Optional.of((T) (joinedLicenses.isEmpty() ? "?" : joinedLicenses)); } if (key.length == 2) { diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java index 34b1983f53e..08e2ddba29d 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java @@ -25,27 +25,50 @@ package org.spongepowered.neoforge.launch.plugin; import net.neoforged.fml.loading.moddiscovery.ModInfo; +import net.neoforged.neoforgespi.language.IModFileInfo; import net.neoforged.neoforgespi.language.IModInfo; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.builtin.InheritableMetadata; import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; import org.spongepowered.plugin.metadata.model.PluginContributor; import org.spongepowered.plugin.metadata.model.PluginDependency; import org.spongepowered.plugin.metadata.model.PluginLinks; +import org.spongepowered.plugin.metadata.model.PluginLoaderSpecification; import java.net.URISyntaxException; import java.net.URL; +import java.util.List; import java.util.Optional; public final class PluginMetadataConverter { + private static final VersionRange ANY_VERSION; + + static { + try { + ANY_VERSION = VersionRange.createFromVersionSpec("*"); + } catch (InvalidVersionSpecificationException e) { + throw new RuntimeException(e); + } + } public static PluginMetadata modToPlugin(final ModInfo info) { - final StandardPluginMetadata.Builder builder = StandardPluginMetadata.builder(); + final List loaders = info.getOwningFile().requiredLanguageLoaders(); + final PluginLoaderSpecification loaderSpec; + if (loaders.isEmpty()) { + loaderSpec = new PluginLoaderSpecification("neoforge", PluginMetadataConverter.ANY_VERSION); + } else { + final VersionRange loaderVersion = loaders.getFirst().acceptedVersions(); + loaderSpec = new PluginLoaderSpecification("neoforge:" + loaders.getFirst().languageName(), loaderVersion == null ? PluginMetadataConverter.ANY_VERSION : loaderVersion); + } + + final InheritableMetadata.Builder builder = InheritableMetadata.builder(); builder - .id(info.getModId()) .name(info.getDisplayName()) - .version(info.getVersion().toString()) + .version(info.getVersion()) + .loader(loaderSpec) .description(info.getDescription()) - .entrypoint("unknown") .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); @@ -62,7 +85,12 @@ public static PluginMetadata modToPlugin(final ModInfo info) { false )); } - return builder.build(); + + return StandardPluginMetadata.builder() + .id(info.getModId()) + .entrypoint("unknown") + .override(builder.build()) + .build(); } private static PluginDependency.LoadOrder orderingToLoad(final IModInfo.Ordering ordering) { diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java index e966582ffde..77c6b28f950 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -148,7 +148,7 @@ public final class Candidate { private final PluginResource resource; private final List locators = new ArrayList<>(); private @MonotonicNonNull UnknownResourceStrategy unknownResourceStrategy; - private final SequencedSet metadata = new LinkedHashSet<>(); + private final SequencedMap metadata = new LinkedHashMap<>(); private boolean locatorFound, readerFound, loaderFound, modFound; public Candidate(final PluginResource resource, final UnknownResourceStrategy unknownResourceStrategy) { @@ -194,16 +194,21 @@ public List locators() { public void readMetadata() { this.metadata.clear(); for (final PluginMetadataReader reader : PluginDiscovery.this.readers) { + final Collection plugins; try { - this.metadata.addAll(reader.readPluginMetadata(PluginDiscovery.this.environment, this.resource, this.locators())); + plugins = reader.readPluginMetadata(PluginDiscovery.this.environment, this.resource, this.locators()); } catch (final Exception e) { PluginDiscovery.this.environment.logger().error("Service '{}' failed to read plugin metadata", reader.name(), e); + continue; + } + for (final PluginMetadata plugin : plugins) { + this.metadata.put(plugin.id(), plugin); } } } - public SequencedSet metadata() { - return Collections.unmodifiableSequencedSet(this.metadata); + public SequencedCollection metadata() { + return Collections.unmodifiableSequencedCollection(this.metadata.sequencedValues()); } public boolean pluginFound() { diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java index 9764eb780ca..205de251b6d 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java @@ -29,7 +29,7 @@ import org.spongepowered.plugin.PluginLoader; import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import org.spongepowered.plugin.metadata.model.ContainerLoader; +import org.spongepowered.plugin.metadata.model.PluginLoaderSpecification; import java.util.Map; import java.util.NoSuchElementException; @@ -49,7 +49,7 @@ protected ServiceLoader newServiceLoader(final Class serviceClass) { } public PluginCandidate create(final PluginResource resource, final PluginMetadata metadata) { - final ContainerLoader loaderSpec = metadata.container().loader(); + final PluginLoaderSpecification loaderSpec = metadata.loader(); final PluginLoader loader = this.loaders.get(loaderSpec.name()); if (loader == null) { throw new NoSuchElementException("Cannot find loader " + loaderSpec.name()); diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java index c8406525ecf..e92ef203eaa 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java @@ -58,7 +58,7 @@ public Collection readPluginMetadata(final Environment } try (final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { - return MetadataParser.read(reader).metadata(); + return MetadataParser.read(reader).plugins(); } } return List.of(); From 63505e3055943c7c1413f2c7c5df0cde4f04f51e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 28 Jun 2026 23:12:45 +0200 Subject: [PATCH 551/586] Allow multiple entrypoints per plugin --- .../launch/plugin/ForgePluginContainer.java | 1 + .../launch/plugin/ForgePluginManager.java | 1 + .../plugin/PluginMetadataConverter.java | 1 - .../launch/plugin/PluginModContainer.java | 3 ++- .../launch/plugin/NeoPluginContainer.java | 6 ------ .../launch/plugin/NeoPluginManager.java | 1 + .../plugin/PluginMetadataConverter.java | 1 - .../common/command/sponge/SpongeCommand.java | 2 -- .../common/inject/plugin/PluginGuice.java | 7 ++++--- .../inject/plugin/PrivatePluginModule.java | 14 ++++++++----- .../launch/plugin/SpongePluginContainer.java | 13 +++++++++--- .../plugin/loader/JavaPluginLoader.java | 21 +++++++++++++------ .../client/gui/widget/MetadataPanel.java | 5 +++-- .../vanilla/launch/VanillaLaunch.java | 2 +- .../plugin/VanillaDummyPluginContainer.java | 3 +-- .../launch/plugin/VanillaPluginManager.java | 2 ++ 16 files changed, 50 insertions(+), 33 deletions(-) diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java index 1d5e58138a7..22836ad946a 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java @@ -75,6 +75,7 @@ public Optional locateResource(String relative) { return Files.exists(p) ? Optional.of(p.toUri()) : Optional.empty(); } + @SuppressWarnings("removal") @Override public Object instance() { return this.modContainer.getMod(); diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java index c3ae1d2c9d1..ee2852b8c63 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginManager.java @@ -37,6 +37,7 @@ @Singleton public final class ForgePluginManager implements SpongePluginManager { + @SuppressWarnings("removal") @Override public Optional fromInstance(final Object instance) { return ModList.get().getModContainerByObject(Objects.requireNonNull(instance, "instance")).flatMap(ForgePluginContainer::of); diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java index 9b30c9c741c..311137aa8b2 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java @@ -88,7 +88,6 @@ public static PluginMetadata modToPlugin(final ModInfo info) { return StandardPluginMetadata.builder() .id(info.getModId()) - .entrypoint("unknown") .override(builder.build()) .build(); } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index aa37cf1e883..249fc3044fe 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -119,9 +119,10 @@ private void constructPlugin() { @Override public boolean matches(Object mod) { - return mod == this.container.instance(); + return mod == this.getMod(); } + @SuppressWarnings("removal") @Override public Object getMod() { return this.container.instance(); diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java index 31371283ccf..ecc06cbfaa8 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java @@ -41,7 +41,6 @@ public class NeoPluginContainer implements PluginContainer { private final ModContainer modContainer; private final JarContents jar; - private final Object instance = new Object(); private Logger logger; private PluginMetadata pluginMetadata; @@ -72,11 +71,6 @@ public Optional locateResource(final String relative) { return this.jar.findFile(Objects.requireNonNull(relative, "relative")); } - @Override - public Object instance() { - return this.instance; - } - private static final Map mods = new MapMaker().weakKeys().makeMap(); public static Optional of(final ModContainer modContainer) { diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java index 4c7c1897549..9eb003f1c66 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginManager.java @@ -38,6 +38,7 @@ @Singleton public final class NeoPluginManager implements SpongePluginManager { + @SuppressWarnings("removal") @Override public Optional fromInstance(final Object instance) { for (final ModContainer mod : ModList.get().getSortedMods()) { diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java index 08e2ddba29d..d09c56d978c 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java @@ -88,7 +88,6 @@ public static PluginMetadata modToPlugin(final ModInfo info) { return StandardPluginMetadata.builder() .id(info.getModId()) - .entrypoint("unknown") .override(builder.build()) .build(); } diff --git a/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java b/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java index 32229c68b34..5a89efe23ce 100644 --- a/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java +++ b/src/main/java/org/spongepowered/common/command/sponge/SpongeCommand.java @@ -691,8 +691,6 @@ private Component createContainerMeta(final PluginMetadata pluginMetadata) { contributor.description().ifPresent(x -> builder.append(Component.text(" (" + x + ")"))); } } - - this.appendPluginMeta(builder, "Entrypoint", pluginMetadata.entrypoint()); return builder.build(); } diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java index ca7fcad4725..d35a7e76d08 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java @@ -31,17 +31,18 @@ import org.spongepowered.plugin.PluginContainer; import java.util.ArrayList; +import java.util.Collection; import java.util.List; public final class PluginGuice { - public static Injector create(final PluginContainer container, final Class pluginClass, final @Nullable Injector platformInjector) { - final List modules = new ArrayList<>(List.of(new PublicPluginModule(container), new PrivatePluginModule(container, pluginClass))); + public static Injector create(final PluginContainer container, final Collection> pluginClasses, final @Nullable Injector platformInjector) { + final List modules = new ArrayList<>(List.of(new PublicPluginModule(container), new PrivatePluginModule(container, pluginClasses))); final @Nullable Object customModule = container.metadata().property("guice-module").orElse(null); if (customModule != null) { try { - final Class moduleClass = Class.forName(customModule.toString(), true, pluginClass.getClassLoader()); + final Class moduleClass = Class.forName(customModule.toString()); final Module moduleInstance = (Module) moduleClass.getConstructor().newInstance(); modules.add(moduleInstance); } catch (final Exception ex) { diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java b/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java index 4b52f073d9c..f70c2de1159 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java @@ -31,6 +31,8 @@ import org.spongepowered.common.inject.provider.PluginConfigurationModule; import org.spongepowered.plugin.PluginContainer; +import java.util.Collection; + /** * A module installed for each plugin. @@ -41,17 +43,19 @@ public final class PrivatePluginModule extends PrivateModule { private final PluginContainer container; - private final Class pluginClass; + private final Collection> pluginClasses; - PrivatePluginModule(final PluginContainer container, final Class pluginClass) { + PrivatePluginModule(final PluginContainer container, final Collection> pluginClasses) { this.container = container; - this.pluginClass = pluginClass; + this.pluginClasses = pluginClasses; } @Override protected void configure() { - this.bind(this.pluginClass).in(Scopes.SINGLETON); - this.expose(this.pluginClass); + for (final Class pluginClass : this.pluginClasses) { + this.bind(pluginClass).in(Scopes.SINGLETON); + this.expose(pluginClass); + } this.install(new InjectionPointProvider()); diff --git a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java index 898beda7b5c..fc3e5820fda 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java @@ -32,16 +32,23 @@ import java.util.Optional; public class SpongePluginContainer extends StandardPluginContainer { - + private Object instance = this; private Injector injector; public SpongePluginContainer(final PluginResource resource, final PluginMetadata metadata) { super(resource, metadata); } + @SuppressWarnings("removal") @Override - public void initializeInstance(final Object instance) { - super.initializeInstance(instance); + public Object instance() { + return this.instance; + } + + public void setInstanceIfMissing(final Object instance) { + if (this.instance == this) { + this.instance = instance; + } } public Optional injector() { diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java index 749b71f6641..7d0052e0ae1 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java @@ -35,6 +35,9 @@ import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; +import java.util.ArrayList; +import java.util.List; + public final class JavaPluginLoader implements PluginLoader { private static final ArtifactVersion version = new DefaultArtifactVersion("1.0"); @@ -51,15 +54,21 @@ public String name() { @Override public PluginContainer loadPlugin(Environment environment, PluginResource resource, PluginMetadata metadata) throws Exception { final SpongePluginContainer container = new SpongePluginContainer(resource, metadata); - final String mainClass = container.metadata().entrypoint(); - final Class pluginClass = Class.forName(mainClass); - final Injector pluginInjector = PluginGuice.create(container, pluginClass, Launch.instance().lifecycle().platformInjector()); - final Object plugin = pluginInjector.getInstance(pluginClass); + final List> pluginClasses = new ArrayList<>(); + for (final String className : container.metadata().entrypoints().main()) { + pluginClasses.add(Class.forName(className)); + } + + final Injector pluginInjector = PluginGuice.create(container, pluginClasses, Launch.instance().lifecycle().platformInjector()); container.setInjector(pluginInjector); - container.initializeInstance(plugin); - Sponge.eventManager().registerListeners(container, plugin); + for (final Class pluginClass : pluginClasses) { + final Object plugin = pluginInjector.getInstance(pluginClass); + container.setInstanceIfMissing(plugin); + Sponge.eventManager().registerListeners(container, plugin); + } + return container; } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java index 31af1ab3ced..2798e7dc725 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/client/gui/widget/MetadataPanel.java @@ -92,8 +92,9 @@ public void setMetadata(@Nullable final PluginMetadata metadata) { // Details this.categories.add(new Category("Details") - .addEntry(new Entry("ID", metadata.id())).addEntry(new Entry("Name", metadata.name().orElse(null))) - .addEntry(new Entry("Version", metadata.version().toString())).addEntry(new Entry("Entry", metadata.entrypoint())) + .addEntry(new Entry("ID", metadata.id())) + .addEntry(new Entry("Name", metadata.name().orElse(null))) + .addEntry(new Entry("Version", metadata.version().toString())) .addEntry(new Entry("Description", metadata.description().orElse(null)))); // Contributors diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java index ad9cca94c8a..219edd712bf 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/VanillaLaunch.java @@ -101,7 +101,7 @@ protected final void createPlatformPlugins() { for (final PluginDiscovery.Candidate candidate : this.pluginPlatform().discovery().candidates()) { for (final PluginMetadata metadata : candidate.metadata()) { if (VanillaLaunch.PLATFORM_IDS.contains(metadata.id())) { - this.pluginManager().addPlugin(new VanillaDummyPluginContainer(candidate.resource(), metadata, this)); + this.pluginManager().addPlugin(new VanillaDummyPluginContainer(candidate.resource(), metadata)); } } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java index 28cf69a4eed..ee96a863e7a 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java @@ -31,8 +31,7 @@ public final class VanillaDummyPluginContainer extends SpongePluginContainer implements DummyPluginContainer { - public VanillaDummyPluginContainer(final PluginResource resource, final PluginMetadata metadata, final Object instance) { + public VanillaDummyPluginContainer(final PluginResource resource, final PluginMetadata metadata) { super(resource, metadata); - this.initializeInstance(instance); } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java index 2932ff1047c..b57964f363b 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java @@ -61,6 +61,7 @@ public VanillaPluginManager(final VanillaLaunch launch) { this.containerToResource = new Object2ObjectOpenHashMap<>(); } + @SuppressWarnings("removal") @Override public Optional fromInstance(final Object instance) { return Optional.ofNullable(this.instancesToPlugins.get(Objects.requireNonNull(instance, "instance"))); @@ -154,6 +155,7 @@ public void loadPlugins() { this.ready = true; } + @SuppressWarnings("removal") public void addPlugin(final PluginContainer plugin) { this.plugins.put(plugin.metadata().id(), Objects.requireNonNull(plugin, "plugin")); this.sortedPlugins.add(plugin); From 90f6e1ca93ae2eb7ee3106306a3d2db19d360b7f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 6 Jul 2026 23:02:15 +0200 Subject: [PATCH 552/586] Prevent batches for already known discovery services --- .../applaunch/plugin/PluginServiceLoader.java | 12 +++--- .../plugin/discovery/PluginDiscovery.java | 39 ++++++++++++------- .../plugin/loader/PluginCandidateFactory.java | 7 +++- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java index dddd142ea19..71c333222c2 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginServiceLoader.java @@ -27,8 +27,8 @@ import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.PluginService; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.function.Predicate; @@ -40,12 +40,12 @@ protected PluginServiceLoader(final Environment environment) { this.environment = environment; } - protected final Map loadServices(final String serviceDescription, final Class serviceClass) { + protected final List loadServices(final String serviceDescription, final Class serviceClass) { return this.loadServices(serviceDescription, serviceClass, c -> true); } - protected final Map loadServices(final String serviceDescription, final Class serviceClass, final Predicate> filter) { - final Map services = new HashMap<>(); + protected final List loadServices(final String serviceDescription, final Class serviceClass, final Predicate> filter) { + final List services = new ArrayList<>(); this.newServiceLoader(serviceClass).stream() .filter(provider -> filter.test(provider.type())) .forEach(provider -> { @@ -58,7 +58,7 @@ protected final Map loadServices(final Stri } this.environment.logger().info("Found {} '{}'.", serviceDescription, service.name()); - services.put(service.name(), service); + services.add(service); }); return services; } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java index 77c6b28f950..49aac41b650 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -39,7 +39,7 @@ public abstract class PluginDiscovery extends PluginServiceLoader { private Map candidates; - private Collection readers; + private List readers; protected PluginDiscovery(final Environment environment) { super(environment); @@ -47,7 +47,10 @@ protected PluginDiscovery(final Environment environment) { public final void discoverPluginResources() { final Map candidates = new HashMap<>(); - final Set> locatorsFound = new HashSet<>(); + final List readers = new ArrayList<>(); + + final Set locatorClasses = new HashSet<>(); + final Set readerClasses = new HashSet<>(); int maxBatches = 10; final String maxBatchesProp = System.getProperty("sponge.discovery.maxBatches"); @@ -60,11 +63,13 @@ public final void discoverPluginResources() { int batch = 1; while (true) { - this.environment.logger().info("Running plugin locators batch #{} ...", batch); + this.environment.logger().info("Running discovery batch #{} ...", batch); final List batchServices = new ArrayList<>(); - for (final PluginResourceLocator locator : this.loadServices("resource locator", PluginResourceLocator.class, locatorsFound::add).values()) { + readers.addAll(this.loadServices("metadata reader", PluginMetadataReader.class, cl -> readerClasses.add(cl.getName()))); + + for (final PluginResourceLocator locator : this.loadServices("resource locator", PluginResourceLocator.class, cl -> locatorClasses.add(cl.getName()))) { final Collection results; try { results = locator.locatePluginResources(this.environment); @@ -79,8 +84,8 @@ public final void discoverPluginResources() { if (candidate == null) { candidate = new Candidate(result.resource(), result.unknownResourceStrategy()); candidates.put(result.resource(), candidate); - candidate.detectServices(); - if (candidate.locatorFound || candidate.readerFound) { + candidate.detectServices(locatorClasses, readerClasses); + if (candidate.newDiscoveryServiceFound) { batchServices.add((SpongeJVMPluginResource) result.resource()); } } else { @@ -96,7 +101,7 @@ public final void discoverPluginResources() { } if (++batch > maxBatches) { - this.environment.logger().warn("Max locator batches reached."); + this.environment.logger().warn("Max batches reached."); break; } @@ -112,8 +117,6 @@ public final void discoverPluginResources() { this.environment.logger().debug("Found {} located by [{}] ({}).", candidate.resource, candidate.locatorNames(), candidate.serviceNames()); } - final Collection readers = this.loadServices("metadata reader", PluginMetadataReader.class).values(); - this.candidates = candidates; this.readers = readers; } @@ -150,6 +153,7 @@ public final class Candidate { private @MonotonicNonNull UnknownResourceStrategy unknownResourceStrategy; private final SequencedMap metadata = new LinkedHashMap<>(); private boolean locatorFound, readerFound, loaderFound, modFound; + private boolean newDiscoveryServiceFound; public Candidate(final PluginResource resource, final UnknownResourceStrategy unknownResourceStrategy) { this.resource = resource; @@ -160,12 +164,19 @@ public PluginResource resource() { return this.resource; } - private void detectServices() { + private void detectServices(final Set existingLocators, final Set existingReaders) { if (this.resource instanceof SpongeJVMPluginResource jvmResource) { - final Set services = jvmResource.module().provides().stream().map(ModuleDescriptor.Provides::service).collect(Collectors.toSet()); - this.locatorFound = services.contains(PluginResourceLocator.class.getName()); - this.readerFound = services.contains(PluginMetadataReader.class.getName()); - this.loaderFound = services.contains(PluginLoader.class.getName()); + final Map> providers = new HashMap<>(); + for (final ModuleDescriptor.Provides provides : jvmResource.module().provides()) { + providers.put(provides.service(), provides.providers()); + } + final List locators = providers.getOrDefault(PluginResourceLocator.class.getName(), Collections.emptyList()); + final List readers = providers.getOrDefault(PluginMetadataReader.class.getName(), Collections.emptyList()); + final List loaders = providers.getOrDefault(PluginLoader.class.getName(), Collections.emptyList()); + this.locatorFound = !locators.isEmpty(); + this.readerFound = !readers.isEmpty(); + this.loaderFound = !loaders.isEmpty(); + this.newDiscoveryServiceFound = locators.stream().anyMatch(key -> !existingLocators.contains(key)) || readers.stream().anyMatch(key -> !existingReaders.contains(key)); } } diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java index 205de251b6d..e3e896d571c 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java @@ -31,16 +31,19 @@ import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginLoaderSpecification; +import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.ServiceLoader; public final class PluginCandidateFactory extends PluginServiceLoader { - private final Map loaders; + private final Map loaders = new HashMap<>(); public PluginCandidateFactory(final Environment environment) { super(environment); - this.loaders = this.loadServices("plugin loader", PluginLoader.class); + for (final PluginLoader loader : this.loadServices("plugin loader", PluginLoader.class)) { + this.loaders.put(loader.name(), loader); + } } @Override From 0683b592748040f565353a1fc3fb97df144d9f95 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 8 Jul 2026 23:44:12 +0200 Subject: [PATCH 553/586] PluginResource can be backed by multiple paths --- .../discovery/SecureJarPluginResource.java | 22 ++++++++++--------- .../mod/discovery/SpongeNeoModLocator.java | 3 ++- .../discovery/JarContentsPluginResource.java | 20 ++++++++--------- .../plugin/VanillaTransformationService.java | 18 +++++++-------- .../discovery/MinecraftMetadataReader.java | 2 +- .../discovery/SecureJarPluginResource.java | 20 +++++++++-------- .../VanillaAccessWidenerTransformer.java | 2 +- .../VanillaSuperclassChangeTransformer.java | 2 +- 8 files changed, 47 insertions(+), 42 deletions(-) diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java index 2397b22120e..8b304c4d765 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -32,13 +32,14 @@ import java.lang.module.ModuleDescriptor; import java.net.URI; import java.nio.file.Path; -import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.jar.Manifest; public final class SecureJarPluginResource implements SpongeJVMPluginResource { - private final Path[] paths; + private final Path[] pathsArray; + private final List paths; private final SecureJar jar; public SecureJarPluginResource(final Path[] paths) { @@ -46,7 +47,8 @@ public SecureJarPluginResource(final Path[] paths) { if (paths.length == 0) { throw new IllegalArgumentException("Need at least one path"); } - this.paths = paths; + this.pathsArray = paths; + this.paths = List.of(paths); this.jar = SecureJar.from(jar -> new PluginJarMetadata(jar, paths), paths); } @@ -55,17 +57,17 @@ public SecureJar jar() { } public SecureJar pluginJar(final PluginMetadata metadata) { - return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.paths); + return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.pathsArray); } @SuppressWarnings("UnstableApiUsage") public SecureJar modJar(final ModJarMetadata metadata) { - return SecureJar.from(jar -> metadata, this.paths); + return SecureJar.from(jar -> metadata, this.pathsArray); } @Override - public Path path() { - return this.jar.getPrimaryPath(); + public List paths() { + return this.paths; } @Override @@ -91,16 +93,16 @@ public boolean equals(Object obj) { if (!(obj instanceof SecureJarPluginResource that)) { return false; } - return Arrays.equals(this.paths, that.paths); + return this.paths.equals(that.paths); } @Override public int hashCode() { - return Arrays.hashCode(this.paths); + return this.paths.hashCode(); } @Override public String toString() { - return "SecureJarPluginResource[paths=" + Arrays.toString(this.paths) + "]"; + return "SecureJarPluginResource[paths=" + this.paths + "]"; } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index 475b60cd5c4..caaec6a79bc 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -66,11 +66,12 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) for (final PluginDiscovery.Candidate candidate : this.discovery.candidates()) { if (candidate.resource() instanceof JarContentsPluginResource resource) { // skip duplicates - if (!context.addLocated(resource.path())) { + if (resource.paths().stream().anyMatch(context::isLocated)) { candidate.setModFound(); candidate.logResult(); continue; } + resource.paths().forEach(context::addLocated); // attempt to load as mod or plugin IModFile modFile = null; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java index 67a9d75d70b..789d329f974 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java @@ -33,13 +33,13 @@ import java.lang.module.ModuleDescriptor; import java.net.URI; import java.nio.file.Path; -import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.jar.Manifest; public final class JarContentsPluginResource implements SpongeJVMPluginResource { - private final Path[] paths; + private final List paths; private final JarContents jar; public JarContentsPluginResource(final Path[] paths) { @@ -47,9 +47,9 @@ public JarContentsPluginResource(final Path[] paths) { if (paths.length == 0) { throw new IllegalArgumentException("Need at least one path"); } - this.paths = paths; + this.paths = List.of(paths); try { - this.jar = JarContents.ofPaths(Arrays.asList(paths)); + this.jar = JarContents.ofPaths(this.paths); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -57,7 +57,7 @@ public JarContentsPluginResource(final Path[] paths) { public JarContentsPluginResource(final JarContents jar) { Objects.requireNonNull(jar, "jar"); - this.paths = jar.getContentRoots().toArray(new Path[0]); + this.paths = List.copyOf(jar.getContentRoots()); this.jar = jar; } @@ -66,8 +66,8 @@ public JarContents jar() { } @Override - public Path path() { - return this.jar.getPrimaryPath(); + public List paths() { + return this.paths; } @Override @@ -93,16 +93,16 @@ public boolean equals(Object obj) { if (!(obj instanceof JarContentsPluginResource that)) { return false; } - return Arrays.equals(this.paths, that.paths); + return this.paths.equals(that.paths); } @Override public int hashCode() { - return Arrays.hashCode(this.paths); + return this.paths.hashCode(); } @Override public String toString() { - return "JarContentsPluginResource[paths=" + Arrays.toString(this.paths) + "]"; + return "JarContentsPluginResource[paths=" + this.paths + "]"; } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java index a8048fd4df9..6afef8f3732 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java @@ -40,6 +40,7 @@ import org.spongepowered.vanilla.applaunch.transformation.VanillaAccessWidenerTransformer; import org.spongepowered.vanilla.applaunch.transformation.VanillaSuperclassChangeTransformer; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -85,17 +86,16 @@ public List beginScanning(final IEnvironment env) { case GAME_LIBRARY: if (resource instanceof SecureJarPluginResource jarResource) { gameLibs.add(candidate.pluginFound() ? jarResource.pluginJar(candidate.metadata().getFirst()) : jarResource.jar()); - } - // Offer jar to the Mixin service - if (mixin != null) { - mixin.offerResource(resource.path(), resource.path().getFileName().toString()); - } + if (mixin != null) { + final Path path = jarResource.jar().getPrimaryPath(); + mixin.offerResource(path, path.getFileName().toString()); - // Log warning about plugin using Mixin - if (mixin != null && resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { - if (candidate.metadata().stream().noneMatch(m -> "spongevanilla".equals(m.id()))) { - this.platform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", resource.path()); + if (resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { + if (candidate.metadata().stream().noneMatch(m -> "spongevanilla".equals(m.id()))) { + this.platform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", path); + } + } } } break; diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java index e92ef203eaa..f59c0561201 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java @@ -50,7 +50,7 @@ public String name() { @Override public Collection readPluginMetadata(final Environment environment, final PluginResource resource, final List locators) throws Exception { if (resource instanceof JVMPluginResource && resource.locateResource("net/minecraft/server/MinecraftServer.class").isPresent()) { - environment.logger().debug("Container in path '{}' has been detected as Minecraft.", resource.path()); + environment.logger().debug("{} has been detected as Minecraft.", resource); final InputStream input = MinecraftMetadataReader.class.getClassLoader().getResourceAsStream("META-INF/minecraft_sponge_plugins.json"); if (input == null) { diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java index fa3222ace14..3a2e8929130 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -31,13 +31,14 @@ import java.lang.module.ModuleDescriptor; import java.net.URI; import java.nio.file.Path; -import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.jar.Manifest; public final class SecureJarPluginResource implements SpongeJVMPluginResource { - private final Path[] paths; + private final Path[] pathsArray; + private final List paths; private final SecureJar jar; public SecureJarPluginResource(final Path[] paths) { @@ -45,7 +46,8 @@ public SecureJarPluginResource(final Path[] paths) { if (paths.length == 0) { throw new IllegalArgumentException("Need at least one path"); } - this.paths = paths; + this.pathsArray = paths; + this.paths = List.of(paths); this.jar = SecureJar.from(jar -> new PluginJarMetadata(jar, paths), paths); } @@ -54,12 +56,12 @@ public SecureJar jar() { } public SecureJar pluginJar(final PluginMetadata metadata) { - return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.paths); + return SecureJar.from(jar -> new PluginJarMetadata(jar, metadata), this.pathsArray); } @Override - public Path path() { - return this.jar.getPrimaryPath(); + public List paths() { + return this.paths; } @Override @@ -85,16 +87,16 @@ public boolean equals(Object obj) { if (!(obj instanceof SecureJarPluginResource that)) { return false; } - return Arrays.equals(this.paths, that.paths); + return this.paths.equals(that.paths); } @Override public int hashCode() { - return Arrays.hashCode(this.paths); + return this.paths.hashCode(); } @Override public String toString() { - return "SecureJarPluginResource[paths=" + Arrays.toString(this.paths) + "]"; + return "SecureJarPluginResource[paths=" + this.paths + "]"; } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java index ba2ff2f515b..1efdfb6d802 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java @@ -77,7 +77,7 @@ protected Collection collectResources() { try { resources.add(plugin.locateResource(path).get().toURL()); } catch (final Exception e) { - LOGGER.warn("Failed to locate access widener {} from {}", path, plugin.path().getFileName(), e); + LOGGER.warn("Failed to locate access widener {} from {}", path, plugin, e); } } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java index 3a6eb40b982..cb81c28f99d 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java @@ -82,7 +82,7 @@ protected Collection collectResources() { try { resources.add(plugin.locateResource(scPath).get().toURL()); } catch (final Exception e) { - LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin.path().getFileName()); + LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin); } } } From 349030b0eda3521e3b7ab59d60085fc87bd5b1d1 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 6 Jul 2026 23:02:58 +0200 Subject: [PATCH 554/586] Add plugin-spi tests --- .../plugin/discovery/PluginDiscoveryTest.java | 54 +++++++++++++++ .../discovery/spi/DummyMetadataReader.java | 68 +++++++++++++++++++ .../discovery/spi/DummyPluginResource.java | 53 +++++++++++++++ .../discovery/spi/DummyResourceLocator.java | 48 +++++++++++++ .../plugin/discovery/spi/package-info.java | 6 ++ .../plugin/loader/PluginLoaderTest.java | 46 +++++++++++++ .../loader/spi/DummyPluginContainer.java | 38 +++++++++++ .../plugin/loader/spi/DummyPluginLoader.java | 50 ++++++++++++++ .../org.spongepowered.plugin.PluginLoader | 2 + ...ered.plugin.discovery.PluginMetadataReader | 1 + ...red.plugin.discovery.PluginResourceLocator | 1 + 11 files changed, 367 insertions(+) create mode 100644 src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java create mode 100644 src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyMetadataReader.java create mode 100644 src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java create mode 100644 src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyResourceLocator.java create mode 100644 src/test/java/org/spongepowered/common/plugin/discovery/spi/package-info.java create mode 100644 src/test/java/org/spongepowered/common/plugin/loader/PluginLoaderTest.java create mode 100644 src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginContainer.java create mode 100644 src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginLoader.java create mode 100644 src/test/resources/META-INF/services/org.spongepowered.plugin.PluginLoader create mode 100644 src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader create mode 100644 src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java b/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java new file mode 100644 index 00000000000..09675fcb5ac --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.discovery; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.common.plugin.discovery.spi.DummyMetadataReader; +import org.spongepowered.plugin.PluginService; +import org.spongepowered.plugin.discovery.ResourceLoading; + +import java.util.List; +import java.util.Optional; + +public class PluginDiscoveryTest { + + @Test + public void verifyDummyCandidate() { + // locator + Optional candidate = AppLaunch.pluginPlatform().discovery().candidates().stream() + .filter(c -> c.resource().property("dummy_key").isPresent()).findFirst(); + assertTrue(candidate.isPresent()); + assertEquals("dummy_value", candidate.get().resource().property("dummy_key").orElse(null)); + assertIterableEquals(List.of("dummy_locator"), candidate.get().locators().stream().map(PluginService::name).toList()); + + // reader + assertEquals(ResourceLoading.GAME_LIBRARY, candidate.get().loading()); + assertIterableEquals(List.of(DummyMetadataReader.DUMMY_METADATA), candidate.get().metadata()); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyMetadataReader.java b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyMetadataReader.java new file mode 100644 index 00000000000..86b00487367 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyMetadataReader.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.discovery.spi; + +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.discovery.PluginMetadataReader; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.builtin.InheritableMetadata; +import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; +import org.spongepowered.plugin.metadata.model.PluginLoaderSpecification; + +import java.util.Collection; +import java.util.List; + +public class DummyMetadataReader implements PluginMetadataReader { + private static final VersionRange ANY_VERSION; + + static { + try { + ANY_VERSION = VersionRange.createFromVersionSpec("*"); + } catch (InvalidVersionSpecificationException e) { + throw new RuntimeException(e); + } + } + + public static final PluginMetadata DUMMY_METADATA = StandardPluginMetadata.builder().id("dummy_plugin") + .global(InheritableMetadata.builder().loader(new PluginLoaderSpecification("dummy_loader", ANY_VERSION)).version(new DefaultArtifactVersion("1.0.0")).build()).build(); + + @Override + public Collection readPluginMetadata(final Environment environment, final PluginResource resource, final List locators) { + if (resource instanceof DummyPluginResource) { + return List.of(DummyMetadataReader.DUMMY_METADATA); + } + return List.of(); + } + + @Override + public String name() { + return "dummy_reader"; + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java new file mode 100644 index 00000000000..853d783a093 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java @@ -0,0 +1,53 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.discovery.spi; + +import org.spongepowered.plugin.discovery.PluginResource; + +import java.net.URI; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; + +/** + * WARNING: This class may exist in multiple classloaders. + */ +public class DummyPluginResource implements PluginResource { + + @Override + public List paths() { + return List.of(); + } + + @Override + public Optional property(final String key) { + return "dummy_key".equals(key) ? Optional.of("dummy_value") : Optional.empty(); + } + + @Override + public Optional locateResource(final String path) { + return Optional.empty(); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyResourceLocator.java b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyResourceLocator.java new file mode 100644 index 00000000000..8f7c05a1790 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyResourceLocator.java @@ -0,0 +1,48 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.discovery.spi; + +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.discovery.UnknownResourceStrategy; + +import java.util.Collection; +import java.util.List; + +/** + * WARNING: This class may exist in multiple classloaders. + */ +public class DummyResourceLocator implements PluginResourceLocator { + + @Override + public Collection locatePluginResources(final Environment environment) { + return List.of(new Result(new DummyPluginResource(), UnknownResourceStrategy.IGNORE)); + } + + @Override + public String name() { + return "dummy_locator"; + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/spi/package-info.java b/src/test/java/org/spongepowered/common/plugin/discovery/spi/package-info.java new file mode 100644 index 00000000000..ebbacf576e3 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/discovery/spi/package-info.java @@ -0,0 +1,6 @@ +/** + * WARNING: + * Classes in this package exist in two classloaders: a discovery batch classloader and the game classloader. + * Don't attempt to cast instances across different classloaders. + */ +package org.spongepowered.common.plugin.discovery.spi; diff --git a/src/test/java/org/spongepowered/common/plugin/loader/PluginLoaderTest.java b/src/test/java/org/spongepowered/common/plugin/loader/PluginLoaderTest.java new file mode 100644 index 00000000000..3fa33cdfdbd --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/loader/PluginLoaderTest.java @@ -0,0 +1,46 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.loader; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.spongepowered.api.Sponge; +import org.spongepowered.common.plugin.discovery.spi.DummyMetadataReader; +import org.spongepowered.common.plugin.loader.spi.DummyPluginContainer; +import org.spongepowered.plugin.PluginContainer; + +import java.util.Optional; + +public class PluginLoaderTest { + + @Test + public void verifyDummyContainer() { + final Optional container = Sponge.pluginManager().plugin("dummy_plugin"); + assertTrue(container.isPresent()); + assertInstanceOf(DummyPluginContainer.class, container.get()); + assertEquals(DummyMetadataReader.DUMMY_METADATA, container.get().metadata()); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginContainer.java b/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginContainer.java new file mode 100644 index 00000000000..049ca2cbfe6 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginContainer.java @@ -0,0 +1,38 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.loader.spi; + +import org.spongepowered.plugin.builtin.StandardPluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; + +/** + * Technically not needed to load a plugin, but exist for the tests. + */ +public class DummyPluginContainer extends StandardPluginContainer { + public DummyPluginContainer(final PluginResource resource, final PluginMetadata metadata) { + super(resource, metadata); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginLoader.java b/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginLoader.java new file mode 100644 index 00000000000..4b277d4cfb0 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/loader/spi/DummyPluginLoader.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.loader.spi; + +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.PluginLoader; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.plugin.metadata.PluginMetadata; + +public class DummyPluginLoader implements PluginLoader { + @Override + public ArtifactVersion version() { + return new DefaultArtifactVersion("1.0.0"); + } + + @Override + public PluginContainer loadPlugin(final Environment environment, final PluginResource resource, final PluginMetadata metadata) { + return new DummyPluginContainer(resource, metadata); + } + + @Override + public String name() { + return "dummy_loader"; + } +} diff --git a/src/test/resources/META-INF/services/org.spongepowered.plugin.PluginLoader b/src/test/resources/META-INF/services/org.spongepowered.plugin.PluginLoader new file mode 100644 index 00000000000..8f4bfeae9dc --- /dev/null +++ b/src/test/resources/META-INF/services/org.spongepowered.plugin.PluginLoader @@ -0,0 +1,2 @@ +org.spongepowered.common.launch.plugin.loader.JavaPluginLoader +org.spongepowered.common.plugin.loader.spi.DummyPluginLoader diff --git a/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader b/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader new file mode 100644 index 00000000000..216d458b97d --- /dev/null +++ b/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginMetadataReader @@ -0,0 +1 @@ +org.spongepowered.common.plugin.discovery.spi.DummyMetadataReader diff --git a/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator new file mode 100644 index 00000000000..9686213daee --- /dev/null +++ b/src/test/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -0,0 +1 @@ +org.spongepowered.common.plugin.discovery.spi.DummyResourceLocator From 6d3b74291bb4b0a0d4b8cb62b9937675b2b4488d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Thu, 9 Jul 2026 19:31:44 +0200 Subject: [PATCH 555/586] Support non-jar resources on modded platforms --- .../mod/discovery/PluginFileParser.java | 14 +++++-- .../mod/discovery/SpongeForgeModLocator.java | 37 ++++++++++++++++--- .../mod/discovery/PluginFileReader.java | 14 ++++--- .../mod/discovery/SpongeNeoModLocator.java | 15 +++++++- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java index e18de88e664..66ab60c842f 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java @@ -37,6 +37,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.forge.applaunch.mod.metadata.PluginFileConfigurable; +import org.spongepowered.forge.applaunch.plugin.discovery.PluginJarMetadata; import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; import java.lang.reflect.Constructor; @@ -87,11 +88,18 @@ private static boolean useModJarMetadata(final SecureJar jar) { return data.findFile(PluginFileParser.MODS_TOML).isPresent(); } - public static ModFile newPluginFile(final IModProvider provider, final PluginDiscovery.Candidate candidate) { + public static ModFile newJarPluginFile(final IModProvider provider, final PluginDiscovery.Candidate candidate) { final SecureJarPluginResource resource = (SecureJarPluginResource) candidate.resource(); - final SecureJar jar = resource.pluginJar(candidate.metadata().getFirst()); - final PluginFileConfigurable config = new PluginFileConfigurable(resource, candidate.metadata()); + return PluginFileParser.newPluginFile(provider, candidate, resource.pluginJar(candidate.metadata().getFirst())); + } + + public static ModFile newNonJarPluginFile(final IModProvider provider, final PluginDiscovery.Candidate candidate, final Path tempPath) { + final SecureJar jar = SecureJar.from(j -> new PluginJarMetadata(j, candidate.metadata().getFirst()), tempPath); + return PluginFileParser.newPluginFile(provider, candidate, jar); + } + private static ModFile newPluginFile(final IModProvider provider, final PluginDiscovery.Candidate candidate, final SecureJar jar) { + final PluginFileConfigurable config = new PluginFileConfigurable(candidate.resource(), candidate.metadata()); return new ModFile(jar, provider, file -> parsePluginFileInfo(file, config), "MOD"); } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java index 3ab62dbd3bc..630f9224cfd 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java @@ -37,12 +37,15 @@ import org.spongepowered.forge.applaunch.plugin.discovery.ForgePluginDiscovery; import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; +import java.io.IOException; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; +import java.util.jar.JarOutputStream; public final class SpongeForgeModLocator extends AbstractModProvider implements IModLocator { private static final Logger LOGGER = LogManager.getLogger(); @@ -65,14 +68,17 @@ public List scanMods() { final List mods = new ArrayList<>(); + Path virtualDir = null; + int virtualJarCount = 0; + for (final PluginDiscovery.Candidate candidate : this.discovery.candidates()) { + IModFile modFile; if (candidate.resource() instanceof SecureJarPluginResource resource) { candidate.readMetadata(); // attempt to load as mod or plugin - IModFile modFile; if (candidate.pluginFound()) { - modFile = PluginFileParser.newPluginFile(this, candidate); + modFile = PluginFileParser.newJarPluginFile(this, candidate); } else { modFile = PluginFileParser.newModFile(this, resource); if (modFile != null) { @@ -94,12 +100,33 @@ public List scanMods() { break; } } + } else { + candidate.readMetadata(); + if (!candidate.pluginFound()) { + candidate.logResult(); + continue; + } - mods.add(new ModFileOrException(modFile, null)); - } + // Forge requires each mod to have an existing file, so we generate one + final Path path; + try { + if (virtualDir == null) { + virtualDir = Files.createTempDirectory("sponge_resources_"); + } + path = virtualDir.resolve(virtualJarCount++ + ".jar"); + + // an empty jar is enough + new JarOutputStream(Files.newOutputStream(path)).close(); + } catch (IOException e) { + LOGGER.error("Failed to create virtual jar for resource {}", candidate.resource(), e); + continue; + } - // TODO else: Forge can only loads jar mods, do we make a dummy jar? + LOGGER.debug("Using temporary jar {} for resource {}", path, candidate.resource()); + modFile = PluginFileParser.newNonJarPluginFile(this, candidate, path); + } + mods.add(new ModFileOrException(modFile, null)); candidate.logResult(); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java index 396b738152c..31d329aaceb 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/PluginFileReader.java @@ -52,11 +52,7 @@ public class PluginFileReader implements IModFileReader { if (!candidate.pluginFound()) { return null; } - final PluginFileConfigurable config = new PluginFileConfigurable(resource, candidate.metadata()); - final ModJarMetadata mjm = new ModJarMetadata(); - final IModFile modFile = new ModFile(jar, mjm, file -> newModFileInfo(file, config), attributes); - mjm.setModFile(modFile); - return modFile; + return PluginFileReader.newPluginFile(jar, candidate, attributes); } @Override @@ -64,6 +60,14 @@ public String toString() { return "sponge manifest"; } + static IModFile newPluginFile(final JarContents jar, final PluginDiscovery.Candidate candidate, final ModFileDiscoveryAttributes attributes) { + final PluginFileConfigurable config = new PluginFileConfigurable(candidate.resource(), candidate.metadata()); + final ModJarMetadata mjm = new ModJarMetadata(); + final IModFile modFile = new ModFile(jar, mjm, file -> newModFileInfo(file, config), attributes); + mjm.setModFile(modFile); + return modFile; + } + private static IModFileInfo newModFileInfo(final IModFile file, final PluginFileConfigurable config) throws InvalidModFileException { return new ModFileInfo((ModFile) file, config, (info) -> {}, List.of()); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index caaec6a79bc..c5a4c5b8021 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -24,6 +24,7 @@ */ package org.spongepowered.neoforge.applaunch.mod.discovery; +import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; @@ -62,6 +63,7 @@ public SpongeNeoModLocator() { @Override public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) { final ModFileDiscoveryAttributes attributes = ModFileDiscoveryAttributes.DEFAULT.withLocator(this); + int virtualJarCount = 0; for (final PluginDiscovery.Candidate candidate : this.discovery.candidates()) { if (candidate.resource() instanceof JarContentsPluginResource resource) { @@ -99,9 +101,18 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) } pipeline.addModFile(modFile); - } + } else { + candidate.readMetadata(); + if (!candidate.pluginFound()) { + candidate.logResult(); + continue; + } + + // This jar is only used as an identifier and does not need to actually exist + final JarContents jar = JarContents.empty(Path.of("sponge_resource_" + virtualJarCount++)); - // TODO else: Neo can only loads jar mods, do we make a dummy jar? + pipeline.addModFile(PluginFileReader.newPluginFile(jar, candidate, attributes)); + } candidate.logResult(); } From 9e274a20851ff2b071da1521bc342a245df88c05 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 19 Jul 2026 21:42:55 +0200 Subject: [PATCH 556/586] Support PluginConflict from plugin-meta --- .../SpongeForgeDependencyLocator.java | 12 ++++ .../PluginDependencyConfigurable.java | 4 +- .../metadata}/PluginMetadataConverter.java | 18 ++--- .../launch/plugin/ForgePluginContainer.java | 5 +- .../metadata/PluginConflictConfigurable.java | 70 +++++++++++++++++++ .../PluginDependencyConfigurable.java | 8 +-- .../mod/metadata/PluginFileConfigurable.java | 6 +- .../metadata}/PluginMetadataConverter.java | 43 ++++++++---- .../launch/plugin/NeoPluginContainer.java | 4 +- .../plugin/PluginPlatformConstants.java | 2 + .../applaunch/plugin}/VersionChecker.java | 2 +- .../plugin/discovery/PluginDiscovery.java | 33 +++++++++ .../plugin/loader/PluginCandidateFactory.java | 1 + .../plugin/VanillaTransformationService.java | 4 ++ .../plugin/resolver/DependencyResolver.java | 2 +- 15 files changed, 179 insertions(+), 35 deletions(-) rename forge/src/{main/java/org/spongepowered/forge/launch/plugin => applaunch/java/org/spongepowered/forge/applaunch/plugin/metadata}/PluginMetadataConverter.java (87%) create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginConflictConfigurable.java rename neoforge/src/{main/java/org/spongepowered/neoforge/launch/plugin => applaunch/java/org/spongepowered/neoforge/applaunch/plugin/metadata}/PluginMetadataConverter.java (71%) rename src/{main/java/org/spongepowered/common/launch/plugin/loader => applaunch/java/org/spongepowered/common/applaunch/plugin}/VersionChecker.java (97%) diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java index ca6dcdb2705..a1d7f9c155f 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java @@ -33,11 +33,15 @@ import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.forge.applaunch.mod.discovery.library.Log4JLogger; +import org.spongepowered.forge.applaunch.plugin.metadata.PluginMetadataConverter; import org.spongepowered.libs.LibraryManager; +import org.spongepowered.plugin.metadata.PluginMetadata; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; public class SpongeForgeDependencyLocator extends AbstractModProvider implements IDependencyLocator { private static final Logger LOGGER = LogManager.getLogger(); @@ -46,6 +50,14 @@ public class SpongeForgeDependencyLocator extends AbstractModProvider implements public List scanMods(final Iterable loadedMods) { final List modFiles = new ArrayList<>(); + final Stream allMetadata = StreamSupport.stream(loadedMods.spliterator(), false) + .flatMap(file -> file.getModInfos().stream()) + .map(info -> info.getConfig().getConfigElement("spongeMetadata").orElseGet(() -> PluginMetadataConverter.modToPlugin(info))); + + if (AppLaunch.pluginPlatform().discovery().checkConflicts(allMetadata)) { + throw new IllegalStateException("Fatal plugin conflicts have been detected."); + } + // Add Sponge-specific libraries if (FMLEnvironment.production) { final PluginPlatform platform = AppLaunch.pluginPlatform(); diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java index d6bb24ccb44..30e592d2506 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/metadata/PluginDependencyConfigurable.java @@ -52,7 +52,7 @@ public Optional getConfigElement(final String... key) { case "modId" -> (Optional) Optional.of(this.dependency.id()); case "mandatory" -> (Optional) Optional.of(!this.dependency.optional()); case "versionRange" -> (Optional) Optional.of(this.dependency.version().toString()); - case "ordering" -> (Optional) Optional.of(this.loadToOrdering(this.dependency.loadOrder()).toString()); + case "ordering" -> (Optional) Optional.of(PluginDependencyConfigurable.loadToOrdering(this.dependency.loadOrder()).toString()); case "side" -> (Optional) Optional.of(IModInfo.DependencySide.BOTH.toString()); default -> Optional.empty(); }; @@ -63,7 +63,7 @@ public List getConfigList(final String... key) { return Collections.emptyList(); } - private IModInfo.Ordering loadToOrdering(final PluginDependency.LoadOrder order) { + private static IModInfo.Ordering loadToOrdering(final PluginDependency.LoadOrder order) { return switch (order) { case UNDEFINED -> IModInfo.Ordering.NONE; case BEFORE -> IModInfo.Ordering.BEFORE; diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/metadata/PluginMetadataConverter.java similarity index 87% rename from forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java rename to forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/metadata/PluginMetadataConverter.java index 311137aa8b2..4887354ecb0 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginMetadataConverter.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/metadata/PluginMetadataConverter.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge.launch.plugin; +package org.spongepowered.forge.applaunch.plugin.metadata; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.forgespi.language.IModFileInfo; @@ -54,7 +54,7 @@ public final class PluginMetadataConverter { } @SuppressWarnings("UnstableApiUsage") - public static PluginMetadata modToPlugin(final ModInfo info) { + public static PluginMetadata modToPlugin(final IModInfo info) { final List loaders = info.getOwningFile().requiredLanguageLoaders(); final PluginLoaderSpecification loaderSpec; if (loaders.isEmpty()) { @@ -69,20 +69,22 @@ public static PluginMetadata modToPlugin(final ModInfo info) { .version(info.getVersion()) .loader(loaderSpec) .description(info.getDescription()) - .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); - try { - final URL issueURL = info.getOwningFile().getIssueURL(); - builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); - } catch (URISyntaxException ignored) {} + if (info instanceof ModInfo modInfo) { + builder.addContributor(new PluginContributor(modInfo.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())); + try { + final URL issueURL = modInfo.getOwningFile().getIssueURL(); + builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); + } catch (URISyntaxException ignored) {} + } for (final IModInfo.ModVersion dependency : info.getDependencies()) { builder.addDependency(new PluginDependency( dependency.getModId(), dependency.getVersionRange(), PluginMetadataConverter.orderingToLoad(dependency.getOrdering()), - false + !dependency.isMandatory() )); } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java index 22836ad946a..b584a4e937d 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java @@ -26,10 +26,10 @@ import com.google.common.collect.MapMaker; import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.forge.applaunch.plugin.metadata.PluginMetadataConverter; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.metadata.PluginMetadata; @@ -40,7 +40,6 @@ import java.util.Objects; import java.util.Optional; -@SuppressWarnings("UnstableApiUsage") public class ForgePluginContainer implements PluginContainer { private final ModContainer modContainer; private final IModFile modFile; @@ -56,7 +55,7 @@ private ForgePluginContainer(final ModContainer modContainer) { @Override public PluginMetadata metadata() { if (this.pluginMetadata == null) { - this.pluginMetadata = PluginMetadataConverter.modToPlugin((ModInfo) this.modContainer.getModInfo()); + this.pluginMetadata = PluginMetadataConverter.modToPlugin(this.modContainer.getModInfo()); } return this.pluginMetadata; } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginConflictConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginConflictConfigurable.java new file mode 100644 index 00000000000..c7c9c18c618 --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginConflictConfigurable.java @@ -0,0 +1,70 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.mod.metadata; + +import net.neoforged.neoforgespi.language.IConfigurable; +import net.neoforged.neoforgespi.language.IModInfo; +import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; +import org.spongepowered.plugin.metadata.model.PluginConflict; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +// ModVersion +public final class PluginConflictConfigurable implements IConfigurable { + + private final PluginConflict conflict; + + public PluginConflictConfigurable(final PluginConflict conflict) { + this.conflict = conflict; + } + + @SuppressWarnings("unchecked") + @Override + public Optional getConfigElement(final String... key) { + if (key.length != 1) { + return Optional.empty(); + } + + return switch (key[0]) { + case "modId" -> (Optional) Optional.of(this.conflict.id()); + case "type" -> (Optional) Optional.of(PluginConflictConfigurable.fatalToDependencyType(this.conflict.fatal()).toString()); + case "versionRange" -> (Optional) Optional.of(this.conflict.version().toString()); + case "reason" -> (Optional) this.conflict.reason(); + case "side" -> (Optional) Optional.of(IModInfo.DependencySide.BOTH.toString()); + default -> Optional.empty(); + }; + } + + @Override + public List getConfigList(final String... key) { + return Collections.emptyList(); + } + + private static IModInfo.DependencyType fatalToDependencyType(final boolean fatal) { + return fatal && !PluginPlatformConstants.IGNORE_FATAL_CONFLICTS ? IModInfo.DependencyType.INCOMPATIBLE : IModInfo.DependencyType.DISCOURAGED; + } +} diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java index b198266cdce..2e678c525df 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginDependencyConfigurable.java @@ -50,9 +50,9 @@ public Optional getConfigElement(final String... key) { return switch (key[0]) { case "modId" -> (Optional) Optional.of(this.dependency.id()); - case "type" -> (Optional) Optional.of(this.optionalToDependencyType(this.dependency.optional()).toString()); + case "type" -> (Optional) Optional.of(PluginDependencyConfigurable.optionalToDependencyType(this.dependency.optional()).toString()); case "versionRange" -> (Optional) Optional.of(this.dependency.version().toString()); - case "ordering" -> (Optional) Optional.of(this.loadToOrdering(this.dependency.loadOrder()).toString()); + case "ordering" -> (Optional) Optional.of(PluginDependencyConfigurable.loadToOrdering(this.dependency.loadOrder()).toString()); case "side" -> (Optional) Optional.of(IModInfo.DependencySide.BOTH.toString()); default -> Optional.empty(); }; @@ -63,7 +63,7 @@ public List getConfigList(final String... key) { return Collections.emptyList(); } - private IModInfo.Ordering loadToOrdering(final PluginDependency.LoadOrder order) { + private static IModInfo.Ordering loadToOrdering(final PluginDependency.LoadOrder order) { return switch (order) { case UNDEFINED -> IModInfo.Ordering.NONE; case BEFORE -> IModInfo.Ordering.BEFORE; @@ -71,7 +71,7 @@ private IModInfo.Ordering loadToOrdering(final PluginDependency.LoadOrder order) }; } - private IModInfo.DependencyType optionalToDependencyType(final boolean optional) { + private static IModInfo.DependencyType optionalToDependencyType(final boolean optional) { return optional ? IModInfo.DependencyType.OPTIONAL : IModInfo.DependencyType.REQUIRED; } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java index bd499cffe32..c4f104c05d5 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -30,6 +30,7 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; // ModFileInfo public final class PluginFileConfigurable implements IConfigurable { @@ -123,7 +124,10 @@ public List getConfigList(final String... key) { } if ("dependencies".equals(query)) { - return metadata.dependencies().stream().map(PluginDependencyConfigurable::new).toList(); + return Stream.concat( + metadata.dependencies().stream().map(PluginDependencyConfigurable::new), + metadata.conflicts().stream().map(PluginConflictConfigurable::new) + ).toList(); } return Collections.emptyList(); diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/metadata/PluginMetadataConverter.java similarity index 71% rename from neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/metadata/PluginMetadataConverter.java index d09c56d978c..4000325613f 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/PluginMetadataConverter.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/metadata/PluginMetadataConverter.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.launch.plugin; +package org.spongepowered.neoforge.applaunch.plugin.metadata; import net.neoforged.fml.loading.moddiscovery.ModInfo; import net.neoforged.neoforgespi.language.IModFileInfo; @@ -32,6 +32,7 @@ import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.builtin.InheritableMetadata; import org.spongepowered.plugin.metadata.builtin.StandardPluginMetadata; +import org.spongepowered.plugin.metadata.model.PluginConflict; import org.spongepowered.plugin.metadata.model.PluginContributor; import org.spongepowered.plugin.metadata.model.PluginDependency; import org.spongepowered.plugin.metadata.model.PluginLinks; @@ -53,7 +54,7 @@ public final class PluginMetadataConverter { } } - public static PluginMetadata modToPlugin(final ModInfo info) { + public static PluginMetadata modToPlugin(final IModInfo info) { final List loaders = info.getOwningFile().requiredLanguageLoaders(); final PluginLoaderSpecification loaderSpec; if (loaders.isEmpty()) { @@ -69,21 +70,37 @@ public static PluginMetadata modToPlugin(final ModInfo info) { .version(info.getVersion()) .loader(loaderSpec) .description(info.getDescription()) - .addContributor(new PluginContributor(info.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())) .properties(info.getModProperties()); - try { - final URL issueURL = info.getOwningFile().getIssueURL(); - builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); - } catch (URISyntaxException ignored) {} + if (info instanceof ModInfo modInfo) { + builder.addContributor(new PluginContributor(modInfo.getConfigElement("authors").orElse("unknown").toString(), Optional.empty())); + try { + final URL issueURL = modInfo.getOwningFile().getIssueURL(); + builder.links(new PluginLinks(null, null, issueURL == null ? null : issueURL.toURI())); + } catch (URISyntaxException ignored) {} + } for (final IModInfo.ModVersion dependency : info.getDependencies()) { - builder.addDependency(new PluginDependency( - dependency.getModId(), - dependency.getVersionRange(), - PluginMetadataConverter.orderingToLoad(dependency.getOrdering()), - false - )); + switch (dependency.getType()) { + case REQUIRED: + case OPTIONAL: + builder.addDependency(new PluginDependency( + dependency.getModId(), + dependency.getVersionRange(), + PluginMetadataConverter.orderingToLoad(dependency.getOrdering()), + dependency.getType() == IModInfo.DependencyType.OPTIONAL + )); + break; + case INCOMPATIBLE: + case DISCOURAGED: + builder.addConflict(new PluginConflict( + dependency.getModId(), + dependency.getVersionRange(), + dependency.getType() == IModInfo.DependencyType.INCOMPATIBLE, + dependency.getReason() + )); + break; + } } return StandardPluginMetadata.builder() diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java index ecc06cbfaa8..4456cd84b93 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java @@ -27,9 +27,9 @@ import com.google.common.collect.MapMaker; import net.neoforged.fml.ModContainer; import net.neoforged.fml.jarcontents.JarContents; -import net.neoforged.fml.loading.moddiscovery.ModInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.neoforge.applaunch.plugin.metadata.PluginMetadataConverter; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.metadata.PluginMetadata; @@ -53,7 +53,7 @@ private NeoPluginContainer(final ModContainer modContainer) { @Override public PluginMetadata metadata() { if (this.pluginMetadata == null) { - this.pluginMetadata = PluginMetadataConverter.modToPlugin((ModInfo) this.modContainer.getModInfo()); + this.pluginMetadata = PluginMetadataConverter.modToPlugin(this.modContainer.getModInfo()); } return this.pluginMetadata; } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java index 14330e20648..dc8bb0487f2 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java @@ -32,4 +32,6 @@ private PluginPlatformConstants() { public static final String METADATA_FILE_PATH = "META-INF/sponge_plugins.json"; public static final String ENVIRONMENT_LOCATOR_VARIABLE_NAME = "SPONGE_PLUGINS"; + public static final boolean IGNORE_FATAL_CONFLICTS = Boolean.getBoolean("sponge.discovery.ignoreFatalConflicts"); + } diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/VersionChecker.java similarity index 97% rename from src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java rename to src/applaunch/java/org/spongepowered/common/applaunch/plugin/VersionChecker.java index 488898c0f73..c01635f33e9 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/VersionChecker.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/VersionChecker.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.common.launch.plugin.loader; +package org.spongepowered.common.applaunch.plugin; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.VersionRange; diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java index 49aac41b650..49e549f0e36 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -25,17 +25,22 @@ package org.spongepowered.common.applaunch.plugin.discovery; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; import org.spongepowered.common.applaunch.plugin.PluginServiceLoader; +import org.spongepowered.common.applaunch.plugin.VersionChecker; import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.PluginLoader; import org.spongepowered.plugin.PluginService; import org.spongepowered.plugin.discovery.*; import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.builtin.MetadataParser; +import org.spongepowered.plugin.metadata.model.PluginConflict; import java.lang.module.ModuleDescriptor; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public abstract class PluginDiscovery extends PluginServiceLoader { private Map candidates; @@ -147,6 +152,34 @@ public final void logMetadataWarnings() { } } + public final boolean checkConflicts() { + return this.checkConflicts(this.candidates.values().stream().flatMap(c -> c.metadata.values().stream())); + } + + public final boolean checkConflicts(final Stream allMetadata) { + final Map map = new LinkedHashMap<>(); + allMetadata.forEachOrdered(m -> map.put(m.id(), m)); + + boolean anyFatal = false; + for (final PluginMetadata metadata : map.values()) { + for (final PluginConflict conflict : metadata.conflicts()) { + final @Nullable PluginMetadata target = map.get(conflict.id()); + if (target != null && VersionChecker.check(conflict.version(), target.version())) { + if (conflict.fatal() && !PluginPlatformConstants.IGNORE_FATAL_CONFLICTS) { + this.environment.logger().fatal("Plugin {}={} is fatally conflicting with {}={} in range {}. Reason: {}", + metadata.id(), metadata.version(), target.id(), target.version(), conflict.version(), conflict.reason().orElse("?")); + anyFatal = true; + } else { + this.environment.logger().warn("Plugin {}={} is conflicting with {}={} in range {}. Reason: {}", + metadata.id(), metadata.version(), target.id(), target.version(), conflict.version(), conflict.reason().orElse("?")); + } + } + } + } + + return anyFatal; + } + public final class Candidate { private final PluginResource resource; private final List locators = new ArrayList<>(); diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java index e3e896d571c..02f12484517 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/PluginCandidateFactory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.launch.plugin.loader; import org.spongepowered.common.applaunch.plugin.PluginServiceLoader; +import org.spongepowered.common.applaunch.plugin.VersionChecker; import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.PluginLoader; import org.spongepowered.plugin.discovery.PluginResource; diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java index 6afef8f3732..396ef37bdcf 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java @@ -106,6 +106,10 @@ public List beginScanning(final IEnvironment env) { this.platform.discovery().logMetadataWarnings(); + if (this.platform.discovery().checkConflicts()) { + throw new IllegalStateException("Fatal plugin conflicts have been detected."); + } + return List.of(new Resource(IModuleLayerManager.Layer.PLUGIN, libs), new Resource(IModuleLayerManager.Layer.GAME, gameLibs)); } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java index 736147410f4..f88d646cf7c 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/resolver/DependencyResolver.java @@ -26,8 +26,8 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.api.util.Tuple; +import org.spongepowered.common.applaunch.plugin.VersionChecker; import org.spongepowered.common.launch.plugin.loader.PluginCandidate; -import org.spongepowered.common.launch.plugin.loader.VersionChecker; import org.spongepowered.plugin.metadata.model.PluginDependency; import java.util.ArrayList; From 3ff78812dafb8f42afa898aa4a886e82e7e5db15 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 19 Jul 2026 21:46:56 +0200 Subject: [PATCH 557/586] Migrate Sponge mod manifests to plugin manifests --- .../mod/discovery/PluginFileParser.java | 7 -- .../mod/discovery/SpongeForgeModLocator.java | 33 -------- .../discovery/SpongeForgeResourceLocator.java | 71 ++++++++++++++++ ...red.plugin.discovery.PluginResourceLocator | 1 + .../{SpongeForgeMod.java => SpongeForge.java} | 16 ++-- .../org/spongepowered/forge/SpongeMod.java | 31 ------- .../forge/launch/ForgeLaunch.java | 8 ++ .../launch/inject/ModContainerModule.java | 20 ++++- .../launch/plugin/PluginModContainer.java | 5 ++ .../resource-templates/META-INF/mods.toml | 56 ------------- .../META-INF/sponge_plugins.json | 57 +++++++++++++ neoforge/build.gradle.kts | 22 +++-- .../mod/discovery/SpongeNeoModLocator.java | 46 ---------- .../mod/metadata/PluginFileConfigurable.java | 11 +++ .../discovery/SpongeNeoResourceLocator.java | 83 +++++++++++++++++++ ...red.plugin.discovery.PluginResourceLocator | 1 + .../org/spongepowered/neoforge/SpongeMod.java | 31 ------- .../{SpongeNeoMod.java => SpongeNeo.java} | 10 ++- .../neoforge/launch/NeoLaunch.java | 8 ++ .../launch/inject/ModContainerModule.java | 20 ++++- .../META-INF/neoforge.mods.toml | 64 -------------- .../META-INF/sponge_plugins.json | 65 +++++++++++++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 - .../common/inject/plugin/PluginGuice.java | 20 ++--- .../spongepowered/common/launch/Launch.java | 6 ++ .../plugin/loader/JavaPluginLoader.java | 3 +- vanilla/build.gradle.kts | 3 +- .../META-INF/sponge_plugins.json | 23 +++-- 28 files changed, 402 insertions(+), 320 deletions(-) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SpongeForgeResourceLocator.java rename forge/src/main/java/org/spongepowered/forge/{SpongeForgeMod.java => SpongeForge.java} (93%) delete mode 100644 forge/src/main/java/org/spongepowered/forge/SpongeMod.java rename neoforge/src/main/java/org/spongepowered/neoforge/SpongeAPIMod.java => forge/src/main/java/org/spongepowered/forge/launch/inject/ModContainerModule.java (67%) delete mode 100644 forge/src/main/resource-templates/META-INF/mods.toml create mode 100644 forge/src/main/resource-templates/META-INF/sponge_plugins.json create mode 100644 neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/SpongeNeoResourceLocator.java delete mode 100644 neoforge/src/main/java/org/spongepowered/neoforge/SpongeMod.java rename neoforge/src/main/java/org/spongepowered/neoforge/{SpongeNeoMod.java => SpongeNeo.java} (96%) rename forge/src/main/java/org/spongepowered/forge/SpongeAPIMod.java => neoforge/src/main/java/org/spongepowered/neoforge/launch/inject/ModContainerModule.java (67%) delete mode 100644 neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml create mode 100644 neoforge/src/main/resource-templates/META-INF/sponge_plugins.json delete mode 100644 neoforge/src/main/resources/META-INF/MANIFEST.MF diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java index 66ab60c842f..73c6d7fe696 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java @@ -24,7 +24,6 @@ */ package org.spongepowered.forge.applaunch.mod.discovery; -import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.fml.loading.moddiscovery.ModFile; @@ -109,12 +108,6 @@ private static ModFile newPluginFile(final IModProvider provider, final PluginDi return PluginFileParser.newModFile(provider, mjm, jar); } - public static @Nullable ModFile newModFile(final IModProvider provider, final Path... paths) { - final ModJarMetadata mjm = newModJarMetadata(); - final SecureJar jar = SecureJar.from(j -> PluginFileParser.useModJarMetadata(j) ? mjm : JarMetadata.from(j, paths), paths); - return PluginFileParser.newModFile(provider, mjm, jar); - } - private static @Nullable ModFile newModFile(final IModProvider provider, final ModJarMetadata mjm, final SecureJar jar) { final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); final String type = data.getManifest().getMainAttributes().getValue("FMLModType"); diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java index 630f9224cfd..bd3bc54e015 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java @@ -24,8 +24,6 @@ */ package org.spongepowered.forge.applaunch.mod.discovery; -import com.google.common.collect.ImmutableMap; -import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.forgespi.locating.IModFile; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; @@ -38,10 +36,6 @@ import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -132,33 +126,6 @@ public List scanMods() { this.discovery.logMetadataWarnings(); - if (!FMLEnvironment.production) { - return mods; - } - - try { - URL rootJar = SpongeForgeModLocator.class.getProtectionDomain().getCodeSource().getLocation(); - FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar - Files.list(fs.getPath("jars")) - .filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar")) - .map(path -> { - try { - URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); - final Map env = ImmutableMap.of("packagePath", path); - FileSystem jijFS = FileSystems.newFileSystem(jij, env); - return jijFS.getPath("/"); // root of the archive to load - } catch (Exception e) { - throw new RuntimeException(e); - } - }) - .map((path) -> PluginFileParser.newModFile(this, path)) - .filter(Objects::nonNull) - .map((modFile -> new ModFileOrException(modFile, null))) - .forEach(mods::add); - } catch (Exception e) { - LOGGER.error("Failed to scan embedded mod candidates", e); - } - return mods; } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SpongeForgeResourceLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SpongeForgeResourceLocator.java new file mode 100644 index 00000000000..176e04541b9 --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SpongeForgeResourceLocator.java @@ -0,0 +1,71 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.plugin.discovery; + +import com.google.common.collect.ImmutableMap; +import net.minecraftforge.fml.loading.FMLEnvironment; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.discovery.UnknownResourceStrategy; + +import java.net.URI; +import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.*; + +public final class SpongeForgeResourceLocator implements PluginResourceLocator { + + @Override + public String name() { + return "spongeforge"; + } + + @Override + public Collection locatePluginResources(final Environment environment) throws Exception { + if (!FMLEnvironment.production) { + return Collections.emptyList(); + } + + final URL rootJar = SpongeForgeResourceLocator.class.getProtectionDomain().getCodeSource().getLocation(); + final FileSystem fs = FileSystems.getFileSystem(rootJar.toURI()); // FML has already opened a file system for this jar + return Files.list(fs.getPath("jars")) + .filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar")) + .map(path -> { + try { + URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize(); + final Map env = ImmutableMap.of("packagePath", path); + FileSystem jijFS = FileSystems.newFileSystem(jij, env); + return jijFS.getPath("/"); // root of the archive to load + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .map((path) -> new Result(JVMPluginResource.create(environment, path), UnknownResourceStrategy.WARN)) + .toList(); + } +} diff --git a/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator index 93a6e7f4172..c6bd66dcae5 100644 --- a/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator +++ b/forge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -1 +1,2 @@ +org.spongepowered.forge.applaunch.plugin.discovery.SpongeForgeResourceLocator org.spongepowered.common.applaunch.plugin.discovery.SpongePropertyResourceLocator diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForge.java similarity index 93% rename from forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java rename to forge/src/main/java/org/spongepowered/forge/SpongeForge.java index 032d4deedeb..1991fe3f05d 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForge.java @@ -24,17 +24,17 @@ */ package org.spongepowered.forge; +import com.google.inject.Inject; import net.minecraft.client.Minecraft; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; import net.minecraftforge.event.server.ServerAboutToStartEvent; import net.minecraftforge.event.server.ServerStartedEvent; import net.minecraftforge.event.server.ServerStoppingEvent; +import net.minecraftforge.eventbus.api.bus.BusGroup; import net.minecraftforge.eventbus.api.listener.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.api.Client; @@ -50,21 +50,21 @@ import org.spongepowered.forge.hook.ForgeGeneralHooks; import org.spongepowered.forge.hook.ForgeItemHooks; import org.spongepowered.forge.hook.ForgeWorldHooks; +import org.spongepowered.plugin.builtin.jvm.Plugin; -@Mod("spongeforge") -public final class SpongeForgeMod { +@Plugin("spongeforge") +public final class SpongeForge { private final Logger logger = LogManager.getLogger("spongeforge"); - public SpongeForgeMod(FMLJavaModLoadingContext ctx) { + @Inject + public SpongeForge(final BusGroup group) { // WorldPersistenceHooks.addHook(SpongeLevelDataPersistence.INSTANCE); // TODO SF 1.19.4 - final var group = ctx.getModBusGroup(); - // modBus: add all FML events with it FMLCommonSetupEvent.getBus(group).addListener(this::onCommonSetup); FMLClientSetupEvent.getBus(group).addListener(this::onClientSetup); - EntityAttributeCreationEvent.getBus(group).addListener(this::onEntityAttributeCreationEvent); + EntityAttributeCreationEvent.BUS.addListener(this::onEntityAttributeCreationEvent); // annotation events, for non-FML things MinecraftForge.EVENT_BUS.register(this); diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeMod.java deleted file mode 100644 index 3785f28e1e5..00000000000 --- a/forge/src/main/java/org/spongepowered/forge/SpongeMod.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.forge; - -import net.minecraftforge.fml.common.Mod; - -@Mod("sponge") -public class SpongeMod { -} diff --git a/forge/src/main/java/org/spongepowered/forge/launch/ForgeLaunch.java b/forge/src/main/java/org/spongepowered/forge/launch/ForgeLaunch.java index 224441a417c..f33be6da325 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/ForgeLaunch.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/ForgeLaunch.java @@ -30,16 +30,19 @@ import com.google.inject.Module; import com.google.inject.Stage; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.loading.FMLLoader; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.inject.SpongeCommonModule; import org.spongepowered.common.inject.SpongeModule; import org.spongepowered.common.launch.Launch; +import org.spongepowered.forge.launch.inject.ModContainerModule; import org.spongepowered.forge.launch.inject.SpongeForgeModule; import org.spongepowered.forge.launch.plugin.ForgePluginManager; import org.spongepowered.plugin.PluginContainer; import java.util.List; +import java.util.Optional; public final class ForgeLaunch extends Launch { @@ -88,4 +91,9 @@ public PluginContainer platformPlugin() { return this.spongeForgePlugin; } + + @Override + public Optional modModule(final PluginContainer plugin) { + return ModList.get().getModContainerById(plugin.metadata().id()).map(ModContainerModule::new); + } } diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeAPIMod.java b/forge/src/main/java/org/spongepowered/forge/launch/inject/ModContainerModule.java similarity index 67% rename from neoforge/src/main/java/org/spongepowered/neoforge/SpongeAPIMod.java rename to forge/src/main/java/org/spongepowered/forge/launch/inject/ModContainerModule.java index f132db9b9f2..720e4cef49b 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeAPIMod.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/inject/ModContainerModule.java @@ -22,10 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge; +package org.spongepowered.forge.launch.inject; -import net.neoforged.fml.common.Mod; +import com.google.inject.PrivateModule; +import net.minecraftforge.eventbus.api.bus.BusGroup; +import net.minecraftforge.fml.ModContainer; -@Mod("spongeapi") -public class SpongeAPIMod { +public final class ModContainerModule extends PrivateModule { + private final ModContainer modContainer; + + public ModContainerModule(final ModContainer modContainer) { + this.modContainer = modContainer; + } + + @Override + protected void configure() { + this.bind(ModContainer.class).toInstance(this.modContainer); + this.bind(BusGroup.class).toInstance(this.modContainer.getModBusGroup()); + } } diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java index 249fc3044fe..a8145b9eb36 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/PluginModContainer.java @@ -128,6 +128,11 @@ public Object getMod() { return this.container.instance(); } + @Override + public BusGroup getModBusGroup() { + return this.busGroup; + } + @SuppressWarnings("unchecked") @Override protected void acceptEvent(final T e) { diff --git a/forge/src/main/resource-templates/META-INF/mods.toml b/forge/src/main/resource-templates/META-INF/mods.toml deleted file mode 100644 index dd478d7f7fa..00000000000 --- a/forge/src/main/resource-templates/META-INF/mods.toml +++ /dev/null @@ -1,56 +0,0 @@ -modLoader="javafml" -loaderVersion="[53,)" -license="MIT License" - -issueTrackerURL="https://github.com/SpongePowered/Sponge/issues" - - -[[mods]] -modId="spongeforge" -version="{{ version }}" -displayName="SpongeForge" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description = "{{ description }}" - -[[dependencies.spongeforge]] -modId="forge" -mandatory=true -versionRange="[{{ forgeVersion }},)" -ordering="AFTER" -side="BOTH" - -[[dependencies.spongeforge]] -modId="sponge" -mandatory=true -versionRange="[{{ version }}]" -ordering="AFTER" -side="BOTH" - - -[[mods]] -modId="sponge" -version="{{ version }}" -displayName="Sponge" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description="The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms" - -[[dependencies.sponge]] -modId="spongeapi" -mandatory=true -versionRange="[{{ apiVersion }},)" -ordering="AFTER" -side="BOTH" - - -[[mods]] -modId="spongeapi" -version="{{ apiVersion }}" -displayName="SpongeAPI" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description="A Minecraft plugin API" diff --git a/forge/src/main/resource-templates/META-INF/sponge_plugins.json b/forge/src/main/resource-templates/META-INF/sponge_plugins.json new file mode 100644 index 00000000000..5ce964326cf --- /dev/null +++ b/forge/src/main/resource-templates/META-INF/sponge_plugins.json @@ -0,0 +1,57 @@ +{ + "global": { + "loader": { + "name": "java_plain", + "version": "1.0" + }, + "license": "MIT", + "links": { + "homepage": "https://www.spongepowered.org", + "source": "https://www.spongepowered.org/source", + "issues": "https://www.spongepowered.org/issues" + }, + "contributors": [ + { + "name": "SpongePowered", + "description": "Lead Developer" + } + ] + }, + "plugins": [ + { + "id": "spongeforge", + "name": "SpongeForge", + "version": "{{ version }}", + "entrypoints": ["org.spongepowered.forge.SpongeForge"], + "description": "{{ description }}", + "dependencies": [ + { + "id": "forge", + "version": "[{{ forgeVersion }},)" + }, + { + "id": "sponge", + "version": "{{ version }}" + } + ] + }, + { + "id": "sponge", + "name": "Sponge", + "version": "{{ version }}", + "description": "The common Sponge implementation", + "dependencies": [ + { + "id": "spongeapi", + "version": "{{ apiVersion }}" + } + ] + }, + { + "id": "spongeapi", + "name": "SpongeAPI", + "version": "{{ apiVersion }}", + "description": "The Minecraft API specification" + } + ] +} \ No newline at end of file diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index ab347317a31..726f892ae90 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -242,6 +242,15 @@ val neoManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } +val modManifest = java.manifest { + attributes( + "Access-Widener" to "common.accesswidener", + "Superclass-Transformer" to "common.superclasschange,neoforge.superclasschange", + "MixinConfigs" to mixinConfigs.joinToString(","), + "LithiumOptions" to "mixin.world.tick_scheduler=false,mixin.collections.entity_filtering=false" + ) +} + sourceSets { main { blossom.resources { @@ -249,7 +258,6 @@ sourceSets { property("version", version.toString()) property("description", description.toString()) property("neoForgeVersion", neoForgeVersion) - property("mixins", mixinConfigs.joinToString(",") { "{config=\"$it\"}" }) } } @@ -290,6 +298,13 @@ tasks { dependsOn(emitDependencies) } + named(main.processResourcesTaskName, ProcessResources::class) { + val manifestFile = this.destinationDir.resolve("META-INF/MANIFEST.MF") + doLast { + modManifest.writeTo(manifestFile) + } + } + val servicesShadowJar by register("servicesShadowJar", ShadowJar::class) { group = "build" archiveClassifier.set("services") @@ -324,10 +339,7 @@ tasks { manifest { from(neoManifest) - attributes( - "Access-Widener" to "common.accesswidener", - "Superclass-Transformer" to "common.superclasschange,neoforge.superclasschange" - ) + from(modManifest) } from(commonMain.map { it.output }) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index c5a4c5b8021..38282a9f8f6 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -25,34 +25,21 @@ package org.spongepowered.neoforge.applaunch.mod.discovery; import net.neoforged.fml.jarcontents.JarContents; -import net.neoforged.fml.loading.FMLEnvironment; -import net.neoforged.fml.loading.FMLPaths; import net.neoforged.fml.loading.moddiscovery.readers.JarModsDotTomlModFileReader; import net.neoforged.neoforgespi.ILaunchContext; import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; import net.neoforged.neoforgespi.locating.IModFile; import net.neoforged.neoforgespi.locating.IModFileCandidateLocator; -import net.neoforged.neoforgespi.locating.IncompatibleFileReporting; import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.neoforge.applaunch.plugin.NeoPluginPlatform; import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; import org.spongepowered.neoforge.applaunch.plugin.discovery.NeoPluginDiscovery; -import java.net.URI; -import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.Map; public final class SpongeNeoModLocator implements IModFileCandidateLocator { - private static final Logger LOGGER = LogManager.getLogger(); - private final NeoPluginDiscovery discovery; public SpongeNeoModLocator() { @@ -118,39 +105,6 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) } this.discovery.logMetadataWarnings(); - - if (!FMLEnvironment.isProduction()) { - return; - } - - // Official JiJ cannot be used in a service jar. We have to reimplement it. - // FML 10 only supports files directly on disk, so we must extract them. - try { - final URL rootJar = SpongeNeoModLocator.class.getProtectionDomain().getCodeSource().getLocation(); - final Path cacheDir = FMLPaths.JIJ_CACHEDIR.get(); - - try (final FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + rootJar), Map.of())) { - final Path jarsDir = fs.getPath("jars"); - - // Difference with the official JiJ: our checksums are precalculated, to avoid unnecessary IO. - for (final String line : Files.readAllLines(jarsDir.resolve("checksums.txt"))) { - final int i = line.indexOf(' '); - final String digest = line.substring(0, i), name = line.substring(i + 1); - final Path target = cacheDir.resolve(digest).resolve(name); - - // FML does not verify the cached file checksum, so neither do we. - // The checksum is only there to distinguish different files. - if (!Files.exists(target)) { - Files.createDirectories(target.getParent()); - Files.copy(jarsDir.resolve(name), target); - } - - pipeline.addPath(target, attributes, IncompatibleFileReporting.WARN_ALWAYS); - } - } - } catch (Exception e) { - LOGGER.error("Failed to register embedded mod candidates", e); - } } @Override diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java index c4f104c05d5..c10b39d4369 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -70,6 +70,17 @@ public Optional getConfigElement(final String... key) { return Optional.of((T) (joinedLicenses.isEmpty() ? "?" : joinedLicenses)); } + if ("lithium:options".equals(query)) { + return this.resource.property("LithiumOptions").map(value -> { + final Map map = new HashMap<>(); + for (final String entry : value.split(",")) { + final int i = entry.indexOf('='); + map.put(entry.substring(0, i), Boolean.valueOf(entry.substring(i + 1))); + } + return (T) map; + }); + } + if (key.length == 2) { final String plugin = key[1]; final PluginMetadata metadata = this.plugins.get(plugin); diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/SpongeNeoResourceLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/SpongeNeoResourceLocator.java new file mode 100644 index 00000000000..25d7167d4af --- /dev/null +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/SpongeNeoResourceLocator.java @@ -0,0 +1,83 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.neoforge.applaunch.plugin.discovery; + +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.fml.loading.FMLPaths; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; +import org.spongepowered.plugin.discovery.PluginResourceLocator; +import org.spongepowered.plugin.discovery.UnknownResourceStrategy; + +import java.net.URI; +import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +public final class SpongeNeoResourceLocator implements PluginResourceLocator { + + @Override + public String name() { + return "spongeneo"; + } + + @Override + public Collection locatePluginResources(final Environment environment) throws Exception { + final List resources = new LinkedList<>(); + if (!FMLEnvironment.isProduction()) { + return resources; + } + + // Official JiJ cannot be used in a service jar. We have to reimplement it. + // FML 10 only supports files directly on disk, so we must extract them. + final URL rootJar = SpongeNeoResourceLocator.class.getProtectionDomain().getCodeSource().getLocation(); + final Path cacheDir = FMLPaths.JIJ_CACHEDIR.get(); + + try (final FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + rootJar), Map.of())) { + final Path jarsDir = fs.getPath("jars"); + + // Difference with the official JiJ: our checksums are precalculated, to avoid unnecessary IO. + for (final String line : Files.readAllLines(jarsDir.resolve("checksums.txt"))) { + final int i = line.indexOf(' '); + final String digest = line.substring(0, i), name = line.substring(i + 1); + final Path target = cacheDir.resolve(digest).resolve(name); + + // FML does not verify the cached file checksum, so neither do we. + // The checksum is only there to distinguish different files. + if (!Files.exists(target)) { + Files.createDirectories(target.getParent()); + Files.copy(jarsDir.resolve(name), target); + } + + resources.add(new Result(JVMPluginResource.create(environment, target), UnknownResourceStrategy.WARN)); + } + } + + return resources; + } +} diff --git a/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator b/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator index 93a6e7f4172..be7de628e45 100644 --- a/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator +++ b/neoforge/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.discovery.PluginResourceLocator @@ -1 +1,2 @@ +org.spongepowered.neoforge.applaunch.plugin.discovery.SpongeNeoResourceLocator org.spongepowered.common.applaunch.plugin.discovery.SpongePropertyResourceLocator diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeMod.java deleted file mode 100644 index 2191386a358..00000000000 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeMod.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.neoforge; - -import net.neoforged.fml.common.Mod; - -@Mod("sponge") -public class SpongeMod { -} diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeo.java similarity index 96% rename from neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java rename to neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeo.java index b79889aee68..57197b21027 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeoMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/SpongeNeo.java @@ -24,10 +24,10 @@ */ package org.spongepowered.neoforge; +import com.google.inject.Inject; import net.minecraft.client.Minecraft; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.common.NeoForge; @@ -50,13 +50,15 @@ import org.spongepowered.neoforge.hook.NeoGeneralHooks; import org.spongepowered.neoforge.hook.NeoItemHooks; import org.spongepowered.neoforge.hook.NeoWorldHooks; +import org.spongepowered.plugin.builtin.jvm.Plugin; -@Mod("spongeneo") -public final class SpongeNeoMod { +@Plugin("spongeneo") +public final class SpongeNeo { private final Logger logger = LogManager.getLogger("spongeneo"); - public SpongeNeoMod(IEventBus modBus) { + @Inject + public SpongeNeo(IEventBus modBus) { // modBus: add all FML events with it modBus.addListener(this::onCommonSetup); modBus.addListener(this::onClientSetup); diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/NeoLaunch.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/NeoLaunch.java index 57ce3dcb301..669b0527584 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/NeoLaunch.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/NeoLaunch.java @@ -30,16 +30,19 @@ import com.google.inject.Module; import com.google.inject.Stage; import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.ModList; import net.neoforged.fml.loading.FMLEnvironment; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.inject.SpongeCommonModule; import org.spongepowered.common.inject.SpongeModule; import org.spongepowered.common.launch.Launch; +import org.spongepowered.neoforge.launch.inject.ModContainerModule; import org.spongepowered.neoforge.launch.inject.SpongeNeoModule; import org.spongepowered.neoforge.launch.plugin.NeoPluginManager; import org.spongepowered.plugin.PluginContainer; import java.util.List; +import java.util.Optional; public final class NeoLaunch extends Launch { @@ -88,4 +91,9 @@ public PluginContainer platformPlugin() { return this.spongeNeoPlugin; } + + @Override + public Optional modModule(final PluginContainer plugin) { + return ModList.get().getModContainerById(plugin.metadata().id()).map(ModContainerModule::new); + } } diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeAPIMod.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/inject/ModContainerModule.java similarity index 67% rename from forge/src/main/java/org/spongepowered/forge/SpongeAPIMod.java rename to neoforge/src/main/java/org/spongepowered/neoforge/launch/inject/ModContainerModule.java index 863a0654753..414e59a7e6d 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeAPIMod.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/inject/ModContainerModule.java @@ -22,10 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.forge; +package org.spongepowered.neoforge.launch.inject; -import net.minecraftforge.fml.common.Mod; +import com.google.inject.PrivateModule; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; -@Mod("spongeapi") -public class SpongeAPIMod { +public final class ModContainerModule extends PrivateModule { + private final ModContainer modContainer; + + public ModContainerModule(final ModContainer modContainer) { + this.modContainer = modContainer; + } + + @Override + protected void configure() { + this.bind(ModContainer.class).toInstance(this.modContainer); + this.bind(IEventBus.class).toInstance(this.modContainer.getEventBus()); + } } diff --git a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml b/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml deleted file mode 100644 index bd8f185db5c..00000000000 --- a/neoforge/src/main/resource-templates/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,64 +0,0 @@ -modLoader="javafml" -loaderVersion="[4,)" -license="MIT License" - -issueTrackerURL="https://github.com/SpongePowered/Sponge/issues" - -mixins = [{{ mixins }}] - - -[[mods]] -modId="spongeneo" -version="{{ version }}" -displayName="SpongeNeo" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description = "{{ description }}" - -[[dependencies.spongeneo]] -modId="neoforge" -type="required" -versionRange="[{{ neoForgeVersion }},)" -ordering="AFTER" - -[[dependencies.spongeneo]] -modId="sponge" -type="required" -versionRange="[{{ version }}]" -ordering="AFTER" - - -[[mods]] -modId="sponge" -version="{{ version }}" -displayName="Sponge" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description="The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms" - -[[dependencies.sponge]] -modId="spongeapi" -type="required" -versionRange="[{{ apiVersion }},)" -ordering="AFTER" - - -[[mods]] -modId="spongeapi" -version="{{ apiVersion }}" -displayName="SpongeAPI" -displayTest="IGNORE_SERVER_VERSION" -credits="SpongePowered and Contributors" -authors="SpongePowered" -description="A Minecraft plugin API" - - -["lithium:options"] -"mixin.world.tick_scheduler"=false -"mixin.collections.entity_filtering"=false - -[[dependencies.spongeneo]] -modId="adventure_platform_neoforge" -type="incompatible" diff --git a/neoforge/src/main/resource-templates/META-INF/sponge_plugins.json b/neoforge/src/main/resource-templates/META-INF/sponge_plugins.json new file mode 100644 index 00000000000..631ae5853bf --- /dev/null +++ b/neoforge/src/main/resource-templates/META-INF/sponge_plugins.json @@ -0,0 +1,65 @@ +{ + "global": { + "loader": { + "name": "java_plain", + "version": "1.0" + }, + "license": "MIT", + "links": { + "homepage": "https://www.spongepowered.org", + "source": "https://www.spongepowered.org/source", + "issues": "https://www.spongepowered.org/issues" + }, + "contributors": [ + { + "name": "SpongePowered", + "description": "Lead Developer" + } + ] + }, + "plugins": [ + { + "id": "spongeneo", + "name": "SpongeNeo", + "version": "{{ version }}", + "entrypoints": ["org.spongepowered.neoforge.SpongeNeo"], + "description": "{{ description }}", + "dependencies": [ + { + "id": "neoforge", + "version": "[{{ neoForgeVersion }},)" + }, + { + "id": "sponge", + "version": "{{ version }}" + } + ], + "conflicts": [ + { + "id": "adventure_platform_neoforge", + "version": "*", + "fatal": true, + "reason": "SpongeNeo provides its own implementation of Adventure" + } + ] + }, + { + "id": "sponge", + "name": "Sponge", + "version": "{{ version }}", + "description": "The common Sponge implementation", + "dependencies": [ + { + "id": "spongeapi", + "version": "{{ apiVersion }}" + } + ] + }, + { + "id": "spongeapi", + "name": "SpongeAPI", + "version": "{{ apiVersion }}", + "description": "The Minecraft API specification" + } + ] +} \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/MANIFEST.MF b/neoforge/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 6818dcc8cd0..00000000000 --- a/neoforge/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Superclass-Transformer: common.superclasschange,neoforge.superclasschange diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java index d35a7e76d08..b1a1cb5fc2d 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java @@ -24,20 +24,25 @@ */ package org.spongepowered.common.inject.plugin; -import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.launch.Launch; import org.spongepowered.plugin.PluginContainer; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; public final class PluginGuice { - public static Injector create(final PluginContainer container, final Collection> pluginClasses, final @Nullable Injector platformInjector) { - final List modules = new ArrayList<>(List.of(new PublicPluginModule(container), new PrivatePluginModule(container, pluginClasses))); + public static Injector create(final PluginContainer container, final Collection> pluginClasses) { + final List modules = new LinkedList<>(); + modules.add(new PublicPluginModule(container)); + modules.add(new PrivatePluginModule(container, pluginClasses)); + + final Launch launch = Launch.instance(); + launch.modModule(container).ifPresent(modules::add); final @Nullable Object customModule = container.metadata().property("guice-module").orElse(null); if (customModule != null) { @@ -51,11 +56,6 @@ public static Injector create(final PluginContainer container, final Collection< } final Module module = new PriorityOverrideModule(modules); - - if (platformInjector != null) { - return platformInjector.createChildInjector(module); - } else { - return Guice.createInjector(module); - } + return launch.lifecycle().platformInjector().createChildInjector(module); } } diff --git a/src/main/java/org/spongepowered/common/launch/Launch.java b/src/main/java/org/spongepowered/common/launch/Launch.java index 491f78e68ec..a541ec25f54 100644 --- a/src/main/java/org/spongepowered/common/launch/Launch.java +++ b/src/main/java/org/spongepowered/common/launch/Launch.java @@ -25,6 +25,7 @@ package org.spongepowered.common.launch; import com.google.inject.Injector; +import com.google.inject.Module; import com.google.inject.Stage; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -39,6 +40,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; public abstract class Launch { @@ -166,4 +168,8 @@ public final void auditMixins() { } public abstract Injector createInjector(); + + public Optional modModule(final PluginContainer plugin) { + return Optional.empty(); + } } diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java index 7d0052e0ae1..45b976bec90 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java @@ -29,7 +29,6 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.spongepowered.api.Sponge; import org.spongepowered.common.inject.plugin.PluginGuice; -import org.spongepowered.common.launch.Launch; import org.spongepowered.common.launch.plugin.SpongePluginContainer; import org.spongepowered.plugin.*; import org.spongepowered.plugin.discovery.PluginResource; @@ -60,7 +59,7 @@ public PluginContainer loadPlugin(Environment environment, PluginResource resour pluginClasses.add(Class.forName(className)); } - final Injector pluginInjector = PluginGuice.create(container, pluginClasses, Launch.instance().lifecycle().platformInjector()); + final Injector pluginInjector = PluginGuice.create(container, pluginClasses); container.setInjector(pluginInjector); for (final Class pluginClass : pluginClasses) { diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index b439a0c6332..70f93d19633 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -319,8 +319,9 @@ appLaunch.apply { main.apply { blossom.resources { property("apiVersion", apiVersion) - property("minecraftVersion", minecraftVersion) property("version", version.toString()) + property("description", description.toString()) + property("minecraftVersion", minecraftVersion) } } installer.apply { diff --git a/vanilla/src/main/resource-templates/META-INF/sponge_plugins.json b/vanilla/src/main/resource-templates/META-INF/sponge_plugins.json index 45938219309..9f8ee4b862a 100644 --- a/vanilla/src/main/resource-templates/META-INF/sponge_plugins.json +++ b/vanilla/src/main/resource-templates/META-INF/sponge_plugins.json @@ -1,10 +1,10 @@ { - "loader": { - "name": "java_plain", - "version": "1.0" - }, - "license": "MIT", "global": { + "loader": { + "name": "java_plain", + "version": "1.0" + }, + "license": "MIT", "links": { "homepage": "https://www.spongepowered.org", "source": "https://www.spongepowered.org/source", @@ -22,9 +22,12 @@ "id": "spongevanilla", "name": "SpongeVanilla", "version": "{{ version }}", - "entrypoint": "org.spongepowered.vanilla.SpongeVanilla", - "description": "Vanilla Minecraft with Sponge", + "description": "{{ description }}", "dependencies": [ + { + "id": "minecraft", + "version": "{{ minecraftVersion }}" + }, { "id": "sponge", "version": "{{ version }}" @@ -35,13 +38,8 @@ "id": "sponge", "name": "Sponge", "version": "{{ version }}", - "entrypoint": "org.spongepowered.common.SpongeCommon", "description": "The common Sponge implementation", "dependencies": [ - { - "id": "minecraft", - "version": "{{ minecraftVersion }}" - }, { "id": "spongeapi", "version": "{{ apiVersion }}" @@ -52,7 +50,6 @@ "id": "spongeapi", "name": "SpongeAPI", "version": "{{ apiVersion }}", - "entrypoint": "org.spongepowered.api.Sponge", "description": "The Minecraft API specification" } ] From 83e9fb5e3f168a1ff4722b4c2b960db7bf72c1b4 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 19 Jul 2026 21:48:11 +0200 Subject: [PATCH 558/586] Support plugins in unit tests --- build.gradle.kts | 9 +++++ .../applaunch/plugin/PluginPlatform.java | 10 ++++- .../plugin/PluginPlatformConstants.java | 1 + .../applaunch/test/TestEnvironment.java | 32 ++++++++++++++++ .../common/mixin/plugin/TestPlugin.java | 4 +- .../entrypoint/EntrypointPlugin_Main.java | 35 ++++++++++++++++++ .../entrypoint/PluginEntrypointTest.java | 37 +++++++++++++++++++ .../META-INF/sponge_test_plugins.json | 32 ++++++++++++++++ 8 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 src/applaunch/java/org/spongepowered/common/applaunch/test/TestEnvironment.java create mode 100644 src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java create mode 100644 src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java create mode 100644 src/test/resource-templates/META-INF/sponge_test_plugins.json diff --git a/build.gradle.kts b/build.gradle.kts index 9cb6c134069..703d31c1839 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,7 @@ plugins { id("implementation-structure") id(apiLibs.plugins.ideaExt.get().pluginId) alias(libs.plugins.versions) + alias(libs.plugins.blossom) } val apiVersion: String by project @@ -158,6 +159,14 @@ idea { } } +sourceSets { + test { + blossom.resources { + property("apiVersion", apiVersion.replace("-SNAPSHOT", "")) + } + } +} + allprojects { configurations.configureEach { resolutionStrategy.dependencySubstitution { diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java index 176a86eec8b..c7ec9d90478 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java @@ -24,11 +24,13 @@ */ package org.spongepowered.common.applaunch.plugin; +import com.google.common.collect.ImmutableList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.config.LaunchConfig; import org.spongepowered.common.applaunch.config.TokenReplacement; import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; +import org.spongepowered.common.applaunch.test.TestEnvironment; import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.blackboard.Blackboard; import org.spongepowered.plugin.blackboard.Keys; @@ -74,11 +76,17 @@ public PluginPlatform() { } this.pluginDirectories = List.of(modsDirectory, additionalPluginsDirectory); + ImmutableList.Builder metadataFilePaths = ImmutableList.builder(); + metadataFilePaths.add(PluginPlatformConstants.METADATA_FILE_PATH); + if (TestEnvironment.isActive()) { + metadataFilePaths.add(PluginPlatformConstants.TEST_METADATA_FILE_PATH); + } + final Blackboard blackboard = this.environment.blackboard(); blackboard.set(Keys.VERSION, version); blackboard.set(Keys.BASE_DIRECTORY, baseDirectory); blackboard.set(Keys.PLUGIN_DIRECTORIES, this.pluginDirectories); - blackboard.set(Keys.METADATA_FILE_PATHS, List.of(PluginPlatformConstants.METADATA_FILE_PATH)); + blackboard.set(Keys.METADATA_FILE_PATHS, metadataFilePaths.build()); blackboard.set(JVMKeys.ENVIRONMENT_LOCATOR_VARIABLE_NAME, PluginPlatformConstants.ENVIRONMENT_LOCATOR_VARIABLE_NAME); blackboard.set(JVMKeys.JVM_PLUGIN_RESOURCE_FACTORY, this); } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java index dc8bb0487f2..8e6b2beb8e6 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java @@ -30,6 +30,7 @@ private PluginPlatformConstants() { } public static final String METADATA_FILE_PATH = "META-INF/sponge_plugins.json"; + public static final String TEST_METADATA_FILE_PATH = "META-INF/sponge_test_plugins.json"; public static final String ENVIRONMENT_LOCATOR_VARIABLE_NAME = "SPONGE_PLUGINS"; public static final boolean IGNORE_FATAL_CONFLICTS = Boolean.getBoolean("sponge.discovery.ignoreFatalConflicts"); diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/test/TestEnvironment.java b/src/applaunch/java/org/spongepowered/common/applaunch/test/TestEnvironment.java new file mode 100644 index 00000000000..be3685b47e8 --- /dev/null +++ b/src/applaunch/java/org/spongepowered/common/applaunch/test/TestEnvironment.java @@ -0,0 +1,32 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.applaunch.test; + +public class TestEnvironment { + + public static boolean isActive() { + return "true".equals(System.getProperty("sponge.test.active")); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java b/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java index a51d74ab859..56ce44006cd 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/plugin/TestPlugin.java @@ -24,11 +24,13 @@ */ package org.spongepowered.common.mixin.plugin; +import org.spongepowered.common.applaunch.test.TestEnvironment; + public final class TestPlugin extends AbstractMixinConfigPlugin { private final boolean active; public TestPlugin() { - this.active = "true".equals(System.getProperty("sponge.test.active")); + this.active = TestEnvironment.isActive(); } @Override diff --git a/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java new file mode 100644 index 00000000000..e6acc6dde3f --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java @@ -0,0 +1,35 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.entrypoint; + +import java.util.concurrent.atomic.AtomicInteger; + +public class EntrypointPlugin_Main { + public static final AtomicInteger INSTANCES = new AtomicInteger(); + + public EntrypointPlugin_Main() { + EntrypointPlugin_Main.INSTANCES.incrementAndGet(); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java b/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java new file mode 100644 index 00000000000..37c59ef6412 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java @@ -0,0 +1,37 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.entrypoint; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class PluginEntrypointTest { + + @Test + public void verifyMainEntrypoint() { + assertEquals(1, EntrypointPlugin_Main.INSTANCES.get()); + } +} diff --git a/src/test/resource-templates/META-INF/sponge_test_plugins.json b/src/test/resource-templates/META-INF/sponge_test_plugins.json new file mode 100644 index 00000000000..d2080f61b7c --- /dev/null +++ b/src/test/resource-templates/META-INF/sponge_test_plugins.json @@ -0,0 +1,32 @@ +{ + "loader": { + "name": "java_plain", + "version": "1.0" + }, + "license": "MIT", + "global": { + "version": "{{ apiVersion }}", + "links": { + "homepage": "https://www.spongepowered.org", + "source": "https://www.spongepowered.org/source", + "issues": "https://www.spongepowered.org/issues" + }, + "contributors": [ + { + "name": "SpongePowered", + "description": "Lead Developer" + } + ] + }, + "plugins": [ + { + "id": "entrypoint", + "description": "Verifies entrypoints are properly called.", + "entrypoints": { + "main": [ + "org.spongepowered.common.plugin.entrypoint.EntrypointPlugin_Main" + ] + } + } + ] +} From abd323ba162c8994a966c89be1da39aa193f721e Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 22 Jul 2026 21:53:19 +0200 Subject: [PATCH 559/586] Provide plugin-spi version in blackboard on all platforms --- build.gradle.kts | 4 ++++ .../forge/applaunch/plugin/ForgePluginPlatform.java | 6 ------ .../neoforge/applaunch/plugin/NeoPluginPlatform.java | 7 ------- .../common/applaunch/plugin/PluginPlatformConstants.java | 2 ++ .../common/applaunch/plugin/PluginPlatform.java | 7 ++----- .../vanilla/applaunch/plugin/VanillaPluginPlatform.java | 7 ------- 6 files changed, 8 insertions(+), 25 deletions(-) rename src/applaunch/{java => java-templates}/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java (96%) diff --git a/build.gradle.kts b/build.gradle.kts index 703d31c1839..8181bc72710 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,6 +68,10 @@ val applaunch by sourceSets.registering { configurations.named(implementationConfigurationName) { extendsFrom(serviceLayerConfig.get()) } + + blossom.javaSources { + property("pluginSpiVersion", apiLibs.pluginSpi.get().version) + } } // Game layer diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java index a1fe3600c31..0c9c987ce6a 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java @@ -24,8 +24,6 @@ */ package org.spongepowered.forge.applaunch.plugin; -import cpw.mods.modlauncher.Launcher; -import cpw.mods.modlauncher.api.IEnvironment; import net.minecraftforge.fml.loading.FMLPaths; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.forge.applaunch.plugin.discovery.ForgePluginDiscovery; @@ -45,10 +43,6 @@ public ForgePluginPlatform() { this.discovery = new ForgePluginDiscovery(this.environment()); } - @Override - public String version() { - return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev"); - } @Override public boolean vanilla() { return false; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java index a547f7cdd0d..e391b071b94 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/NeoPluginPlatform.java @@ -26,7 +26,6 @@ import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.neoforge.common.NeoForgeVersion; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; import org.spongepowered.neoforge.applaunch.plugin.discovery.NeoPluginDiscovery; @@ -41,12 +40,6 @@ public NeoPluginPlatform() { this.discovery = new NeoPluginDiscovery(this.environment()); } - @SuppressWarnings("UnstableApiUsage") - @Override - public String version() { - return NeoForgeVersion.getVersion(); - } - @Override public boolean vanilla() { return false; diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java b/src/applaunch/java-templates/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java similarity index 96% rename from src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java rename to src/applaunch/java-templates/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java index 8e6b2beb8e6..fd6e9035fe7 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java +++ b/src/applaunch/java-templates/org/spongepowered/common/applaunch/plugin/PluginPlatformConstants.java @@ -29,6 +29,8 @@ public final class PluginPlatformConstants { private PluginPlatformConstants() { } + public static final String SPI_VERSION = "{{ pluginSpiVersion }}"; + public static final String METADATA_FILE_PATH = "META-INF/sponge_plugins.json"; public static final String TEST_METADATA_FILE_PATH = "META-INF/sponge_test_plugins.json"; public static final String ENVIRONMENT_LOCATOR_VARIABLE_NAME = "SPONGE_PLUGINS"; diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java index c7ec9d90478..ab8e0d0b56f 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/PluginPlatform.java @@ -55,8 +55,7 @@ public abstract class PluginPlatform implements JVMPluginResource.Factory { public PluginPlatform() { this.environment = new StandardEnvironment(PluginPlatform.LOGGER); - final String version = this.version(); - this.logger().info("SpongePowered PLUGIN Subsystem Version={} Source={}", version, this.getCodeSource()); + this.logger().info("SpongePowered PLUGIN Subsystem Version={} Source={}", PluginPlatformConstants.SPI_VERSION, this.getCodeSource()); final Path baseDirectory = this.baseDirectory(); final Path modsDirectory = this.modsDirectory(); @@ -83,7 +82,7 @@ public PluginPlatform() { } final Blackboard blackboard = this.environment.blackboard(); - blackboard.set(Keys.VERSION, version); + blackboard.set(Keys.VERSION, PluginPlatformConstants.SPI_VERSION); blackboard.set(Keys.BASE_DIRECTORY, baseDirectory); blackboard.set(Keys.PLUGIN_DIRECTORIES, this.pluginDirectories); blackboard.set(Keys.METADATA_FILE_PATHS, metadataFilePaths.build()); @@ -95,8 +94,6 @@ public final Logger logger() { return PluginPlatform.LOGGER; } - public abstract String version(); - protected String getCodeSource() { try { return this.getClass().getProtectionDomain().getCodeSource().getLocation().toString(); diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java index 753b2fa0ec1..af2e3f2712f 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaPluginPlatform.java @@ -28,7 +28,6 @@ import cpw.mods.modlauncher.api.IEnvironment; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.common.applaunch.plugin.PluginPlatform; -import org.spongepowered.plugin.builtin.StandardEnvironment; import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; import org.spongepowered.vanilla.applaunch.plugin.discovery.VanillaPluginDiscovery; @@ -48,12 +47,6 @@ public VanillaPluginPlatform() { this.discovery = new VanillaPluginDiscovery(this.environment()); } - @Override - public String version() { - final String implVersion = StandardEnvironment.class.getPackage().getImplementationVersion(); - return implVersion == null ? "dev" : implVersion; - } - @Override public boolean vanilla() { return true; From fda13a495ebbb40dfb81f65ccb09ca54e5d7a495 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 29 Jul 2026 13:29:46 +0200 Subject: [PATCH 560/586] Support sided entrypoints --- .../spongepowered/common/SpongeLifecycle.java | 14 +++++ .../common/inject/SpongeModule.java | 7 ++- ...odule.java => PluginDependencyModule.java} | 30 +++++----- .../inject/plugin/PluginEntrypointModule.java | 53 ++++++++++++++++++ .../common/inject/plugin/PluginGuice.java | 16 ++++-- .../inject/plugin/PrivatePluginModule.java | 17 +----- .../launch/plugin/SpongePluginContainer.java | 44 ++++++++++++--- .../plugin/loader/JavaPluginLoader.java | 26 ++------- .../entrypoint/EntrypointPlugin_Main.java | 20 ++++++- .../entrypoint/EntrypointPlugin_Server.java | 56 +++++++++++++++++++ .../entrypoint/PluginEntrypointTest.java | 9 ++- .../META-INF/sponge_test_plugins.json | 3 + .../plugin/VanillaDummyPluginContainer.java | 6 ++ 13 files changed, 234 insertions(+), 67 deletions(-) rename src/main/java/org/spongepowered/common/inject/plugin/{PublicPluginModule.java => PluginDependencyModule.java} (70%) create mode 100644 src/main/java/org/spongepowered/common/inject/plugin/PluginEntrypointModule.java create mode 100644 src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Server.java diff --git a/src/main/java/org/spongepowered/common/SpongeLifecycle.java b/src/main/java/org/spongepowered/common/SpongeLifecycle.java index 709a7c54b63..b695f18943b 100644 --- a/src/main/java/org/spongepowered/common/SpongeLifecycle.java +++ b/src/main/java/org/spongepowered/common/SpongeLifecycle.java @@ -39,6 +39,7 @@ import org.spongepowered.api.Client; import org.spongepowered.api.Engine; import org.spongepowered.api.Game; +import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.EventContext; @@ -47,6 +48,7 @@ import org.spongepowered.api.registry.RegistryRoots; import org.spongepowered.api.registry.RegistryType; import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.bridge.core.WritableRegistryBridge; import org.spongepowered.common.bridge.server.packs.resources.ResourceManagerBridge; import org.spongepowered.common.data.SpongeDataManager; @@ -61,6 +63,7 @@ import org.spongepowered.common.event.manager.SpongeEventManager; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.launch.Lifecycle; +import org.spongepowered.common.launch.plugin.SpongePluginContainer; import org.spongepowered.common.network.channel.SpongeChannelManager; import org.spongepowered.common.profile.SpongeGameProfileManager; import org.spongepowered.common.registry.SpongeBuilderProvider; @@ -258,6 +261,17 @@ public void establishClientRegistries(final Client client) { @Override public void callStartingEngineEvent(final Engine engine) { + final boolean server = engine instanceof Server; + for (final PluginContainer container : this.game.pluginManager().plugins()) { + if (container instanceof SpongePluginContainer spongeContainer) { + try { + spongeContainer.loadSidedEntrypoints(server); + } catch (final Exception e) { + PluginPlatform.LOGGER.error("Failed to load {} sided entrypoints of plugin {}", server ? "server" : "client", container.metadata().id(), e); + } + } + } + this.game.eventManager().post(SpongeEventFactory.createStartingEngineEvent(PhaseTracker.getInstance().currentCause(), engine, this.game, (TypeToken) TypeToken.get(engine.getClass()))); } diff --git a/src/main/java/org/spongepowered/common/inject/SpongeModule.java b/src/main/java/org/spongepowered/common/inject/SpongeModule.java index f20dc056a25..2e7d34909ad 100644 --- a/src/main/java/org/spongepowered/common/inject/SpongeModule.java +++ b/src/main/java/org/spongepowered/common/inject/SpongeModule.java @@ -25,6 +25,9 @@ package org.spongepowered.common.inject; import com.google.inject.AbstractModule; +import org.spongepowered.api.Client; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.inject.provider.ConfigDirAnnotation; @@ -35,6 +38,8 @@ public final class SpongeModule extends AbstractModule { @Override protected void configure() { this.bind(Path.class).annotatedWith(ConfigDirAnnotation.SHARED).toInstance(SpongeCommon.pluginConfigDirectory()); - } + this.bind(Server.class).toProvider(Sponge::server); + this.bind(Client.class).toProvider(Sponge::client); + } } diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PublicPluginModule.java b/src/main/java/org/spongepowered/common/inject/plugin/PluginDependencyModule.java similarity index 70% rename from src/main/java/org/spongepowered/common/inject/plugin/PublicPluginModule.java rename to src/main/java/org/spongepowered/common/inject/plugin/PluginDependencyModule.java index 49d633ce16a..0074200b18d 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PublicPluginModule.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PluginDependencyModule.java @@ -26,6 +26,7 @@ import com.google.inject.AbstractModule; import org.spongepowered.api.Sponge; +import org.spongepowered.api.plugin.PluginManager; import org.spongepowered.common.launch.plugin.SpongePluginContainer; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.metadata.model.PluginDependency; @@ -35,36 +36,39 @@ * Contains the values that are publicly visible and shared * across dependencies. */ -public final class PublicPluginModule extends AbstractModule { +public final class PluginDependencyModule extends AbstractModule { private final PluginContainer container; - PublicPluginModule(final PluginContainer container) { + PluginDependencyModule(final PluginContainer container) { this.container = container; } @Override protected void configure() { final BindingHelper bindingHelper = new BindingHelper(this.binder().withSource(BindingHelper.class)); + final PluginManager manager = Sponge.pluginManager(); + for (final PluginDependency dependency : this.container.metadata().dependencies()) { if (dependency.loadOrder() != PluginDependency.LoadOrder.AFTER) { continue; } - Sponge.pluginManager().plugin(dependency.id()) - .flatMap(p -> ((SpongePluginContainer) p).injector()) - .ifPresent(bindingHelper::bindFrom); + if (manager.plugin(dependency.id()).orElse(null) instanceof SpongePluginContainer spongeContainer) { + spongeContainer.injector().ifPresent(bindingHelper::bindFrom); + } } // Indirect dependencies - Sponge.pluginManager() - .plugins() - .stream() - .filter(p -> p.metadata().dependency(this.container.metadata().id()) - .map(PluginDependency::loadOrder) - .orElse(PluginDependency.LoadOrder.UNDEFINED) == PluginDependency.LoadOrder.BEFORE) - .flatMap(p -> ((SpongePluginContainer) p).injector().stream()) - .forEach(bindingHelper::bindFrom); + for (final PluginContainer other : manager.plugins()) { + if (other.metadata().dependency(this.container.metadata().id()).map(PluginDependency::loadOrder).orElse(PluginDependency.LoadOrder.UNDEFINED) != PluginDependency.LoadOrder.BEFORE) { + continue; + } + + if (other instanceof SpongePluginContainer spongeContainer) { + spongeContainer.injector().ifPresent(bindingHelper::bindFrom); + } + } bindingHelper.bind(); } diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PluginEntrypointModule.java b/src/main/java/org/spongepowered/common/inject/plugin/PluginEntrypointModule.java new file mode 100644 index 00000000000..fbd57ae8046 --- /dev/null +++ b/src/main/java/org/spongepowered/common/inject/plugin/PluginEntrypointModule.java @@ -0,0 +1,53 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.inject.plugin; + +import com.google.inject.PrivateModule; +import com.google.inject.Scopes; + +import java.util.Collection; + + +/** + * A private module installed for each plugin. + * Contains the entrypoint classes. + */ +public final class PluginEntrypointModule extends PrivateModule { + + private final Collection> pluginClasses; + + PluginEntrypointModule(final Collection> pluginClasses) { + this.pluginClasses = pluginClasses; + } + + @Override + protected void configure() { + for (final Class pluginClass : this.pluginClasses) { + this.bind(pluginClass).in(Scopes.SINGLETON); + this.expose(pluginClass); + } + } + +} diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java index b1a1cb5fc2d..9e15381687f 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PluginGuice.java @@ -28,7 +28,7 @@ import com.google.inject.Module; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.launch.Launch; -import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.common.launch.plugin.SpongePluginContainer; import java.util.Collection; import java.util.LinkedList; @@ -36,10 +36,11 @@ public final class PluginGuice { - public static Injector create(final PluginContainer container, final Collection> pluginClasses) { + public static Injector createMain(final SpongePluginContainer container, final Collection> pluginClasses) { final List modules = new LinkedList<>(); - modules.add(new PublicPluginModule(container)); - modules.add(new PrivatePluginModule(container, pluginClasses)); + modules.add(new PluginDependencyModule(container)); + modules.add(new PluginEntrypointModule(pluginClasses)); + modules.add(new PrivatePluginModule(container)); final Launch launch = Launch.instance(); launch.modModule(container).ifPresent(modules::add); @@ -55,7 +56,10 @@ public static Injector create(final PluginContainer container, final Collection< } } - final Module module = new PriorityOverrideModule(modules); - return launch.lifecycle().platformInjector().createChildInjector(module); + return launch.lifecycle().platformInjector().createChildInjector(new PriorityOverrideModule(modules)); + } + + public static Injector createChild(final SpongePluginContainer container, final Collection> pluginClasses) { + return container.injector().get().createChildInjector(new PluginEntrypointModule(pluginClasses)); } } diff --git a/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java b/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java index f70c2de1159..c385eeb2583 100644 --- a/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java +++ b/src/main/java/org/spongepowered/common/inject/plugin/PrivatePluginModule.java @@ -31,32 +31,21 @@ import org.spongepowered.common.inject.provider.PluginConfigurationModule; import org.spongepowered.plugin.PluginContainer; -import java.util.Collection; - - /** - * A module installed for each plugin. - * + * A private module installed for each plugin. * Contains the values that are not shared for dependencies or - * that require access to the private resources, like the plugin class. + * that require access to the private resources, like the plugin container. */ public final class PrivatePluginModule extends PrivateModule { private final PluginContainer container; - private final Collection> pluginClasses; - PrivatePluginModule(final PluginContainer container, final Collection> pluginClasses) { + PrivatePluginModule(final PluginContainer container) { this.container = container; - this.pluginClasses = pluginClasses; } @Override protected void configure() { - for (final Class pluginClass : this.pluginClasses) { - this.bind(pluginClass).in(Scopes.SINGLETON); - this.expose(pluginClass); - } - this.install(new InjectionPointProvider()); this.bind(PluginContainer.class).toInstance(this.container); diff --git a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java index fc3e5820fda..76737e38e0d 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/SpongePluginContainer.java @@ -25,12 +25,18 @@ package org.spongepowered.common.launch.plugin; import com.google.inject.Injector; +import org.spongepowered.api.Sponge; +import org.spongepowered.common.inject.plugin.PluginGuice; import org.spongepowered.plugin.builtin.StandardPluginContainer; import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; +import org.spongepowered.plugin.metadata.model.PluginEntrypoints; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +@SuppressWarnings("deprecation") // registerListeners public class SpongePluginContainer extends StandardPluginContainer { private Object instance = this; private Injector injector; @@ -45,17 +51,39 @@ public Object instance() { return this.instance; } - public void setInstanceIfMissing(final Object instance) { - if (this.instance == this) { - this.instance = instance; - } - } - public Optional injector() { return Optional.ofNullable(this.injector); } - public void setInjector(final Injector injector) { - this.injector = injector; + public void loadMainEntrypoints() throws Exception { + final List> pluginClasses = new ArrayList<>(); + for (final String className : this.metadata().entrypoints().main()) { + pluginClasses.add(Class.forName(className)); + } + + final Injector pluginInjector = PluginGuice.createMain(this, pluginClasses); + this.injector = pluginInjector; + + for (final Class pluginClass : pluginClasses) { + final Object plugin = pluginInjector.getInstance(pluginClass); + if (this.instance == this) { + this.instance = plugin; + } + Sponge.eventManager().registerListeners(this, plugin); + } + } + + public void loadSidedEntrypoints(boolean server) throws Exception { + final List> pluginClasses = new ArrayList<>(); + final PluginEntrypoints entrypoints = this.metadata().entrypoints(); + for (final String className : server ? entrypoints.server() : entrypoints.client()) { + pluginClasses.add(Class.forName(className)); + } + + final Injector pluginInjector = PluginGuice.createChild(this, pluginClasses); + for (final Class pluginClass : pluginClasses) { + final Object plugin = pluginInjector.getInstance(pluginClass); + Sponge.eventManager().registerListeners(this, plugin); + } } } diff --git a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java index 45b976bec90..80c76b9809d 100644 --- a/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java +++ b/src/main/java/org/spongepowered/common/launch/plugin/loader/JavaPluginLoader.java @@ -24,19 +24,15 @@ */ package org.spongepowered.common.launch.plugin.loader; -import com.google.inject.Injector; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.spongepowered.api.Sponge; -import org.spongepowered.common.inject.plugin.PluginGuice; import org.spongepowered.common.launch.plugin.SpongePluginContainer; -import org.spongepowered.plugin.*; +import org.spongepowered.plugin.Environment; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.PluginLoader; import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import java.util.ArrayList; -import java.util.List; - public final class JavaPluginLoader implements PluginLoader { private static final ArtifactVersion version = new DefaultArtifactVersion("1.0"); @@ -53,21 +49,7 @@ public String name() { @Override public PluginContainer loadPlugin(Environment environment, PluginResource resource, PluginMetadata metadata) throws Exception { final SpongePluginContainer container = new SpongePluginContainer(resource, metadata); - - final List> pluginClasses = new ArrayList<>(); - for (final String className : container.metadata().entrypoints().main()) { - pluginClasses.add(Class.forName(className)); - } - - final Injector pluginInjector = PluginGuice.create(container, pluginClasses); - container.setInjector(pluginInjector); - - for (final Class pluginClass : pluginClasses) { - final Object plugin = pluginInjector.getInstance(pluginClass); - container.setInstanceIfMissing(plugin); - Sponge.eventManager().registerListeners(container, plugin); - } - + container.loadMainEntrypoints(); return container; } } diff --git a/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java index e6acc6dde3f..04d8c52112a 100644 --- a/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java +++ b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Main.java @@ -24,12 +24,28 @@ */ package org.spongepowered.common.plugin.entrypoint; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.inject.Inject; +import org.spongepowered.api.Game; +import org.spongepowered.api.Sponge; + import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; public class EntrypointPlugin_Main { - public static final AtomicInteger INSTANCES = new AtomicInteger(); + public static final AtomicInteger INSTANCES_COUNT = new AtomicInteger(); + public static final AtomicReference INSTANCE = new AtomicReference<>(); + + @Inject + private Game game; public EntrypointPlugin_Main() { - EntrypointPlugin_Main.INSTANCES.incrementAndGet(); + EntrypointPlugin_Main.INSTANCES_COUNT.incrementAndGet(); + EntrypointPlugin_Main.INSTANCE.set(this); + } + + public void test() { + assertEquals(Sponge.game(), this.game); } } diff --git a/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Server.java b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Server.java new file mode 100644 index 00000000000..7856bf50da5 --- /dev/null +++ b/src/test/java/org/spongepowered/common/plugin/entrypoint/EntrypointPlugin_Server.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.plugin.entrypoint; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.inject.Inject; +import org.spongepowered.api.Game; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +public class EntrypointPlugin_Server { + public static final AtomicInteger INSTANCES_COUNT = new AtomicInteger(); + public static final AtomicReference INSTANCE = new AtomicReference<>(); + + @Inject + private Game game; + + @Inject + private Server server; + + public EntrypointPlugin_Server() { + EntrypointPlugin_Server.INSTANCES_COUNT.incrementAndGet(); + EntrypointPlugin_Server.INSTANCE.set(this); + } + + public void test() { + assertEquals(Sponge.game(), this.game); + assertEquals(Sponge.server(), this.server); + } +} diff --git a/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java b/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java index 37c59ef6412..9cf8e696d5f 100644 --- a/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java +++ b/src/test/java/org/spongepowered/common/plugin/entrypoint/PluginEntrypointTest.java @@ -32,6 +32,13 @@ public class PluginEntrypointTest { @Test public void verifyMainEntrypoint() { - assertEquals(1, EntrypointPlugin_Main.INSTANCES.get()); + assertEquals(1, EntrypointPlugin_Main.INSTANCES_COUNT.get()); + EntrypointPlugin_Main.INSTANCE.get().test(); + } + + @Test + public void verifyServerEntrypoint() { + assertEquals(1, EntrypointPlugin_Server.INSTANCES_COUNT.get()); + EntrypointPlugin_Server.INSTANCE.get().test(); } } diff --git a/src/test/resource-templates/META-INF/sponge_test_plugins.json b/src/test/resource-templates/META-INF/sponge_test_plugins.json index d2080f61b7c..c426e175cb4 100644 --- a/src/test/resource-templates/META-INF/sponge_test_plugins.json +++ b/src/test/resource-templates/META-INF/sponge_test_plugins.json @@ -25,6 +25,9 @@ "entrypoints": { "main": [ "org.spongepowered.common.plugin.entrypoint.EntrypointPlugin_Main" + ], + "server": [ + "org.spongepowered.common.plugin.entrypoint.EntrypointPlugin_Server" ] } } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java index ee96a863e7a..a4201db1157 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaDummyPluginContainer.java @@ -34,4 +34,10 @@ public final class VanillaDummyPluginContainer extends SpongePluginContainer imp public VanillaDummyPluginContainer(final PluginResource resource, final PluginMetadata metadata) { super(resource, metadata); } + + @Override + public void loadMainEntrypoints() {} + + @Override + public void loadSidedEntrypoints(boolean server) {} } From 0885a5d84f0bfa8925cb4393228db37e3eeaf0ba Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 29 Jul 2026 20:48:20 +0200 Subject: [PATCH 561/586] Remove ResourceLoading --- .../mod/discovery/PluginFileParser.java | 4 +-- .../SpongeForgeDependencyLocator.java | 2 +- .../mod/discovery/SpongeForgeModLocator.java | 16 +++------ .../mod/discovery/SpongeNeoModLocator.java | 18 +++------- .../plugin/discovery/PluginDiscovery.java | 19 ++++------ .../SpongePropertyResourceLocator.java | 3 +- .../plugin/discovery/PluginDiscoveryTest.java | 3 +- .../plugin/VanillaTransformationService.java | 36 +++++++------------ .../VanillaAccessWidenerTransformer.java | 3 +- .../VanillaSuperclassChangeTransformer.java | 3 +- 10 files changed, 36 insertions(+), 71 deletions(-) diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java index 73c6d7fe696..21781a36955 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/PluginFileParser.java @@ -125,8 +125,8 @@ private static ModFile newPluginFile(final IModProvider provider, final PluginDi return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, type); } - public static ModFile newLibraryFile(final IModProvider provider, final boolean game, final SecureJar jar) { - return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, game ? "GAMELIBRARY" : "LIBRARY"); + public static ModFile newGameLibraryFile(final IModProvider provider, final SecureJar jar) { + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, "GAMELIBRARY"); } private static class DummyModProvider extends AbstractModProvider { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java index a1d7f9c155f..37656bf37ea 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeDependencyLocator.java @@ -78,7 +78,7 @@ public List scanMods(final Iterable loadedMods) { for (final LibraryManager.Library library : libraryManager.getAll("main")) { final Path path = library.file(); SpongeForgeDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - modFiles.add(PluginFileParser.newLibraryFile(this, true, SecureJar.from(path))); + modFiles.add(PluginFileParser.newGameLibraryFile(this, SecureJar.from(path))); } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java index bd3bc54e015..0419cd5ab7b 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/mod/discovery/SpongeForgeModLocator.java @@ -81,18 +81,12 @@ public List scanMods() { } if (modFile == null) { - // determine fallback type - switch (candidate.loading()) { - case IGNORED: - candidate.logResult(); - continue; - case LIBRARY: - modFile = PluginFileParser.newLibraryFile(this, false, resource.jar()); - break; - case GAME_LIBRARY: - modFile = PluginFileParser.newLibraryFile(this, true, resource.jar()); - break; + // fallback + if (!candidate.gameResource()) { + candidate.logResult(); + continue; } + modFile = PluginFileParser.newGameLibraryFile(this, resource.jar()); } } else { candidate.readMetadata(); diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index 38282a9f8f6..f0f7153868c 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -69,20 +69,12 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) } catch (Exception ignored) {} if (modFile == null) { - // determine fallback type - IModFile.Type type = null; - switch (candidate.loading()) { - case IGNORED: - candidate.logResult(); - continue; - case LIBRARY: - type = IModFile.Type.LIBRARY; - break; - case GAME_LIBRARY: - type = IModFile.Type.GAMELIBRARY; - break; + // fallback + if (!candidate.gameResource()) { + candidate.logResult(); + continue; } - modFile = IModFile.create(resource.jar(), JarModsDotTomlModFileReader::manifestParser, type, attributes); + modFile = IModFile.create(resource.jar(), JarModsDotTomlModFileReader::manifestParser, IModFile.Type.GAMELIBRARY, attributes); } else if (!candidate.pluginFound()) { candidate.setModFound(); } diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java index 49e549f0e36..f73105277b7 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -142,8 +142,8 @@ public final Candidate candidate(final PluginResource resource) { return candidate; } - public final Collection resources(final ResourceLoading loading) { - return this.candidates.values().stream().filter((c) -> c.loading() == loading).map(Candidate::resource).toList(); + public final Collection gameResources() { + return this.candidates.values().stream().filter(Candidate::gameResource).map(Candidate::resource).toList(); } public final void logMetadataWarnings() { @@ -259,14 +259,14 @@ public boolean pluginFound() { return !this.metadata.isEmpty(); } - public ResourceLoading loading() { + public boolean gameResource() { if (this.pluginFound() || this.loaderFound) { - return ResourceLoading.GAME_LIBRARY; + return true; } if (this.locatorFound || this.readerFound) { - return ResourceLoading.IGNORED; + return false; } - return this.unknownResourceStrategy.loading(); + return this.unknownResourceStrategy.load(); } public void setModFound() { @@ -282,12 +282,7 @@ public void logResult() { return; } - final String result = switch (this.unknownResourceStrategy.loading()) { - case IGNORED -> "ignored"; - case LIBRARY -> "loaded as a standard library"; - case GAME_LIBRARY -> "loaded as a game library"; - }; - + final String result = this.unknownResourceStrategy.load() ? "loaded as a game library" : "ignored"; if (this.unknownResourceStrategy.warn()) { PluginDiscovery.this.environment.logger().warn("The unknown resource {} will be {}.", this.resource, result); } else { diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java index 046dd4108ec..7174ba058e2 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/SpongePropertyResourceLocator.java @@ -27,7 +27,6 @@ import org.spongepowered.plugin.Environment; import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; import org.spongepowered.plugin.discovery.PluginResourceLocator; -import org.spongepowered.plugin.discovery.ResourceLoading; import org.spongepowered.plugin.discovery.UnknownResourceStrategy; import java.io.File; @@ -49,7 +48,7 @@ public Collection locatePluginResources(final Environment environment) { final Set resources = new HashSet<>(); final String resourcesProp = System.getProperty("sponge.resources"); if (resourcesProp != null) { - final UnknownResourceStrategy strategy = new UnknownResourceStrategy(false, ResourceLoading.GAME_LIBRARY); + final UnknownResourceStrategy strategy = new UnknownResourceStrategy(false, true); for (final String entry : resourcesProp.split(File.pathSeparator)) { if (entry.isBlank()) { diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java b/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java index 09675fcb5ac..b8d81311396 100644 --- a/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java +++ b/src/test/java/org/spongepowered/common/plugin/discovery/PluginDiscoveryTest.java @@ -31,7 +31,6 @@ import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.plugin.discovery.spi.DummyMetadataReader; import org.spongepowered.plugin.PluginService; -import org.spongepowered.plugin.discovery.ResourceLoading; import java.util.List; import java.util.Optional; @@ -48,7 +47,7 @@ public void verifyDummyCandidate() { assertIterableEquals(List.of("dummy_locator"), candidate.get().locators().stream().map(PluginService::name).toList()); // reader - assertEquals(ResourceLoading.GAME_LIBRARY, candidate.get().loading()); + assertTrue(candidate.get().gameResource()); assertIterableEquals(List.of(DummyMetadataReader.DUMMY_METADATA), candidate.get().metadata()); } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java index 396ef37bdcf..4263f563cbd 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/VanillaTransformationService.java @@ -68,37 +68,25 @@ public List beginScanning(final IEnvironment env) { this.platform.discovery().discoverPluginResources(); - final List libs = new ArrayList<>(); final List gameLibs = new ArrayList<>(); for (final PluginDiscovery.Candidate candidate : this.platform.discovery().candidates()) { final PluginResource resource = candidate.resource(); candidate.readMetadata(); - switch (candidate.loading()) { - case IGNORED: - break; - case LIBRARY: - if (resource instanceof SecureJarPluginResource jarResource) { - libs.add(jarResource.jar()); - } - break; - case GAME_LIBRARY: - if (resource instanceof SecureJarPluginResource jarResource) { - gameLibs.add(candidate.pluginFound() ? jarResource.pluginJar(candidate.metadata().getFirst()) : jarResource.jar()); - - if (mixin != null) { - final Path path = jarResource.jar().getPrimaryPath(); - mixin.offerResource(path, path.getFileName().toString()); - - if (resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { - if (candidate.metadata().stream().noneMatch(m -> "spongevanilla".equals(m.id()))) { - this.platform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", path); - } - } + if (candidate.gameResource() && resource instanceof SecureJarPluginResource jarResource) { + gameLibs.add(candidate.pluginFound() ? jarResource.pluginJar(candidate.metadata().getFirst()) : jarResource.jar()); + + if (mixin != null) { + final Path path = jarResource.jar().getPrimaryPath(); + mixin.offerResource(path, path.getFileName().toString()); + + if (resource.property(org.spongepowered.asm.util.Constants.ManifestAttributes.MIXINCONFIGS).isPresent()) { + if (candidate.metadata().stream().noneMatch(m -> "spongevanilla".equals(m.id()))) { + this.platform.logger().warn("Plugin from {} uses Mixins to modify the Minecraft Server. If something breaks, remove it before reporting the problem to Sponge!", path); } } - break; + } } candidate.logResult(); @@ -110,7 +98,7 @@ public List beginScanning(final IEnvironment env) { throw new IllegalStateException("Fatal plugin conflicts have been detected."); } - return List.of(new Resource(IModuleLayerManager.Layer.PLUGIN, libs), new Resource(IModuleLayerManager.Layer.GAME, gameLibs)); + return List.of(new Resource(IModuleLayerManager.Layer.GAME, gameLibs)); } @SuppressWarnings("rawtypes") diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java index 1efdfb6d802..83a279397fa 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java @@ -32,7 +32,6 @@ import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.applaunch.transformation.AccessWidenerTransformer; import org.spongepowered.plugin.discovery.PluginResource; -import org.spongepowered.plugin.discovery.ResourceLoading; import java.net.URL; import java.util.*; @@ -70,7 +69,7 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (final PluginResource plugin : this.discovery.resources(ResourceLoading.GAME_LIBRARY)) { + for (final PluginResource plugin : this.discovery.gameResources()) { final Optional attribute = plugin.property(AccessWidenerTransformer.MANIFEST_ATTRIBUTE); if (attribute.isPresent()) { for (final String path : attribute.get().split(",")) { diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java index cb81c28f99d..6e8079cf233 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java @@ -32,7 +32,6 @@ import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.applaunch.transformation.SuperclassChangeTransformer; import org.spongepowered.plugin.discovery.PluginResource; -import org.spongepowered.plugin.discovery.ResourceLoading; import java.net.URL; import java.util.*; @@ -75,7 +74,7 @@ public Set targets() { @Override protected Collection collectResources() { final Collection resources = new ArrayList<>(); - for (final PluginResource plugin : this.discovery.resources(ResourceLoading.GAME_LIBRARY)) { + for (final PluginResource plugin : this.discovery.gameResources()) { final Optional attribute = plugin.property(SuperclassChangeTransformer.MANIFEST_ATTRIBUTE); if (attribute.isPresent()) { for (final String scPath : attribute.get().split(",")) { From 7f9a066f34bc364b4d0fc042af1055ca0d9e8c63 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 31 Jul 2026 13:08:16 +0200 Subject: [PATCH 562/586] Update verification metadata --- gradle/verification-metadata.xml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a7a4c2c9186..acd5560750c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -21,8 +21,8 @@ - + @@ -8567,6 +8567,11 @@ + + + + + @@ -8978,6 +8983,11 @@ + + + + + @@ -11262,6 +11272,11 @@ + + + + + @@ -11284,6 +11299,11 @@ + + + + + From 3775c172101264413d034bb5c35167017e7198c2 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 9 Aug 2026 22:15:08 +0200 Subject: [PATCH 563/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index b08258c147f..3e582fed416 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit b08258c147f8411218ba1e60b28249de48bca979 +Subproject commit 3e582fed416b17bfa6ef0f12e9f9ea771c7bece1 From a3cb3169b35eed84435b7431398519d50a8ae3a6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 11:37:22 +0200 Subject: [PATCH 564/586] Bump Forge to 61.1.5 and NeoForge to 21.11.45 --- forge/gradle.properties | 2 +- gradle/verification-metadata.xml | 91 ++++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 13366137a4c..760d9f26994 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=61.0.6 +forgeVersion=61.1.5 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index acd5560750c..710e8ede12b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4850,6 +4850,11 @@ + + + + + @@ -4925,6 +4930,11 @@ + + + + + @@ -4994,6 +5004,11 @@ + + + + + @@ -5173,6 +5188,11 @@ + + + + + @@ -5352,6 +5372,11 @@ + + + + + @@ -5617,6 +5642,11 @@ + + + + + @@ -5652,6 +5682,11 @@ + + + + + @@ -5729,6 +5764,11 @@ + + + + + @@ -5908,6 +5948,11 @@ + + + + + @@ -6095,6 +6140,11 @@ + + + + + @@ -6361,6 +6411,11 @@ + + + + + @@ -6901,6 +6956,17 @@ + + + + + + + + + + + @@ -10560,6 +10626,11 @@ + + + + + @@ -10616,6 +10687,11 @@ + + + + + @@ -10685,6 +10761,11 @@ + + + + + @@ -10754,6 +10835,11 @@ + + + + + @@ -10794,6 +10880,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index f6da24fbfff..6d5b0f51f59 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=21.11.36-beta +neoForgeVersion=21.11.45 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 6fab9f7138e9996805b0af27cd6414d615bb4305 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 13:07:10 +0200 Subject: [PATCH 565/586] Register plugins as mixin containers on Neo --- .../mod/discovery/SpongeLanguageLoader.java | 6 +++ .../mod/metadata/PluginFileConfigurable.java | 13 ------- .../discovery/JarContentsPluginResource.java | 7 +++- .../plugin/discovery/NeoPluginDiscovery.java | 12 ++++++ .../PluginResourceContainerHandle.java} | 37 +++++++++++-------- 5 files changed, 45 insertions(+), 30 deletions(-) rename neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/{mod/metadata/PluginMixinConfigurable.java => plugin/discovery/PluginResourceContainerHandle.java} (62%) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java index aadde5e3b22..6da38598c34 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeLanguageLoader.java @@ -33,6 +33,8 @@ import net.neoforged.neoforgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.neoforge.applaunch.plugin.NeoPluginPlatform; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -41,6 +43,10 @@ public final class SpongeLanguageLoader extends BuiltInLanguageLoader { private static final Logger LOGGER = LogManager.getLogger(); + public SpongeLanguageLoader() { + AppLaunch.pluginPlatform().discovery().registerMixinContainers(); + } + @Override public String name() { return "sponge"; diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java index c10b39d4369..ad785d27012 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginFileConfigurable.java @@ -111,19 +111,6 @@ public List getConfigList(final String... key) { return this.plugins.values().stream().map(PluginMetadataConfigurable::new).toList(); } - if ("mixins".equals(query)) { - final Optional mixinConfigs = this.resource.property("MixinConfigs"); - if (mixinConfigs.isEmpty()) { - return Collections.emptyList(); - } - - final List mixinConfigurables = new ArrayList<>(); - for (final String config : mixinConfigs.get().split(",")) { - mixinConfigurables.add(new PluginMixinConfigurable(config.trim())); - } - return mixinConfigurables; - } - if (key.length != 2) { return Collections.emptyList(); } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java index 789d329f974..f9db26d9ba1 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java @@ -26,6 +26,7 @@ import net.neoforged.fml.jarcontents.JarContents; import net.neoforged.fml.jarmoduleinfo.JarModuleInfo; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; import java.io.IOException; @@ -41,6 +42,7 @@ public final class JarContentsPluginResource implements SpongeJVMPluginResource { private final List paths; private final JarContents jar; + private @MonotonicNonNull ModuleDescriptor descriptor; public JarContentsPluginResource(final Path[] paths) { Objects.requireNonNull(paths, "paths"); @@ -82,7 +84,10 @@ public Manifest manifest() { @Override public ModuleDescriptor module() { - return JarModuleInfo.from(this.jar).createDescriptor(this.jar); + if (this.descriptor == null) { + this.descriptor = JarModuleInfo.from(this.jar).createDescriptor(this.jar); + } + return this.descriptor; } @Override diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java index cc054cd2488..76991344c23 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java @@ -26,6 +26,8 @@ import net.neoforged.fml.jarcontents.CompositeJarContents; import net.neoforged.fml.jarcontents.JarContents; +import net.neoforged.fml.loading.mixin.FMLMixinService; +import org.spongepowered.asm.service.MixinService; import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; import org.spongepowered.plugin.Environment; @@ -71,4 +73,14 @@ protected void appendDiscoveryServices(final List resou this.currentLoader = loader; this.environment.logger().debug("Built new service layer {} on top of {}.", loader.getName(), parentLoader.getName()); } + + @SuppressWarnings("UnstableApiUsage") + public void registerMixinContainers() { + final FMLMixinService mixinService = (FMLMixinService) MixinService.getService(); + for (final PluginDiscovery.Candidate candidate : this.candidates()) { + if (candidate.pluginFound() && candidate.resource() instanceof JarContentsPluginResource jarResource) { + mixinService.addMixinContainer(new PluginResourceContainerHandle(jarResource)); + } + } + } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java similarity index 62% rename from neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java rename to neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java index fc9612029c9..b972dc30c7d 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/metadata/PluginMixinConfigurable.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java @@ -22,32 +22,37 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.neoforge.applaunch.mod.metadata; +package org.spongepowered.neoforge.applaunch.plugin.discovery; -import net.neoforged.neoforgespi.language.IConfigurable; +import org.spongepowered.asm.launch.platform.container.IContainerHandle; -import java.util.Collections; +import java.util.Collection; import java.util.List; -import java.util.Optional; -public final class PluginMixinConfigurable implements IConfigurable { - private final String config; +public class PluginResourceContainerHandle implements IContainerHandle { + private final JarContentsPluginResource resource; - public PluginMixinConfigurable(final String config) { - this.config = config; + public PluginResourceContainerHandle(final JarContentsPluginResource resource) { + this.resource = resource; } - @SuppressWarnings("unchecked") @Override - public Optional getConfigElement(final String... key) { - if (key.length == 1 && "config".equals(key[0])) { - return Optional.of((T) this.config); - } - return Optional.empty(); + public String getAttribute(final String name) { + return this.resource.property(name).orElse(null); } @Override - public List getConfigList(final String... key) { - return Collections.emptyList(); + public Collection getNestedContainers() { + return List.of(); + } + + @Override + public String getId() { + return this.resource.module().name(); + } + + @Override + public String getDescription() { + return this.resource.toString(); } } From 263e485fb79317ea2d5b6e6c7a7dc417302956ff Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 15:06:00 +0200 Subject: [PATCH 566/586] Do not mark unknown resources as located on Neo --- .../neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java index f0f7153868c..0aec3618e38 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/mod/discovery/SpongeNeoModLocator.java @@ -60,7 +60,6 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) candidate.logResult(); continue; } - resource.paths().forEach(context::addLocated); // attempt to load as mod or plugin IModFile modFile = null; @@ -79,6 +78,7 @@ public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) candidate.setModFound(); } + resource.paths().forEach(context::addLocated); pipeline.addModFile(modFile); } else { candidate.readMetadata(); From a8169a0021a3e631de54796b86fd13f1a0a75bed Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 15:14:35 +0200 Subject: [PATCH 567/586] Use plugin id as mixin container id --- .../plugin/discovery/NeoPluginDiscovery.java | 4 ++-- .../discovery/PluginResourceContainerHandle.java | 12 ++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java index 76991344c23..32cc856a141 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/NeoPluginDiscovery.java @@ -78,8 +78,8 @@ protected void appendDiscoveryServices(final List resou public void registerMixinContainers() { final FMLMixinService mixinService = (FMLMixinService) MixinService.getService(); for (final PluginDiscovery.Candidate candidate : this.candidates()) { - if (candidate.pluginFound() && candidate.resource() instanceof JarContentsPluginResource jarResource) { - mixinService.addMixinContainer(new PluginResourceContainerHandle(jarResource)); + if (candidate.pluginFound()) { + mixinService.addMixinContainer(new PluginResourceContainerHandle(candidate.metadata().getFirst().id(), candidate.resource())); } } } diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java index b972dc30c7d..9740c4aa951 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/PluginResourceContainerHandle.java @@ -25,16 +25,12 @@ package org.spongepowered.neoforge.applaunch.plugin.discovery; import org.spongepowered.asm.launch.platform.container.IContainerHandle; +import org.spongepowered.plugin.discovery.PluginResource; import java.util.Collection; import java.util.List; -public class PluginResourceContainerHandle implements IContainerHandle { - private final JarContentsPluginResource resource; - - public PluginResourceContainerHandle(final JarContentsPluginResource resource) { - this.resource = resource; - } +public record PluginResourceContainerHandle(String id, PluginResource resource) implements IContainerHandle { @Override public String getAttribute(final String name) { @@ -48,11 +44,11 @@ public Collection getNestedContainers() { @Override public String getId() { - return this.resource.module().name(); + return this.id; } @Override public String getDescription() { - return this.resource.toString(); + return this.toString(); } } From e9cee7f82858fecc83c28e73b136c0f1309a645f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 15:20:53 +0200 Subject: [PATCH 568/586] Fix SPI crash when a jar contains an invalid module descriptor --- .../applaunch/plugin/discovery/PluginDiscovery.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java index f73105277b7..be10598da23 100644 --- a/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java +++ b/src/applaunch/java/org/spongepowered/common/applaunch/plugin/discovery/PluginDiscovery.java @@ -199,8 +199,16 @@ public PluginResource resource() { private void detectServices(final Set existingLocators, final Set existingReaders) { if (this.resource instanceof SpongeJVMPluginResource jvmResource) { + final ModuleDescriptor descriptor; + try { + descriptor = jvmResource.module(); + } catch (Exception ex) { + PluginDiscovery.this.environment.logger().warn("Cannot read module descriptor of {}", jvmResource, ex); + return; + } + final Map> providers = new HashMap<>(); - for (final ModuleDescriptor.Provides provides : jvmResource.module().provides()) { + for (final ModuleDescriptor.Provides provides : descriptor.provides()) { providers.put(provides.service(), provides.providers()); } final List locators = providers.getOrDefault(PluginResourceLocator.class.getName(), Collections.emptyList()); From ea52f524f186ae7493f6b9ae8154bc60107e2b19 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 15 Aug 2026 15:56:28 +0200 Subject: [PATCH 569/586] Bump Forge to 64.1.1 and NeoForge to 26.1.2.95 --- forge/gradle.properties | 2 +- gradle/libs.versions.toml | 12 ++-- gradle/verification-metadata.xml | 116 +++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 124 insertions(+), 8 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 19b01c841c4..684806e869b 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=64.0.1 +forgeVersion=64.1.1 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9af7694656c..29ebeb44972 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,14 +4,14 @@ format = { version = "1.1" } # Implementation-only dependencies, or dependencies that use a different version than in API # See SpongeAPI's gradle/libs.versions.toml for many dependency declarations that Sponge also uses [versions] -asm = "9.8" +asm = "9.9.1" log4j = "2.25.2" mixin = "0.8.7" -mixinextras = "0.5.3" -modlauncher = "10.2.3" -securemodules = "2.2.22" -fancymodloader = "10.0.36" -jarjar = "0.3.26" +mixinextras = "0.5.4" +modlauncher = "10.2.6" +securemodules = "2.2.24" +fancymodloader = "11.0.15" +jarjar = "0.4.2" guava = "32.1.2-jre" jline = "3.25.1" tinylog = "2.7.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 75f2d1eefc8..4a209e60437 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2780,6 +2780,11 @@ + + + + + @@ -2804,6 +2809,11 @@ + + + + + @@ -3592,6 +3602,11 @@ + + + + + @@ -4753,6 +4768,11 @@ + + + + + @@ -4998,6 +5018,11 @@ + + + + + @@ -5078,6 +5103,11 @@ + + + + + @@ -5277,6 +5307,11 @@ + + + + + @@ -5476,6 +5511,11 @@ + + + + + @@ -5675,6 +5715,11 @@ + + + + + @@ -5858,6 +5903,11 @@ + + + + + @@ -6102,6 +6152,11 @@ + + + + + @@ -6309,6 +6364,11 @@ + + + + + @@ -6516,6 +6576,11 @@ + + + + + @@ -6602,6 +6667,11 @@ + + + + + @@ -7303,6 +7373,17 @@ + + + + + + + + + + + @@ -7508,6 +7589,11 @@ + + + + + @@ -7648,6 +7734,11 @@ + + + + + @@ -11378,6 +11469,11 @@ + + + + + @@ -11452,6 +11548,11 @@ + + + + + @@ -11521,6 +11622,11 @@ + + + + + @@ -11603,6 +11709,11 @@ + + + + + @@ -11672,6 +11783,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 9bf88fa5950..df2f4536c38 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.1.2.31-beta +neoForgeVersion=26.1.2.95 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 6def94c2e3a136d2107a031b5978fef6445b9137 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 16 Aug 2026 19:38:40 +0200 Subject: [PATCH 570/586] Update readme badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2dd894ee81b..08faf3cc7bc 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) +[![SpongeVanilla 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) +[![SpongeForge 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 1.21.11](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=1.21.11&queryOpt=%3Aversion%3D1.21.11-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D1.21.11-*) +[![SpongeNeo 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) ## Prerequisites From f9b3c52010747c800115e9548ac10bcf8badcd0c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 16 Aug 2026 21:02:17 +0200 Subject: [PATCH 571/586] Disable mixin debug on Forge --- forge/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 2b3dbe90c56..ab7728668ee 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -243,8 +243,8 @@ minecraft { runs { configureEach { -// jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath - jvmArgs("-Dmixin.debug=true", "-Dmixin.debug.export=true", "-Dmixin.dumpTargetOnFailure=true") + // jvmArgs("-Dsponge.bootstrap.debug=true") // Uncomment to debug bootstrap classpath + // jvmArgs("-Dmixin.debug=true", "-Dmixin.debug.export=true", "-Dmixin.dumpTargetOnFailure=true") mainClass.set("org.spongepowered.bootstrap.forge.ForgeBootstrap") args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) From 9c5563ad804b7a9939ca0357aab7b60b10099a13 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 16 Aug 2026 21:40:47 +0200 Subject: [PATCH 572/586] Bump actions/cache to 6.1.0 --- .github/workflows/common-integration-test.yaml | 2 +- .github/workflows/common-run-build.yaml | 2 +- .github/workflows/deploy.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/common-integration-test.yaml b/.github/workflows/common-integration-test.yaml index 3becbb81bae..626e1c94897 100644 --- a/.github/workflows/common-integration-test.yaml +++ b/.github/workflows/common-integration-test.yaml @@ -32,7 +32,7 @@ jobs: with: distribution: temurin java-version: "${{ matrix.java }}" - - uses: "actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf" # v4.2.2 + - uses: "actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9" # v6.1.0 with: path: "${{ github.workspace}}/libraries" key: "${{runner.os}}-${{matrix.java}}-it-libraries-${{ hashFiles('code/build.gradle.kts') }}-${{ github.workspace }}/code/libraries.json" diff --git a/.github/workflows/common-run-build.yaml b/.github/workflows/common-run-build.yaml index b3427aed0c0..f73c909eb1e 100644 --- a/.github/workflows/common-run-build.yaml +++ b/.github/workflows/common-run-build.yaml @@ -34,7 +34,7 @@ jobs: runtime_version: 25 publishing_branch_regex: 'api-\d+' - name: setup / cache minecraft dependencies - uses: "actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf" # v4.2.2 + uses: "actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9" # v6.1.0 if: "!startsWith(github.ref, 'refs/heads/update/') || matrix.project == 'vanilla'" with: path: | diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 90567c19f33..27f4f5fae7e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -55,7 +55,7 @@ jobs: publishing_branch_regex: '' - name: setup / minecraft cache if: "!(matrix.skipUpdateBranch && startsWith(github.ref, 'refs/heads/update/'))" - uses: "actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf" # v4.2.2 + uses: "actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9" # v6.1.0 with: path: | ${{ github.workspace}}/buildSrc/.gradle/ From c7a75ccbfeb6ac4ddc457b5acf8f09ac78ab31b2 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 18 Aug 2026 13:31:45 +0200 Subject: [PATCH 573/586] Bump ForgeGradle to 7.0.34 and ModDevGradle to 2.0.144 --- gradle/libs.versions.toml | 4 ++-- gradle/verification-metadata.xml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 29ebeb44972..74fa4bbe695 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -70,5 +70,5 @@ blossom = { id = "net.kyori.blossom", version = "2.1.0" } indra-licenserSpotless = { id = "net.kyori.indra.licenser.spotless", version = "3.1.3" } shadow = { id = "com.gradleup.shadow", version = "9.0.2" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } -forgeGradle = { id = "net.minecraftforge.gradle", version = "7.0.17" } -modDevGradle = { id = "net.neoforged.moddev", version = "2.0.141" } +forgeGradle = { id = "net.minecraftforge.gradle", version = "7.0.34" } +modDevGradle = { id = "net.neoforged.moddev", version = "2.0.144" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4a209e60437..dfba3fb392f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5913,6 +5913,11 @@ + + + + + @@ -6621,6 +6626,11 @@ + + + + + @@ -6749,6 +6759,11 @@ + + + + + @@ -7218,6 +7233,11 @@ + + + + + @@ -7452,6 +7472,11 @@ + + + + + @@ -7949,6 +7974,11 @@ + + + + + From 329594bb5b5b9b68d8d2a65ef2285f0a0f8cdb4f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 18 Aug 2026 19:54:38 +0200 Subject: [PATCH 574/586] Bump SpongeAPI --- SpongeAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index 932f73f584f..81abfec52d6 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 932f73f584fc0881a6a352f79e052ddba5662977 +Subproject commit 81abfec52d68edbdfc210bccba106cf6dfb35823 From 7d825dde66ce664167eaf8becd63a70f07e4267d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 18 Aug 2026 20:19:31 +0200 Subject: [PATCH 575/586] Bump Forge to 65.1.1 and NeoForge to 26.2.0.62 --- forge/gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 76 ++++++++++++++++++++++++++++++++ neoforge/gradle.properties | 2 +- 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index 3c6c60ee9fb..eacd81e315c 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=65.0.9 +forgeVersion=65.1.1 mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 74fa4bbe695..6c7b2736289 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ format = { version = "1.1" } # Implementation-only dependencies, or dependencies that use a different version than in API # See SpongeAPI's gradle/libs.versions.toml for many dependency declarations that Sponge also uses [versions] -asm = "9.9.1" +asm = "9.10.1" log4j = "2.25.2" mixin = "0.8.7" mixinextras = "0.5.4" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 384731eb166..c82e15fe461 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -272,6 +272,11 @@ + + + + + @@ -350,6 +355,11 @@ + + + + + @@ -5542,6 +5552,11 @@ + + + + + @@ -5751,6 +5766,11 @@ + + + + + @@ -5960,6 +5980,11 @@ + + + + + @@ -6153,6 +6178,11 @@ + + + + + @@ -6412,6 +6442,11 @@ + + + + + @@ -6629,6 +6664,11 @@ + + + + + @@ -6846,6 +6886,11 @@ + + + + + @@ -7309,6 +7354,11 @@ + + + + + @@ -7325,6 +7375,11 @@ + + + + + @@ -7675,6 +7730,17 @@ + + + + + + + + + + + @@ -7900,6 +7966,11 @@ + + + + + @@ -8045,6 +8116,11 @@ + + + + + diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 2155d02fb99..33f2bf10d5e 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -2,5 +2,5 @@ name=SpongeNeo implementation=NeoForge description=The SpongeAPI implementation for NeoForge -neoForgeVersion=26.2.0.32-beta +neoForgeVersion=26.2.0.62 mixinConfigs=mixins.spongeneo.accessors.json,mixins.spongeneo.api.json,mixins.spongeneo.inventory.json,mixins.spongeneo.core.json,mixins.spongeneo.tracker.json From 842484a6fee4454377b2dd7ad7236c79dc865929 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 18 Aug 2026 20:24:34 +0200 Subject: [PATCH 576/586] Update readme badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 08faf3cc7bc..e20543e2ae4 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,19 @@ The SpongeAPI implementation targeting vanilla Minecraft and 3rd party platforms [![SpongeVanilla Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeVanilla 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) +[![SpongeVanilla 26.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongevanilla?label=26.2&queryOpt=%3Aversion%3D26.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongevanilla%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.2-*) ### SpongeForge [![SpongeForge Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeForge 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) +[![SpongeForge 26.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeforge?label=26.2&queryOpt=%3Aversion%3D26.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeforge%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.2-*) ### SpongeNeo [![SpongeNeo Latest](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=Latest&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered) -[![SpongeNeo 26.1.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=26.1.2&queryOpt=%3Aversion%3D26.1.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.1.2-*) +[![SpongeNeo 26.2](https://img.shields.io/nexus/maven-releases/org.spongepowered/spongeneo?label=26.2&queryOpt=%3Aversion%3D26.2-*&server=https%3A%2F%2Frepo.spongepowered.org%2F)](https://repo.spongepowered.org/#browse/search=attributes.maven2.artifactId%3Dspongeneo%20AND%20attributes.maven2.groupId%3Dorg.spongepowered%20AND%20version%3D26.2-*) ## Prerequisites From d58d231a6fd7e609ca23006eb650459261bbb8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:48:34 +0300 Subject: [PATCH 577/586] Fix Human movement by restoring the body rotation tick (#4301) The 25w02a update (ac2bbe5557) adapted HumanEntity to Mojang's new tickHeadTurn(float) signature but dropped the super call in the process. Mob.tickHeadTurn is solely bodyRotationControl.clientTick(), which is the only thing that ever writes yBodyRot, so the Human's yBodyRot was frozen at its spawn value. Since LookControl clamps yHeadRot to within getMaxHeadYRot() of yBodyRot while navigating, and this override copies yHeadRot onto yRot (the vector moveRelative steers by), the movement direction was pinned to a cone around that stale angle and MoveControl's steering was overwritten every tick. Humans walked into walls, moved sideways, and oscillated between two blocks. --- .../spongepowered/common/entity/living/human/HumanEntity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java index 5ce21e78282..4669357f3b1 100644 --- a/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java +++ b/src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java @@ -304,6 +304,8 @@ public void internalSetAbsorptionAmount(float amount) { @Override protected void tickHeadTurn(final float p_110146_1_) { + // Must run first, it is the only thing that updates yBodyRot, which the look control clamps yHeadRot against + super.tickHeadTurn(p_110146_1_); // Make the body rotation follow head rotation this.setYRot(this.getYHeadRot()); } From 91d01e795eb031430cabbb0639b3db4c67858d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ossi=20Erkkil=C3=A4?= <52257907+avaruus1@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:49:36 +0300 Subject: [PATCH 578/586] Fix HumanEntity registration missed during udate (#4304) Previously, Minecraft registered the EntityTypes in the `EntityType` class, but the registration was moved to EntityTypes class. --- ...TypeMixin_Vanilla.java => EntityTypesMixin_Vanilla.java} | 6 +++--- vanilla/src/mixins/resources/mixins.spongevanilla.core.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/{EntityTypeMixin_Vanilla.java => EntityTypesMixin_Vanilla.java} (93%) diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypesMixin_Vanilla.java similarity index 93% rename from vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java rename to vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypesMixin_Vanilla.java index 532bd30c450..284f6c265cb 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypeMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/world/entity/EntityTypesMixin_Vanilla.java @@ -25,15 +25,15 @@ package org.spongepowered.vanilla.mixin.core.world.entity; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.entity.SpongeEntityTypes; -@Mixin(EntityType.class) -public abstract class EntityTypeMixin_Vanilla { +@Mixin(EntityTypes.class) +public abstract class EntityTypesMixin_Vanilla { @Inject(method = "", at = @At("TAIL")) private static void impl$registerSpongeTypes(CallbackInfo ci) { diff --git a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json index 778d3c7fd45..7df7d999a87 100644 --- a/vanilla/src/mixins/resources/mixins.spongevanilla.core.json +++ b/vanilla/src/mixins/resources/mixins.spongevanilla.core.json @@ -35,7 +35,7 @@ "server.packs.repository.PackRepositoryMixin_Vanilla", "tags.TagLoaderMixin_Vanilla", "world.entity.EntityMixin_Vanilla", - "world.entity.EntityTypeMixin_Vanilla", + "world.entity.EntityTypesMixin_Vanilla", "world.entity.LivingEntityMixin_Vanilla", "world.entity.LivingEntityMixin_Vanilla_Damage", "world.entity.ai.attributes.DefaultAttributesMixin", From 7c86c7f6b38481ea63549cc1bc62606b784ca9aa Mon Sep 17 00:00:00 2001 From: GiganttinenEtana <161160078+GiganttinenEtana@users.noreply.github.com> Date: Sat, 29 Aug 2026 20:00:42 +0000 Subject: [PATCH 579/586] Add missing keys for hiding tool tip data components (#4305) * Add HIDE_POTION_EFFECTS key * Add HIDE_ARMOR_TRIM key * Added missing hide keys --- SpongeAPI | 2 +- .../item/stack/HideFlagsItemStackData.java | 31 ++++++++++++------- .../test/data/ConsumableDataTest.java | 6 +++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 133a4568efb..6c5697aea8d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 133a4568efbfb3bd248eef56796949c8245b9bb5 +Subproject commit 6c5697aea8da56663b4ed2f441e084272b965444 diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java index 2c64a27e994..44c1a702bee 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/HideFlagsItemStackData.java @@ -24,14 +24,16 @@ */ package org.spongepowered.common.data.provider.item.stack; +import com.google.common.collect.ImmutableMap; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.TooltipDisplay; +import org.spongepowered.api.data.Key; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.value.Value; import org.spongepowered.common.data.provider.DataProviderRegistrator; -import java.util.Map; - public final class HideFlagsItemStackData { private HideFlagsItemStackData() { @@ -39,15 +41,22 @@ private HideFlagsItemStackData() { // @formatter:off public static void register(final DataProviderRegistrator registrator) { - final var keyToComponentMapping = Map.of( - Keys.HIDE_ATTRIBUTES, DataComponents.ATTRIBUTE_MODIFIERS, - Keys.HIDE_ENCHANTMENTS, DataComponents.ENCHANTMENTS, - Keys.HIDE_CAN_DESTROY, DataComponents.CAN_BREAK, - Keys.HIDE_CAN_PLACE, DataComponents.CAN_PLACE_ON, - Keys.HIDE_STORED_ENCHANTMENTS, DataComponents.STORED_ENCHANTMENTS, - Keys.HIDE_UNBREAKABLE, DataComponents.UNBREAKABLE, - Keys.HIDE_MISCELLANEOUS, DataComponents.CUSTOM_DATA - ); + final ImmutableMap>, DataComponentType> keyToComponentMapping = new ImmutableMap.Builder>, DataComponentType>() + .put(Keys.HIDE_ARMOR_TRIM, DataComponents.TRIM) + .put(Keys.HIDE_ATTRIBUTES, DataComponents.ATTRIBUTE_MODIFIERS) + .put(Keys.HIDE_BANNER_PATTERNS, DataComponents.BANNER_PATTERNS) + .put(Keys.HIDE_BUNDLE_CONTENTS, DataComponents.BUNDLE_CONTENTS) + .put(Keys.HIDE_CAN_DESTROY, DataComponents.CAN_BREAK) + .put(Keys.HIDE_CAN_PLACE, DataComponents.CAN_PLACE_ON) + .put(Keys.HIDE_COLOR, DataComponents.DYED_COLOR) + .put(Keys.HIDE_ENCHANTMENTS, DataComponents.ENCHANTMENTS) + .put(Keys.HIDE_INSTRUMENT, DataComponents.INSTRUMENT) + .put(Keys.HIDE_MISCELLANEOUS, DataComponents.CUSTOM_DATA) + .put(Keys.HIDE_MUSIC_DISC, DataComponents.JUKEBOX_PLAYABLE) + .put(Keys.HIDE_POTION_EFFECTS, DataComponents.POTION_CONTENTS) + .put(Keys.HIDE_STORED_ENCHANTMENTS, DataComponents.STORED_ENCHANTMENTS) + .put(Keys.HIDE_UNBREAKABLE, DataComponents.UNBREAKABLE) + .build(); final var mutableItem = registrator .asMutable(ItemStack.class); diff --git a/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java index 2f228a8f3a5..e5bb59a3d58 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java @@ -99,7 +99,11 @@ private CommandResult items(final CommandContext commandContext) { stack4.offer(Keys.CUSTOM_NAME, Component.text("Teleport on death")); stack4.offerSingle(Keys.DEATH_PROTECTION_ACTIONS, ItemAction.teleportRandomly(20)); - player.inventory().offer(stack1, stack2, stack3, stack4); + final ItemStack stack5 = ItemStack.of(ItemTypes.POTION); + stack5.offer(Keys.CUSTOM_NAME, Component.text("Hide potion effects")); + stack5.offer(Keys.HIDE_POTION_EFFECTS, true); + + player.inventory().offer(stack1, stack2, stack3, stack4, stack5); return CommandResult.success(); } From 57b015b1199b150c088402951ab2f751ccf2a980 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 31 Aug 2026 23:07:01 +0200 Subject: [PATCH 580/586] Resolve plugin config path using the original id --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 10 ++++++++++ .../common/config/PluginConfigManager.java | 8 +++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 3e582fed416..cbe6503ea3a 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 3e582fed416b17bfa6ef0f12e9f9ea771c7bece1 +Subproject commit cbe6503ea3a43430c1cefc165efcd55687688444 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 710e8ede12b..f70a19110d8 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11368,6 +11368,11 @@ + + + + + @@ -11395,6 +11400,11 @@ + + + + + diff --git a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java index 68249067f77..0d5514a3150 100644 --- a/src/main/java/org/spongepowered/common/config/PluginConfigManager.java +++ b/src/main/java/org/spongepowered/common/config/PluginConfigManager.java @@ -67,16 +67,18 @@ public final class PluginConfigManager implements ConfigManager { .build(); } + @SuppressWarnings("deprecation") @Override public ConfigRoot sharedConfig(final PluginContainer container) { - return new PluginConfigRoot(this.serializers, container.metadata().id().toLowerCase(), + return new PluginConfigRoot(this.serializers, container.metadata().originalId().toLowerCase(), SpongeCommon.pluginConfigDirectory()); } + @SuppressWarnings("deprecation") @Override public ConfigRoot pluginConfig(final PluginContainer container) { - return new PluginConfigRoot(this.serializers, container.metadata().id().toLowerCase(), - SpongeCommon.pluginConfigDirectory().resolve(container.metadata().id().toLowerCase())); + return new PluginConfigRoot(this.serializers, container.metadata().originalId().toLowerCase(), + SpongeCommon.pluginConfigDirectory().resolve(container.metadata().originalId().toLowerCase())); } @Override From b7e6fe153e3442d9e4757713d6826a3743aa5c60 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 16 Sep 2026 21:14:33 +0200 Subject: [PATCH 581/586] Implement PluginContainer#resource --- SpongeAPI | 2 +- .../discovery/SecureJarPluginResource.java | 20 ++++++++++++++++-- .../launch/plugin/ForgePluginContainer.java | 21 ++++++++++--------- .../discovery/JarContentsPluginResource.java | 14 +++++++++++-- .../launch/plugin/NeoPluginContainer.java | 18 +++++++++------- .../discovery/spi/DummyPluginResource.java | 2 +- .../discovery/MinecraftMetadataReader.java | 2 +- .../discovery/SecureJarPluginResource.java | 10 +++++++-- .../VanillaAccessWidenerTransformer.java | 2 +- .../VanillaSuperclassChangeTransformer.java | 2 +- .../launch/plugin/VanillaPluginManager.java | 10 --------- .../server/packs/PluginPackResources.java | 14 +++++++------ .../server/packs/PluginRepositorySource.java | 13 +----------- 13 files changed, 74 insertions(+), 56 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index cbe6503ea3a..d31140dc611 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit cbe6503ea3a43430c1cefc165efcd55687688444 +Subproject commit d31140dc611b999cd260e5a82529ad39d055d4c1 diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java index 8b304c4d765..aaf0c383b83 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -29,6 +29,7 @@ import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; +import java.io.InputStream; import java.lang.module.ModuleDescriptor; import java.net.URI; import java.nio.file.Path; @@ -52,6 +53,16 @@ public SecureJarPluginResource(final Path[] paths) { this.jar = SecureJar.from(jar -> new PluginJarMetadata(jar, paths), paths); } + /** + * We can't determine all paths from the jar. Use this constructor as a last resort. + */ + public SecureJarPluginResource(final SecureJar jar) { + Objects.requireNonNull(jar, "jar"); + this.pathsArray = new Path[]{jar.getPrimaryPath()}; + this.paths = List.of(jar.getPrimaryPath()); + this.jar = jar; + } + public SecureJar jar() { return this.jar; } @@ -71,8 +82,13 @@ public List paths() { } @Override - public Optional locateResource(final String path) { - return this.jar.moduleDataProvider().findFile(path); + public Optional locate(final String path) { + return this.jar.moduleDataProvider().findFile(Objects.requireNonNull(path, "path")); + } + + @Override + public Optional open(final String path) { + return this.jar.moduleDataProvider().open(Objects.requireNonNull(path, "path")); } @Override diff --git a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java index b584a4e937d..5d0b3225708 100644 --- a/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java +++ b/forge/src/main/java/org/spongepowered/forge/launch/plugin/ForgePluginContainer.java @@ -29,15 +29,13 @@ import net.minecraftforge.forgespi.locating.IModFile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.forge.applaunch.plugin.discovery.SecureJarPluginResource; import org.spongepowered.forge.applaunch.plugin.metadata.PluginMetadataConverter; import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Map; -import java.util.Objects; import java.util.Optional; public class ForgePluginContainer implements PluginContainer { @@ -46,12 +44,21 @@ public class ForgePluginContainer implements PluginContainer { private Logger logger; private PluginMetadata pluginMetadata; + private PluginResource pluginResource; private ForgePluginContainer(final ModContainer modContainer) { this.modContainer = modContainer; this.modFile = modContainer.getModInfo().getOwningFile().getFile(); } + @Override + public PluginResource resource() { + if (this.pluginResource == null) { + this.pluginResource = new SecureJarPluginResource(this.modFile.getSecureJar()); + } + return this.pluginResource; + } + @Override public PluginMetadata metadata() { if (this.pluginMetadata == null) { @@ -68,12 +75,6 @@ public Logger logger() { return this.logger; } - @Override - public Optional locateResource(String relative) { - final Path p = this.modFile.findResource(Objects.requireNonNull(relative, "relative")); - return Files.exists(p) ? Optional.of(p.toUri()) : Optional.empty(); - } - @SuppressWarnings("removal") @Override public Object instance() { diff --git a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java index f9db26d9ba1..aa8af788d5d 100644 --- a/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java +++ b/neoforge/src/applaunch/java/org/spongepowered/neoforge/applaunch/plugin/discovery/JarContentsPluginResource.java @@ -30,6 +30,7 @@ import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.lang.module.ModuleDescriptor; import java.net.URI; @@ -73,8 +74,17 @@ public List paths() { } @Override - public Optional locateResource(String path) { - return this.jar.findFile(path); + public Optional locate(final String path) { + return this.jar.findFile(Objects.requireNonNull(path, "path")); + } + + @Override + public Optional open(final String path) { + try { + return Optional.ofNullable(this.jar.openFile(Objects.requireNonNull(path, "path"))); + } catch (final IOException ignored) { + return Optional.empty(); + } } @Override diff --git a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java index 4456cd84b93..1765c27a30a 100644 --- a/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java +++ b/neoforge/src/main/java/org/spongepowered/neoforge/launch/plugin/NeoPluginContainer.java @@ -29,13 +29,13 @@ import net.neoforged.fml.jarcontents.JarContents; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.neoforge.applaunch.plugin.discovery.JarContentsPluginResource; import org.spongepowered.neoforge.applaunch.plugin.metadata.PluginMetadataConverter; import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; -import java.net.URI; import java.util.Map; -import java.util.Objects; import java.util.Optional; public class NeoPluginContainer implements PluginContainer { @@ -44,12 +44,21 @@ public class NeoPluginContainer implements PluginContainer { private Logger logger; private PluginMetadata pluginMetadata; + private PluginResource pluginResource; private NeoPluginContainer(final ModContainer modContainer) { this.modContainer = modContainer; this.jar = modContainer.getModInfo().getOwningFile().getFile().getContents(); } + @Override + public PluginResource resource() { + if (this.pluginResource == null) { + this.pluginResource = new JarContentsPluginResource(this.jar); + } + return this.pluginResource; + } + @Override public PluginMetadata metadata() { if (this.pluginMetadata == null) { @@ -66,11 +75,6 @@ public Logger logger() { return this.logger; } - @Override - public Optional locateResource(final String relative) { - return this.jar.findFile(Objects.requireNonNull(relative, "relative")); - } - private static final Map mods = new MapMaker().weakKeys().makeMap(); public static Optional of(final ModContainer modContainer) { diff --git a/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java index 853d783a093..c57ad44b255 100644 --- a/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java +++ b/src/test/java/org/spongepowered/common/plugin/discovery/spi/DummyPluginResource.java @@ -47,7 +47,7 @@ public Optional property(final String key) { } @Override - public Optional locateResource(final String path) { + public Optional locate(final String path) { return Optional.empty(); } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java index f59c0561201..d6149e0d015 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/MinecraftMetadataReader.java @@ -49,7 +49,7 @@ public String name() { @Override public Collection readPluginMetadata(final Environment environment, final PluginResource resource, final List locators) throws Exception { - if (resource instanceof JVMPluginResource && resource.locateResource("net/minecraft/server/MinecraftServer.class").isPresent()) { + if (resource instanceof JVMPluginResource && resource.locate("net/minecraft/server/MinecraftServer.class").isPresent()) { environment.logger().debug("{} has been detected as Minecraft.", resource); final InputStream input = MinecraftMetadataReader.class.getClassLoader().getResourceAsStream("META-INF/minecraft_sponge_plugins.json"); diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java index 3a2e8929130..c046d010eb1 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/discovery/SecureJarPluginResource.java @@ -28,6 +28,7 @@ import org.spongepowered.common.applaunch.plugin.discovery.SpongeJVMPluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; +import java.io.InputStream; import java.lang.module.ModuleDescriptor; import java.net.URI; import java.nio.file.Path; @@ -65,8 +66,13 @@ public List paths() { } @Override - public Optional locateResource(final String path) { - return this.jar.moduleDataProvider().findFile(path); + public Optional locate(final String path) { + return this.jar.moduleDataProvider().findFile(Objects.requireNonNull(path, "path")); + } + + @Override + public Optional open(final String path) { + return this.jar.moduleDataProvider().open(Objects.requireNonNull(path, "path")); } @Override diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java index 83a279397fa..3e1744a7c6f 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaAccessWidenerTransformer.java @@ -74,7 +74,7 @@ protected Collection collectResources() { if (attribute.isPresent()) { for (final String path : attribute.get().split(",")) { try { - resources.add(plugin.locateResource(path).get().toURL()); + resources.add(plugin.locate(path).get().toURL()); } catch (final Exception e) { LOGGER.warn("Failed to locate access widener {} from {}", path, plugin, e); } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java index 6e8079cf233..954a4255768 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/transformation/VanillaSuperclassChangeTransformer.java @@ -79,7 +79,7 @@ protected Collection collectResources() { if (attribute.isPresent()) { for (final String scPath : attribute.get().split(",")) { try { - resources.add(plugin.locateResource(scPath).get().toURL()); + resources.add(plugin.locate(scPath).get().toURL()); } catch (final Exception e) { LOGGER.warn("Failed to locate superclass changer {} from {}", scPath, plugin); } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java index b57964f363b..9f01c5a416e 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/launch/plugin/VanillaPluginManager.java @@ -27,14 +27,12 @@ import com.google.inject.Singleton; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.apache.logging.log4j.Level; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.applaunch.plugin.PluginPlatform; import org.spongepowered.common.applaunch.plugin.discovery.PluginDiscovery; import org.spongepowered.common.launch.plugin.SpongePluginManager; import org.spongepowered.common.launch.plugin.loader.PluginCandidate; import org.spongepowered.common.util.PrettyPrinter; import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.discovery.PluginResource; import org.spongepowered.plugin.metadata.PluginMetadata; import org.spongepowered.plugin.metadata.model.PluginDependency; import org.spongepowered.vanilla.launch.VanillaLaunch; @@ -50,7 +48,6 @@ public final class VanillaPluginManager implements SpongePluginManager { private final Map plugins; private final Map instancesToPlugins; private final List sortedPlugins; - private final Map containerToResource; private boolean ready = false; public VanillaPluginManager(final VanillaLaunch launch) { @@ -58,7 +55,6 @@ public VanillaPluginManager(final VanillaLaunch launch) { this.plugins = new Object2ObjectOpenHashMap<>(); this.instancesToPlugins = new IdentityHashMap<>(); this.sortedPlugins = new ArrayList<>(); - this.containerToResource = new Object2ObjectOpenHashMap<>(); } @SuppressWarnings("removal") @@ -141,7 +137,6 @@ public void loadPlugins() { try { final PluginContainer container = candidate.load(); this.addPlugin(container); - this.containerToResource.put(container, candidate.resource()); } catch (final Exception e) { failedInstances.put(candidate, "Failed to construct: see stacktrace(s) above this message for details."); platform.logger().error("Failed to construct plugin {}", id, e); @@ -165,11 +160,6 @@ public void addPlugin(final PluginContainer plugin) { } } - @Nullable - public PluginResource resource(final PluginContainer container) { - return this.containerToResource.get(container); - } - private boolean stillValid(final PluginCandidate candidate, final Map consequential) { final Optional failedId = candidate.metadata().dependencies().stream().filter(d -> !this.isDependencyStillValid(d)).findFirst(); diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java index c1038dd41b0..c8d926ff780 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginPackResources.java @@ -38,7 +38,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.spongepowered.common.SpongeCommon; -import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.discovery.PluginResource; +import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; import java.io.IOException; import java.io.InputStream; @@ -56,15 +57,16 @@ public final class PluginPackResources extends AbstractPackResources { private static final Logger LOGGER = LogUtils.getLogger(); - private final PluginContainer container; + private final PluginResource resource; private final PackMetadataSection metadata; private final @Nullable Path pluginRoot; - public PluginPackResources(final PackLocationInfo info, final PluginContainer container, final @Nullable Path pluginRoot) { + public PluginPackResources(final PackLocationInfo info, final PluginResource resource) { super(info); - this.container = container; + this.resource = resource; this.metadata = new PackMetadataSection(Component.literal("Plugin Resources"), new InclusiveRange<>(PackFormat.of(6))); - this.pluginRoot = pluginRoot; + // TODO: provide hook in the resource to return the file system for all resource types? + this.pluginRoot = resource instanceof SecureJarPluginResource jarResource ? jarResource.jar().getRootPath() : null; } @Override @@ -74,7 +76,7 @@ public IoSupplier getRootResource(final String... var1) { } private IoSupplier getResource(final String rawPath) { - final Optional uri = this.container.locateResource(rawPath); + final Optional uri = this.resource.locate(rawPath); if (uri.isEmpty()) { return null; } diff --git a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java index a512faf69e9..40be5e1f2d6 100644 --- a/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java +++ b/vanilla/src/main/java/org/spongepowered/vanilla/server/packs/PluginRepositorySource.java @@ -33,15 +33,11 @@ import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.PackSource; import net.minecraft.server.packs.repository.RepositorySource; -import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.launch.Launch; import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.discovery.PluginResource; -import org.spongepowered.vanilla.applaunch.plugin.discovery.SecureJarPluginResource; import org.spongepowered.vanilla.bridge.server.packs.repository.PackRepositoryBridge_Vanilla; import org.spongepowered.vanilla.launch.plugin.VanillaPluginManager; -import java.nio.file.Path; import java.util.Optional; import java.util.function.Consumer; @@ -63,15 +59,8 @@ public void loadPacks(final Consumer callback) { // The pack ID is prepended with "plugin-", as this will be the namespace we have to use a valid // character as a separator final String id = "plugin-" + pluginContainer.metadata().id(); - final PluginResource resource = pluginManager.resource(pluginContainer); - // TODO: provide hook in the resource to return the file system for all resource types? - @Nullable Path pluginRoot = null; - if (resource instanceof SecureJarPluginResource jarResource) { - pluginRoot = jarResource.jar().getRootPath(); - } - final PackLocationInfo info = new PackLocationInfo(id, Component.literal(id), PackSource.DEFAULT, Optional.empty()); - final PluginPackResources packResources = new PluginPackResources(info, pluginContainer, pluginRoot); + final PluginPackResources packResources = new PluginPackResources(info, pluginContainer.resource()); final Pack.ResourcesSupplier packSupplier = new Pack.ResourcesSupplier() { @Override From f8ef5635402aa720d11bc78c93d016bc0278b04d Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Wed, 16 Sep 2026 21:24:24 +0200 Subject: [PATCH 582/586] Update verification metadata --- SpongeAPI | 2 +- gradle/verification-metadata.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/SpongeAPI b/SpongeAPI index d31140dc611..3f305b64bc4 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d31140dc611b999cd260e5a82529ad39d055d4c1 +Subproject commit 3f305b64bc4fa08acb5c85ef9825498510252c69 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f70a19110d8..05813b8dd5a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11405,6 +11405,11 @@ + + + + + From e0402e377cf63b3334d7903959f7858fea50c023 Mon Sep 17 00:00:00 2001 From: StealWonders <6114858+StealWonders@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:27:53 +0200 Subject: [PATCH 583/586] Fix equipment change crash for Mannequin (#4312) --- .../mixin/inventory/api/TraitMixin_AdapterInventory_API.java | 3 ++- .../inventory/impl/TraitMixin_InventoryBridge_Inventory.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java index 978c6686b2e..099aaf6baa8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java @@ -26,12 +26,13 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.Mannequin; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.CampfireBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.inventory.adapter.impl.DefaultImplementedAdapterInventory; -@Mixin({ArmorStand.class, Mob.class, Player.class, CampfireBlockEntity.class}) +@Mixin({ArmorStand.class, Mannequin.class, Mob.class, Player.class, CampfireBlockEntity.class}) public abstract class TraitMixin_AdapterInventory_API implements DefaultImplementedAdapterInventory.WithClear { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java index bca9ba50105..b52e3a1c5c5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java @@ -29,6 +29,7 @@ import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.Mannequin; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecartContainer; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -68,6 +69,7 @@ ResultContainer.class, AbstractMinecartContainer.class, ArmorStand.class, + Mannequin.class, Mob.class, MerchantContainer.class, CampfireBlockEntity.class, From 277a2099fc12d043b4fe1d1c8b89a48bd33e4f1f Mon Sep 17 00:00:00 2001 From: StealWonders <6114858+StealWonders@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:27:53 +0200 Subject: [PATCH 584/586] Fix equipment change crash for Mannequin (#4312) (cherry picked from commit e0402e377cf63b3334d7903959f7858fea50c023) --- .../mixin/inventory/api/TraitMixin_AdapterInventory_API.java | 3 ++- .../inventory/impl/TraitMixin_InventoryBridge_Inventory.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java index 978c6686b2e..099aaf6baa8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_AdapterInventory_API.java @@ -26,12 +26,13 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.Mannequin; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.CampfireBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.inventory.adapter.impl.DefaultImplementedAdapterInventory; -@Mixin({ArmorStand.class, Mob.class, Player.class, CampfireBlockEntity.class}) +@Mixin({ArmorStand.class, Mannequin.class, Mob.class, Player.class, CampfireBlockEntity.class}) public abstract class TraitMixin_AdapterInventory_API implements DefaultImplementedAdapterInventory.WithClear { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java index 259d84bbe9d..5616575c890 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/impl/TraitMixin_InventoryBridge_Inventory.java @@ -29,6 +29,7 @@ import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.Mannequin; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -68,6 +69,7 @@ ResultContainer.class, AbstractMinecartContainer.class, ArmorStand.class, + Mannequin.class, Mob.class, MerchantContainer.class, CampfireBlockEntity.class, From bf7582d84415e59a0620bd6a8a1e2f34bb47bd1c Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 2 Oct 2026 13:54:33 +0200 Subject: [PATCH 585/586] Fix armor stand data unit test --- .../data/provider/entity/ArmorStandData.java | 2 +- .../common/data/EntityDataTest.java | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java index f948e7b8071..7194d88b880 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ArmorStandData.java @@ -81,7 +81,7 @@ public static void register(final DataProviderRegistrator registrator) { .get(ArmorStand::showArms) .set(ArmorStand::setShowArms) .create(Keys.HAS_BASE_PLATE) - .get(h -> !h.showBasePlate()) + .get(ArmorStand::showBasePlate) .set((h, v) -> h.setNoBasePlate(!v)) .create(Keys.HAS_MARKER) .get(ArmorStand::isMarker) diff --git a/src/test/java/org/spongepowered/common/data/EntityDataTest.java b/src/test/java/org/spongepowered/common/data/EntityDataTest.java index 1c3af4ec7fc..a13158af4a5 100644 --- a/src/test/java/org/spongepowered/common/data/EntityDataTest.java +++ b/src/test/java/org/spongepowered/common/data/EntityDataTest.java @@ -294,7 +294,6 @@ public void testFallingBlock() { DataTest.checkOfferData(fallingBlock, Keys.MAX_FALL_DAMAGE, 50.0); } - @Disabled @Test public void testArmorStand() { final ArmorStand armorStand = this.location.createEntity(EntityTypes.ARMOR_STAND.get()); @@ -306,9 +305,6 @@ public void testArmorStand() { armorStand.equip(EquipmentTypes.MAINHAND.get(), ItemStack.of(ItemTypes.DIAMOND)); armorStand.equip(EquipmentTypes.OFFHAND.get(), ItemStack.of(ItemTypes.DIAMOND)); - DataTest.checkOfferData(armorStand, Keys.BODY_ROTATIONS, Map.of(BodyParts.CHEST.get(), Vector3d.RIGHT)); - DataTest.checkOfferData(armorStand, Keys.CHEST_ROTATION, Vector3d.from(0, 90, 0)); - DataTest.checkOfferData(armorStand, Keys.HAS_ARMS, false); DataTest.checkOfferData(armorStand, Keys.HAS_ARMS, true); @@ -318,14 +314,24 @@ public void testArmorStand() { DataTest.checkOfferData(armorStand, Keys.HAS_MARKER, true); DataTest.checkOfferData(armorStand, Keys.HAS_MARKER, false); - DataTest.checkOfferData(armorStand, Keys.HEAD_ROTATION, Vector3d.from(0, 90, 0)); - DataTest.checkOfferData(armorStand, Keys.LEFT_ARM_ROTATION, Vector3d.from(0, -90, -90)); - DataTest.checkOfferData(armorStand, Keys.LEFT_LEG_ROTATION, Vector3d.from(0, -90, -45)); - DataTest.checkOfferData(armorStand, Keys.RIGHT_ARM_ROTATION, Vector3d.from(0, 90, 90)); - DataTest.checkOfferData(armorStand, Keys.RIGHT_LEG_ROTATION, Vector3d.from(0, 90, 45)); - DataTest.checkOfferData(armorStand, Keys.IS_SMALL, true); DataTest.checkOfferData(armorStand, Keys.IS_SMALL, false); + + DataTest.checkOfferData(armorStand, Keys.HEAD_ROTATION, new Vector3d(0, 90, 0)); + DataTest.checkOfferData(armorStand, Keys.CHEST_ROTATION, new Vector3d(0, 90, 0)); + DataTest.checkOfferData(armorStand, Keys.LEFT_ARM_ROTATION, new Vector3d(0, -90, -90)); + DataTest.checkOfferData(armorStand, Keys.RIGHT_ARM_ROTATION, new Vector3d(0, 90, 90)); + DataTest.checkOfferData(armorStand, Keys.LEFT_LEG_ROTATION, new Vector3d(0, -90, -45)); + DataTest.checkOfferData(armorStand, Keys.RIGHT_LEG_ROTATION, new Vector3d(0, 90, 45)); + + DataTest.checkOfferData(armorStand, Keys.BODY_ROTATIONS, Map.of( + BodyParts.HEAD.get(), new Vector3d(0, -90, 0), + BodyParts.CHEST.get(), new Vector3d(0, -90, 0), + BodyParts.LEFT_ARM.get(), new Vector3d(0, 90, 90), + BodyParts.RIGHT_ARM.get(), new Vector3d(0, -90, -90), + BodyParts.LEFT_LEG.get(), new Vector3d(0, 90, 45), + BodyParts.RIGHT_LEG.get(), new Vector3d(0, -90, -45) + )); } @Test From 7357ee1b977b04d2a3c65cfb42617e19f7427689 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Fri, 2 Oct 2026 14:02:22 +0200 Subject: [PATCH 586/586] Make Mannequin extends ArmorEquipable --- SpongeAPI | 2 +- .../TraitMixin_ArmorEquipable_Inventory_API.java | 3 ++- .../spongepowered/common/data/EntityDataTest.java | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/SpongeAPI b/SpongeAPI index 6c5697aea8d..f7088f6a8ba 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit 6c5697aea8da56663b4ed2f441e084272b965444 +Subproject commit f7088f6a8baa661d788a536732e04372164b2c44 diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_ArmorEquipable_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_ArmorEquipable_Inventory_API.java index 66569883a51..0e441cbd09a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_ArmorEquipable_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/TraitMixin_ArmorEquipable_Inventory_API.java @@ -28,6 +28,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.Mannequin; import net.minecraft.world.entity.player.Player; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.type.HandType; @@ -49,7 +50,7 @@ import java.util.Optional; // All living implementors of ArmorEquipable -@Mixin({ArmorStand.class, Mob.class, Player.class}) +@Mixin({ArmorStand.class, Mannequin.class, Mob.class, Player.class}) public abstract class TraitMixin_ArmorEquipable_Inventory_API implements ArmorEquipable { // TODO can we implement canEquip? diff --git a/src/test/java/org/spongepowered/common/data/EntityDataTest.java b/src/test/java/org/spongepowered/common/data/EntityDataTest.java index a13158af4a5..c4cec49413d 100644 --- a/src/test/java/org/spongepowered/common/data/EntityDataTest.java +++ b/src/test/java/org/spongepowered/common/data/EntityDataTest.java @@ -57,6 +57,7 @@ import org.spongepowered.api.entity.EntityArchetype; import org.spongepowered.api.entity.EntitySnapshot; import org.spongepowered.api.entity.EntityTypes; +import org.spongepowered.api.entity.Mannequin; import org.spongepowered.api.entity.living.ArmorStand; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.entity.living.animal.Sheep; @@ -334,6 +335,18 @@ public void testArmorStand() { )); } + @Test + public void testMannequin() { + final Mannequin mannequin = this.location.createEntity(EntityTypes.MANNEQUIN.get()); + + mannequin.equip(EquipmentTypes.CHEST.get(), ItemStack.of(ItemTypes.LEATHER_CHESTPLATE)); + mannequin.equip(EquipmentTypes.FEET.get(), ItemStack.of(ItemTypes.CHAINMAIL_BOOTS)); + mannequin.equip(EquipmentTypes.HEAD.get(), ItemStack.of(ItemTypes.GOLDEN_HELMET)); + mannequin.equip(EquipmentTypes.LEGS.get(), ItemStack.of(ItemTypes.DIAMOND_LEGGINGS)); + mannequin.equip(EquipmentTypes.MAINHAND.get(), ItemStack.of(ItemTypes.DIAMOND)); + mannequin.equip(EquipmentTypes.OFFHAND.get(), ItemStack.of(ItemTypes.DIAMOND)); + } + @Test public void testCreeper() { final Entity creeper = this.location.createEntity(EntityTypes.CREEPER.get());