From 6d9e6809a92db1c9baa37bfd1c9694bf8cd236d9 Mon Sep 17 00:00:00 2001 From: Jupiops Date: Wed, 25 Mar 2020 22:06:16 +0100 Subject: [PATCH] updated UUIDFetcher and GameProfileBuilder to make skin chnage work again --- .idea/.gitignore | 2 + ...aven__com_google_code_gson_gson_2_8_6.xml} | 8 +- ...bukkit_craftbukkit_1_8_8_R0_1_SNAPSHOT.xml | 13 ++ ...Maven__org_projectlombok_lombok_1_18_4.xml | 13 -- .idea/zTag.iml | 4 +- pom.xml | 18 +- src/main/java/de/pkmnplatin/ztag/TagBase.java | 15 +- .../pkmnplatin/ztag/profile/TagProfile.java | 18 +- .../de/pkmnplatin/ztag/reflect/Version.java | 13 +- .../ztag/util/GameProfileBuilder.java | 176 +++++++++++++++ .../ztag/util/GameProfileFetcher.java | 209 ------------------ .../de/pkmnplatin/ztag/util/UUIDFetcher.java | 172 ++++++++------ .../java/de/pkmnplatin/ztag/zTagEvent.java | 79 +++++-- 13 files changed, 418 insertions(+), 322 deletions(-) create mode 100644 .idea/.gitignore rename .idea/libraries/{Maven__com_google_code_gson_gson_2_8_0.xml => Maven__com_google_code_gson_gson_2_8_6.xml} (66%) create mode 100644 .idea/libraries/Maven__org_bukkit_craftbukkit_1_8_8_R0_1_SNAPSHOT.xml delete mode 100644 .idea/libraries/Maven__org_projectlombok_lombok_1_18_4.xml create mode 100644 src/main/java/de/pkmnplatin/ztag/util/GameProfileBuilder.java delete mode 100644 src/main/java/de/pkmnplatin/ztag/util/GameProfileFetcher.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..e7e9d11 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml diff --git a/.idea/libraries/Maven__com_google_code_gson_gson_2_8_0.xml b/.idea/libraries/Maven__com_google_code_gson_gson_2_8_6.xml similarity index 66% rename from .idea/libraries/Maven__com_google_code_gson_gson_2_8_0.xml rename to .idea/libraries/Maven__com_google_code_gson_gson_2_8_6.xml index 6e5d5b7..82a9f20 100644 --- a/.idea/libraries/Maven__com_google_code_gson_gson_2_8_0.xml +++ b/.idea/libraries/Maven__com_google_code_gson_gson_2_8_6.xml @@ -1,13 +1,13 @@ - + - + - + - + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_bukkit_craftbukkit_1_8_8_R0_1_SNAPSHOT.xml b/.idea/libraries/Maven__org_bukkit_craftbukkit_1_8_8_R0_1_SNAPSHOT.xml new file mode 100644 index 0000000..2a3dc1d --- /dev/null +++ b/.idea/libraries/Maven__org_bukkit_craftbukkit_1_8_8_R0_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_projectlombok_lombok_1_18_4.xml b/.idea/libraries/Maven__org_projectlombok_lombok_1_18_4.xml deleted file mode 100644 index 71063d7..0000000 --- a/.idea/libraries/Maven__org_projectlombok_lombok_1_18_4.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/zTag.iml b/.idea/zTag.iml index b8b6cf9..fb5bbba 100644 --- a/.idea/zTag.iml +++ b/.idea/zTag.iml @@ -11,7 +11,7 @@ - - + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index cdbb273..049299d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.pkmnplatin.ztag ztag - 1.0-SNAPSHOT + 2.0-SNAPSHOT @@ -20,17 +20,25 @@ + + + + + + + + - org.projectlombok - lombok - LATEST + org.bukkit + craftbukkit + 1.8.8-R0.1-SNAPSHOT com.google.code.gson gson - 2.8.0 + 2.8.6 compile diff --git a/src/main/java/de/pkmnplatin/ztag/TagBase.java b/src/main/java/de/pkmnplatin/ztag/TagBase.java index 138918d..14dfbd0 100644 --- a/src/main/java/de/pkmnplatin/ztag/TagBase.java +++ b/src/main/java/de/pkmnplatin/ztag/TagBase.java @@ -2,7 +2,6 @@ import de.pkmnplatin.ztag.profile.ProfileManager; import de.pkmnplatin.ztag.reflect.Version; -import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.mcstats.Metrics; @@ -10,15 +9,25 @@ /** * Created by Jona on 16.06.2017. */ -@Getter public class TagBase extends JavaPlugin { - @Getter private static TagBase instance; private Version version; private ProfileManager profileManager; + public static TagBase getInstance() { + return instance; + } + + public Version getVersion() { + return version; + } + + public ProfileManager getProfileManager() { + return profileManager; + } + public static void log(String msg) { instance.getLogger().info(msg); } diff --git a/src/main/java/de/pkmnplatin/ztag/profile/TagProfile.java b/src/main/java/de/pkmnplatin/ztag/profile/TagProfile.java index 331377e..209b396 100644 --- a/src/main/java/de/pkmnplatin/ztag/profile/TagProfile.java +++ b/src/main/java/de/pkmnplatin/ztag/profile/TagProfile.java @@ -1,13 +1,11 @@ package de.pkmnplatin.ztag.profile; import de.pkmnplatin.ztag.TagBase; -import lombok.Getter; import org.bukkit.entity.Player; /** * Created by Jona on 06.07.2017. */ -@Getter public class TagProfile { private final Player player; @@ -16,6 +14,22 @@ public class TagProfile { private String skin; private final String realName; + public Player getPlayer() { + return player; + } + + public String getTag() { + return tag; + } + + public String getSkin() { + return skin; + } + + public String getRealName() { + return realName; + } + public TagProfile(Player player, String realName, String tag, String skin) { this.player = player; this.realName = realName; diff --git a/src/main/java/de/pkmnplatin/ztag/reflect/Version.java b/src/main/java/de/pkmnplatin/ztag/reflect/Version.java index 635adf9..0a6cbb7 100644 --- a/src/main/java/de/pkmnplatin/ztag/reflect/Version.java +++ b/src/main/java/de/pkmnplatin/ztag/reflect/Version.java @@ -1,6 +1,5 @@ package de.pkmnplatin.ztag.reflect; -import lombok.Getter; import org.bukkit.Bukkit; /** @@ -20,14 +19,22 @@ public enum Version { v1_8_R2("1.8.2", 182), v1_8_R1("1.8.0 - 1.8.1", 181); - @Getter private String mcVersion; - @Getter private int versionId; + private String mcVersion; + private int versionId; Version(String mcVersion, int versionId) { this.mcVersion = mcVersion; this.versionId = versionId; } + public String getMcVersion() { + return mcVersion; + } + + public int getVersionId() { + return versionId; + } + public static Version detectServerVersion() { String versionString = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; for (Version v : Version.values()) { diff --git a/src/main/java/de/pkmnplatin/ztag/util/GameProfileBuilder.java b/src/main/java/de/pkmnplatin/ztag/util/GameProfileBuilder.java new file mode 100644 index 0000000..acd9c00 --- /dev/null +++ b/src/main/java/de/pkmnplatin/ztag/util/GameProfileBuilder.java @@ -0,0 +1,176 @@ +package de.pkmnplatin.ztag.util; + +import com.google.gson.*; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; +import com.mojang.util.UUIDTypeAdapter; +import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; + +/** + * @author Jofkos + * @see https://gist.github.com/Jofkos/79af290e94acdc7d7d5b + */ + +public class GameProfileBuilder { + + private static final String SERVICE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/%s?unsigned=false"; + private static final String JSON_SKIN = "{\"timestamp\":%d,\"profileId\":\"%s\",\"profileName\":\"%s\",\"isPublic\":true,\"textures\":{\"SKIN\":{\"url\":\"%s\"}}}"; + private static final String JSON_CAPE = "{\"timestamp\":%d,\"profileId\":\"%s\",\"profileName\":\"%s\",\"isPublic\":true,\"textures\":{\"SKIN\":{\"url\":\"%s\"},\"CAPE\":{\"url\":\"%s\"}}}"; + + private static Gson gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).registerTypeAdapter(GameProfile.class, new GameProfileSerializer()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create(); + + private static HashMap cache = new HashMap(); + + private static long cacheTime = -1; + + /** + * Don't run in main thread! + *

+ * Fetches the GameProfile from the Mojang servers + * + * @param uuid The player uuid + * @return The GameProfile + * @throws IOException If something wents wrong while fetching + * @see GameProfile + */ + public static GameProfile fetch(UUID uuid) throws IOException { + return fetch(uuid, false); + } + + /** + * Don't run in main thread! + *

+ * Fetches the GameProfile from the Mojang servers + * + * @param uuid The player uuid + * @param forceNew If true the cache is ignored + * @return The GameProfile + * @throws IOException If something wents wrong while fetching + * @see GameProfile + */ + public static GameProfile fetch(UUID uuid, boolean forceNew) throws IOException { + if (!forceNew && cache.containsKey(uuid) && cache.get(uuid).isValid()) { + return cache.get(uuid).profile; + } else { + HttpURLConnection connection = (HttpURLConnection) new URL(String.format(SERVICE_URL, UUIDTypeAdapter.fromUUID(uuid))).openConnection(); + connection.setReadTimeout(5000); + + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + String json = new BufferedReader(new InputStreamReader(connection.getInputStream())).readLine(); + + GameProfile result = gson.fromJson(json, GameProfile.class); + cache.put(uuid, new CachedProfile(result)); + return result; + } else { + if (!forceNew && cache.containsKey(uuid)) { + return cache.get(uuid).profile; + } + JsonObject error = (JsonObject) new JsonParser().parse(new BufferedReader(new InputStreamReader(connection.getErrorStream())).readLine()); + throw new IOException(error.get("error").getAsString() + ": " + error.get("errorMessage").getAsString()); + } + } + } + + /** + * Builds a GameProfile for the specified args + * + * @param uuid The uuid + * @param name The name + * @param skin The url from the skin image + * @return A GameProfile built from the arguments + * @see GameProfile + */ + public static GameProfile getProfile(UUID uuid, String name, String skin) { + return getProfile(uuid, name, skin, null); + } + + /** + * Builds a GameProfile for the specified args + * + * @param uuid The uuid + * @param name The name + * @param skinUrl Url from the skin image + * @param capeUrl Url from the cape image + * @return A GameProfile built from the arguments + * @see GameProfile + */ + public static GameProfile getProfile(UUID uuid, String name, String skinUrl, String capeUrl) { + GameProfile profile = new GameProfile(uuid, name); + boolean cape = capeUrl != null && !capeUrl.isEmpty(); + + List args = new ArrayList(); + args.add(System.currentTimeMillis()); + args.add(UUIDTypeAdapter.fromUUID(uuid)); + args.add(name); + args.add(skinUrl); + if (cape) args.add(capeUrl); + + profile.getProperties().put("textures", new Property("textures", Base64Coder.encodeString(String.format(cape ? JSON_CAPE : JSON_SKIN, args.toArray(new Object[args.size()]))))); + return profile; + } + + /** + * Sets the time as long as you want to keep the gameprofiles in cache (-1 = never remove it) + * + * @param time cache time (default = -1) + */ + public static void setCacheTime(long time) { + cacheTime = time; + } + + private static class GameProfileSerializer implements JsonSerializer, JsonDeserializer { + + public GameProfile deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + JsonObject object = (JsonObject) json; + UUID id = object.has("id") ? (UUID) context.deserialize(object.get("id"), UUID.class) : null; + String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null; + GameProfile profile = new GameProfile(id, name); + + if (object.has("properties")) { + for (Entry prop : ((PropertyMap) context.deserialize(object.get("properties"), PropertyMap.class)).entries()) { + profile.getProperties().put(prop.getKey(), prop.getValue()); + } + } + return profile; + } + + public JsonElement serialize(GameProfile profile, Type type, JsonSerializationContext context) { + JsonObject result = new JsonObject(); + if (profile.getId() != null) + result.add("id", context.serialize(profile.getId())); + if (profile.getName() != null) + result.addProperty("name", profile.getName()); + if (!profile.getProperties().isEmpty()) + result.add("properties", context.serialize(profile.getProperties())); + return result; + } + + } + + private static class CachedProfile { + + private long timestamp = System.currentTimeMillis(); + private GameProfile profile; + + public CachedProfile(GameProfile profile) { + this.profile = profile; + } + + public boolean isValid() { + return cacheTime < 0 || (System.currentTimeMillis() - timestamp) < cacheTime; + } + } +} \ No newline at end of file diff --git a/src/main/java/de/pkmnplatin/ztag/util/GameProfileFetcher.java b/src/main/java/de/pkmnplatin/ztag/util/GameProfileFetcher.java deleted file mode 100644 index 05ab745..0000000 --- a/src/main/java/de/pkmnplatin/ztag/util/GameProfileFetcher.java +++ /dev/null @@ -1,209 +0,0 @@ -package de.pkmnplatin.ztag.util; - -import com.google.common.collect.ForwardingMultimap; -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; -import com.google.gson.*; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import de.pkmnplatin.ztag.TagBase; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Type; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.*; - -/** - * Created by Jona on 11.07.2017. - */ -public class GameProfileFetcher { - - private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0"; - private static Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).registerTypeAdapter(GameProfile.class, new GameProfileSerializer()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create(); - private static HashMap gameProfileCache = new HashMap<>(); - - public static GameProfile getGameProfile(UUID uuid) { - if (gameProfileCache.containsKey(uuid)) { - return gameProfileCache.get(uuid); - } else { - try { - HttpURLConnection con = (HttpURLConnection) new URL("https://use.gameapis.net/mc/player/profile/" + uuid).openConnection(); - con.setRequestProperty("User-Agent", USER_AGENT); - BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); - JsonObject main = gson.fromJson(reader, JsonElement.class).getAsJsonObject(); - reader.close(); - con.disconnect(); - String id = main.get("id").getAsString(); - String name = main.get("name").getAsString(); - main = main.get("properties").getAsJsonArray().get(0).getAsJsonObject(); - String signature = main.get("signature").getAsString(); - String value = main.get("value").getAsString(); - GameProfile gp = gson.fromJson(getJSONString(id, name, signature, value), GameProfile.class); - gameProfileCache.put(uuid, gp); - return gp; - } catch (Exception ex) { - TagBase.log(ex); - } - } - return null; - } - - private static String getJSONString(String id, String name, String signature, String value) { - return "{ \n" + - " \"id\":\"" + id + "\",\n" + - " \"name\":\"" + name + "\",\n" + - " \"properties\":[ \n" + - " { \n" + - " \"signature\":\"" + signature + "\",\n" + - " \"name\":\"textures\",\n" + - " \"value\":\"" + value + "\"\n" + - " }\n" + - " ]\n" + - "}"; - } - - private static class GameProfileSerializer implements JsonSerializer, JsonDeserializer { - - public GameProfile deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) throws JsonParseException { - final JsonObject object = (JsonObject) json; - final UUID id = object.has("id") ? ((UUID) context.deserialize(object.get("id"), (Type) UUID.class)) : null; - final String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null; - final GameProfile profile = new GameProfile(id, name); - if (object.has("properties")) { - for (final Map.Entry prop : ((PropertyMap) context.deserialize(object.get("properties"), PropertyMap.class)).toRealMap().entries()) { - profile.getProperties().put(prop.getKey(), prop.getValue()); - } - } - return profile; - } - - public JsonElement serialize(final GameProfile profile, final Type type, final JsonSerializationContext context) { - final JsonObject result = new JsonObject(); - if (profile.getId() != null) { - result.add("id", context.serialize(profile.getId())); - } - if (profile.getName() != null) { - result.addProperty("name", profile.getName()); - } - if (!profile.getProperties().isEmpty()) { - result.add("properties", context.serialize(profile.getProperties())); - } - return result; - } - } - - private static class UUIDTypeAdapter extends TypeAdapter { - - public UUIDTypeAdapter() { - } - - public void write(JsonWriter var1, UUID var2) throws IOException { - var1.value(fromUUID(var2)); - } - - public UUID read(JsonReader var1) throws IOException { - return fromString(var1.nextString()); - } - - public static String fromUUID(UUID var0) { - return var0.toString().replace("-", ""); - } - - public static UUID fromString(String var0) { - return UUID.fromString(var0.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); - } - } - - private static class PropertyMap extends ForwardingMultimap { - - private final Multimap properties = LinkedHashMultimap.create(); - - public PropertyMap() { - } - - protected Multimap delegate() { - return this.properties; - } - - public static class Serializer implements JsonSerializer, JsonDeserializer { - public Serializer() { - } - - public PropertyMap deserialize(JsonElement var1, Type var2, JsonDeserializationContext var3) throws JsonParseException { - PropertyMap var4 = new PropertyMap(); - if (var1 instanceof JsonObject) { - JsonObject var5 = (JsonObject) var1; - Iterator var6 = var5.entrySet().iterator(); - - while (true) { - Map.Entry var7; - do { - if (!var6.hasNext()) { - return var4; - } - - var7 = (Map.Entry) var6.next(); - } while (!(var7.getValue() instanceof JsonArray)); - - Iterator var8 = ((JsonArray) var7.getValue()).iterator(); - - while (var8.hasNext()) { - JsonElement var9 = (JsonElement) var8.next(); - var4.put((String) var7.getKey(), new Property((String) var7.getKey(), var9.getAsString())); - } - } - } else if (var1 instanceof JsonArray) { - Iterator var10 = ((JsonArray) var1).iterator(); - - while (var10.hasNext()) { - JsonElement var11 = (JsonElement) var10.next(); - if (var11 instanceof JsonObject) { - JsonObject var12 = (JsonObject) var11; - String var13 = var12.getAsJsonPrimitive("name").getAsString(); - String var14 = var12.getAsJsonPrimitive("value").getAsString(); - if (var12.has("signature")) { - var4.put(var13, new Property(var13, var14, var12.getAsJsonPrimitive("signature").getAsString())); - } else { - var4.put(var13, new Property(var13, var14)); - } - } - } - } - - return var4; - } - - public JsonElement serialize(PropertyMap var1, Type var2, JsonSerializationContext var3) { - JsonArray var4 = new JsonArray(); - - JsonObject var7; - for (Iterator var5 = var1.values().iterator(); var5.hasNext(); var4.add(var7)) { - Property var6 = (Property) var5.next(); - var7 = new JsonObject(); - var7.addProperty("name", var6.getName()); - var7.addProperty("value", var6.getValue()); - if (var6.hasSignature()) { - var7.addProperty("signature", var6.getSignature()); - } - } - - return var4; - } - } - - public PropertyMap toRealMap() { - PropertyMap realMap = new PropertyMap(); - for(String key : this.properties.keySet()) { - Collection prop = this.properties.get(key); - realMap.putAll(key, prop); - } - return realMap; - } - } - -} diff --git a/src/main/java/de/pkmnplatin/ztag/util/UUIDFetcher.java b/src/main/java/de/pkmnplatin/ztag/util/UUIDFetcher.java index 7a16ac8..5fabddf 100644 --- a/src/main/java/de/pkmnplatin/ztag/util/UUIDFetcher.java +++ b/src/main/java/de/pkmnplatin/ztag/util/UUIDFetcher.java @@ -2,93 +2,139 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.mojang.util.UUIDTypeAdapter; -import com.mysql.jdbc.StringUtils; -import de.pkmnplatin.ztag.TagBase; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; /** - * Created by Jona on 07.07.2017. + * @author Jofkos + * @see https://gist.github.com/Jofkos/d0c469528b032d820f42 */ + public class UUIDFetcher { - private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0"; + /** + * Date when name changes were introduced + * + * @see UUIDFetcher#getUUIDAt(String, long) + */ + public static final long FEBRUARY_2015 = 1422748800000L; - private static HashMap nameCache = new HashMap<>(); - private static HashMap uuidCache = new HashMap<>(); - private static Gson gson = new GsonBuilder().create(); + private static Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); - public static String getName(UUID uuid) { - if(nameCache.containsKey(uuid)) { - return nameCache.get(uuid); - } - try { - HttpURLConnection con = (HttpURLConnection) new URL("https://use.gameapis.net/mc/player/profile/" + uuid.toString()).openConnection(); - con.setRequestProperty("User-Agent", USER_AGENT); - BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); - JsonObject main = gson.fromJson(reader, JsonElement.class).getAsJsonObject(); - reader.close(); - con.disconnect(); - String name = main.get("name").getAsString(); - String sId = main.get("id").getAsString(); - if((! isValid(name) && isValid(sId))) { - return null; - } - UUID id = UUIDTypeAdapter.fromString(sId); - if(! (isValid(id.toString()))) { - return null; - } - nameCache.put(id, name); - uuidCache.put(name, id); - return name; - } catch (Exception ex) { - TagBase.log(ex); - } - return null; + private static final String UUID_URL = "https://api.mojang.com/users/profiles/minecraft/%s?at=%d"; + private static final String NAME_URL = "https://api.mojang.com/user/profiles/%s/names"; + + private static Map uuidCache = new HashMap(); + private static Map nameCache = new HashMap(); + + private static ExecutorService pool = Executors.newCachedThreadPool(); + + private String name; + private UUID id; + + /** + * Fetches the uuid asynchronously and passes it to the consumer + * + * @param name The name + * @param action Do what you want to do with the uuid her + */ + public static void getUUID(String name, Consumer action) { + pool.execute(() -> action.accept(getUUID(name))); } + /** + * Fetches the uuid synchronously and returns it + * + * @param name The name + * @return The uuid + */ public static UUID getUUID(String name) { - if(uuidCache.containsKey(name.toLowerCase())) { - return uuidCache.get(name.toLowerCase()); + return getUUIDAt(name, System.currentTimeMillis()); + } + + /** + * Fetches the uuid synchronously for a specified name and time and passes the result to the consumer + * + * @param name The name + * @param timestamp Time when the player had this name in milliseconds + * @param action Do what you want to do with the uuid her + */ + public static void getUUIDAt(String name, long timestamp, Consumer action) { + pool.execute(() -> action.accept(getUUIDAt(name, timestamp))); + } + + /** + * Fetches the uuid synchronously for a specified name and time + * + * @param name The name + * @param timestamp Time when the player had this name in milliseconds + * @see UUIDFetcher#FEBRUARY_2015 + */ + public static UUID getUUIDAt(String name, long timestamp) { + name = name.toLowerCase(); + if (uuidCache.containsKey(name)) { + return uuidCache.get(name); } try { - HttpURLConnection con = (HttpURLConnection) new URL("https://use.gameapis.net/mc/player/profile/" + name).openConnection(); - con.setRequestProperty("User-Agent", USER_AGENT); - BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); - JsonObject main = gson.fromJson(reader, JsonElement.class).getAsJsonObject(); - reader.close(); - con.disconnect(); - String nme = main.get("name").getAsString(); - String sId = main.get("id").getAsString(); - if((! isValid(name) && isValid(sId))) { - return null; - } - UUID id = UUIDTypeAdapter.fromString(sId); - if(! (isValid(id.toString()))) { - return null; - } - nameCache.put(id, nme); - uuidCache.put(nme, id); - return id; - } catch (Exception ex) { - TagBase.log(ex); + HttpURLConnection connection = (HttpURLConnection) new URL(String.format(UUID_URL, name, timestamp / 1000)).openConnection(); + connection.setReadTimeout(5000); + UUIDFetcher data = gson.fromJson(new BufferedReader(new InputStreamReader(connection.getInputStream())), UUIDFetcher.class); + + uuidCache.put(name, data.id); + nameCache.put(data.id, data.name); + + return data.id; + } catch (Exception e) { + e.printStackTrace(); } + return null; } - private static boolean isValid(String string) { - if(StringUtils.isNullOrEmpty(string) || string.equals("null")) { - return false; - } - return true; + /** + * Fetches the name asynchronously and passes it to the consumer + * + * @param uuid The uuid + * @param action Do what you want to do with the name her + */ + public static void getName(UUID uuid, Consumer action) { + pool.execute(() -> action.accept(getName(uuid))); } + /** + * Fetches the name synchronously and returns it + * + * @param uuid The uuid + * @return The name + */ + public static String getName(UUID uuid) { + if (nameCache.containsKey(uuid)) { + return nameCache.get(uuid); + } + try { + HttpURLConnection connection = (HttpURLConnection) new URL(String.format(NAME_URL, UUIDTypeAdapter.fromUUID(uuid))).openConnection(); + connection.setReadTimeout(5000); + UUIDFetcher[] nameHistory = gson.fromJson(new BufferedReader(new InputStreamReader(connection.getInputStream())), UUIDFetcher[].class); + UUIDFetcher currentNameData = nameHistory[nameHistory.length - 1]; + + uuidCache.put(currentNameData.name.toLowerCase(), uuid); + nameCache.put(uuid, currentNameData.name); + + return currentNameData.name; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } } diff --git a/src/main/java/de/pkmnplatin/ztag/zTagEvent.java b/src/main/java/de/pkmnplatin/ztag/zTagEvent.java index 4385835..ba0de41 100644 --- a/src/main/java/de/pkmnplatin/ztag/zTagEvent.java +++ b/src/main/java/de/pkmnplatin/ztag/zTagEvent.java @@ -4,11 +4,8 @@ import com.mojang.authlib.properties.Property; import de.pkmnplatin.ztag.profile.TagProfile; import de.pkmnplatin.ztag.reflect.Reflection; -import de.pkmnplatin.ztag.util.GameProfileFetcher; +import de.pkmnplatin.ztag.util.GameProfileBuilder; import de.pkmnplatin.ztag.util.UUIDFetcher; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -16,30 +13,73 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import java.io.IOException; import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import static de.pkmnplatin.ztag.reflect.Reflection.*; /** * Created by Jona on 06.07.2017. */ -@Getter -@Setter public class zTagEvent extends Event { - private static final ExecutorService pool = Executors.newCachedThreadPool(); - - @Setter(AccessLevel.NONE) private Player player; - @Setter(AccessLevel.NONE) private TagProfile profile; - @Setter(AccessLevel.NONE) private List players = new ArrayList(); + private Player player; + private TagProfile profile; + private List players = new ArrayList(); private boolean updateChunk = true; private boolean forceSkinUpdate = true; private String tag; private String skin; + public Player getPlayer() { + return player; + } + + public TagProfile getProfile() { + return profile; + } + + public List getPlayers() { + return players; + } + + public boolean isUpdateChunk() { + return updateChunk; + } + + public boolean isForceSkinUpdate() { + return forceSkinUpdate; + } + + public String getTag() { + return tag; + } + + public String getSkin() { + return skin; + } + + public void setUpdateChunk(boolean updateChunk) { + this.updateChunk = updateChunk; + } + + public void setForceSkinUpdate(boolean forceSkinUpdate) { + this.forceSkinUpdate = forceSkinUpdate; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public void setSkin(String skin) { + this.skin = skin; + } + + public static void setHandlerList(HandlerList handlerList) { + zTagEvent.handlerList = handlerList; + } + public zTagEvent(Player player, String tag, String skin) { this(player, tag, skin, Bukkit.getOnlinePlayers().toArray(new Player[Bukkit.getOnlinePlayers().size()])); } @@ -73,12 +113,12 @@ public zTagEvent(Player player, String tag, String skin, Player... forWho) { final double maxHealth = player.getMaxHealth(); final double health = player.getHealth(); - if(forceSkinUpdate) { + if (forceSkinUpdate) { sendPacket(player, removePlayer); sendPacket(player, respawnPacket); sendPacket(player, addPlayer); player.teleport(location); - if(updateChunk) { + if (updateChunk) { Chunk chunk = player.getWorld().getChunkAt(player.getLocation()); player.getWorld().refreshChunk(chunk.getX() + 8, chunk.getZ() + 8); } @@ -94,7 +134,7 @@ public zTagEvent(Player player, String tag, String skin, Player... forWho) { player.setMaxHealth(maxHealth); player.setHealth(health); - if(!players.isEmpty()) { + if (!players.isEmpty()) { for (Player p : players) { if (p != player) { sendPacket(p, removePlayer); @@ -114,11 +154,14 @@ private GameProfile fixSkin(GameProfile gp, String skin) { if (uuid == null) { return gp; } - GameProfile fetched = GameProfileFetcher.getGameProfile(uuid); - if(fetched != null) { + GameProfile fetched = null; + try { + fetched = GameProfileBuilder.fetch(uuid); Collection props = fetched.getProperties().get("textures"); gp.getProperties().removeAll("textures"); gp.getProperties().putAll("textures", props); + } catch (IOException e) { +// e.printStackTrace(); } return gp; }