package com.griefcraft.util;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class UUIDRegistry {
/**
* Temporal caches
*/
private static final Map<String, PlayerInfo> nameToUUIDCache = new HashMap<String, PlayerInfo>();
private static final Map<UUID, PlayerInfo> UUIDToNameCache = new HashMap<UUID, PlayerInfo>();
static class PlayerInfo {
private UUID uuid;
private String name;
public PlayerInfo(UUID uuid, String name) {
this.uuid = uuid;
this.name = name;
}
public UUID getUUID() {
return uuid;
}
public String getName() {
return name;
}
}
/**
* Update the cache with a new UUID/name pair
*
* @param uuid
* @param name
*/
public static void updateCache(UUID uuid, String name) {
PlayerInfo playerInfo = new PlayerInfo(uuid, name);
nameToUUIDCache.put(name.toLowerCase(), playerInfo);
UUIDToNameCache.put(uuid, playerInfo);
}
/**
* Check if a uuid in string form is a valid Java UUID
*
* @param uuid
* @return true if the string is a valid UUID
*/
public static boolean isValidUUID(String uuid) {
return uuid.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
}
/**
* Get the name for the given UUID. If it is not already known, it will be retrieved from the account servers.
*
* @param uuid
* @return
*/
public static String getName(UUID uuid) {
if (uuid == null) {
return null;
}
if (UUIDToNameCache.containsKey(uuid)) {
return UUIDToNameCache.get(uuid).getName();
}
// First way: if they're on the server already
Player player = Bukkit.getPlayer(uuid);
if (player != null) {
updateCache(uuid, player.getName());
return player.getName();
}
// Second way: if they have been on the server before
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
if (offlinePlayer != null && offlinePlayer.getName() != null) {
updateCache(uuid, offlinePlayer.getName());
return offlinePlayer.getName();
}
// Third way: use the web API
try {
Map<UUID, String> results = new NameFetcher(Arrays.asList(uuid)).call();
if (results.containsKey(uuid)) {
return results.get(uuid);
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
/**
* Get the UUID for the given name. If it is not already known, it will be retrieved from the account servers.
*
* @param name
* @return
* @throws Exception
*/
public static UUID getUUID(String name) {
String nameLower = name.toLowerCase();
try {
if (nameToUUIDCache.containsKey(nameLower)) {
return nameToUUIDCache.get(nameLower).getUUID();
}
if (isValidUUID(name)) {
return UUID.fromString(name);
}
if (Bukkit.getOnlineMode()) {
Map<String, UUID> results = new UUIDFetcher(Arrays.asList(nameLower)).call();
// The returned name is the exact casing; so we need to look for it
// in the case-insensitive version
for (String key : results.keySet()) {
if (key.equalsIgnoreCase(name)) {
UUID uuid = results.get(key);
updateCache(uuid, key);
return uuid;
}
}
} else {
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
if (offlinePlayer != null && offlinePlayer.getUniqueId() != null) {
if (offlinePlayer.getName() != null) {
name = offlinePlayer.getName();
}
updateCache(offlinePlayer.getUniqueId(), name);
return offlinePlayer.getUniqueId();
}
}
nameToUUIDCache.put(nameLower, null);
return null;
} catch (Exception e) {
nameToUUIDCache.put(nameLower, null);
return null;
}
}
/**
* Attempts to format a player's name, which can be a name or a UUID. If the owner is a UUID and then
* UUID is unknown, then "Unknown (uuid)" will be returned.
*
* @param name
* @return
*/
public static String formatPlayerName(String name) {
if (isValidUUID(name)) {
String formattedName = getName(UUID.fromString(name));
if (formattedName == null) {
return "Unknown (" + name + ")";
} else {
return formattedName + " (" + name + ")";
}
} else {
return name;
}
}
}