diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 4d3d1a36..b31a0f23 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -126,17 +126,6 @@ public class DisguiseUtilities { // + " on a entity. Removed the old disguise."); disguiseItel.remove(); - /* if (name != null) { - if (!disguise.getObservers().contains(name)) { - d.setViewDisguise(name); - } - } else { - for (String playername : d.getObservers()) { - if (!disguise.getObservers().contains(playername)) { - d.setViewDisguise(playername); - } - } - }*/ } } } @@ -230,6 +219,10 @@ public class DisguiseUtilities { return new TargetedDisguise[0]; } + public static Object getGameProfile(String playerName) { + return gameProfiles.get(playerName); + } + public static TargetedDisguise getMainDisguise(UUID entityId) { TargetedDisguise toReturn = null; if (getDisguises().containsKey(entityId)) { @@ -271,55 +264,52 @@ public class DisguiseUtilities { } public static Object getProfile(final String playerName) { - Player player = Bukkit.getPlayerExact(playerName); - if (player != null) { - return ReflectionManager.getGameProfile(player); + if (gameProfiles.containsKey(playerName)) { + if (gameProfiles.get(playerName) != null) { + return gameProfiles.get(playerName); + } } else { - if (gameProfiles.containsKey(playerName)) { - if (gameProfiles.get(playerName) != null) { - return gameProfiles.get(playerName); + Player player = Bukkit.getPlayerExact(playerName); + if (player != null) { + Object gameProfile = ReflectionManager.getGameProfile(player); + if (ReflectionManager.hasSkinBlob(gameProfile)) { + gameProfiles.put(playerName, gameProfile); + return gameProfile; } - } else { - // Add null so that if this is called again. I already know I'm doing something about it - gameProfiles.put(playerName, null); - Bukkit.getScheduler().scheduleAsyncDelayedTask(libsDisguises, new Runnable() { - public void run() { - try { - Object gameprofile = ReflectionManager.grabUUID(ReflectionManager.getGameProfile(null, playerName, - false)); - if (gameprofile != null) { - final Object gameProfile = ReflectionManager.grabSkullBlob(gameprofile); - Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { - public void run() { - if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { - gameProfiles.put(playerName, gameProfile); - } - for (HashSet disguises : DisguiseUtilities.getDisguises().values()) { - for (TargetedDisguise disguise : disguises) { - if (disguise.getType() == DisguiseType.PLAYER - && ((PlayerDisguise) disguise).getName().equals(playerName)) { - DisguiseUtilities.refreshTrackers((TargetedDisguise) disguise); - if (disguise.getEntity() instanceof Player - && disguise.isSelfDisguiseVisible()) { - DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), - disguise); - } + } + // Add null so that if this is called again. I already know I'm doing something about it + gameProfiles.put(playerName, null); + Bukkit.getScheduler().scheduleAsyncDelayedTask(libsDisguises, new Runnable() { + public void run() { + try { + final Object gameProfile = lookupGameProfile(playerName); + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { + public void run() { + if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { + gameProfiles.put(playerName, gameProfile); + for (HashSet disguises : DisguiseUtilities.getDisguises().values()) { + for (TargetedDisguise disguise : disguises) { + if (disguise.getType() == DisguiseType.PLAYER + && ((PlayerDisguise) disguise).getName().equals(playerName)) { + DisguiseUtilities.refreshTrackers((TargetedDisguise) disguise); + if (disguise.getEntity() instanceof Player && disguise.isSelfDisguiseVisible()) { + DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), disguise); } } } } - }); + } } - } catch (Exception e) { - if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { - gameProfiles.remove(playerName); - } - System.out.print("[LibsDisguises] Error when fetching " + playerName + "'s uuid from mojang: " - + e.getMessage()); + }); + } catch (Exception e) { + if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { + gameProfiles.remove(playerName); } + System.out.print("[LibsDisguises] Error when fetching " + playerName + "'s uuid from mojang: " + + e.getMessage()); } - }); - } + } + }); } return ReflectionManager.getGameProfile(null, playerName); } @@ -351,6 +341,10 @@ public class DisguiseUtilities { return selfDisguisesIds; } + public static boolean hasGameProfile(String playerName) { + return getGameProfile(playerName) != null; + } + public static void init(LibsDisguises disguises) { libsDisguises = disguises; } @@ -363,6 +357,39 @@ public class DisguiseUtilities { return false; } + /** + * This is called on a thread as it is thread blocking + */ + public static Object lookupGameProfile(String playerName) { + Object gameprofile = ReflectionManager.grabProfileAddUUID(playerName); + return ReflectionManager.grabSkullBlob(gameprofile); + } + + /** + * This is safe to call from the main thread + */ + public static void lookupGameProfileAndStore(final String playerName) { + if (!gameProfiles.containsKey(playerName)) { + gameProfiles.put(playerName, null); + Bukkit.getScheduler().scheduleAsyncDelayedTask(libsDisguises, new Runnable() { + public void run() { + try { + final Object gameProfile = lookupGameProfile(playerName); + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { + public void run() { + if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) { + gameProfiles.put(playerName, gameProfile); + } + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + } + } + /** * @param Resends * the entity to all the watching players, which is where the magic begins diff --git a/src/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java b/src/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java new file mode 100644 index 00000000..01340060 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java @@ -0,0 +1,33 @@ +package me.libraryaddict.disguise.utilities; + +import java.lang.reflect.Field; +import java.util.UUID; + +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.ProfileLookupCallback; + +public class LibsProfileLookupCaller implements ProfileLookupCallback { + private GameProfile gameProfile; + + public GameProfile getGameProfile() { + return gameProfile; + } + + @Override + public void onProfileLookupFailed(GameProfile gameProfile, Exception arg1) { + try { + Field field = GameProfile.class.getDeclaredField("id"); + field.setAccessible(true); + field.set(gameProfile, UUID.randomUUID()); + } catch (Exception e) { + e.printStackTrace(); + } + this.onProfileLookupSucceeded(gameProfile); + } + + @Override + public void onProfileLookupSucceeded(GameProfile profile) { + gameProfile = profile; + } + +} diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index b0de4ecd..4df10cb9 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -218,15 +218,11 @@ public class ReflectionManager { } public static Object getGameProfile(UUID uuid, String playerName) { - return getGameProfile(uuid, playerName, true); - } - - public static Object getGameProfile(UUID uuid, String playerName, boolean createUuid) { try { try { return Class.forName("net.minecraft.util.com.mojang.authlib.GameProfile") .getConstructor(UUID.class, String.class) - .newInstance(uuid != null || !createUuid ? uuid : UUID.randomUUID(), playerName); + .newInstance(uuid != null ? uuid : UUID.randomUUID(), playerName); } catch (NoSuchMethodException ex) { return Class.forName("net.minecraft.util.com.mojang.authlib.GameProfile") .getConstructor(String.class, String.class).newInstance(uuid != null ? uuid.toString() : "", playerName); @@ -303,6 +299,28 @@ public class ReflectionManager { return null; } + public static Object grabProfileAddUUID(String playername) { + try { + Object minecraftServer = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); + for (Method method : getNmsClass("MinecraftServer").getMethods()) { + if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) { + Object profileRepo = method.invoke(minecraftServer); + Object agent = Class.forName("net.minecraft.util.com.mojang.authlib.Agent").getField("MINECRAFT").get(null); + LibsProfileLookupCaller callback = new LibsProfileLookupCaller(); + profileRepo + .getClass() + .getMethod("findProfilesByNames", String[].class, agent.getClass(), + Class.forName("net.minecraft.util.com.mojang.authlib.ProfileLookupCallback")) + .invoke(profileRepo, new String[] { playername }, agent, callback); + return callback.getGameProfile(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + public static Object grabSkullBlob(Object gameProfile) { try { Object minecraftServer = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); @@ -319,20 +337,20 @@ public class ReflectionManager { return null; } - public static Object grabUUID(Object gameProfile) { + public static boolean hasSkinBlob(Object gameprofile) { try { - Object minecraftServer = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); - for (Method method : getNmsClass("MinecraftServer").getMethods()) { - if (method.getReturnType().getSimpleName().equals("MinecraftSessionService")) { - Object session = method.invoke(minecraftServer); - return session.getClass().getMethod("hasJoinedServer", gameProfile.getClass(), String.class) - .invoke(session, gameProfile, null); - } - } + Field propField = gameprofile.getClass().getDeclaredField("properties"); + propField.setAccessible(true); + Object propMap = propField.get(gameprofile); + propField = propMap.getClass().getDeclaredField("properties"); + propField.setAccessible(true); + propMap = propField.get(propMap); + return !(Boolean) propMap.getClass().getMethod("isEmpty").invoke(propMap); + } catch (NoSuchFieldException ex) { } catch (Exception ex) { ex.printStackTrace(); } - return null; + return true; } public static void setAllowSleep(Player player) {