diff --git a/pom.xml b/pom.xml index 4378eaf69..e3c0e7c2b 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,14 @@ org.apache ru.tehkode.libs.org.apache + + com.mojang + ru.tehkode.libs.com.mojang + + + com.google.gson + ru.tehkode.libs.com.google.gson + @@ -150,6 +158,11 @@ updater LATEST + + com.mojang + AccountsClient + unspecified + diff --git a/src/main/java/ru/tehkode/permissions/PermissionManager.java b/src/main/java/ru/tehkode/permissions/PermissionManager.java index 21f219019..cfbfbd3ee 100644 --- a/src/main/java/ru/tehkode/permissions/PermissionManager.java +++ b/src/main/java/ru/tehkode/permissions/PermissionManager.java @@ -707,4 +707,8 @@ public Collection getGroupNames() { public Logger getLogger() { return logger; } + + public ScheduledExecutorService getExecutor() { + return executor; + } } diff --git a/src/main/java/ru/tehkode/permissions/bukkit/commands/UtilityCommands.java b/src/main/java/ru/tehkode/permissions/bukkit/commands/UtilityCommands.java index b67cd5fc0..a5d9d9729 100644 --- a/src/main/java/ru/tehkode/permissions/bukkit/commands/UtilityCommands.java +++ b/src/main/java/ru/tehkode/permissions/bukkit/commands/UtilityCommands.java @@ -18,6 +18,10 @@ */ package ru.tehkode.permissions.bukkit.commands; +import com.google.common.collect.Iterables; +import com.mojang.api.profiles.HttpProfileRepository; +import com.mojang.api.profiles.Profile; +import com.mojang.api.profiles.ProfileRepository; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -34,9 +38,12 @@ import java.io.File; import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; public class UtilityCommands extends PermissionsCommand { @@ -151,41 +158,59 @@ public void printHierarchy(PermissionsEx plugin, CommandSender sender, Map args) { - PermissionBackend backend = plugin.getPermissionsManager().getBackend(); + public void convertUUID(final PermissionsEx plugin, final CommandSender sender, Map args) { + final PermissionBackend backend = plugin.getPermissionsManager().getBackend(); if (!plugin.getServer().getOnlineMode() && !"force".equals(args.get("force"))) { sender.sendMessage(ChatColor.RED + "This server is running in offline mode and UUIDs may not be stable. Please run '/pex convert uuid force' to perform conversion anyway, or switch to online mode."); return; } - int count = 0; - sender.sendMessage("Beginning conversion to UUID (This may take a while (a long while))"); + final ProfileRepository repo = new HttpProfileRepository("minecraft"); + final Collection userIdentifiers = backend.getUserIdentifiers(); + for (Iterator it = backend.getUserIdentifiers().iterator(); it.hasNext(); ) { + try { + UUID.fromString(it.next()); + it.remove(); + } catch (IllegalArgumentException ex) { + } + } + + if (userIdentifiers.isEmpty()) { + sender.sendMessage(ChatColor.RED + "No users to convert!"); + return; + } + + sender.sendMessage("Beginning conversion to UUID in " + (int) Math.ceil(userIdentifiers.size() / 50000.0) + " batches of max 50k (1 batch is executed every 10 minutes)"); backend.setPersistent(false); - try { - Collection userIdentifiers = backend.getUserIdentifiers(); - for (String name : backend.getUserIdentifiers()) { + final Iterator> splitIdentifiers = Iterables.partition(userIdentifiers, 50 * 1000).iterator(); // 50k users per 10 minutes + final AtomicInteger batchNum = new AtomicInteger(1); + + plugin.getPermissionsManager().getExecutor().execute(new Runnable() { + @Override + public void run() { + List names = splitIdentifiers.next(); try { - UUID uid = UUID.fromString(name); - continue; - } catch (IllegalArgumentException ex) { - // We aren't doing uuid - OfflinePlayer player = plugin.getServer().getOfflinePlayer(name); - if (player.getName() == null || player.getUniqueId() == null) { - sender.sendMessage("Unable to convert user named " + name + " because name or UUID in profile was null!"); - continue; + for (Profile profile : repo.findProfilesByNames(names.toArray(new String[names.size()]))) { + PermissionsUserData data = backend.getUserData(profile.getName()); + data.setIdentifier(profile.getId().replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); + data.setOption("name", profile.getName(), null); } - - PermissionsUserData userData = backend.getUserData(name); - userData.setIdentifier(player.getUniqueId().toString()); - userData.setOption("name", player.getName(), null); - if (++count % 100 == 0) { - sender.sendMessage(ChatColor.GRAY + "Converted " + count + " of " + userIdentifiers.size() + " users"); + } catch (Exception e) { + ErrorReport.handleError("While converting batch " + batchNum.get() + " to UUID", e); + backend.setPersistent(true); + return; + } + if (splitIdentifiers.hasNext()) { + plugin.getPermissionsManager().getExecutor().schedule(this, 10, TimeUnit.MINUTES); + plugin.getLogger().info("Completed conversion batch " + batchNum.getAndIncrement() + " of " + (int) Math.ceil(userIdentifiers.size() / 50000.0)); + } else { + plugin.getLogger().info("UUID conversion complete"); + if (!(sender instanceof Player) || ((Player) sender).isOnline()) { + sender.sendMessage("UUID conversion complete"); } + backend.setPersistent(true); } } - } finally { - backend.setPersistent(true); - } - sender.sendMessage(ChatColor.GREEN + "Conversion to UUID complete!"); + }); } @Command(name = "pex",