Fixed Player disguises

Fixed all disguises
Fixed issue where players would crash upon joining
Fixed issue where disguises would crash when player left and reentered a location where a disguise previously was

This is basically a beta build, FIND BUGS FOR ME! :D
This commit is contained in:
NavidK0 2016-03-14 00:55:36 -04:00
parent 27baf53073
commit 24b6ed702b
7 changed files with 120 additions and 66 deletions

View File

@ -236,15 +236,15 @@ public class LibsDisguises extends JavaPlugin {
for (WrappedWatchableObject watch : watcher.getWatchableObjects()) {
disguiseValues.setMetaValue(watch.getIndex(), watch.getValue());
// Uncomment when I need to find the new datawatcher values for a class..
int id = watch.getIndex();
Object val = watch.getValue();
Class<?> valClazz = val != null ? watch.getValue().getClass() : null;
try {
val = val.toString();
} catch (Exception e) {
val = val != null ? val.getClass() : "null";
}
System.out.println("Disguise: " + disguiseType + ", ID: " + id + ", Class: " + (val == null ? "null" : valClazz) + ", Value: " + val);
// int id = watch.getIndex();
// Object val = watch.getValue();
// Class<?> valClazz = val != null ? watch.getValue().getClass() : null;
// try {
// val = val.toString();
// } catch (Exception e) {
// val = val != null ? val.getClass() : "null";
// }
// System.out.println("Disguise: " + disguiseType + ", ID: " + id + ", Class: " + (val == null ? "null" : valClazz) + ", Value: " + val);
}
DisguiseSound sound = DisguiseSound.getType(disguiseType.name());
if (sound != null) {

View File

@ -508,7 +508,7 @@ public abstract class Disguise {
}
if (isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) {
throw new RuntimeException(
"Cannot disguise a living entity with a misc disguise. Renable MiscDisguisesForLiving in the config to do this");
"Cannot disguise a living entity with a misc disguise. Reenable MiscDisguisesForLiving in the config to do this");
}
this.entity = entity;
setupWatcher();

View File

@ -11,7 +11,6 @@ import java.util.List;
public abstract class TargetedDisguise extends Disguise {
public enum TargetType {
HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS, SHOW_TO_EVERYONE_BUT_THESE_PLAYERS
}

View File

@ -10,6 +10,7 @@ import java.util.HashSet;
*/
public enum DisguiseSound {
//TODO: Sounds need to be updated to reflect new 1.9 sounds... oh god...
ARROW(null, null, null, null, "random.bowhit"),
BAT("entity.bat.hurt", null, "entity.bat.death", "entity.bat.idle", "damage.fallsmall", "entity.bat.loop", "damage.fallbig",
"entity.bat.takeoff"),
@ -25,9 +26,8 @@ public enum DisguiseSound {
ELDER_GUARDIAN("entity.guardian.elder.hit", null, "entity.guardian.elder.death", "entity.guardian.elder.death"),
ENDER_DRAGON("entity.enderdragon.hit", null, "entity.enderdragon.end", "entity.enderdragon.growl", "damage.fallsmall",
"entity.enderdragon.wings", "damage.fallbig"),
//TODO: Fix enderman sounds
// ENDERMAN("entity.endermen.hit", "step.grass", "entity.endermen.death", "entity.endermen.idle", "entity.endermen.scream",
// "entity.endermen.portal", "entity.endermen.stare"),
ENDERMAN("entity.endermen.hit", "step.grass", "entity.endermen.death", "entity.endermen.idle", "entity.endermen.scream",
"entity.endermen.portal", "entity.endermen.stare"),
ENDERMITE("entity.silverfish.hit", "entity.silverfish.step", "entity.silverfish.kill", "entity.silverfish.ambient"),
GHAST("entity.ghast.scream", null, "entity.ghast.death", "entity.ghast.moan", "damage.fallsmall", "entity.ghast.fireball",
"damage.fallbig", "entity.ghast.affectionate_scream", "entity.ghast.charge"),
@ -43,7 +43,7 @@ public enum DisguiseSound {
OCELOT("entity.cat.hitt", "step.grass", "entity.cat.hitt", "entity.cat.meow", "entity.cat.purreow", "entity.cat.purr"),
PIG("entity.pig.ambient", "entity.pig.step", "entity.pig.death", "entity.pig.ambient"),
PIG_ZOMBIE("entity.zombiepig.zpighurt", null, "entity.zombiepig.zpigdeath", "entity.zombiepig.zpig", "entity.zombiepig.zpigangry"),
PLAYER("game.player.hurt", "step.grass", "game.player.hurt", null),
PLAYER("entity.player.hurt", "step.grass", "entity.player.hurt", null),
RABBIT("entity.rabbit.hurt", "entity.rabbit.hop", "entity.rabbit.death", "entity.rabbit.idle"),
SHEEP("entity.sheep.ambient", "entity.sheep.step", null, "entity.sheep.ambient", "entity.sheep.shear"),
SHULKER("entity.shulker.hurt", null, "entity.shulker.death", "entity.shulker.ambient", "entity.shulker.open",

View File

@ -256,7 +256,7 @@ public class DisguiseUtilities {
if (entityTrackerEntry != null) {
Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry);
// If the tracker exists. Remove himself from his tracker
trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException
trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException
PacketContainer destroyPacket = new PacketContainer(Server.ENTITY_DESTROY);
destroyPacket.getIntegerArrays().write(0, new int[]{disguise.getEntity().getEntityId()});
for (Object p : trackedPlayers) {
@ -435,18 +435,18 @@ public class DisguiseUtilities {
}
/**
* Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targetted disguise.
* Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targeted disguise.
*
* @param disguise
* @return
*/
public static ArrayList<Player> getPerverts(Disguise disguise) {
ArrayList<Player> players = new ArrayList<>();
public static List<Player> getPerverts(Disguise disguise) {
List<Player> players = new ArrayList<>();
try {
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
if (entityTrackerEntry != null) {
Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry);
trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException
trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException
for (Object p : trackedPlayers) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (((TargetedDisguise) disguise).canSee(player)) {
@ -630,7 +630,7 @@ public class DisguiseUtilities {
ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
ReflectionManager.getNmsClass("EntityPlayer"));
trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException
trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException
for (final Object p : trackedPlayers) {
Player pl = (Player) ReflectionManager.getBukkitEntity(p);
if (player.equalsIgnoreCase((pl).getName())) {
@ -672,7 +672,7 @@ public class DisguiseUtilities {
ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
ReflectionManager.getNmsClass("EntityPlayer"));
trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException
trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException
for (final Object p : trackedPlayers) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (player != entity) {
@ -725,7 +725,7 @@ public class DisguiseUtilities {
Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry);
final Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear", ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer"));
trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException
trackedPlayers = (Set) new HashSet(trackedPlayers).clone();
for (final Object p : trackedPlayers) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (disguise.getEntity() != player && disguise.canSee(player)) {
@ -785,6 +785,7 @@ public class DisguiseUtilities {
t.removeEntry(player.getName());
t.unregister();
}
// player.spigot().setCollidesWithEntities(true);
//Finish up
// Remove the fake entity ID from the disguise bin
selfDisguised.remove(player.getUniqueId());
@ -1030,6 +1031,7 @@ public class DisguiseUtilities {
t.setOption(Option.COLLISION_RULE, OptionStatus.NEVER);
t.addEntry(player.getName());
}
// player.spigot().setCollidesWithEntities(false);
//Finish up
selfDisguised.add(player.getUniqueId());
sendSelfDisguise(player, (TargetedDisguise) disguise);

View File

@ -29,7 +29,6 @@ import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.SheepWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.WolfWatcher;
import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType;
import org.bukkit.Art;
@ -45,13 +44,11 @@ import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Zombie;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@ -207,7 +204,6 @@ public class PacketsManager {
mods.write(5, pitch);
} else if (disguise.getType().isPlayer()) {
//TODO: Make player disguises visible again
spawnPackets[0] = new PacketContainer(Server.NAMED_ENTITY_SPAWN);
PlayerDisguise playerDisguise = (PlayerDisguise) disguise;
String name = playerDisguise.getSkin() != null ? playerDisguise.getSkin() : playerDisguise.getName();
int entityId = disguisedEntity.getEntityId();
@ -215,23 +211,25 @@ public class PacketsManager {
if (!DisguiseUtilities.hasGameProfile(name)) {
removeName = !DisguiseUtilities.getAddedByPlugins().contains(name);
}
WrappedGameProfile gameProfile = playerDisguise.getGameProfile();
if (removeName) {
DisguiseUtilities.getAddedByPlugins().remove(name);
}
Object entityPlayer = ReflectionManager.createEntityPlayer(player.getWorld(), gameProfile);
spawnPackets[0] = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(Server.NAMED_ENTITY_SPAWN, entityPlayer)
.createPacket(entityPlayer);
//Write spawn packet in order
spawnPackets[0].getIntegers().write(0, entityId); //Id
spawnPackets[0].getSpecificModifier(UUID.class).write(0, gameProfile.getUUID()); //UUID
StructureModifier<Double> doubleMods = spawnPackets[0].getDoubles();
doubleMods.write(0, Math.floor(loc.getX() * 32)); //x
doubleMods.write(1, Math.floor(loc.getY() * 32)); //y
doubleMods.write(2, Math.floor(loc.getZ() * 32)); //z
StructureModifier<Byte> byteMods = spawnPackets[0].getBytes();
byteMods.write(0, yaw); //yaw
byteMods.write(1, pitch); //pitch
spawnPackets[0].getDoubles().write(0, loc.getX());
spawnPackets[0].getDoubles().write(1, loc.getY());
spawnPackets[0].getDoubles().write(2, loc.getZ());
spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); //watcher, duh
if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) {
PacketContainer[] newPackets = new PacketContainer[spawnPackets.length + 1];
System.arraycopy(spawnPackets, 1, newPackets, 2, spawnPackets.length - 1);
@ -266,21 +264,41 @@ public class PacketsManager {
delayedPacket.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4));
delayedPackets = new PacketContainer[]{delayedPacket};
} else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) {
int entityId = disguisedEntity.getEntityId();
LivingEntity entity = (LivingEntity) disguisedEntity.getWorld().spawnEntity(loc, disguise.getType().getEntityType());
entity.setVelocity(disguisedEntity.getVelocity());
if (disguise.getType() == DisguiseType.SLIME || disguise.getType() == DisguiseType.MAGMA_CUBE) {
((Slime) entity).setSize(((SlimeWatcher) disguise.getWatcher()).getSize());
}
Object nms = ReflectionManager.getNmsEntity(entity);
PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacketConstructor(Server.SPAWN_ENTITY_LIVING, nms).createPacket(nms).deepClone();
spawnPackets[0] = packet;
spawnPackets[0].getIntegers().write(0, entityId);
spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher()));
entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1, Integer.MAX_VALUE, true, false));
entity.remove();
Vector vec = disguisedEntity.getVelocity();
spawnPackets[0] = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_LIVING);
StructureModifier<Object> mods = spawnPackets[0].getModifier();
mods.write(0, disguisedEntity.getEntityId());
mods.write(1, UUID.randomUUID());
mods.write(2, disguise.getType().getTypeId());
//region Vector calculations
double d1 = 3.9D;
double d2 = vec.getX();
double d3 = vec.getY();
double d4 = vec.getZ();
if (d2 < -d1)
d2 = -d1;
if (d3 < -d1)
d3 = -d1;
if (d4 < -d1)
d4 = -d1;
if (d2 > d1)
d2 = d1;
if (d3 > d1)
d3 = d1;
if (d4 > d1)
d4 = d1;
//endregion
mods.write(3, loc.getX());
mods.write(4, loc.getY());
mods.write(5, loc.getZ());
mods.write(6, (int) (d2 * 8000.0D));
mods.write(7, (int) (d3 * 8000.0D));
mods.write(8, (int) (d4 * 8000.0D));
mods.write(9, yaw);
mods.write(10, pitch);
spawnPackets[0].getDataWatcherModifier().write(0,
createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher()));
} else if (disguise.getType().isMisc()) {
//TODO: Fix falling blocks, BlockPosition Serializer in ProtocolLib
int objectId = disguise.getType().getObjectId();
int data = ((MiscDisguise) disguise).getData();
if (disguise.getType() == DisguiseType.FALLING_BLOCK) {
@ -922,7 +940,6 @@ public class PacketsManager {
} else if (event.getPacketType() == PacketType.Play.Client.WINDOW_CLICK) {
int slot = event.getPacket().getIntegers().read(1);
org.bukkit.inventory.ItemStack clickedItem;
//TODO: Check this to make sure it is accurate
if (event.getPacket().getShorts().read(0) == 1) {
// Its a shift click
clickedItem = event.getPacket().getItemModifier().read(0);
@ -1390,7 +1407,6 @@ public class PacketsManager {
packets[0] = packets[0].shallowClone();
packets[0].getModifier().write(2, (itemStack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemStack)));
}
//TODO: Add left hand here
if (disguise.getWatcher().isRightClicking() && slot == EquipmentSlot.HAND) {
ItemStack heldItem = packets[0].getItemModifier().read(0);
if (heldItem != null && heldItem.getType() != Material.AIR) {
@ -1456,8 +1472,8 @@ public class PacketsManager {
mods.write(1, yaw);
PacketContainer look = new PacketContainer(Server.ENTITY_LOOK);
look.getIntegers().write(0, entity.getEntityId());
look.getBytes().write(3, yaw);
look.getBytes().write(4, pitch);
look.getBytes().write(0, yaw);
look.getBytes().write(1, pitch);
packets = new PacketContainer[]{look, rotation};
}
}

View File

@ -6,6 +6,7 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.google.common.collect.ImmutableMap;
import com.mojang.authlib.GameProfile;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Art;
@ -90,7 +91,7 @@ public class ReflectionManager {
try {
Class<?> entityClass = getNmsClass("Entity" + entityName);
Object entityObject;
Object world = getWorld(Bukkit.getWorlds().get(0));
Object world = getWorldServer(Bukkit.getWorlds().get(0));
switch (entityName) {
case "Player":
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
@ -223,12 +224,21 @@ public class ReflectionManager {
}
public static Object getEntityTrackerEntry(Entity target) throws Exception {
Object world = getWorld(target.getWorld());
Object world = getWorldServer(target.getWorld());
Object tracker = trackerField.get(world);
Object trackedEntities = entitiesField.get(tracker);
return ihmGet.invoke(trackedEntities, target.getEntityId());
}
public static Object getMinecraftServer() {
try {
return getCraftMethod("CraftServer", "getServer").invoke(Bukkit.getServer());
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static String getEnumArt(Art art) {
try {
Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art);
@ -442,15 +452,6 @@ public class ReflectionManager {
return null;
}
public static Object getWorld(World world) {
try {
return getCraftClass("CraftWorld").getDeclaredMethod("getHandle").invoke(world);
} catch (Exception e) {
e.printStackTrace(System.out);
}
return null;
}
public static WrappedGameProfile grabProfileAddUUID(String playername) {
try {
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
@ -679,4 +680,40 @@ public class ReflectionManager {
int k = combinedId >> 12 & 15;
return new ImmutablePair<>(j, k);
}
public static Object getWorldServer(World w) {
try {
return getCraftMethod("CraftWorld", "getHandle").invoke(w);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object getPlayerInteractManager(World w) {
Object worldServer = getWorldServer(w);
try {
return getNmsConstructor("PlayerInteractManager", getNmsClass("World")).newInstance(worldServer);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static Object createEntityPlayer(World w, WrappedGameProfile profile) {
Object entityPlayer = null;
try {
entityPlayer = getNmsConstructor("EntityPlayer",
getNmsClass("MinecraftServer"),
getNmsClass("WorldServer"),
GameProfile.class,
getNmsClass("PlayerInteractManager"))
.newInstance(getMinecraftServer(), getWorldServer(w), profile.getHandle(), getPlayerInteractManager(w));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return entityPlayer;
}
}