From d4eb32640b60f8d7f01c097d6ff69402f525856c Mon Sep 17 00:00:00 2001 From: roadhog360 <11903511+Roadhog360@users.noreply.github.com> Date: Mon, 6 Jan 2025 06:13:20 -0600 Subject: [PATCH] More spectator fixes Fixed jitter when attempting to pick up items from slots Possibly fixed spectators being able to body-block players Removed spectators from being considered as Creative mode players Fixed spectators having an item stuck in their cursor if someone else changes their game mode while they were dragging items, it'll get put in their inventory or thrown on the ground if no room is available. Fixed AE2 containers largely ignoring many checks (including `canTakeStack`) by just no-opping their inventory code for spectators Fixed spectators being able to spectate spectators --- dependencies.gradle | 1 + .../mixinplugin/EtFuturumEarlyMixins.java | 1 + .../mixinplugin/EtFuturumLateMixins.java | 9 +++- .../early/spectator/MixinContainerChest.java | 4 +- .../early/spectator/MixinEntityPlayer.java | 52 +++++++++++++++---- .../mixins/early/spectator/MixinGameType.java | 2 +- .../mixins/early/spectator/MixinSlot.java | 20 +++++++ .../spectator/client/MixinEntityPlayer.java | 2 +- .../spectator/MixinPacketInventoryAction.java | 22 ++++++++ .../etfuturum/spectator/SpectatorMode.java | 3 +- 10 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinSlot.java create mode 100644 src/main/java/ganymedes01/etfuturum/mixins/late/spectator/MixinPacketInventoryAction.java diff --git a/dependencies.gradle b/dependencies.gradle index d40d41f4..1969226d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -50,6 +50,7 @@ dependencies { compileOnly "codechicken:CodeChickenLib:1.7.10-1.1.3.140:dev" compileOnly "codechicken:CodeChickenCore:1.7.10-1.0.7.47:dev" compileOnly 'com.github.GTNewHorizons:ironchest:6.0.87' + compileOnly 'curse.maven:applied-energistics-2-223794:2296430' compileOnly("com.github.GTNewHorizons:TinkersConstruct:1.12.6-GTNH:dev") { transitive = false diff --git a/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumEarlyMixins.java b/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumEarlyMixins.java index 40a36434..42753ca9 100644 --- a/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumEarlyMixins.java +++ b/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumEarlyMixins.java @@ -93,6 +93,7 @@ public List getMixins(Set loadedCoreMods) { mixins.add("spectator.MixinNetHandlerPlayServer"); mixins.add("spectator.MixinInventoryPlayer"); mixins.add("spectator.MixinContainerChest"); + mixins.add("spectator.MixinSlot"); if (side == MixinEnvironment.Side.CLIENT) { mixins.add("spectator.client.MixinEntityRenderer"); mixins.add("spectator.client.MixinEntityPlayer"); diff --git a/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumLateMixins.java b/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumLateMixins.java index 2d8259b4..59ce4888 100644 --- a/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumLateMixins.java +++ b/src/main/java/ganymedes01/etfuturum/mixinplugin/EtFuturumLateMixins.java @@ -20,8 +20,13 @@ public String getMixinConfig() { public List getMixins(Set loadedMods) { List mixins = new ArrayList<>(); - if(ConfigMixins.enableSpectatorMode && loadedMods.contains("IronChest")) { - mixins.add("spectator.MixinContainerIronChest"); + if (ConfigMixins.enableSpectatorMode) { + if (loadedMods.contains("IronChest")) { + mixins.add("spectator.MixinContainerIronChest"); + } + if (loadedMods.contains("appliedenergistics2")) { + mixins.add("spectator.MixinPacketInventoryAction"); + } } return mixins; diff --git a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinContainerChest.java b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinContainerChest.java index 9c560bd9..019e5f8f 100644 --- a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinContainerChest.java +++ b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinContainerChest.java @@ -7,9 +7,9 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; +import net.minecraft.inventory.ContainerBeacon; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.InventoryBasic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -20,7 +20,7 @@ public abstract class MixinContainerChest extends Container { @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/inventory/IInventory;openInventory()V")) private void ignoreOpenInventoryInSpectator(IInventory chestInv, Operation original, @Local(ordinal = 0, argsOnly = true) IInventory playerInv) { - if (!(playerInv instanceof InventoryPlayer) || !SpectatorMode.isSpectator(((InventoryPlayer) playerInv).player)) { + if (!(playerInv instanceof InventoryPlayer inv) || !SpectatorMode.isSpectator(inv.player)) { original.call(chestInv); } } diff --git a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinEntityPlayer.java b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinEntityPlayer.java index 88431293..7dc741e1 100644 --- a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinEntityPlayer.java +++ b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinEntityPlayer.java @@ -1,22 +1,29 @@ package ganymedes01.etfuturum.mixins.early.spectator; import ganymedes01.etfuturum.spectator.SpectatorMode; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.item.EntityXPOrb; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; +import net.minecraft.world.WorldSettings; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EntityPlayer.class) public abstract class MixinEntityPlayer extends EntityLivingBase { - @Shadow - public InventoryPlayer inventory; + @Shadow public InventoryPlayer inventory; + + @Shadow public abstract EntityItem dropPlayerItemWithRandomChoice(ItemStack itemStackIn, boolean p_71019_2_); public MixinEntityPlayer(World p_i1595_1_) { super(p_i1595_1_); @@ -24,37 +31,42 @@ public MixinEntityPlayer(World p_i1595_1_) { @Override public boolean canBePushed() { - return !SpectatorMode.isSpectator((EntityPlayer) (Object) this); + return !SpectatorMode.isSpectator((EntityPlayer) (Object) this) && super.canBePushed(); } @Override public boolean canBeCollidedWith() { - return !SpectatorMode.isSpectator((EntityPlayer) (Object) this); + return !SpectatorMode.isSpectator((EntityPlayer) (Object) this) && !super.canBeCollidedWith(); } @Override protected void collideWithNearbyEntities() { - if (!SpectatorMode.isSpectator((EntityPlayer) (Object) this)) + if (!SpectatorMode.isSpectator((EntityPlayer) (Object) this)) { super.collideWithNearbyEntities(); + } } @Override public boolean isOnLadder() { - if (SpectatorMode.isSpectator((EntityPlayer) (Object) this)) + if (SpectatorMode.isSpectator((EntityPlayer) (Object) this)) { return false; + } return super.isOnLadder(); } @Override public boolean handleWaterMovement() { - if (SpectatorMode.isSpectator((EntityPlayer) (Object) this)) + if (SpectatorMode.isSpectator((EntityPlayer) (Object) this)) { return false; + } return super.handleWaterMovement(); } - @Override - public ItemStack getEquipmentInSlot(int p_71124_1_) { - return SpectatorMode.isSpectator((EntityPlayer) (Object) this) ? null : p_71124_1_ == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[p_71124_1_ - 1]; + @Inject(method = "getEquipmentInSlot", at = @At(value = "HEAD"), cancellable = true) + public void getNullEquipmentIfSpectator(int p_71124_1_, CallbackInfoReturnable cir) { + if(SpectatorMode.isSpectator((EntityPlayer) (Object) this)) { + cir.setReturnValue(null); + } } @Inject(method = "isCurrentToolAdventureModeExempt", at = @At(value = "HEAD"), cancellable = true) @@ -63,4 +75,24 @@ public void isSpectating(int p_82246_1_, int p_82246_2_, int p_82246_3_, Callbac cir.setReturnValue(false); } } + + @Inject(method = "setGameType", at = @At("HEAD")) + private void dropCarriedItem(WorldSettings.GameType gameType, CallbackInfo ci) { + if(gameType == SpectatorMode.SPECTATOR_GAMETYPE) { + ItemStack stack = inventory.getItemStack(); // Item in cursor + // Tries to add ItemStack to inventory, else drops it on the ground. + // This is to prevent spectators from having a cursor item. + if(stack != null) { + if(!inventory.addItemStackToInventory(stack)) { + dropPlayerItemWithRandomChoice(stack, true); + } + } + } + } + + @Override + public boolean canAttackWithItem() + { + return false; + } } diff --git a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinGameType.java b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinGameType.java index ed179b72..e9fc885c 100644 --- a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinGameType.java +++ b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinGameType.java @@ -21,7 +21,7 @@ public void configureSpecCaps(PlayerCapabilities caps, CallbackInfo ci) { if (etfuturum$isSpectator()) { ci.cancel(); caps.allowFlying = true; - caps.isCreativeMode = true; + caps.isCreativeMode = false; caps.disableDamage = true; caps.allowEdit = false; caps.isFlying = true; diff --git a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinSlot.java b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinSlot.java new file mode 100644 index 00000000..1edde035 --- /dev/null +++ b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/MixinSlot.java @@ -0,0 +1,20 @@ +package ganymedes01.etfuturum.mixins.early.spectator; + +import ganymedes01.etfuturum.spectator.SpectatorMode; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Slot.class) +public class MixinSlot { + @Inject(method = "canTakeStack", at = @At(value = "HEAD"), cancellable = true) + private void cancelTake(EntityPlayer p_82869_1_, CallbackInfoReturnable cir) { + if(SpectatorMode.isSpectator(p_82869_1_)) { + cir.setReturnValue(false); + } + } +} diff --git a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/client/MixinEntityPlayer.java b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/client/MixinEntityPlayer.java index 669b17de..1b429a25 100644 --- a/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/client/MixinEntityPlayer.java +++ b/src/main/java/ganymedes01/etfuturum/mixins/early/spectator/client/MixinEntityPlayer.java @@ -12,7 +12,7 @@ public class MixinEntityPlayer { @Inject(method = "isInvisibleToPlayer", at = @At("HEAD"), cancellable = true) public void isInvisibleToPlayer(EntityPlayer player, CallbackInfoReturnable cir) { if (SpectatorMode.isSpectator(player)) { - cir.setReturnValue(false); + cir.setReturnValue(false); //TODO: Make it so spectators can see each other } } } diff --git a/src/main/java/ganymedes01/etfuturum/mixins/late/spectator/MixinPacketInventoryAction.java b/src/main/java/ganymedes01/etfuturum/mixins/late/spectator/MixinPacketInventoryAction.java new file mode 100644 index 00000000..d04d98a6 --- /dev/null +++ b/src/main/java/ganymedes01/etfuturum/mixins/late/spectator/MixinPacketInventoryAction.java @@ -0,0 +1,22 @@ +package ganymedes01.etfuturum.mixins.late.spectator; + +import appeng.container.AEBaseContainer; +import appeng.core.sync.packets.PacketInventoryAction; +import appeng.helpers.InventoryAction; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import ganymedes01.etfuturum.spectator.SpectatorMode; +import net.minecraft.entity.player.EntityPlayerMP; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(PacketInventoryAction.class) +public class MixinPacketInventoryAction { + @WrapOperation(method = "serverPacketData", remap = false, at = @At(value = "INVOKE", + target = "Lappeng/container/AEBaseContainer;doAction(Lnet/minecraft/entity/player/EntityPlayerMP;Lappeng/helpers/InventoryAction;IJ)V")) + private void cancelInventoryActions(AEBaseContainer instance, EntityPlayerMP player, InventoryAction action, int slot, long id, Operation original) { + if(!SpectatorMode.isSpectator(player)) { + original.call(instance, player, action, slot, id); + } + } +} diff --git a/src/main/java/ganymedes01/etfuturum/spectator/SpectatorMode.java b/src/main/java/ganymedes01/etfuturum/spectator/SpectatorMode.java index cdbbe5ca..9a723c78 100644 --- a/src/main/java/ganymedes01/etfuturum/spectator/SpectatorMode.java +++ b/src/main/java/ganymedes01/etfuturum/spectator/SpectatorMode.java @@ -192,7 +192,8 @@ public void onPlayerTick(TickEvent.PlayerTickEvent event) { Entity entityToSpectate = SPECTATING_ENTITIES.get(event.player); if (entityToSpectate != null) { - if (entityToSpectate.isDead || event.player.isSneaking()) { + if ((entityToSpectate instanceof EntityPlayer spectatingPlayer && isSpectator(spectatingPlayer)) + || entityToSpectate.isDead || event.player.isSneaking()) { SPECTATING_ENTITIES.remove(event.player); return; }