From 21e7ba8d221996f22e5d55ffb023b294a7c7bc0c Mon Sep 17 00:00:00 2001 From: Travis Watkins Date: Fri, 28 Mar 2014 23:48:15 -0500 Subject: [PATCH] Implement API for dealing with player UUIDs. Adds BUKKIT-5071 --- .../craftbukkit/CraftOfflinePlayer.java | 15 +++++ .../org/bukkit/craftbukkit/CraftServer.java | 25 +++++++- .../craftbukkit/util/MojangNameLookup.java | 63 +++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/bukkit/craftbukkit/util/MojangNameLookup.java diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java index 36bcfef321..24b0066279 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -4,6 +4,7 @@ import java.io.File; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import net.minecraft.server.BanEntry; import net.minecraft.server.EntityPlayer; @@ -41,6 +42,20 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa return name; } + // TODO: In 1.7.6+ OfflinePlayer lookup should be by UUID and store it like it does the name now + public UUID getUniqueId() { + NBTTagCompound data = getData(); + if (data == null) { + return null; + } + + if (data.hasKeyOfType("UUIDMost", 4) && data.hasKeyOfType("UUIDLeast", 4)) { + return new UUID(data.getLong("UUIDMost"), data.getLong("UUIDLeast")); + } + + return null; + } + public Server getServer() { return server; } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 04f8a6931e..2b5aa31a4c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -14,7 +14,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.logging.Level; @@ -22,7 +21,6 @@ import java.util.logging.Logger; import javax.imageio.ImageIO; -import net.minecraft.server.BanEntry; import net.minecraft.server.ChunkCoordinates; import net.minecraft.server.CommandAchievement; import net.minecraft.server.CommandBan; @@ -141,6 +139,7 @@ import org.bukkit.craftbukkit.updater.BukkitDLUpdaterService; import org.bukkit.craftbukkit.util.CraftIconCache; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.DatFileFilter; +import org.bukkit.craftbukkit.util.MojangNameLookup; import org.bukkit.craftbukkit.util.Versioning; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; @@ -514,6 +513,17 @@ public final class CraftServer implements Server { return null; } + // TODO: In 1.7.6+ this should use the server's UUID->EntityPlayer map + public Player getPlayer(UUID id) { + for (Player player : getOnlinePlayers()) { + if (player.getUniqueId().equals(id)) { + return player; + } + } + + return null; + } + public int broadcastMessage(String message) { return broadcast(message, BROADCAST_CHANNEL_USERS); } @@ -1282,6 +1292,17 @@ public final class CraftServer implements Server { return result; } + // TODO: In 1.7.6+ this should just lookup the UUID-based player data filename + public OfflinePlayer getOfflinePlayer(UUID id) { + String name = MojangNameLookup.lookupName(id); + if (name == null) { + // This is completely wrong + name = "InvalidUUID"; + } + + return getOfflinePlayer(name); + } + @SuppressWarnings("unchecked") public Set getIPBans() { return new HashSet(playerList.getIPBans().getEntries().keySet()); diff --git a/src/main/java/org/bukkit/craftbukkit/util/MojangNameLookup.java b/src/main/java/org/bukkit/craftbukkit/util/MojangNameLookup.java new file mode 100644 index 0000000000..1db4874d6d --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/util/MojangNameLookup.java @@ -0,0 +1,63 @@ +package org.bukkit.craftbukkit.util; + +import net.minecraft.util.com.google.gson.Gson; +import net.minecraft.util.com.google.common.base.Charsets; +import net.minecraft.util.org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.UUID; + +public class MojangNameLookup { + private static final Logger logger = LogManager.getFormatterLogger(MojangNameLookup.class); + + public static String lookupName(UUID id) { + if (id == null) { + return null; + } + + InputStream inputStream = null; + try { + URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + id.toString().replace("-", "")); + URLConnection connection = url.openConnection(); + connection.setConnectTimeout(15000); + connection.setReadTimeout(15000); + connection.setUseCaches(false); + inputStream = connection.getInputStream(); + String result = IOUtils.toString(inputStream, Charsets.UTF_8); + Gson gson = new Gson(); + Response response = gson.fromJson(result, Response.class); + if (response == null || response.name == null) { + logger.warn("Failed to lookup name from UUID"); + return null; + } + + if (response.cause != null && response.cause.length() > 0) { + logger.warn("Failed to lookup name from UUID: %s", response.errorMessage); + return null; + } + + return response.name; + } catch (MalformedURLException ex) { + logger.warn("Malformed URL in UUID lookup"); + return null; + } catch (IOException ex) { + IOUtils.closeQuietly(inputStream); + } finally { + IOUtils.closeQuietly(inputStream); + } + + return null; + } + + private class Response { + String errorMessage; + String cause; + String name; + } +}