From 880bdb4d2adbcab1058390073d6e67fd485ceb30 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 20 Apr 2025 12:04:59 -0700 Subject: [PATCH 01/17] 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 31cbd93bd3747a80ffa9f70b0ddb2e4893dceaa3 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 10 May 2025 17:41:32 -0700 Subject: [PATCH 02/17] 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 03/17] 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 04/17] 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 05/17] 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 4e82ec47e2ae4690129067b773e351c8ebc68e66 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sat, 7 Jun 2025 13:05:16 -0700 Subject: [PATCH 06/17] 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 07/17] 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 08/17] 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 09/17] 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 10/17] 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 11/17] 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 cfd1a515037e41f17edd53e51fcca9db64711005 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 9 Jun 2025 11:01:57 +0200 Subject: [PATCH 12/17] 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 4d8273813fd15125525494469fb384969f5d603e Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 18 Jun 2025 17:42:34 -0700 Subject: [PATCH 13/17] 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 14/17] 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 15/17] 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 16/17] 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 17/17] 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