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
This commit is contained in:
Dan Mulloy 2017-07-17 18:54:58 -04:00
parent 9255c5a6ab
commit 5d39f7145d
3 changed files with 163 additions and 34 deletions

View File

@ -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()));
}
}
}

View File

@ -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<Packet> 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);

View File

@ -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<WatchableObject> processMeta(List<WatchableObject> list)
{
List<MetaWrapper> 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<WatchableObject> processSpawnMeta(List<WatchableObject> list)
{
List<MetaWrapper> 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());
}
}