diff --git a/.idea/libraries/Maven__cglib_cglib_nodep_2_2_2.xml b/.idea/libraries/Maven__cglib_cglib_nodep_2_2_2.xml new file mode 100644 index 00000000..5145a35f --- /dev/null +++ b/.idea/libraries/Maven__cglib_cglib_nodep_2_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_comphenix_executors_BukkitExecutors_1_1_SNAPSHOT.xml b/.idea/libraries/Maven__com_comphenix_executors_BukkitExecutors_1_1_SNAPSHOT.xml new file mode 100644 index 00000000..0832d019 --- /dev/null +++ b/.idea/libraries/Maven__com_comphenix_executors_BukkitExecutors_1_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_comphenix_protocol_ProtocolLib_API_4_2_0_SNAPSHOT.xml b/.idea/libraries/Maven__com_comphenix_protocol_ProtocolLib_API_4_2_0_SNAPSHOT.xml new file mode 100644 index 00000000..3206ed01 --- /dev/null +++ b/.idea/libraries/Maven__com_comphenix_protocol_ProtocolLib_API_4_2_0_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 00000000..e96534fb --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config.yml b/config.yml index 83eea23c..e953df47 100644 --- a/config.yml +++ b/config.yml @@ -1,6 +1,47 @@ # Shall I notify people of a LibsDisguises update? NotifyUpdate: true +# The disguise plugin stores all GameProfiles inside a file called 'cache.yml' +# This means that the plugin doesn't need to constantly call Mojang just to find a skin for an offline player +# However some people may prefer to disable this. +# Even if you disable this, if there was disguises in the cache already then it will use them +SaveCache: true + +# This option is useless if you don't enable SaveCache! +# If a player has been disguised before and their skin saved into the cache +# When they join the server will automatically update the cache incase they changed their skin +UpdatePlayersCache: true + +# Should the server save the disguises so that when they are alive again, they are disguised again +# Players - Are player disguises saved +# Entities - Are entities disguises saved +SaveDisguises: + Players: false + Entities: false + +# Where does it save the disguises and gameprofiles to +SaveData: + # If this is true, then it saves to mysql. If this is false, then it saves to file + # I do not provide help for setting up Mysql or the databases, there are guides online for that + UseMySQL: false + # What is the IP and Port required to connect + IP: 'localhost:3306' + User: 'root' + Password: 'password' + Database: 'LibsDisguises' + # What is the table for GameProfiles called? You shouldn't need to touch this + GameProfiles: 'GameProfileCache' + # What is the table for disguises called? + Disguises: 'DisguisesCache' + +# This I don't really recommend turning on as it can make a memory leak.. +# These disguises, as normal will not persist after a server restart. +# There is also no EntityDeath option as entities do not revive after death. +# The EntityDespawn option is when you leave the chunk the entity is and the chunk is unloaded +KeepDisguises: + EntityDespawn: false + PlayerDeath: false + # How should the plugin handle self disguises scoreboards? # MODIFY_SCOREBOARD - Modifies the player's current team if possible, otherwise assigns them to a new scoreboard team # IGNORE_SCOREBOARD - Doesn't touch scoreboards at all, effectively means that if you didn't disable pushing in their scoreboard team; They will still be pushed around @@ -68,6 +109,7 @@ NameAboveHeadAlwaysVisible: true # This WILL conflict with NoCheatPlus. Other plugins may also get problems. # This shouldn't really be enabled for players as it also interferes with their movement because the server thinks the player is larger than he really is. # That makes the player unable to approach this building because the server thinks he is trying to glitch inside blocks. +# This feature is highly experimental and is garanteed to cause problems for players who are disguised ModifyBoundingBox: false # This prevents disguised players from being targeted by monsters. @@ -93,15 +135,6 @@ DisguiseCloneExpire: 10 # Max disguises to store at a time with the DisguiseClone command DisguiseCloneSize: 3 -# This I don't really recommend turning on as it can make a memory leak.. -# These disguises, as normal will not persist after a server restart. -# There is also no EntityDeath option as entities do not revive after death. -# The EntityDespawn option is when you leave the chunk the entity is and the chunk is unloaded -KeepDisguises: - EntityDespawn: false - PlayerDeath: false - PlayerLogout: false - # This controls if a entitys max health is determined by the entity, or by the disguise. # Wither is 200, a player is 20. With this enabled, a player disguised as a wither will have the boss bar health accurate to the players health. # Else it will be 1/20 of the boss bar when he is full health. diff --git a/src/me/libraryaddict/disguise/DisguiseConfig.java b/src/me/libraryaddict/disguise/DisguiseConfig.java index 61d91d06..1f25f511 100644 --- a/src/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/me/libraryaddict/disguise/DisguiseConfig.java @@ -58,6 +58,36 @@ public class DisguiseConfig { private static boolean viewSelfDisguise; private static boolean witherSkullEnabled; private static DisguisePushing disablePushing = DisguisePushing.MODIFY_SCOREBOARD; + private static boolean saveCache; + private static boolean updatePlayerCache; + private static boolean savePlayerDisguises; + private static boolean saveEntityDisguises; + private static boolean useSQL; + private static String ip, database, user, pass, disguiseTable, profileTable; + + public static String getDatabaseIP() { + return ip; + } + + public static String getDatabase() { + return database; + } + + public static String getDatabaseUser() { + return user; + } + + public static String getDatabasePass() { + return pass; + } + + public static String getDatabaseProfileTable() { + return disguiseTable; + } + + public static String getDatabaseDisguiseTable() { + return profileTable; + } public static Entry getCustomDisguise(String disguise) { for (Entry entry : customDisguises.entrySet()) { @@ -71,6 +101,22 @@ public class DisguiseConfig { return null; } + public static boolean isSavePlayerDisguises() { + return savePlayerDisguises; + } + + public static boolean isSaveEntityDisguises() { + return saveEntityDisguises; + } + + public static void setSavePlayerDisguises(boolean saveDisguises) { + savePlayerDisguises = saveDisguises; + } + + public static void setSaveEntityDisguises(boolean saveDisguises) { + saveEntityDisguises = saveDisguises; + } + public static DisguisePushing getPushingOption() { return disablePushing; } @@ -103,6 +149,22 @@ public class DisguiseConfig { return updateNotificationPermission; } + public static boolean isSaveCache() { + return saveCache; + } + + public static void setSaveCache(boolean doCache) { + saveCache = doCache; + } + + public static boolean isUpdatePlayerCache() { + return updatePlayerCache; + } + + public static void setUpdatePlayerCache(boolean setUpdatePlayerCache) { + updatePlayerCache = setUpdatePlayerCache; + } + public static void initConfig(ConfigurationSection config) { setSoundsEnabled(config.getBoolean("DisguiseSounds")); setVelocitySent(config.getBoolean("SendVelocity")); @@ -144,6 +206,15 @@ public class DisguiseConfig { setHideDisguisedPlayers(config.getBoolean("HideDisguisedPlayersFromTab")); setShowDisguisedPlayersInTab(config.getBoolean("ShowPlayerDisguisesInTab")); setDisabledInvisibility(config.getBoolean("DisableInvisibility")); + setSaveCache(config.getBoolean("SaveCache")); + setUpdatePlayerCache(config.getBoolean("UpdatePlayerCache")); + setSaveEntityDisguises(config.getBoolean("SaveDisguises.Entities")); + setSavePlayerDisguises(config.getBoolean("SaveDisguises.Players")); + useSQL = config.getBoolean("SaveData.UseMySQL", false); + ip = config.getString("SaveData.IP", "localhost:3306"); + user = config.getString("SaveData.User", "root"); + pass = config.getString("SaveData.Password", "password"); + database try { String option = config.getString("SelfDisguisesScoreboard", @@ -193,7 +264,8 @@ public class DisguiseConfig { } catch (DisguiseParseException e) { System.err.println( - "[LibsDisguises] Error while loading custom disguise '" + key + "'" + (e.getMessage() == null ? "" : ": " + e.getMessage())); + "[LibsDisguises] Error while loading custom disguise '" + key + "'" + (e.getMessage() == null ? + "" : ": " + e.getMessage())); if (e.getMessage() == null) e.printStackTrace(); @@ -204,7 +276,8 @@ public class DisguiseConfig { } System.out.println( - "[LibsDisguises] Loaded " + customDisguises.size() + " custom disguise" + (customDisguises.size() == 1 ? "" : "s")); + "[LibsDisguises] Loaded " + customDisguises.size() + " custom disguise" + (customDisguises.size() == 1 ? + "" : "s")); } public static boolean isAnimationPacketsEnabled() { diff --git a/src/me/libraryaddict/disguise/DisguiseListener.java b/src/me/libraryaddict/disguise/DisguiseListener.java index 30c2358a..a152db30 100644 --- a/src/me/libraryaddict/disguise/DisguiseListener.java +++ b/src/me/libraryaddict/disguise/DisguiseListener.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import com.comphenix.protocol.wrappers.WrappedGameProfile; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -26,6 +27,8 @@ import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.vehicle.VehicleEnterEvent; import org.bukkit.event.vehicle.VehicleExitEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -89,14 +92,15 @@ public class DisguiseListener implements Listener { continue; } - p.sendMessage( - String.format(DisguiseConfig.getUpdateMessage(), currentVersion, latestVersion)); + p.sendMessage(String.format(DisguiseConfig.getUpdateMessage(), currentVersion, + latestVersion)); } } }); } catch (Exception ex) { - System.out.print(String.format("[LibsDisguises] Failed to check for update: %s", ex.getMessage())); + System.out.print( + String.format("[LibsDisguises] Failed to check for update: %s", ex.getMessage())); } } }, 0, (20 * 60 * 60 * 6)); // Check every 6 hours @@ -189,6 +193,39 @@ public class DisguiseListener implements Listener { } } + @EventHandler + public void onChunkUnload(ChunkUnloadEvent event) { + if (!DisguiseConfig.isSaveEntityDisguises()) + return; + + for (Entity entity : event.getChunk().getEntities()) { + Disguise[] disguises = DisguiseAPI.getDisguises(entity); + + if (disguises.length <= 0) + continue; + + DisguiseUtilities.saveDisguises(entity.getUniqueId(), disguises); + } + } + + @EventHandler + public void onChunkLoad(ChunkLoadEvent event) { + if (!DisguiseConfig.isSaveEntityDisguises()) + return; + + for (Entity entity : event.getChunk().getEntities()) { + Disguise[] disguises = DisguiseUtilities.getSavedDisguises(entity.getUniqueId()); + + if (disguises.length <= 0) + continue; + + for (Disguise disguise : disguises) { + disguise.setEntity(entity); + disguise.startDisguise(); + } + } + } + @EventHandler public void onJoin(PlayerJoinEvent event) { Player p = event.getPlayer(); @@ -201,6 +238,24 @@ public class DisguiseListener implements Listener { chunkMove(p, p.getLocation(), null); } + if (DisguiseConfig.isSaveCache() && DisguiseConfig.isUpdatePlayerCache() && DisguiseUtilities.hasCacheEntry( + p.getName())) { + WrappedGameProfile profile = WrappedGameProfile.fromPlayer(p); + + if (!profile.getProperties().isEmpty()) { + DisguiseUtilities.addGameProfile(p.getName(), profile); + } + } + + if (DisguiseConfig.isSavePlayerDisguises()) { + Disguise[] disguises = DisguiseUtilities.getSavedDisguises(p.getUniqueId()); + + for (Disguise disguise : disguises) { + disguise.setEntity(p); + disguise.startDisguise(); + } + } + for (HashSet disguiseList : DisguiseUtilities.getDisguises().values()) { for (TargetedDisguise targetedDisguise : disguiseList) { if (targetedDisguise.getEntity() == null) @@ -239,8 +294,9 @@ public class DisguiseListener implements Listener { PacketContainer addTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); addTab.getPlayerInfoAction().write(0, PlayerInfoAction.ADD_PLAYER); - addTab.getPlayerInfoDataLists().write(0, Arrays.asList(new PlayerInfoData(disguise.getGameProfile(), 0, - NativeGameMode.SURVIVAL, WrappedChatComponent.fromText(disguise.getGameProfile().getName())))); + addTab.getPlayerInfoDataLists().write(0, Arrays.asList( + new PlayerInfoData(disguise.getGameProfile(), 0, NativeGameMode.SURVIVAL, + WrappedChatComponent.fromText(disguise.getGameProfile().getName())))); ProtocolLibrary.getProtocolManager().sendServerPacket(p, addTab); } @@ -261,8 +317,9 @@ public class DisguiseListener implements Listener { Location to = event.getTo(); Location from = event.getFrom(); - if (DisguiseUtilities.getChunkCord(to.getBlockX()) != DisguiseUtilities.getChunkCord(from.getBlockX()) - || DisguiseUtilities.getChunkCord(to.getBlockZ()) != DisguiseUtilities.getChunkCord(from.getBlockZ())) { + if (DisguiseUtilities.getChunkCord(to.getBlockX()) != DisguiseUtilities.getChunkCord( + from.getBlockX()) || DisguiseUtilities.getChunkCord( + to.getBlockZ()) != DisguiseUtilities.getChunkCord(from.getBlockZ())) { chunkMove(event.getPlayer(), to, from); } } @@ -286,7 +343,17 @@ public class DisguiseListener implements Listener { @EventHandler public void onQuit(PlayerQuitEvent event) { - ReflectionManager.removePlayer(event.getPlayer()); + if (!DisguiseConfig.isSavePlayerDisguises()) + return; + + Player player = event.getPlayer(); + + Disguise[] disguises = DisguiseAPI.getDisguises(player); + + if (disguises.length <= 0) + return; + + DisguiseUtilities.saveDisguises(player.getUniqueId(), disguises); } @EventHandler @@ -315,7 +382,8 @@ public class DisguiseListener implements Listener { @EventHandler public void onRightClick(PlayerInteractEntityEvent event) { - if (!disguiseEntity.containsKey(event.getPlayer().getName()) && !disguiseClone.containsKey(event.getPlayer().getName())) { + if (!disguiseEntity.containsKey(event.getPlayer().getName()) && !disguiseClone.containsKey( + event.getPlayer().getName())) { return; } @@ -329,8 +397,7 @@ public class DisguiseListener implements Listener { if (entity instanceof Player && !disguiseClone.containsKey(p.getName())) { entityName = entity.getName(); - } - else { + } else { entityName = DisguiseType.getType(entity).toReadable(); } @@ -338,17 +405,14 @@ public class DisguiseListener implements Listener { Boolean[] options = disguiseClone.remove(p.getName()); DisguiseUtilities.createClonedDisguise(p, entity, options); - } - else if (disguiseEntity.containsKey(p.getName())) { + } else if (disguiseEntity.containsKey(p.getName())) { Disguise disguise = disguiseEntity.remove(p.getName()); if (disguise != null) { - if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() - && entity instanceof LivingEntity) { - p.sendMessage(ChatColor.RED - + "Can't disguise a living entity as a misc disguise. This has been disabled in the config!"); - } - else { + if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) { + p.sendMessage( + ChatColor.RED + "Can't disguise a living entity as a misc disguise. This has been disabled in the config!"); + } else { if (entity instanceof Player && DisguiseConfig.isNameOfPlayerShownAboveDisguise()) { if (disguise.getWatcher() instanceof LivingWatcher) { disguise.getWatcher().setCustomName(((Player) entity).getDisplayName()); @@ -365,33 +429,30 @@ public class DisguiseListener implements Listener { if (disguise instanceof PlayerDisguise) { disguiseName = "the player " + ((PlayerDisguise) disguise).getName(); - } - else { + } else { disguiseName += disguise.getType().toReadable(); } if (disguise.isDisguiseInUse()) { - p.sendMessage(ChatColor.RED + "Disguised " + (entity instanceof Player ? "" : "the ") + entityName - + " as " + disguiseName + "!"); - } - else { - p.sendMessage(ChatColor.RED + "Failed to disguise " + (entity instanceof Player ? "" : "the ") - + entityName + " as " + disguiseName + "!"); + p.sendMessage(ChatColor.RED + "Disguised " + (entity instanceof Player ? "" : + "the ") + entityName + " as " + disguiseName + "!"); + } else { + p.sendMessage(ChatColor.RED + "Failed to disguise " + (entity instanceof Player ? "" : + "the ") + entityName + " as " + disguiseName + "!"); } } - } - else { + } else { if (DisguiseAPI.isDisguised(entity)) { DisguiseAPI.undisguiseToAll(entity); - p.sendMessage(ChatColor.RED + "Undisguised " + (entity instanceof Player ? "" : "the ") + entityName); - } - else { - p.sendMessage(ChatColor.RED + (entity instanceof Player ? "" : "the") + entityName + " isn't disguised!"); + p.sendMessage( + ChatColor.RED + "Undisguised " + (entity instanceof Player ? "" : "the ") + entityName); + } else { + p.sendMessage( + ChatColor.RED + (entity instanceof Player ? "" : "the") + entityName + " isn't disguised!"); } } - } - else if (disguiseModify.containsKey(p.getName())) { + } else if (disguiseModify.containsKey(p.getName())) { String[] options = disguiseModify.remove(p.getName()); Disguise disguise = DisguiseAPI.getDisguise(p, entity); @@ -410,8 +471,8 @@ public class DisguiseListener implements Listener { } try { - DisguiseParser.callMethods(p, disguise, perms.get(new DisguisePerm(disguise.getType())), new ArrayList(), - options); + DisguiseParser.callMethods(p, disguise, perms.get(new DisguisePerm(disguise.getType())), + new ArrayList(), options); p.sendMessage(ChatColor.RED + "Modified the disguise!"); } catch (DisguiseParseException ex) { @@ -427,17 +488,17 @@ public class DisguiseListener implements Listener { @EventHandler public void onTarget(EntityTargetEvent event) { - if (DisguiseConfig.isMonstersIgnoreDisguises() && event.getTarget() != null && event.getTarget() instanceof Player - && DisguiseAPI.isDisguised(event.getTarget())) { + if (DisguiseConfig.isMonstersIgnoreDisguises() && event.getTarget() != null && event.getTarget() instanceof Player && DisguiseAPI.isDisguised( + event.getTarget())) { switch (event.getReason()) { - case TARGET_ATTACKED_ENTITY: - case TARGET_ATTACKED_OWNER: - case OWNER_ATTACKED_TARGET: - case CUSTOM: - break; - default: - event.setCancelled(true); - break; + case TARGET_ATTACKED_ENTITY: + case TARGET_ATTACKED_OWNER: + case OWNER_ATTACKED_TARGET: + case CUSTOM: + break; + default: + event.setCancelled(true); + break; } } } @@ -449,8 +510,9 @@ public class DisguiseListener implements Listener { Location from = event.getFrom(); if (DisguiseConfig.isBedPacketsEnabled()) { - if (DisguiseUtilities.getChunkCord(to.getBlockX()) != DisguiseUtilities.getChunkCord(from.getBlockX()) - || DisguiseUtilities.getChunkCord(to.getBlockZ()) != DisguiseUtilities.getChunkCord(from.getBlockZ())) { + if (DisguiseUtilities.getChunkCord(to.getBlockX()) != DisguiseUtilities.getChunkCord( + from.getBlockX()) || DisguiseUtilities.getChunkCord( + to.getBlockZ()) != DisguiseUtilities.getChunkCord(from.getBlockZ())) { chunkMove(player, null, from); Bukkit.getScheduler().runTask(plugin, new Runnable() { @@ -466,8 +528,7 @@ public class DisguiseListener implements Listener { return; } - if (DisguiseConfig.isUndisguiseOnWorldChange() && to.getWorld() != null && from.getWorld() != null - && to.getWorld() != from.getWorld()) { + if (DisguiseConfig.isUndisguiseOnWorldChange() && to.getWorld() != null && from.getWorld() != null && to.getWorld() != from.getWorld()) { for (Disguise disguise : DisguiseAPI.getDisguises(event.getPlayer())) { disguise.removeDisguise(); } @@ -476,7 +537,8 @@ public class DisguiseListener implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onVehicleEnter(VehicleEnterEvent event) { - if (event.getEntered() instanceof Player && DisguiseAPI.isDisguised((Player) event.getEntered(), event.getEntered())) { + if (event.getEntered() instanceof Player && DisguiseAPI.isDisguised((Player) event.getEntered(), + event.getEntered())) { DisguiseUtilities.removeSelfDisguise((Player) event.getEntered()); ((Player) event.getEntered()).updateInventory(); @@ -515,8 +577,7 @@ public class DisguiseListener implements Listener { for (Disguise disguise : DisguiseAPI.getDisguises(event.getPlayer())) { disguise.removeDisguise(); } - } - else { + } else { // Stupid hack to fix worldswitch invisibility bug final boolean viewSelfToggled = DisguiseAPI.isViewSelfToggled(event.getPlayer()); @@ -597,5 +658,4 @@ public class DisguiseListener implements Listener { disguiseRunnable.put(player, runnable); disguiseModify.put(player, args); } - } diff --git a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java index a935a067..2549d9c7 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -1,22 +1,5 @@ package me.libraryaddict.disguise.disguisetypes; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; - import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType.Play.Server; import com.comphenix.protocol.ProtocolLibrary; @@ -26,7 +9,6 @@ import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode; import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction; import com.comphenix.protocol.wrappers.PlayerInfoData; import com.comphenix.protocol.wrappers.WrappedChatComponent; - import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.LibsDisguises; @@ -39,9 +21,20 @@ import me.libraryaddict.disguise.events.UndisguiseEvent; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.PacketsManager; import me.libraryaddict.disguise.utilities.ReflectionManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; -public abstract class Disguise { - private static List viewSelf = new ArrayList<>(); +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +public abstract class Disguise implements Serializable { + private transient static List viewSelf = new ArrayList<>(); /** * Returns the list of people who have /disguiseViewSelf toggled on @@ -52,9 +45,9 @@ public abstract class Disguise { return viewSelf; } - private boolean disguiseInUse; + private transient boolean disguiseInUse; private DisguiseType disguiseType; - private Entity entity; + private transient Entity entity; private boolean hearSelfDisguise = DisguiseConfig.isSelfDisguisesSoundsReplaced(); private boolean hideArmorFromSelf = DisguiseConfig.isHidingArmorFromSelf(); private boolean hideHeldItemFromSelf = DisguiseConfig.isHidingHeldItemFromSelf(); @@ -65,8 +58,8 @@ public abstract class Disguise { private boolean playerHiddenFromTab = DisguiseConfig.isHideDisguisedPlayers(); private boolean replaceSounds = DisguiseConfig.isSoundEnabled(); private boolean showName; - private BukkitTask task; - private Runnable velocityRunnable; + private transient BukkitTask task; + private transient Runnable velocityRunnable; private boolean velocitySent = DisguiseConfig.isVelocitySent(); private boolean viewSelfDisguise = DisguiseConfig.isViewDisguises(); private FlagWatcher watcher; @@ -81,13 +74,12 @@ public abstract class Disguise { /** * Seems I do this method so I can make cleaner constructors on disguises.. * - * @param newType - * The disguise + * @param newType The disguise */ protected void createDisguise() { if (getType().getEntityType() == null) { - throw new RuntimeException("DisguiseType " + getType() - + " was used in a futile attempt to construct a disguise, but this Minecraft version does not have that entity"); + throw new RuntimeException( + "DisguiseType " + getType() + " was used in a futile attempt to construct a disguise, but this Minecraft version does not have that entity"); } // Get if they are a adult now.. @@ -106,14 +98,15 @@ public abstract class Disguise { catch (Exception e) { e.printStackTrace(); } + } else { + getWatcher().setDisguise((TargetedDisguise) this); } // Set the disguise if its a baby or not if (!isAdult) { if (getWatcher() instanceof AgeableWatcher) { ((AgeableWatcher) getWatcher()).setBaby(true); - } - else if (getWatcher() instanceof ZombieWatcher) { + } else if (getWatcher() instanceof ZombieWatcher) { ((ZombieWatcher) getWatcher()).setBaby(true); } } @@ -121,69 +114,69 @@ public abstract class Disguise { final boolean alwaysSendVelocity; switch (getType()) { - case EGG: - case ENDER_PEARL: - case BAT: - case EXPERIENCE_ORB: - case FIREBALL: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WITHER_SKULL: - case FIREWORK: - alwaysSendVelocity = true; - break; - default: - alwaysSendVelocity = false; - break; + case EGG: + case ENDER_PEARL: + case BAT: + case EXPERIENCE_ORB: + case FIREBALL: + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WITHER_SKULL: + case FIREWORK: + alwaysSendVelocity = true; + break; + default: + alwaysSendVelocity = false; + break; } double velocitySpeed = 0.0005; switch (getType()) { - case FIREWORK: - velocitySpeed = -0.040; - break; - case WITHER_SKULL: - velocitySpeed = 0.000001D; - break; - case ARROW: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case BOAT: - case ENDER_CRYSTAL: - case ENDER_DRAGON: - case GHAST: - case ITEM_FRAME: - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PAINTING: - case PLAYER: - case SQUID: - velocitySpeed = 0; - break; - case DROPPED_ITEM: - case PRIMED_TNT: - case WITHER: - case FALLING_BLOCK: - velocitySpeed = 0.04; - break; - case EXPERIENCE_ORB: - velocitySpeed = 0.0221; - break; - case SPIDER: - case BAT: - case CAVE_SPIDER: - velocitySpeed = 0.004; - break; - default: - break; + case FIREWORK: + velocitySpeed = -0.040; + break; + case WITHER_SKULL: + velocitySpeed = 0.000001D; + break; + case ARROW: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case BOAT: + case ENDER_CRYSTAL: + case ENDER_DRAGON: + case GHAST: + case ITEM_FRAME: + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PAINTING: + case PLAYER: + case SQUID: + velocitySpeed = 0; + break; + case DROPPED_ITEM: + case PRIMED_TNT: + case WITHER: + case FALLING_BLOCK: + velocitySpeed = 0.04; + break; + case EXPERIENCE_ORB: + velocitySpeed = 0.0221; + break; + case SPIDER: + case BAT: + case CAVE_SPIDER: + velocitySpeed = 0.004; + break; + default: + break; } final double vectorY = velocitySpeed; @@ -209,16 +202,14 @@ public abstract class Disguise { if (isRemoveDisguiseOnDeath()) { removeDisguise(); - } - else { + } else { entity = null; watcher = getWatcher().clone(disguise); task.cancel(); task = null; } } - } - else { + } else { deadTicks = 0; // If the disguise type is tnt, we need to resend the entity packet else it will turn invisible @@ -230,8 +221,7 @@ public abstract class Disguise { DisguiseUtilities.refreshTrackers(disguise); } - } - else if (getType() == DisguiseType.EVOKER_FANGS) { + } else if (getType() == DisguiseType.EVOKER_FANGS) { refreshDisguise++; if (refreshDisguise == 23) { @@ -239,14 +229,12 @@ public abstract class Disguise { DisguiseUtilities.refreshTrackers(disguise); } - } - else if (getType() == DisguiseType.ITEM_FRAME) { + } else if (getType() == DisguiseType.ITEM_FRAME) { Location loc = getEntity().getLocation(); int newFacing = (((int) loc.getYaw() + 720 + 45) / 90) % 4; - if (loc.getBlockX() != blockX || loc.getBlockY() != blockY || loc.getBlockZ() != blockZ - || newFacing != facing) { + if (loc.getBlockX() != blockX || loc.getBlockY() != blockY || loc.getBlockZ() != blockZ || newFacing != facing) { blockX = loc.getBlockX(); blockY = loc.getBlockY(); blockZ = loc.getBlockZ(); @@ -289,8 +277,9 @@ public abstract class Disguise { mods.write(4, PacketsManager.getYaw(getType(), getEntity().getType(), (byte) Math.floor(loc.getYaw() * 256.0F / 360.0F))); - mods.write(5, PacketsManager.getPitch(getType(), DisguiseType.getType(getEntity().getType()), - (byte) Math.floor(loc.getPitch() * 256.0F / 360.0F))); + mods.write(5, + PacketsManager.getPitch(getType(), DisguiseType.getType(getEntity().getType()), + (byte) Math.floor(loc.getPitch() * 256.0F / 360.0F))); if (isSelfDisguiseVisible() && getEntity() instanceof Player) { PacketContainer selfLookPacket = lookPacket.shallowClone(); @@ -322,19 +311,20 @@ public abstract class Disguise { } mods.write(0, DisguiseAPI.getSelfDisguiseId()); - } - else { + } else { mods.write(0, getEntity().getEntityId()); } - mods.write(2, (int) (8000D * (vectorY * ReflectionManager.getPing(player)) * 0.069D)); + mods.write(2, + (int) (8000D * (vectorY * ReflectionManager.getPing(player)) * 0.069D)); if (lookPacket != null && player != getEntity()) { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, lookPacket, false); + ProtocolLibrary.getProtocolManager().sendServerPacket(player, lookPacket, + false); } - ProtocolLibrary.getProtocolManager().sendServerPacket(player, velocityPacket.shallowClone(), - false); + ProtocolLibrary.getProtocolManager().sendServerPacket(player, + velocityPacket.shallowClone(), false); } } catch (Exception e) { @@ -352,15 +342,14 @@ public abstract class Disguise { for (Player player : DisguiseUtilities.getPerverts(disguise)) { if (getEntity() != player) { ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false); - } - else if (isSelfDisguiseVisible()) { + } else if (isSelfDisguiseVisible()) { PacketContainer selfPacket = packet.shallowClone(); selfPacket.getModifier().write(0, DisguiseAPI.getSelfDisguiseId()); try { - ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfPacket, - false); + ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), + selfPacket, false); } catch (InvocationTargetException e) { e.printStackTrace(); @@ -461,9 +450,9 @@ public abstract class Disguise { * Internal use */ public boolean isRemoveDisguiseOnDeath() { - return getEntity() == null || (getEntity() instanceof Player - ? (!((Player) getEntity()).isOnline() ? !isKeepDisguiseOnPlayerLogout() : !isKeepDisguiseOnPlayerDeath()) - : (!isKeepDisguiseOnEntityDespawn() || getEntity().isDead())); + return getEntity() == null || (getEntity() instanceof Player ? + (!((Player) getEntity()).isOnline() ? !isKeepDisguiseOnPlayerLogout() : + !isKeepDisguiseOnPlayerDeath()) : (!isKeepDisguiseOnEntityDespawn() || getEntity().isDead())); } public boolean isSelfDisguiseSoundsReplaced() { @@ -525,8 +514,8 @@ public abstract class Disguise { if (disguise.isDisplayedInTab()) { PacketContainer deleteTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); deleteTab.getPlayerInfoAction().write(0, PlayerInfoAction.REMOVE_PLAYER); - deleteTab.getPlayerInfoDataLists().write(0, - Arrays.asList(new PlayerInfoData(disguise.getGameProfile(), 0, NativeGameMode.SURVIVAL, + deleteTab.getPlayerInfoDataLists().write(0, Arrays.asList( + new PlayerInfoData(disguise.getGameProfile(), 0, NativeGameMode.SURVIVAL, WrappedChatComponent.fromText(disguise.getName())))); try { @@ -546,8 +535,8 @@ public abstract class Disguise { if (isHidePlayer() && getEntity() instanceof Player) { PacketContainer deleteTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); deleteTab.getPlayerInfoAction().write(0, PlayerInfoAction.ADD_PLAYER); - deleteTab.getPlayerInfoDataLists().write(0, - Arrays.asList(new PlayerInfoData(ReflectionManager.getGameProfile((Player) getEntity()), 0, + deleteTab.getPlayerInfoDataLists().write(0, Arrays.asList( + new PlayerInfoData(ReflectionManager.getGameProfile((Player) getEntity()), 0, NativeGameMode.SURVIVAL, WrappedChatComponent.fromText(((Player) getEntity()).getDisplayName())))); @@ -574,13 +563,11 @@ public abstract class Disguise { // Better refresh the entity to undisguise it if (getEntity().isValid()) { DisguiseUtilities.refreshTrackers((TargetedDisguise) this); - } - else { + } else { DisguiseUtilities.destroyEntity((TargetedDisguise) this); } } - } - else { + } else { // Loop through the disguises because it could be used with a unknown entity id. HashMap> future = DisguiseUtilities.getFutureDisguises(); @@ -595,22 +582,6 @@ public abstract class Disguise { } } - if (isPlayerDisguise()) { - String name = ((PlayerDisguise) this).getName(); - - if (!DisguiseUtilities.getAddedByPlugins().contains(name.toLowerCase())) { - for (HashSet disguise : disguises.values()) { - for (Disguise d : disguise) { - if (d.isPlayerDisguise() && ((PlayerDisguise) d).getName().equals(name)) { - return true; - } - } - } - - DisguiseUtilities.getGameProfiles().remove(name.toLowerCase()); - } - } - return true; } } @@ -640,7 +611,9 @@ public abstract class Disguise { this.entity = entity; - setupWatcher(); + if (entity != null) { + setupWatcher(); + } return this; } @@ -731,7 +704,8 @@ public abstract class Disguise { */ private void setupWatcher() { ArrayList disguiseFlags = MetaIndex.getFlags(getType().getWatcherClass()); - ArrayList entityFlags = MetaIndex.getFlags(DisguiseType.getType(getEntity().getType()).getWatcherClass()); + ArrayList entityFlags = MetaIndex.getFlags( + DisguiseType.getType(getEntity().getType()).getWatcherClass()); for (MetaIndex flag : entityFlags) { if (disguiseFlags.contains(flag)) @@ -770,8 +744,7 @@ public abstract class Disguise { if (DisguiseAPI.getDisguise((Player) getEntity(), getEntity()) == this) { if (isSelfDisguiseVisible()) { DisguiseUtilities.setupFakeDisguise(this); - } - else { + } else { DisguiseUtilities.removeSelfDisguise((Player) getEntity()); } } @@ -783,8 +756,8 @@ public abstract class Disguise { public Disguise setWatcher(FlagWatcher newWatcher) { if (!getType().getWatcherClass().isInstance(newWatcher)) { - throw new IllegalArgumentException(newWatcher.getClass().getSimpleName() + " is not a instance of " - + getType().getWatcherClass().getSimpleName() + " for DisguiseType " + getType().name()); + throw new IllegalArgumentException( + newWatcher.getClass().getSimpleName() + " is not a instance of " + getType().getWatcherClass().getSimpleName() + " for DisguiseType " + getType().name()); } watcher = newWatcher; @@ -823,8 +796,9 @@ public abstract class Disguise { if (disguise.isDisplayedInTab()) { PacketContainer addTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); addTab.getPlayerInfoAction().write(0, PlayerInfoAction.ADD_PLAYER); - addTab.getPlayerInfoDataLists().write(0, Arrays.asList(new PlayerInfoData(disguise.getGameProfile(), 0, - NativeGameMode.SURVIVAL, WrappedChatComponent.fromText(disguise.getName())))); + addTab.getPlayerInfoDataLists().write(0, Arrays.asList( + new PlayerInfoData(disguise.getGameProfile(), 0, NativeGameMode.SURVIVAL, + WrappedChatComponent.fromText(disguise.getName())))); try { for (Player player : Bukkit.getOnlinePlayers()) { @@ -861,8 +835,8 @@ public abstract class Disguise { if (isHidePlayer() && getEntity() instanceof Player) { PacketContainer addTab = new PacketContainer(PacketType.Play.Server.PLAYER_INFO); addTab.getPlayerInfoAction().write(0, PlayerInfoAction.REMOVE_PLAYER); - addTab.getPlayerInfoDataLists().write(0, - Arrays.asList(new PlayerInfoData(ReflectionManager.getGameProfile((Player) getEntity()), 0, + addTab.getPlayerInfoDataLists().write(0, Arrays.asList( + new PlayerInfoData(ReflectionManager.getGameProfile((Player) getEntity()), 0, NativeGameMode.SURVIVAL, WrappedChatComponent.fromText("")))); try { diff --git a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index cbead397..cf0cbe11 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -1,12 +1,17 @@ package me.libraryaddict.disguise.disguisetypes; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - +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.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedSignedProperty; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.utilities.DisguiseUtilities; +import me.libraryaddict.disguise.utilities.ReflectionManager; import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -14,30 +19,37 @@ import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -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.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedWatchableObject; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.*; -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.DisguiseConfig; -import me.libraryaddict.disguise.utilities.DisguiseUtilities; -import me.libraryaddict.disguise.utilities.ReflectionManager; - -public class FlagWatcher { +public class FlagWatcher implements Serializable { private boolean addEntityAnimations = DisguiseConfig.isEntityAnimationsAdded(); /** * These are the entity values I need to add else it could crash them.. */ private HashMap backupEntityValues = new HashMap<>(); - private TargetedDisguise disguise; + private transient TargetedDisguise disguise; private HashMap entityValues = new HashMap<>(); private LibsEquipment equipment; private boolean hasDied; private boolean[] modifiedEntityAnimations = new boolean[8]; - private List watchableObjects; + private transient List watchableObjects; + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.writeBoolean(isEntityAnimationsAdded()); + out. + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + profile = new WrappedGameProfile((UUID) in.readObject(), in.readUTF()); + + for (int i = in.readByte(); i > 0; i--) { + profile.getProperties().put(in.readUTF(), + new WrappedSignedProperty(in.readUTF(), in.readUTF(), in.readUTF())); + } + } public FlagWatcher(Disguise disguise) { this.disguise = (TargetedDisguise) disguise; @@ -97,8 +109,7 @@ public class FlagWatcher { } value = entityValues.get(id); - } - else if (backupEntityValues.containsKey(id)) { + } else if (backupEntityValues.containsKey(id)) { if (backupEntityValues.get(id) == null) { continue; } @@ -121,8 +132,7 @@ public class FlagWatcher { if (!isDirty) { watch.setDirtyState(false); } - } - else { + } else { boolean isDirty = watch.getDirtyState(); watch = ReflectionManager.createWatchable(id, watch.getValue()); @@ -160,8 +170,7 @@ public class FlagWatcher { } } // Here we check for if there is a health packet that says they died. - if (getDisguise().isSelfDisguiseVisible() && getDisguise().getEntity() != null - && getDisguise().getEntity() instanceof Player) { + if (getDisguise().isSelfDisguiseVisible() && getDisguise().getEntity() != null && getDisguise().getEntity() instanceof Player) { for (WrappedWatchableObject watch : newList) { // Its a health packet if (watch.getIndex() == 6) { @@ -173,19 +182,20 @@ public class FlagWatcher { if (newHealth > 0 && hasDied) { hasDied = false; - Bukkit.getScheduler().scheduleSyncDelayedTask(DisguiseUtilities.getPlugin(), new Runnable() { - @Override - public void run() { - try { - DisguiseUtilities.sendSelfDisguise((Player) getDisguise().getEntity(), disguise); - } - catch (Exception ex) { - ex.printStackTrace(); - } - } - }, 2); - } - else if (newHealth <= 0 && !hasDied) { + Bukkit.getScheduler().scheduleSyncDelayedTask(DisguiseUtilities.getPlugin(), + new Runnable() { + @Override + public void run() { + try { + DisguiseUtilities.sendSelfDisguise((Player) getDisguise().getEntity(), + disguise); + } + catch (Exception ex) { + ex.printStackTrace(); + } + } + }, 2); + } else if (newHealth <= 0 && !hasDied) { hasDied = true; } } @@ -300,11 +310,9 @@ public class FlagWatcher { if (entityValues.containsKey(i) && entityValues.get(i) != null) { watchable = ReflectionManager.createWatchable(i, entityValues.get(i)); - } - else if (backupEntityValues.containsKey(i) && backupEntityValues.get(i) != null) { + } else if (backupEntityValues.containsKey(i) && backupEntityValues.get(i) != null) { watchable = ReflectionManager.createWatchable(i, backupEntityValues.get(i)); - } - else { + } else { continue; } @@ -330,7 +338,8 @@ public class FlagWatcher { Object value = entityValues.get(data.getIndex()); if (isEntityAnimationsAdded() && DisguiseConfig.isMetadataPacketsEnabled() && data == MetaIndex.ENTITY_META) { - value = addEntityAnimations((byte) value, WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); + value = addEntityAnimations((byte) value, + WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); } WrappedWatchableObject watch = ReflectionManager.createWatchable(data.getIndex(), value); @@ -356,8 +365,7 @@ public class FlagWatcher { temp.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); ProtocolLibrary.getProtocolManager().sendServerPacket(player, temp); - } - else { + } else { ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); } } @@ -407,8 +415,7 @@ public class FlagWatcher { if (flag) { setData(MetaIndex.ENTITY_META, (byte) (b0 | 1 << byteValue)); - } - else { + } else { setData(MetaIndex.ENTITY_META, (byte) (b0 & ~(1 << byteValue))); } } @@ -453,34 +460,34 @@ public class FlagWatcher { } protected void sendItemStack(EquipmentSlot slot, ItemStack itemStack) { - if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this - || getDisguise().getEntity() == null) + if (!DisguiseAPI.isDisguiseInUse( + getDisguise()) || getDisguise().getWatcher() != this || getDisguise().getEntity() == null) return; if (itemStack == null && getDisguise().getEntity() instanceof LivingEntity) { EntityEquipment equip = ((LivingEntity) getDisguise().getEntity()).getEquipment(); switch (slot) { - case HAND: - itemStack = equip.getItemInMainHand(); - break; - case OFF_HAND: - itemStack = equip.getItemInOffHand(); - break; - case HEAD: - itemStack = equip.getHelmet(); - break; - case CHEST: - itemStack = equip.getChestplate(); - break; - case LEGS: - itemStack = equip.getLeggings(); - break; - case FEET: - itemStack = equip.getBoots(); - break; - default: - break; + case HAND: + itemStack = equip.getItemInMainHand(); + break; + case OFF_HAND: + itemStack = equip.getItemInOffHand(); + break; + case HEAD: + itemStack = equip.getHelmet(); + break; + case CHEST: + itemStack = equip.getChestplate(); + break; + case LEGS: + itemStack = equip.getLeggings(); + break; + case FEET: + itemStack = equip.getBoots(); + break; + default: + break; } } @@ -536,4 +543,7 @@ public class FlagWatcher { } } + protected void setDisguise(TargetedDisguise disguise) { + this.disguise = disguise; + } } diff --git a/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java b/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java index 262c6864..8a97c0d9 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java +++ b/src/me/libraryaddict/disguise/disguisetypes/LibsEquipment.java @@ -5,7 +5,9 @@ import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -public class LibsEquipment implements EntityEquipment { +import java.io.Serializable; + +public class LibsEquipment implements EntityEquipment, Serializable { private ItemStack[] equipment = new ItemStack[EquipmentSlot.values().length]; private FlagWatcher flagWatcher; diff --git a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 257e86c7..b63d7171 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -1,14 +1,5 @@ package me.libraryaddict.disguise.disguisetypes; -import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; -import java.util.UUID; - -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; - import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketContainer; @@ -17,16 +8,24 @@ import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction; import com.comphenix.protocol.wrappers.PlayerInfoData; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedGameProfile; - import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.LibsProfileLookup; +import me.libraryaddict.disguise.utilities.WrappedProfile; import me.libraryaddict.disguise.utilities.ReflectionManager; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.UUID; public class PlayerDisguise extends TargetedDisguise { - private LibsProfileLookup currentLookup; - private WrappedGameProfile gameProfile; + private transient LibsProfileLookup currentLookup; + private WrappedProfile gameProfile; private String playerName; private String skinToUse; private UUID uuid = UUID.randomUUID(); @@ -66,7 +65,8 @@ public class PlayerDisguise extends TargetedDisguise { setName(gameProfile.getName()); - this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(uuid, gameProfile.getName(), gameProfile); + this.gameProfile = new WrappedProfile( + ReflectionManager.getGameProfileWithThisSkin(uuid, gameProfile.getName(), gameProfile)); createDisguise(); } @@ -76,7 +76,7 @@ public class PlayerDisguise extends TargetedDisguise { setName(gameProfile.getName()); - this.gameProfile = ReflectionManager.getGameProfile(uuid, gameProfile.getName()); + this.gameProfile = new WrappedProfile(ReflectionManager.getGameProfile(uuid, gameProfile.getName())); setSkin(skinToUse); @@ -101,8 +101,9 @@ public class PlayerDisguise extends TargetedDisguise { if (currentLookup == null && gameProfile != null) { disguise.skinToUse = getSkin(); - disguise.gameProfile = ReflectionManager.getGameProfileWithThisSkin(disguise.uuid, - getGameProfile().getName(), getGameProfile()); + disguise.gameProfile = new WrappedProfile( + ReflectionManager.getGameProfileWithThisSkin(disguise.uuid, getGameProfile().getName(), + getGameProfile())); } else { disguise.setSkin(getSkin()); } @@ -127,14 +128,14 @@ public class PlayerDisguise extends TargetedDisguise { public WrappedGameProfile getGameProfile() { if (gameProfile == null) { if (getSkin() != null) { - gameProfile = ReflectionManager.getGameProfile(uuid, getName()); + gameProfile = new WrappedProfile(ReflectionManager.getGameProfile(uuid, getName())); } else { - gameProfile = ReflectionManager.getGameProfileWithThisSkin(uuid, getName(), - DisguiseUtilities.getProfileFromMojang(this)); + gameProfile = new WrappedProfile(ReflectionManager.getGameProfileWithThisSkin(uuid, getName(), + DisguiseUtilities.getProfileFromMojang(this))); } } - return gameProfile; + return gameProfile.getProfile(); } public String getName() { @@ -184,7 +185,8 @@ public class PlayerDisguise extends TargetedDisguise { } public void setGameProfile(WrappedGameProfile gameProfile) { - this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(uuid, gameProfile.getName(), gameProfile); + this.gameProfile = new WrappedProfile( + ReflectionManager.getGameProfileWithThisSkin(uuid, gameProfile.getName(), gameProfile)); } @Override @@ -304,7 +306,8 @@ public class PlayerDisguise extends TargetedDisguise { currentLookup = null; this.skinToUse = gameProfile.getName(); - this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(uuid, getName(), gameProfile); + this.gameProfile = new WrappedProfile( + ReflectionManager.getGameProfileWithThisSkin(uuid, getName(), gameProfile)); if (DisguiseUtilities.isDisguiseInUse(this)) { if (isDisplayedInTab()) { diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index c9e2b245..1cf272eb 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -1,27 +1,30 @@ package me.libraryaddict.disguise.utilities; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.regex.Pattern; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.DisguiseConfig.DisguisePushing; +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; +import me.libraryaddict.disguise.disguisetypes.TargetedDisguise; +import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; +import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; +import me.libraryaddict.disguise.utilities.PacketsManager.LibsPackets; +import org.bukkit.*; import org.bukkit.block.BlockFace; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Ageable; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -36,37 +39,16 @@ import org.bukkit.scoreboard.Team.Option; import org.bukkit.scoreboard.Team.OptionStatus; import org.bukkit.util.Vector; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.PacketType.Play.Server; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedGameProfile; - -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.DisguiseConfig; -import me.libraryaddict.disguise.DisguiseConfig.DisguisePushing; -import me.libraryaddict.disguise.LibsDisguises; -import me.libraryaddict.disguise.disguisetypes.Disguise; -import me.libraryaddict.disguise.disguisetypes.DisguiseType; -import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; -import me.libraryaddict.disguise.disguisetypes.TargetedDisguise; -import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; -import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; -import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; -import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; -import me.libraryaddict.disguise.utilities.PacketsManager.LibsPackets; +import java.io.*; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.regex.Pattern; public class DisguiseUtilities { public static final Random random = new Random(); - /** - * This is a list of names which was called by other plugins. As such, don't remove from the gameProfiles as its the duty of - * the plugin to do that. - */ - private static HashSet addedByPlugins = new HashSet<>(); private static LinkedHashMap clonedDisguises = new LinkedHashMap<>(); /** * A hashmap of the uuid's of entitys, alive and dead. And their disguises in use @@ -77,16 +59,16 @@ public class DisguiseUtilities { * a max of a second. */ private static HashMap> futureDisguises = new HashMap<>(); - /** - * A hashmap storing the uuid and skin of a playername - */ - private static HashMap gameProfiles = new HashMap<>(); + private static HashSet savedDisguiseList = new HashSet<>(); + private static HashSet cachedNames = new HashSet<>(); private static LibsDisguises libsDisguises; private static HashMap> runnables = new HashMap<>(); private static HashSet selfDisguised = new HashSet<>(); private static Thread mainThread; private static PacketContainer spawnChunk; - private static HashMap preDisguiseTeam = new HashMap(); + private static HashMap preDisguiseTeam = new HashMap<>(); + private static File profileCache = new File("plugins/LibsDisguises/GameProfiles"), savedDisguises = new File( + "plugins/LibsDisguises/SavedDisguises"); static { try { @@ -142,6 +124,10 @@ public class DisguiseUtilities { } } + public static boolean hasCacheEntry(String playername) { + return cachedNames.contains(playername.toLowerCase()); + } + public static void createClonedDisguise(Player player, Entity toClone, Boolean[] options) { Disguise disguise = DisguiseAPI.getDisguise(player, toClone); @@ -177,10 +163,103 @@ public class DisguiseUtilities { player.sendMessage(ChatColor.RED + "Example usage: /disguise " + reference); } else { player.sendMessage( - ChatColor.RED + "Failed to store the reference, too many cloned disguises. Please set this in the config"); + ChatColor.RED + "Failed to store the reference, too many cloned disguises. Please raise the " + + "maximum cloned disguises, or lower the time they last"); } } + private static void saveDisguiseToFile + + public static void saveDisguises(UUID owningEntity, Disguise[] disguise) { + try { + File disguiseFile = new File(savedDisguises, owningEntity.toString()); + + if (disguise == null || disguise.length == 0) { + if (savedDisguiseList.contains(owningEntity)) { + disguiseFile.delete(); + } else { + return; + } + } else { + Disguise[] disguises = new Disguise[disguise.length]; + + for (int i = 0; i < disguise.length; i++) { + Disguise dis = disguise[i].clone(); + dis.setEntity(null); + + disguises[i] = dis; + } + + FileOutputStream files = new FileOutputStream(disguiseFile); + ObjectOutputStream obj = new ObjectOutputStream(files); + + obj.writeObject(disguises); + + savedDisguiseList.add(owningEntity); + + obj.close(); + files.close(); + } + + savedDisguises.save(new File(libsDisguises.getDataFolder(), "saveddisguises.yml")); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + public static Disguise[] getSavedDisguises(UUID entityUUID) { + return getSavedDisguises(entityUUID, false); + } + + public static Disguise[] getSavedDisguises(UUID entityUUID, boolean remove) { + if (isSavedDisguise(entityUUID)) + return new Disguise[0]; + + String cached = savedDisguises.getString(entityUUID.toString()); + + if (cached == null) { + cachedNames.remove(entityUUID.toString()); + return new Disguise[0]; + } + + try { + ObjectInputStream outputStream = new ObjectInputStream(new ByteArrayInputStream(cached.getBytes())); + + Disguise[] toReturn = (Disguise[]) outputStream.readObject(); + + if (remove) { + removeSavedDisguise(entityUUID); + } + + return toReturn; + } + catch (Exception e) { + System.out.println("Error while loading Entity Disguises, malformed config?"); + e.printStackTrace(); + } + + return new Disguise[0]; + } + + public static void removeSavedDisguise(UUID entityUUID) { + if (!savedDisguiseList.remove(entityUUID)) + return; + + savedDisguises.set(entityUUID.toString(), null); + + try { + savedDisguises.save(new File(libsDisguises.getDataFolder(), "saveddisguises.yml")); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + public static boolean isSavedDisguise(UUID entityUUID) { + return savedDisguiseList.contains(entityUUID); + } + public static boolean addClonedDisguise(String key, Disguise disguise) { if (DisguiseConfig.getMaxClonedDisguises() > 0) { if (clonedDisguises.containsKey(key)) { @@ -250,8 +329,21 @@ public class DisguiseUtilities { } public static void addGameProfile(String string, WrappedGameProfile gameProfile) { - getGameProfiles().put(string, gameProfile); - getAddedByPlugins().add(string.toLowerCase()); + try { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ObjectOutputStream obj = new ObjectOutputStream(bytes); + obj.writeObject(new WrappedProfile(gameProfile)); + + gameProfileCache.set(string.toLowerCase(), new String(bytes.toByteArray())); + cachedNames.add(string.toLowerCase()); + + if (DisguiseConfig.isSaveCache()) { + gameProfileCache.save(new File(libsDisguises.getDataFolder(), "cache.yml")); + } + } + catch (Exception ex) { + ex.printStackTrace(); + } } /** @@ -388,10 +480,6 @@ public class DisguiseUtilities { } } - public static HashSet getAddedByPlugins() { - return addedByPlugins; - } - public static int getChunkCord(int blockCord) { int cord = (int) Math.floor(blockCord / 16D) - 17; @@ -511,11 +599,26 @@ public class DisguiseUtilities { } public static WrappedGameProfile getGameProfile(String playerName) { - return gameProfiles.get(playerName.toLowerCase()); - } + if (!cachedNames.contains(playerName.toLowerCase())) + return null; - public static HashMap getGameProfiles() { - return gameProfiles; + String cached = gameProfileCache.getString(playerName.toLowerCase()); + + if (cached == null) { + cachedNames.remove(playerName.toLowerCase()); + return null; + } + + try { + ObjectInputStream outputStream = new ObjectInputStream(new ByteArrayInputStream(cached.getBytes())); + + return ((WrappedProfile) outputStream.readObject()).getProfile(); + } + catch (Exception e) { + e.printStackTrace(); + } + + return null; } public static TargetedDisguise getMainDisguise(UUID entityId) { @@ -577,18 +680,13 @@ public class DisguiseUtilities { public static WrappedGameProfile getProfileFromMojang(final PlayerDisguise disguise) { final String nameToFetch = disguise.getSkin() != null ? disguise.getSkin() : disguise.getName(); - final boolean remove = getAddedByPlugins().contains(nameToFetch.toLowerCase()); - return getProfileFromMojang(nameToFetch, new LibsProfileLookup() { @Override public void onLookup(WrappedGameProfile gameProfile) { - if (remove) { - getAddedByPlugins().remove(nameToFetch.toLowerCase()); - } - if (DisguiseAPI.isDisguiseInUse(disguise) && (!gameProfile.getName().equals( - disguise.getSkin() != null ? disguise.getSkin() : disguise.getName()) || !gameProfile.getProperties().isEmpty())) { + disguise.getSkin() != null ? disguise.getSkin() : + disguise.getName()) || !gameProfile.getProperties().isEmpty())) { disguise.setGameProfile(gameProfile); DisguiseUtilities.refreshTrackers(disguise); @@ -634,37 +732,22 @@ public class DisguiseUtilities { boolean contactMojang) { final String playerName = origName.toLowerCase(); - if (gameProfiles.containsKey(playerName)) { - if (gameProfiles.get(playerName) != null) { - return gameProfiles.get(playerName); - } + if (cachedNames.contains(playerName)) { + return getGameProfile(playerName); } else if (Pattern.matches("([A-Za-z0-9_]){1,16}", origName)) { - getAddedByPlugins().add(playerName); - - Player player = Bukkit.getPlayerExact(playerName); + final Player player = Bukkit.getPlayerExact(playerName); if (player != null) { WrappedGameProfile gameProfile = ReflectionManager.getGameProfile(player); if (!gameProfile.getProperties().isEmpty()) { - gameProfiles.put(playerName, gameProfile); + addGameProfile(playerName, gameProfile); return gameProfile; } } - if (runnable != null && (contactMojang || gameProfiles.containsKey(playerName))) { - if (!runnables.containsKey(playerName)) { - runnables.put(playerName, new ArrayList<>()); - } - - runnables.get(playerName).add(runnable); - } - - if (contactMojang) { - // Add null so that if this is called again. I already know I'm doing something about it - gameProfiles.put(playerName, null); - + if (contactMojang && !runnables.containsKey(playerName)) { Bukkit.getScheduler().runTaskAsynchronously(libsDisguises, new Runnable() { @Override public void run() { @@ -678,9 +761,7 @@ public class DisguiseUtilities { return; } - if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { - gameProfiles.put(playerName, gameProfile); - } + addGameProfile(playerName, gameProfile); if (runnables.containsKey(playerName)) { for (Object obj : runnables.remove(playerName)) { @@ -695,10 +776,7 @@ public class DisguiseUtilities { }); } catch (Exception e) { - if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { - gameProfiles.remove(playerName); - getAddedByPlugins().remove(playerName); - } + runnables.remove(playerName); System.out.print( "[LibsDisguises] Error when fetching " + playerName + "'s uuid from mojang: " + e.getMessage()); @@ -706,6 +784,14 @@ public class DisguiseUtilities { } }); + if (runnable != null && contactMojang) { + if (!runnables.containsKey(playerName)) { + runnables.put(playerName, new ArrayList<>()); + } + + runnables.get(playerName).add(runnable); + } + return null; } } @@ -740,6 +826,16 @@ public class DisguiseUtilities { public static void init(LibsDisguises disguises) { libsDisguises = disguises; + + gameProfileCache = YamlConfiguration.loadConfiguration(new File(disguises.getDataFolder(), "cache.yml")); + + cachedNames.addAll(gameProfileCache.getKeys(false)); + + savedDisguises = YamlConfiguration.loadConfiguration(new File(disguises.getDataFolder(), "saveddisguises.yml")); + + for (String key : savedDisguises.getKeys(false)) { + savedDisguiseList.add(UUID.fromString(key)); + } } public static boolean isDisguiseInUse(Disguise disguise) { @@ -809,7 +905,7 @@ public class DisguiseUtilities { for (final Object p : trackedPlayers) { Player pl = (Player) ReflectionManager.getBukkitEntity(p); - if (!player.equalsIgnoreCase((pl).getName())) + if (pl == null || !player.equalsIgnoreCase((pl).getName())) continue; clear.invoke(entityTrackerEntry, p); @@ -991,7 +1087,17 @@ public class DisguiseUtilities { } public static void removeGameProfile(String string) { - gameProfiles.remove(string.toLowerCase()); + cachedNames.remove(string.toLowerCase()); + gameProfileCache.set(string.toLowerCase(), null); + + if (DisguiseConfig.isSaveCache()) { + try { + gameProfileCache.save(new File(libsDisguises.getDataFolder(), "cache.yml")); + } + catch (IOException e) { + e.printStackTrace(); + } + } } public static void removeSelfDisguise(Player player) { diff --git a/src/me/libraryaddict/disguise/utilities/PacketsManager.java b/src/me/libraryaddict/disguise/utilities/PacketsManager.java index 53e7161e..d8ea4456 100644 --- a/src/me/libraryaddict/disguise/utilities/PacketsManager.java +++ b/src/me/libraryaddict/disguise/utilities/PacketsManager.java @@ -297,15 +297,6 @@ public class PacketsManager { String name = playerDisguise.getName(); int entityId = disguisedEntity.getEntityId(); - boolean removeName = false; - - if (!DisguiseUtilities.hasGameProfile(name)) { - removeName = !DisguiseUtilities.getAddedByPlugins().contains(name); - } - - if (removeName) { - DisguiseUtilities.getAddedByPlugins().remove(name); - } // Send player info along with the disguise PacketContainer sendTab = new PacketContainer(Server.PLAYER_INFO); diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index 83d3ed11..c3d13b86 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -627,10 +627,6 @@ public class ReflectionManager { return null; } - public static void removePlayer(Player player) { - // Some future remove code if needed - } - public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) { try { Location loc = entity.getLocation(); @@ -888,15 +884,18 @@ public class ReflectionManager { if (value instanceof Optional) { Optional opt = (Optional) value; - serializer = Registry.get((opt.isPresent() ? getNmsClass("IBlockData").isInstance(opt.get()) ? getNmsClass( - "IBlockData") : opt.get().getClass() : UUID.class), true); + serializer = Registry.get((opt.isPresent() ? + getNmsClass("IBlockData").isInstance(opt.get()) ? getNmsClass("IBlockData") : opt.get().getClass() : + UUID.class), true); } else { serializer = Registry.get(value.getClass()); } if (serializer == null) { - throw new IllegalArgumentException( - "Unable to find Serializer for " + value + (value instanceof Optional && ((Optional) value).isPresent() ? " (" + ((Optional) value).get().getClass().getName() + ")" : "") + "! Are you running the latest version of ProtocolLib?"); + throw new IllegalArgumentException("Unable to find Serializer for " + value + ( + value instanceof Optional && ((Optional) value).isPresent() ? + " (" + ((Optional) value).get().getClass().getName() + ")" : + "") + "! Are you running the latest version of ProtocolLib?"); } WrappedDataWatcherObject watcherObject = new WrappedDataWatcherObject(id, serializer); diff --git a/src/me/libraryaddict/disguise/utilities/WrappedProfile.java b/src/me/libraryaddict/disguise/utilities/WrappedProfile.java new file mode 100644 index 00000000..24a158d5 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/WrappedProfile.java @@ -0,0 +1,48 @@ +package me.libraryaddict.disguise.utilities; + +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedSignedProperty; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Map; +import java.util.UUID; + +/** + * Created by libraryaddict on 15/05/2017. + */ +public class WrappedProfile implements Serializable { + private WrappedGameProfile profile; + + public WrappedProfile(WrappedGameProfile profile) { + this.profile = profile; + } + + public WrappedGameProfile getProfile() { + return profile; + } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.writeObject(profile.getUUID()); + out.writeObject(profile.getName()); + out.writeByte(profile.getProperties().size()); + + for (Map.Entry entry : profile.getProperties().entries()) { + WrappedSignedProperty property = entry.getValue(); + + out.writeUTF(entry.getKey()); + out.writeUTF(property.getName()); + out.writeUTF(property.getSignature()); + out.writeUTF(property.getValue()); + } + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + profile = new WrappedGameProfile((UUID) in.readObject(), in.readUTF()); + + for (int i = in.readByte(); i > 0; i--) { + profile.getProperties().put(in.readUTF(), + new WrappedSignedProperty(in.readUTF(), in.readUTF(), in.readUTF())); + } + } +}