diff --git a/pom.xml b/pom.xml
index cec0553af..e649e58e1 100755
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
com.turt2live.metrics:MetricsExtension
commons-logging:commons-logging
net.snaq:dbpool
+ com.turt2live:UUID-Library
@@ -93,6 +94,10 @@
net.snaq
com.gmail.nossr50.dbpool
+
+ com.turt2live.uuid
+ com.gmail.nossr50.uuid
+
@@ -123,7 +128,7 @@
http://repo.md-5.net/content/repositories/releases/
- Plugin MetricsExtension
+ turt2live-repo
http://repo.turt2live.com
@@ -151,6 +156,11 @@
dbpool
5.1
+
+ com.turt2live
+ UUID-Library
+ 0.0.1-SNAPSHOT
+
diff --git a/src/main/java/com/gmail/nossr50/config/Config.java b/src/main/java/com/gmail/nossr50/config/Config.java
index 3aa8d1706..d09cac8ba 100644
--- a/src/main/java/com/gmail/nossr50/config/Config.java
+++ b/src/main/java/com/gmail/nossr50/config/Config.java
@@ -250,6 +250,7 @@ public class Config extends AutoUpdateConfigLoader {
public boolean getUpdateCheckEnabled() { return config.getBoolean("General.Update_Check", true); }
public boolean getPreferBeta() { return config.getBoolean("General.Prefer_Beta", false); }
public boolean getVerboseLoggingEnabled() { return config.getBoolean("General.Verbose_Logging", false); }
+ public boolean getUseUUIDWebCache(){ return config.getBoolean("General.Use_UUID_Web_Cache", false); }
public String getPartyChatPrefix() { return config.getString("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])"); }
public boolean getPartyChatColorLeaderName() { return config.getBoolean("Commands.partychat.Gold_Leader_Name", true); }
diff --git a/src/main/java/com/gmail/nossr50/runnables/database/UUIDUpdateAsyncTask.java b/src/main/java/com/gmail/nossr50/runnables/database/UUIDUpdateAsyncTask.java
index 54504e8c6..a14e44fa8 100644
--- a/src/main/java/com/gmail/nossr50/runnables/database/UUIDUpdateAsyncTask.java
+++ b/src/main/java/com/gmail/nossr50/runnables/database/UUIDUpdateAsyncTask.java
@@ -13,9 +13,10 @@ import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.database.DatabaseManager;
import com.gmail.nossr50.datatypes.database.UpgradeType;
import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.uuid.UUIDFetcher;
+import com.gmail.nossr50.util.uuid.UUIDService;
public class UUIDUpdateAsyncTask extends BukkitRunnable {
+
private mcMMO plugin;
private static final int MAX_LOOKUP = Math.max(HiddenConfig.getInstance().getUUIDConvertAmount(), 100);
private static final int RATE_LIMIT = HiddenConfig.getInstance().getMojangRateLimit();
@@ -25,6 +26,7 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
private List userNames;
private int size;
private int checkedUsers;
+ private int fetchedUsers;
private long startMillis;
public UUIDUpdateAsyncTask(mcMMO plugin, List userNames) {
@@ -32,12 +34,14 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
this.userNames = userNames;
this.checkedUsers = 0;
+ this.fetchedUsers = 0;
this.startMillis = System.currentTimeMillis();
}
@Override
public void run() {
size = userNames.size();
+ UUIDService uuidService = null;
plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + size);
@@ -45,7 +49,7 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
Map fetchedUUIDs = new HashMap();
while (size != 0) {
- if (checkedUsers + 100 > RATE_LIMIT) {
+ if (fetchedUsers + 100 > RATE_LIMIT) {
try {
Thread.sleep(LIMIT_PERIOD);
} catch (InterruptedException e) {
@@ -53,25 +57,27 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
return;
}
startMillis = System.currentTimeMillis();
- checkedUsers = 0;
+ fetchedUsers = 0;
}
if (size > MAX_LOOKUP) {
userNamesSection = userNames.subList(size - MAX_LOOKUP, size);
size -= MAX_LOOKUP;
- }
- else {
+ } else {
userNamesSection = userNames.subList(0, size);
size = 0;
}
try {
- fetchedUUIDs.putAll(new UUIDFetcher(userNamesSection).call());
- }
- catch (Exception e) {
+ if (uuidService == null) uuidService = new UUIDService(userNamesSection);
+ else uuidService.setList(userNamesSection);
+
+ fetchedUUIDs.putAll(uuidService.call());
+ } catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUIDs!", e);
return;
}
+ fetchedUsers += uuidService.getNumberFetched();
checkedUsers += userNamesSection.size();
userNamesSection.clear();
size = userNames.size();
diff --git a/src/main/java/com/gmail/nossr50/util/uuid/UUIDService.java b/src/main/java/com/gmail/nossr50/util/uuid/UUIDService.java
new file mode 100644
index 000000000..065ec952d
--- /dev/null
+++ b/src/main/java/com/gmail/nossr50/util/uuid/UUIDService.java
@@ -0,0 +1,111 @@
+package com.gmail.nossr50.util.uuid;
+
+import com.gmail.nossr50.config.Config;
+import com.google.common.collect.ImmutableList;
+import com.turt2live.uuid.CachingServiceProvider;
+import com.turt2live.uuid.PlayerRecord;
+import com.turt2live.uuid.ServiceProvider;
+import com.turt2live.uuid.turt2live.v2.ApiV2Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Service layer for UUIDs
+ *
+ * @author turt2live
+ */
+public class UUIDService {
+
+ private static final int SERVICE_LIMIT_PER_REQUEST = 100;
+
+ private static ServiceProvider UUID_PROVIDER;
+
+ private List names;
+ private int numFetched = 0; // From last request
+
+ /**
+ * Creates a new UUID service that takes a list of usernames
+ * to lookup via {@link #call()}
+ *
+ * @param names the names to lookup
+ */
+ public UUIDService(List names) {
+ this.names = ImmutableList.copyOf(names);
+ }
+
+ /**
+ * Sets a new list of names to parse
+ *
+ * @param names the names to lookup
+ */
+ public void setList(List names) {
+ this.names = ImmutableList.copyOf(names);
+ }
+
+ /**
+ * Parses the predefined list of names to a UUID map
+ *
+ * @return the generated map
+ */
+ public Map call() throws Exception {
+ int fetched = 0;
+ Map map = new HashMap();
+
+ if (Config.getInstance().getUseUUIDWebCache()) {
+ int requests = (int) Math.ceil(names.size() / SERVICE_LIMIT_PER_REQUEST);
+ for (int i = 0; i < requests; i++) {
+ List subNames = names.subList(i * SERVICE_LIMIT_PER_REQUEST, Math.min((i + 1) * SERVICE_LIMIT_PER_REQUEST, names.size()));
+ List records = UUID_PROVIDER.doBulkLookup(subNames.toArray(new String[subNames.size()]));
+
+ // List only includes successful lookups
+ for (PlayerRecord record : records) {
+ map.put(record.getName(), record.getUuid());
+ if (!record.isCached()) fetched++;
+ }
+ }
+ } else {
+ map = new UUIDFetcher(names).call();
+ fetched = map.size();
+ }
+
+ numFetched = fetched;
+ return map;
+ }
+
+ /**
+ * Gets the number of profiles that were actually fetched from the last
+ * call to {@link #call()}.
+ *
+ * @return the number of profiles actually fetched
+ */
+ public int getNumberFetched() {
+ return numFetched;
+ }
+
+ /**
+ * Gets the UUID for the supplied username
+ *
+ * @param name the username to lookup, cannot be null
+ *
+ * @return the UUID, if found.
+ *
+ * @throws Exception thrown if something goes wrong
+ */
+ public static UUID getUUIDOf(String name) throws Exception {
+ if (name == null) throw new IllegalArgumentException();
+
+ if (Config.getInstance().getUseUUIDWebCache()) {
+ if (UUID_PROVIDER == null) initProvider();
+ PlayerRecord record = UUID_PROVIDER.doLookup(name);
+ return record == null ? null : record.getUuid();
+ } else return UUIDFetcher.getUUIDOf(name);
+ }
+
+ private static void initProvider() {
+ UUID_PROVIDER = new CachingServiceProvider(new ApiV2Service());
+ }
+
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index a0ace507a..2a3b9d592 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -26,6 +26,10 @@ General:
Config_Update_Overwrite: true
# Play level-up sounds
LevelUp_Sounds: true
+ # Instead of asking Mojang for UUIDs, should mcMMO access a web caching service
+ # for player UUIDs? If enabled, mcMMO will use the web service. If disabled, mcMMO
+ # will use Mojang.
+ Use_UUID_Web_Cache: false
# This should fix blocks being broken client side, but not server-side.
# Enable to refresh the chunks around a player at the end of Super Breaker,