mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-06-25 18:24:43 +02:00
UUID updater changes + locale fixes
Co-authored-by: t00thpick1 <t00thpick1dirko@gmail.com>
This commit is contained in:
@ -12,9 +12,6 @@ public class HiddenConfig {
|
||||
private boolean chunkletsEnabled;
|
||||
private int conversionRate;
|
||||
private boolean useEnchantmentBuffs;
|
||||
private int uuidConvertAmount;
|
||||
private int mojangRateLimit;
|
||||
private long mojangLimitPeriod;
|
||||
|
||||
public HiddenConfig(String fileName) {
|
||||
this.fileName = fileName;
|
||||
@ -36,9 +33,6 @@ public class HiddenConfig {
|
||||
chunkletsEnabled = config.getBoolean("Options.Chunklets", true);
|
||||
conversionRate = config.getInt("Options.ConversionRate", 1);
|
||||
useEnchantmentBuffs = config.getBoolean("Options.EnchantmentBuffs", true);
|
||||
uuidConvertAmount = config.getInt("Options.UUIDConvertAmount", 5);
|
||||
mojangRateLimit = config.getInt("Options.MojangRateLimit", 50000);
|
||||
mojangLimitPeriod = config.getLong("Options.MojangLimitPeriod", 600000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,16 +47,4 @@ public class HiddenConfig {
|
||||
public boolean useEnchantmentBuffs() {
|
||||
return useEnchantmentBuffs;
|
||||
}
|
||||
|
||||
public int getUUIDConvertAmount() {
|
||||
return uuidConvertAmount;
|
||||
}
|
||||
|
||||
public int getMojangRateLimit() {
|
||||
return mojangRateLimit;
|
||||
}
|
||||
|
||||
public long getMojangLimitPeriod() {
|
||||
return mojangLimitPeriod;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
|
||||
updateLeaderboards();
|
||||
|
||||
if (mcMMO.getUpgradeManager().shouldUpgrade(UpgradeType.ADD_UUIDS)) {
|
||||
new UUIDUpdateAsyncTask(mcMMO.p, getStoredUsers()).runTaskAsynchronously(mcMMO.p);
|
||||
new UUIDUpdateAsyncTask(mcMMO.p, getStoredUsers()).start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1338,7 +1338,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
|
||||
}
|
||||
|
||||
if (!names.isEmpty()) {
|
||||
new UUIDUpdateAsyncTask(mcMMO.p, names).run();
|
||||
UUIDUpdateAsyncTask updateTask = new UUIDUpdateAsyncTask(mcMMO.p, names);
|
||||
updateTask.start();
|
||||
updateTask.waitUntilFinished();
|
||||
}
|
||||
} finally {
|
||||
massUpdateLock.unlock();
|
||||
|
@ -1,105 +1,130 @@
|
||||
package com.gmail.nossr50.runnables.database;
|
||||
|
||||
import com.gmail.nossr50.config.HiddenConfig;
|
||||
import com.gmail.nossr50.database.DatabaseManager;
|
||||
import com.gmail.nossr50.datatypes.database.UpgradeType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.uuid.UUIDFetcher;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
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();
|
||||
private static final long LIMIT_PERIOD = HiddenConfig.getInstance().getMojangLimitPeriod();
|
||||
private static final int BATCH_SIZE = MAX_LOOKUP * 3;
|
||||
public class UUIDUpdateAsyncTask implements Runnable {
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
|
||||
|
||||
private List<String> userNames;
|
||||
private int size;
|
||||
private int checkedUsers;
|
||||
private long startMillis;
|
||||
private static final int HARD_LIMIT_PERIOD = 600; // Mojang rate limit period is 600 seconds, wait that long if they reject us
|
||||
private static final int RETRY_PERIOD = 60; // Wait 60 seconds on connection failure
|
||||
private static final int DELAY_PERIOD = 100; // Wait 100 seconds between each batch
|
||||
|
||||
private static final int BATCH_SIZE = 100; // 100 at a time
|
||||
|
||||
private final Object awaiter = new Object();
|
||||
private final mcMMO plugin;
|
||||
private final ImmutableList<String> userNames;
|
||||
private int position = 0;
|
||||
|
||||
public UUIDUpdateAsyncTask(mcMMO plugin, List<String> userNames) {
|
||||
this.plugin = plugin;
|
||||
this.userNames = userNames;
|
||||
|
||||
this.checkedUsers = 0;
|
||||
this.startMillis = System.currentTimeMillis();
|
||||
this.userNames = ImmutableList.copyOf(userNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
size = userNames.size();
|
||||
// First iteration
|
||||
if (position == 0)
|
||||
plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + userNames.size());
|
||||
|
||||
plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + size);
|
||||
List<String> batch = userNames.subList(position, Math.min(userNames.size(), position + BATCH_SIZE));
|
||||
|
||||
List<String> userNamesSection;
|
||||
Map<String, UUID> fetchedUUIDs = new HashMap<String, UUID>();
|
||||
Map<String, UUID> fetchedUUIDs = new HashMap<>();
|
||||
HttpURLConnection connection;
|
||||
try {
|
||||
connection = (HttpURLConnection) new URL(PROFILE_URL).openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
|
||||
while (size != 0) {
|
||||
if (checkedUsers + 100 > RATE_LIMIT) {
|
||||
try {
|
||||
Thread.sleep(LIMIT_PERIOD);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
String body = GSON.toJson(batch.toArray(new String[0]));
|
||||
|
||||
try (OutputStream output = connection.getOutputStream()) {
|
||||
output.write(body.getBytes());
|
||||
output.flush();
|
||||
}
|
||||
switch (connection.getResponseCode()) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
break; // All is good
|
||||
case HttpURLConnection.HTTP_BAD_REQUEST:
|
||||
case HttpURLConnection.HTTP_FORBIDDEN:
|
||||
// Rejected, probably rate limit, just wait it out
|
||||
this.runTaskLaterAsynchronously(plugin, Misc.TICK_CONVERSION_FACTOR * HARD_LIMIT_PERIOD);
|
||||
return;
|
||||
default:
|
||||
// Unknown failure
|
||||
this.runTaskLaterAsynchronously(plugin, Misc.TICK_CONVERSION_FACTOR * RETRY_PERIOD);
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream input = connection.getInputStream();
|
||||
InputStreamReader reader = new InputStreamReader(input)) {
|
||||
for (JsonObject jsonProfile : GSON.fromJson(reader, JsonObject[].class)) {
|
||||
UUID id = toUUID(jsonProfile.get("id").getAsString());
|
||||
String name = jsonProfile.get("name").getAsString();
|
||||
fetchedUUIDs.put(name, id);
|
||||
}
|
||||
startMillis = System.currentTimeMillis();
|
||||
checkedUsers = 0;
|
||||
}
|
||||
if (size > MAX_LOOKUP) {
|
||||
userNamesSection = userNames.subList(size - MAX_LOOKUP, size);
|
||||
size -= MAX_LOOKUP;
|
||||
}
|
||||
else {
|
||||
userNamesSection = userNames.subList(0, size);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
fetchedUUIDs.putAll(new UUIDFetcher(userNamesSection).call());
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Handle 429
|
||||
if(e.getMessage() != null)
|
||||
{
|
||||
if (e.getMessage().contains("429")) {
|
||||
size += userNamesSection.size();
|
||||
try {
|
||||
Thread.sleep(LIMIT_PERIOD);
|
||||
} catch (InterruptedException ex) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUIDs!", e);
|
||||
return;
|
||||
}
|
||||
|
||||
checkedUsers += userNamesSection.size();
|
||||
userNamesSection.clear();
|
||||
size = userNames.size();
|
||||
|
||||
Misc.printProgress(checkedUsers, DatabaseManager.progressInterval, startMillis);
|
||||
if (fetchedUUIDs.size() >= BATCH_SIZE) {
|
||||
mcMMO.getDatabaseManager().saveUserUUIDs(fetchedUUIDs);
|
||||
fetchedUUIDs = new HashMap<String, UUID>();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// failure
|
||||
plugin.getLogger().log(Level.SEVERE, "Unable to contact mojang API!", e);
|
||||
this.runTaskLaterAsynchronously(plugin, Misc.TICK_CONVERSION_FACTOR * RETRY_PERIOD);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fetchedUUIDs.size() == 0 || mcMMO.getDatabaseManager().saveUserUUIDs(fetchedUUIDs)) {
|
||||
if (fetchedUUIDs.size() != 0)
|
||||
mcMMO.getDatabaseManager().saveUserUUIDs(fetchedUUIDs);
|
||||
|
||||
position += batch.size();
|
||||
plugin.getLogger().info(String.format("Conversion progress: %d/%d users", position, userNames.size()));
|
||||
|
||||
if (position == userNames.size())
|
||||
{
|
||||
mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_UUIDS);
|
||||
plugin.getLogger().info("UUID upgrade completed!");
|
||||
awaiter.notify();
|
||||
}
|
||||
else
|
||||
this.runTaskLaterAsynchronously(plugin, Misc.TICK_CONVERSION_FACTOR * DELAY_PERIOD); // Schedule next batch
|
||||
}
|
||||
|
||||
// Bukkit runnables don't let themselves reschedule themselves, so we are a pseudo bukkit runnable.
|
||||
private void runTaskLaterAsynchronously(mcMMO plugin, int delay) {
|
||||
plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, this, delay);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this);
|
||||
}
|
||||
|
||||
private static UUID toUUID(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 void waitUntilFinished() {
|
||||
try {
|
||||
awaiter.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// I guess we don't care in this event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user