From 7836e0aaaa5ffaa255a1f2c99e4b206fa48c10ec Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Mon, 17 Jul 2017 18:54:58 -0400 Subject: [PATCH] Fix guardian disguises This commit fixes guardian disguises (esp. elder guardians) and also provides for disguises to modify packets before they're sent if necessary --- .../core/disguise/DisguiseManager.java | 19 +-- .../core/disguise/disguises/DisguiseBase.java | 65 ++++++---- .../disguise/disguises/DisguiseGuardian.java | 113 +++++++++++++++++- 3 files changed, 163 insertions(+), 34 deletions(-) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java b/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java index 89c28093f..44dc988fc 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java @@ -360,6 +360,7 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler final Packet packet = packetInfo.getPacket(); final Player owner = packetInfo.getPlayer(); final PacketVerifier packetVerifier = packetInfo.getVerifier(); + final int protocol = ((CraftPlayer) owner).getHandle().getProtocol(); if (packet instanceof PacketPlayOutPlayerInfo) { @@ -406,7 +407,7 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler { packetInfo.setCancelled(true); - handleSpawnPackets(packetInfo.getVerifier(), latestDisguise); + handleSpawnPackets(packetInfo.getVerifier(), latestDisguise, protocol); } else if (latestDisguise.isHideIfNotDisguised()) { @@ -436,7 +437,7 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler if (latestDisguise != null && containsSpawnDisguise(owner, latestDisguise) && owner.getEntityId() != entityId) { packetInfo.setCancelled(true); - handlePacket(latestDisguise.getMetadataPacket(), packetVerifier); + handlePacket(latestDisguise.modifyMetaPacket(protocol, latestDisguise.getMetadataPacket()), packetVerifier); } } else if (packet instanceof PacketPlayOutEntityEquipment) @@ -475,7 +476,7 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler _handlingPacket = false; } - private void handleSpawnPackets(PacketVerifier packetVerifier, DisguiseBase disguise) + private void handleSpawnPackets(PacketVerifier packetVerifier, DisguiseBase disguise, int protocol) { if (disguise instanceof DisguisePlayer) { @@ -493,14 +494,14 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler handlePacket(infoPacket, packetVerifier); } - handlePacket(pDisguise.getSpawnPacket(), packetVerifier); + handlePacket(pDisguise.modifySpawnPacket(protocol, pDisguise.getSpawnPacket()), packetVerifier); for (Packet packet : pDisguise.getEquipmentPackets()) { handlePacket(packet, packetVerifier); } - handlePacket(pDisguise.getMetadataPacket(), packetVerifier); + handlePacket(pDisguise.modifyMetaPacket(protocol, pDisguise.getMetadataPacket()), packetVerifier); if (pDisguise.getSleepingDirection() != null) { @@ -556,7 +557,7 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler } else { - handlePacket(disguise.getSpawnPacket(), packetVerifier); + handlePacket(disguise.modifySpawnPacket(protocol, disguise.getSpawnPacket()), packetVerifier); if (disguise instanceof DisguiseLiving) { @@ -644,10 +645,12 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler { if (tester.test(player)) { - if (disguise.getEntity() == ((CraftPlayer) player).getHandle()) + EntityPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + if (disguise.getEntity() == nmsPlayer) continue; - UtilPlayer.sendPacket(player, disguise.getMetadataPacket()); + int protocol = nmsPlayer.getProtocol(); + UtilPlayer.sendPacket(player, disguise.modifyMetaPacket(protocol, disguise.getMetadataPacket())); } } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseBase.java b/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseBase.java index 2d0334abc..b9e6cdd9c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseBase.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseBase.java @@ -2,16 +2,9 @@ package mineplex.core.disguise.disguises; import mineplex.core.common.DummyEntity; import mineplex.core.common.util.UtilPlayer; -import net.minecraft.server.v1_8_R3.DataWatcher; -import net.minecraft.server.v1_8_R3.Entity; -import net.minecraft.server.v1_8_R3.EntityPlayer; -import net.minecraft.server.v1_8_R3.EntityTrackerEntry; -import net.minecraft.server.v1_8_R3.IntHashMap; -import net.minecraft.server.v1_8_R3.MinecraftServer; -import net.minecraft.server.v1_8_R3.Packet; -import net.minecraft.server.v1_8_R3.PacketPlayOutEntityMetadata; -import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; -import net.minecraft.server.v1_8_R3.WorldServer; + +import net.minecraft.server.v1_8_R3.*; + import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -21,6 +14,8 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; public abstract class DisguiseBase { @@ -72,15 +67,7 @@ public abstract class DisguiseBase DataWatcher.watch(1, getEntity().getDataWatcher().getShort(1), net.minecraft.server.v1_8_R3.Entity.META_AIR, (int) getEntity().getDataWatcher().getShort(1)); } - public abstract Packet getSpawnPacket(); - - public Packet getMetadataPacket() - { - UpdateDataWatcher(); - return new PacketPlayOutEntityMetadata(getEntity().getId(), DataWatcher, true); - } - - public void resendMetadata() + public void sendToWatchers(Supplier supplier) { if (getEntity() == null || !getEntity().getBukkitEntity().isValid() || !(getEntity().world instanceof WorldServer)) return; @@ -90,14 +77,48 @@ public abstract class DisguiseBase if (tracker.get(getEntity().getId()) == null) return; - Packet packet = getMetadataPacket(); + Packet packet = supplier.get(); + if (packet == null) + return; for (EntityPlayer player : tracker.get(getEntity().getId()).trackedPlayers) { - UtilPlayer.sendPacket(player.getBukkitEntity(), packet); + if (packet instanceof PacketPlayOutEntityMetadata) + { + player.playerConnection.sendPacket(modifyMetaPacket(player.getProtocol(), packet)); + } else if (packet instanceof PacketPlayOutSpawnEntityLiving) + { + player.playerConnection.sendPacket(modifySpawnPacket(player.getProtocol(), packet)); + } else + { + player.playerConnection.sendPacket(packet); + } } } + public abstract Packet getSpawnPacket(); + + public Packet modifySpawnPacket(int protocol, Packet packet) + { + return packet; + } + + public Packet getMetadataPacket() + { + UpdateDataWatcher(); + return new PacketPlayOutEntityMetadata(getEntity().getId(), DataWatcher, true); + } + + public void resendMetadata() + { + sendToWatchers(this::getMetadataPacket); + } + + public Packet modifyMetaPacket(int protocol, Packet packet) + { + return packet; + } + public void setSoundDisguise(DisguiseBase soundDisguise) { _soundDisguise = soundDisguise; @@ -197,7 +218,7 @@ public abstract class DisguiseBase return this._disguiseType; } - public void setEntity(net.minecraft.server.v1_8_R3.Entity entity) + public void setEntity(Entity entity) { _entity.clear(); _entity = new WeakReference<>(entity); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseGuardian.java b/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseGuardian.java index af05e67bb..eaa367258 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseGuardian.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/disguise/disguises/DisguiseGuardian.java @@ -1,11 +1,23 @@ package mineplex.core.disguise.disguises; -import org.bukkit.entity.*; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; -import net.minecraft.server.v1_8_R3.EntityGuardian; +import com.mineplex.MetaWrapper; +import com.mineplex.ProtocolVersion; + +import net.minecraft.server.v1_8_R3.*; +import net.minecraft.server.v1_8_R3.DataWatcher.WatchableObject; + +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; public class DisguiseGuardian extends DisguiseCreature { + private int target = 0; + private boolean elder = false; + public DisguiseGuardian(org.bukkit.entity.Entity entity) { super(EntityType.GUARDIAN, entity); @@ -15,17 +27,33 @@ public class DisguiseGuardian extends DisguiseCreature public void setTarget(int target) { + this.target = target; + DataWatcher.watch(17, target, EntityGuardian.META_TARGET, target); } public void setElder(boolean elder) { - DataWatcher.watch(16, Integer.valueOf(DataWatcher.getInt(16) | 4), EntityGuardian.META_ELDER, (byte) (DataWatcher.getInt(16) | 4)); + this.elder = elder; + + int oldValue = DataWatcher.getInt(16); + int newValue = elder ? oldValue | 4 : oldValue & ~4; + + DataWatcher.watch(16, Integer.valueOf(newValue), EntityGuardian.META_ELDER, (byte) newValue); + + sendToWatchers(() -> new PacketPlayOutEntityDestroy(new int[]{getEntityId()})); + sendToWatchers(this::getSpawnPacket); + sendToWatchers(this::getMetadataPacket); } public boolean isElder() { - return (this.DataWatcher.getInt(16) & 4) != 0; + return elder; + } + + public int getTarget() + { + return target; } protected String getHurtSound() @@ -37,4 +65,81 @@ public class DisguiseGuardian extends DisguiseCreature return "mob.guardian.hit"; } + + // ---- Packet modification for 1.11 and up + + @Override + public Packet modifySpawnPacket(int protocol, Packet packet) + { + if (protocol >= ProtocolVersion.v1_11) + { + PacketPlayOutSpawnEntityLiving newSpawn = (PacketPlayOutSpawnEntityLiving) getSpawnPacket(); + if (isElder()) newSpawn.b = 4; + newSpawn.m = processSpawnMeta(DataWatcher.c()); + return newSpawn; + } + + return packet; + } + + @Override + public Packet modifyMetaPacket(int protocol, Packet packet) + { + if (protocol >= ProtocolVersion.v1_11) + { + PacketPlayOutEntityMetadata newPacket = (PacketPlayOutEntityMetadata) getMetadataPacket(); + newPacket.b = processMeta(newPacket.b); + return newPacket; + } + + return packet; + } + + private List processMeta(List list) + { + List newMeta = new ArrayList<>(); + for (WatchableObject meta : list) + { + MetaWrapper wrapper = new MetaWrapper(meta); + if (wrapper.getIndex() == 11) + { + byte value = (byte) wrapper.getValue(); + newMeta.add(new MetaWrapper(11, DataType.BOOLEAN, (value & 0x02) != 0)); + } else + { + newMeta.add(wrapper); + } + } + + return newMeta.stream().map(MetaWrapper::toWatchableObject).collect(Collectors.toList()); + } + + private List processSpawnMeta(List list) + { + List newMeta = new ArrayList<>(); + for (WatchableObject meta : list) + { + MetaWrapper wrapper = new MetaWrapper(meta); + if (wrapper.getIndex() >= 5) // 1.10 + { + wrapper.setIndex(wrapper.getIndex() + 1); + } + + if (getEntity() instanceof EntityArmorStand && (wrapper.getIndex() == 12 || wrapper.getIndex() == 13)) + { + continue; + } + + if (wrapper.getIndex() < 12) // Skip higher ones in 1.11 + { + newMeta.add(wrapper); + } else if (wrapper.getIndex() == 12) + { + byte value = (byte) wrapper.getValue(); + newMeta.add(new MetaWrapper(12, DataType.BOOLEAN, (value & 0x02) != 0)); + } + } + + return newMeta.stream().map(MetaWrapper::toWatchableObject).collect(Collectors.toList()); + } }