diff --git a/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index d1de2545..4407edf8 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -11,7 +11,6 @@ import org.bukkit.entity.Zombie; public enum DisguiseType { - AREA_EFFECT_CLOUD(3, 0), ARMOR_STAND(78), diff --git a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 255e00b3..38674d42 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -34,6 +34,7 @@ public class PlayerDisguise extends TargetedDisguise public PlayerDisguise(String name, String skinToUse) { this(name); + setSkin(skinToUse); } @@ -42,6 +43,11 @@ public class PlayerDisguise extends TargetedDisguise this(ReflectionManager.getGameProfile(player)); } + public PlayerDisguise(Player player, Player skinToUse) + { + this(ReflectionManager.getGameProfile(player), ReflectionManager.getGameProfile(skinToUse)); + } + public PlayerDisguise(WrappedGameProfile gameProfile) { this(gameProfile.getName()); @@ -49,6 +55,13 @@ public class PlayerDisguise extends TargetedDisguise this.gameProfile = gameProfile; } + public PlayerDisguise(WrappedGameProfile gameProfile, WrappedGameProfile skinToUse) + { + this(gameProfile); + + setSkin(skinToUse); + } + @Override public PlayerDisguise addPlayer(Player player) { diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java index 3e9ab94c..e3e64229 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java @@ -1,199 +1,246 @@ -package me.libraryaddict.disguise.disguisetypes.watchers; - -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; - -import com.comphenix.protocol.PacketType.Play.Server; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.WrappedGameProfile; - -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.DisguiseConfig; -import me.libraryaddict.disguise.disguisetypes.Disguise; -import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; -import me.libraryaddict.disguise.utilities.DisguiseUtilities; - -public class PlayerWatcher extends LivingWatcher { - - private boolean isInBed; - private BlockFace sleepingDirection; - - public PlayerWatcher(Disguise disguise) { - super(disguise); - } - - @Override - public PlayerWatcher clone(Disguise disguise) { - PlayerWatcher watcher = (PlayerWatcher) super.clone(disguise); - watcher.isInBed = isInBed; - return watcher; - } - - public BlockFace getSleepingDirection() { - if (sleepingDirection == null) { - if (this.getDisguise().getEntity() != null && isSleeping()) { - this.sleepingDirection = BlockFace.values()[Math - .round(this.getDisguise().getEntity().getLocation().getYaw() / 90F) & 0x3]; - } else { - return BlockFace.EAST; - } - } - return sleepingDirection; - } - - -// Bit 0 (0x01): Cape enabled -// Bit 1 (0x02): Jacket enabled -// Bit 2 (0x04): Left Sleeve enabled -// Bit 3 (0x08): Right Sleeve enabled -// Bit 4 (0x10): Left Pants Leg enabled -// Bit 5 (0x20): Right Pants Leg enabled -// Bit 6 (0x40): Hat enabled - - private boolean isSkinFlag(int i) { - return ((byte) getValue(12, (byte) 0) & 1 << i) != 0; - } - - public boolean isCapeEnabled() { - return isSkinFlag(1); - } - - public boolean isJackedEnabled() { - return isSkinFlag(2); - } - - public boolean isLeftSleeveEnabled() { - return isSkinFlag(3); - } - - public boolean isRightSleeveEnabled() { - return isSkinFlag(4); - } - - public boolean isLeftPantsEnabled() { - return isSkinFlag(5); - } - - public boolean isRightPantsEnabled() { - return isSkinFlag(6); - } - - public boolean isHatEnabled() { - return isSkinFlag(7); - } - - public void setCapeEnabled(boolean enabled) { - setSkinFlags(1, enabled); - sendData(12); - } - - public void setJackedEnabled(boolean enabled) { - setSkinFlags(2, enabled); - sendData(12); - } - - public void setLeftSleeveEnabled(boolean enabled) { - setSkinFlags(3, enabled); - sendData(12); - } - - public void setRightSleeveEnabled(boolean enabled) { - setSkinFlags(4, enabled); - sendData(12); - } - - public void setLeftPantsEnabled(boolean enabled) { - setSkinFlags(5, enabled); - sendData(12); - } - - public void setRightPantsEnabled(boolean enabled) { - setSkinFlags(6, enabled); - sendData(12); - } - - public void setHatEnabled(boolean enabled) { - setSkinFlags(7, enabled); - sendData(12); - } - - - public boolean isSleeping() { - return isInBed; - } - - public void setSkin(String playerName) { - ((PlayerDisguise) getDisguise()).setSkin(playerName); - } - - public void setSkin(WrappedGameProfile profile) { - ((PlayerDisguise) getDisguise()).setSkin(profile); - } - - public void setSleeping(BlockFace sleepingDirection) { - setSleeping(true, sleepingDirection); - } - - public void setSleeping(boolean sleep) { - setSleeping(sleep, null); - } - - /** - * If no BlockFace is supplied. It grabs it from the entities facing direction if applicable. - * - * @param sleeping - * @param sleepingDirection - */ - public void setSleeping(boolean sleeping, BlockFace sleepingDirection) { - if (sleepingDirection != null) { - this.sleepingDirection = BlockFace.values()[sleepingDirection.ordinal() % 4]; - } - if (sleeping != isSleeping()) { - isInBed = sleeping; - if (DisguiseConfig.isBedPacketsEnabled() && DisguiseUtilities.isDisguiseInUse(getDisguise())) { - try { - if (isSleeping()) { - for (Player player : DisguiseUtilities.getPerverts(getDisguise())) { - PacketContainer[] packets = DisguiseUtilities.getBedPackets(player, this.getDisguise().getEntity() - .getLocation(), player.getLocation(), (PlayerDisguise) this.getDisguise()); - if (getDisguise().getEntity() == player) { - for (PacketContainer packet : packets) { - packet = packet.shallowClone(); - packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); - } - } else { - for (PacketContainer packet : packets) { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); - } - } - } - } else { - PacketContainer packet = new PacketContainer(Server.ANIMATION); - StructureModifier mods = packet.getIntegers(); - mods.write(0, getDisguise().getEntity().getEntityId()); - mods.write(1, 3); - for (Player player : DisguiseUtilities.getPerverts(getDisguise())) { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); - - } - } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - } - } - } - - private void setSkinFlags(int i, boolean flag) { - byte b0 = (byte) getValue(12, (byte) 0); - if (flag) { - setValue(12, (byte) (b0 | 1 << i)); - } else { - setValue(12, (byte) (b0 & (~1 << i))); - } - } - -} +package me.libraryaddict.disguise.disguisetypes.watchers; + +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.WrappedGameProfile; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; +import me.libraryaddict.disguise.utilities.DisguiseUtilities; + +public class PlayerWatcher extends LivingWatcher +{ + private boolean isInBed; + private BlockFace sleepingDirection; + + public PlayerWatcher(Disguise disguise) + { + super(disguise); + } + + @Override + public PlayerWatcher clone(Disguise disguise) + { + PlayerWatcher watcher = (PlayerWatcher) super.clone(disguise); + watcher.isInBed = isInBed; + return watcher; + } + + public BlockFace getSleepingDirection() + { + if (sleepingDirection == null) + { + if (this.getDisguise().getEntity() != null && isSleeping()) + { + this.sleepingDirection = BlockFace + .values()[Math.round(this.getDisguise().getEntity().getLocation().getYaw() / 90F) & 0x3]; + } + else + { + return BlockFace.EAST; + } + } + return sleepingDirection; + } + + // Bit 0 (0x01): Cape enabled + // Bit 1 (0x02): Jacket enabled + // Bit 2 (0x04): Left Sleeve enabled + // Bit 3 (0x08): Right Sleeve enabled + // Bit 4 (0x10): Left Pants Leg enabled + // Bit 5 (0x20): Right Pants Leg enabled + // Bit 6 (0x40): Hat enabled + + private boolean isSkinFlag(int i) + { + return ((byte) getValue(12, (byte) 0) & 1 << i) != 0; + } + + public boolean isCapeEnabled() + { + return isSkinFlag(1); + } + + public boolean isJackedEnabled() + { + return isSkinFlag(2); + } + + public boolean isLeftSleeveEnabled() + { + return isSkinFlag(3); + } + + public boolean isRightSleeveEnabled() + { + return isSkinFlag(4); + } + + public boolean isLeftPantsEnabled() + { + return isSkinFlag(5); + } + + public boolean isRightPantsEnabled() + { + return isSkinFlag(6); + } + + public boolean isHatEnabled() + { + return isSkinFlag(7); + } + + public void setCapeEnabled(boolean enabled) + { + setSkinFlags(1, enabled); + sendData(12); + } + + public void setJackedEnabled(boolean enabled) + { + setSkinFlags(2, enabled); + sendData(12); + } + + public void setLeftSleeveEnabled(boolean enabled) + { + setSkinFlags(3, enabled); + sendData(12); + } + + public void setRightSleeveEnabled(boolean enabled) + { + setSkinFlags(4, enabled); + sendData(12); + } + + public void setLeftPantsEnabled(boolean enabled) + { + setSkinFlags(5, enabled); + sendData(12); + } + + public void setRightPantsEnabled(boolean enabled) + { + setSkinFlags(6, enabled); + sendData(12); + } + + public void setHatEnabled(boolean enabled) + { + setSkinFlags(7, enabled); + sendData(12); + } + + public boolean isSleeping() + { + return isInBed; + } + + public void setSkin(String playerName) + { + ((PlayerDisguise) getDisguise()).setSkin(playerName); + } + + public void setSkin(WrappedGameProfile profile) + { + ((PlayerDisguise) getDisguise()).setSkin(profile); + } + + public void setSleeping(BlockFace sleepingDirection) + { + setSleeping(true, sleepingDirection); + } + + public void setSleeping(boolean sleep) + { + setSleeping(sleep, null); + } + + /** + * If no BlockFace is supplied. It grabs it from the entities facing direction if applicable. + * + * @param sleeping + * @param sleepingDirection + */ + public void setSleeping(boolean sleeping, BlockFace sleepingDirection) + { + if (sleepingDirection != null) + { + this.sleepingDirection = BlockFace.values()[sleepingDirection.ordinal() % 4]; + } + if (sleeping != isSleeping()) + { + isInBed = sleeping; + if (DisguiseConfig.isBedPacketsEnabled() && DisguiseUtilities.isDisguiseInUse(getDisguise())) + { + try + { + if (isSleeping()) + { + for (Player player : DisguiseUtilities.getPerverts(getDisguise())) + { + PacketContainer[] packets = DisguiseUtilities.getBedPackets(player, + this.getDisguise().getEntity().getLocation(), player.getLocation(), + (PlayerDisguise) this.getDisguise()); + if (getDisguise().getEntity() == player) + { + for (PacketContainer packet : packets) + { + packet = packet.shallowClone(); + packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); + } + } + else + { + for (PacketContainer packet : packets) + { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); + } + } + } + } + else + { + PacketContainer packet = new PacketContainer(Server.ANIMATION); + StructureModifier mods = packet.getIntegers(); + mods.write(0, getDisguise().getEntity().getEntityId()); + mods.write(1, 3); + for (Player player : DisguiseUtilities.getPerverts(getDisguise())) + { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); + + } + } + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + } + } + } + + private void setSkinFlags(int i, boolean flag) + { + byte b0 = (byte) getValue(12, (byte) 0); + if (flag) + { + setValue(12, (byte) (b0 | 1 << i)); + } + else + { + setValue(12, (byte) (b0 & (~1 << i))); + } + } + +} diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 9aa6c40a..f2d7a549 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -83,6 +83,7 @@ public class DisguiseUtilities private static HashMap> runnables = new HashMap<>(); private static HashSet selfDisguised = new HashSet<>(); private static Field xChunk, zChunk; + private static Thread mainThread; static { @@ -146,6 +147,11 @@ public class DisguiseUtilities zChunk = bedChunk.getClass().getField("locZ"); zChunk.setAccessible(true); + + Field threadField = ReflectionManager.getNmsField("MinecraftServer", "primaryThread"); + threadField.setAccessible(true); + + mainThread = (Thread) threadField.get(ReflectionManager.getMinecraftServer()); } catch (Exception ex) { @@ -346,6 +352,9 @@ public class DisguiseUtilities */ public static void destroyEntity(TargetedDisguise disguise) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + try { Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity()); @@ -637,6 +646,9 @@ public class DisguiseUtilities */ public static List getPerverts(Disguise disguise) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + List players = new ArrayList<>(); try @@ -865,6 +877,9 @@ public class DisguiseUtilities */ public static void refreshTracker(final TargetedDisguise disguise, String player) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + if (disguise.getEntity() != null && disguise.getEntity().isValid()) { try @@ -959,6 +974,9 @@ public class DisguiseUtilities */ public static void refreshTrackers(Entity entity) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + if (entity.isValid()) { try @@ -1021,6 +1039,9 @@ public class DisguiseUtilities */ public static void refreshTrackers(final TargetedDisguise disguise) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + if (disguise.getEntity().isValid()) { PacketContainer destroyPacket = getDestroyPacket(disguise.getEntity().getEntityId()); @@ -1131,6 +1152,9 @@ public class DisguiseUtilities public static void removeSelfDisguise(Player player) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + if (selfDisguised.contains(player.getUniqueId())) { // Send a packet to destroy the fake entity @@ -1212,6 +1236,9 @@ public class DisguiseUtilities */ public static void sendSelfDisguise(final Player player, final TargetedDisguise disguise) { + if (mainThread != Thread.currentThread()) + throw new IllegalStateException("Cannot modify disguises on an async thread"); + try { if (!disguise.isDisguiseInUse() || !player.isValid() || !player.isOnline() || !disguise.isSelfDisguiseVisible()