Rewrote and retested parts of the plugin to use UUIDs instead of player names to uniquely identify players. Added data migration code to convert old data to the new (UUID) format.
145 lines
5.3 KiB
Java
145 lines
5.3 KiB
Java
//BIG THANKS to EvilMidget38 for providing this handy UUID lookup tool to the Bukkit community! :)
|
|
|
|
package me.ryanhamshire.GriefPrevention;
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
|
|
import org.bukkit.OfflinePlayer;
|
|
import org.json.simple.JSONArray;
|
|
import org.json.simple.JSONObject;
|
|
import org.json.simple.parser.JSONParser;
|
|
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URL;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.*;
|
|
import java.util.concurrent.Callable;
|
|
|
|
class UUIDFetcher implements Callable<Map<String, UUID>> {
|
|
private static final double PROFILES_PER_REQUEST = 100;
|
|
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
|
|
private final JSONParser jsonParser = new JSONParser();
|
|
private final List<String> names;
|
|
private final boolean rateLimiting;
|
|
|
|
//cache for username -> uuid lookups
|
|
private static HashMap<String, UUID> lookupCache;
|
|
|
|
public UUIDFetcher(List<String> names, boolean rateLimiting) {
|
|
this.names = ImmutableList.copyOf(names);
|
|
this.rateLimiting = rateLimiting;
|
|
}
|
|
|
|
public UUIDFetcher(List<String> names) {
|
|
this(names, true);
|
|
}
|
|
|
|
public Map<String, UUID> call() throws Exception {
|
|
Map<String, UUID> uuidMap = new HashMap<String, UUID>();
|
|
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
|
|
for (int i = 0; i < requests; i++) {
|
|
HttpURLConnection connection = createConnection();
|
|
String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
|
|
writeBody(connection, body);
|
|
JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
|
|
for (Object profile : array) {
|
|
JSONObject jsonProfile = (JSONObject) profile;
|
|
String id = (String) jsonProfile.get("id");
|
|
String name = (String) jsonProfile.get("name");
|
|
UUID uuid = UUIDFetcher.getUUID(id);
|
|
uuidMap.put(name, uuid);
|
|
}
|
|
if (rateLimiting && i != requests - 1) {
|
|
Thread.sleep(100L);
|
|
}
|
|
}
|
|
return uuidMap;
|
|
}
|
|
|
|
private static void writeBody(HttpURLConnection connection, String body) throws Exception {
|
|
OutputStream stream = connection.getOutputStream();
|
|
stream.write(body.getBytes());
|
|
stream.flush();
|
|
stream.close();
|
|
}
|
|
|
|
private static HttpURLConnection createConnection() throws Exception {
|
|
URL url = new URL(PROFILE_URL);
|
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
connection.setRequestMethod("POST");
|
|
connection.setRequestProperty("Content-Type", "application/json");
|
|
connection.setUseCaches(false);
|
|
connection.setDoInput(true);
|
|
connection.setDoOutput(true);
|
|
return connection;
|
|
}
|
|
|
|
private static UUID getUUID(String id) {
|
|
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +id.substring(20, 32));
|
|
}
|
|
|
|
public static byte[] toBytes(UUID uuid) {
|
|
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
|
|
byteBuffer.putLong(uuid.getMostSignificantBits());
|
|
byteBuffer.putLong(uuid.getLeastSignificantBits());
|
|
return byteBuffer.array();
|
|
}
|
|
|
|
public static UUID fromBytes(byte[] array) {
|
|
if (array.length != 16) {
|
|
throw new IllegalArgumentException("Illegal byte array length: " + array.length);
|
|
}
|
|
ByteBuffer byteBuffer = ByteBuffer.wrap(array);
|
|
long mostSignificant = byteBuffer.getLong();
|
|
long leastSignificant = byteBuffer.getLong();
|
|
return new UUID(mostSignificant, leastSignificant);
|
|
}
|
|
|
|
public static UUID getUUIDOf(String name) throws Exception
|
|
{
|
|
if(lookupCache == null)
|
|
{
|
|
lookupCache = new HashMap<String, UUID>();
|
|
}
|
|
|
|
UUID result = lookupCache.get(name);
|
|
if(result == null)
|
|
{
|
|
if(lookupCache.containsKey(name)) return null;
|
|
|
|
String correctCasingName = getNameWithCasing(name);
|
|
|
|
result = new UUIDFetcher(Arrays.asList(name)).call().get(correctCasingName);
|
|
if(result == null)
|
|
{
|
|
GriefPrevention.AddLogEntry(correctCasingName + " --> ???");
|
|
lookupCache.put(name, null);
|
|
throw new IllegalArgumentException(name);
|
|
}
|
|
GriefPrevention.AddLogEntry(correctCasingName + " --> " + result.toString());
|
|
lookupCache.put(name, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static String getNameWithCasing(String name)
|
|
{
|
|
OfflinePlayer [] players = GriefPrevention.instance.getServer().getOfflinePlayers();
|
|
for(OfflinePlayer player : players)
|
|
{
|
|
if(player.getName().equalsIgnoreCase(name))
|
|
{
|
|
if(!player.getName().equals(name))
|
|
{
|
|
GriefPrevention.AddLogEntry(name + " --> " + player.getName());
|
|
}
|
|
return player.getName();
|
|
}
|
|
}
|
|
|
|
return name;
|
|
}
|
|
} |