From 66ab7ac3efdc67cb5e372b9635bd7469756d0ffa Mon Sep 17 00:00:00 2001 From: NavidK0 Date: Tue, 29 Dec 2015 15:44:19 -0500 Subject: [PATCH] Fixed ConcurrentModificationException on PaperSpigot/SportsBukkit. --- .../disguise/utilities/DisguiseUtilities.java | 46 ++++++++----------- src/main/resources/plugin.yml | 2 +- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 6ce37ff9..b1096fd1 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -255,9 +255,7 @@ public class DisguiseUtilities { entityTrackerEntry); Object trackedPlayersObj = ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); // If the tracker exists. Remove himself from his tracker - if (isHashSet(trackedPlayersObj)) { - trackedPlayers = (Set) ((HashSet)trackedPlayers).clone(); - } + trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); destroyPacket.getIntegerArrays().write(0, new int[]{disguise.getEntity().getEntityId()}); for (Object p : trackedPlayers) { @@ -443,8 +441,8 @@ public class DisguiseUtilities { try { Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity()); if (entityTrackerEntry != null) { - Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get( - entityTrackerEntry); + Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); + trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException for (Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (((TargetedDisguise) disguise).canSee(player)) { @@ -479,6 +477,19 @@ public class DisguiseUtilities { }); } + /** + * Pass in a set, check if it's a hashset. + * If it's not, return false. + * If you pass in something else, you failed. + * @param obj + * @return + */ + private static boolean isHashSet(Object obj) { + if (obj instanceof HashSet) return true; //It's Spigot/Bukkit + if (obj instanceof Set) return false; //It's PaperSpigot/SportsBukkit + throw new IllegalArgumentException("Object passed was not either a hashset or set!"); + } + /** * Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup using schedulers. The runnable is run once the GameProfile has been successfully dealt with */ @@ -648,9 +659,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - if (isHashSet(trackedPlayers)) { - trackedPlayers = (Set) ((HashSet)trackedPlayers).clone(); - } + trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player pl = (Player) ReflectionManager.getBukkitEntity(p); if (player.equalsIgnoreCase((pl).getName())) { @@ -692,9 +701,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - if (isHashSet(trackedPlayers)) { - trackedPlayers = (Set) ((HashSet)trackedPlayers).clone(); - } + trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (player != entity) { @@ -748,9 +755,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - if (isHashSet(trackedPlayers)) { - trackedPlayers = (Set) ((HashSet)trackedPlayers).clone(); - } + trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (disguise.getEntity() != player && disguise.canSee(player)) { @@ -775,19 +780,6 @@ public class DisguiseUtilities { } } - /** - * Pass in a set, check if it's a hashset. - * If it's not, return false. - * If you pass in something else, you failed. - * @param obj - * @return - */ - private static boolean isHashSet(Object obj) { - if (obj instanceof HashSet) return true; //It's Spigot/Bukkit - if (obj instanceof Set) return false; //It's PaperSpigot/SportsBukkit - throw new IllegalArgumentException("Object passed was not either a hashset or set!"); - } - public static boolean removeDisguise(TargetedDisguise disguise) { UUID entityId = disguise.getEntity().getUniqueId(); if (getDisguises().containsKey(entityId) && getDisguises().get(entityId).remove(disguise)) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4208e4ae..5f868876 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: LibsDisguises main: me.libraryaddict.disguise.LibsDisguises -version: 8.6.6 +version: 8.6.7 author: libraryaddict authors: [Byteflux, Navid K.] depend: [ProtocolLib]