diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index f942b2998..2b607a813 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -40,6 +40,7 @@ import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -102,7 +103,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials public Essentials() { - } public Essentials(final Server server) @@ -187,12 +187,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials settings = new Settings(this); confList.add(settings); execTimer.mark("Settings"); - upgrade.afterSettings(); - execTimer.mark("Upgrade2"); - i18n.updateLocale(settings.getLocale()); userMap = new UserMap(this); confList.add(userMap); execTimer.mark("Init(Usermap)"); + upgrade.afterSettings(); + execTimer.mark("Upgrade2"); + i18n.updateLocale(settings.getLocale()); warps = new Warps(getServer(), this.getDataFolder()); confList.add(warps); execTimer.mark("Init(Spawn/Warp)"); @@ -634,7 +634,14 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials @Override public User getUser(final String base) { - return getOfflineUser((String)base); + return getOfflineUser(base); + } + + //This will return null if there is not a match. + @Override + public User getUser(final UUID base) + { + return userMap.getUser(base); } //This will return null if there is not a match. @@ -664,7 +671,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials return null; } - User user = userMap.getUser(base.getName()); + User user = userMap.getUser(base.getUniqueId()); if (user == null) { diff --git a/Essentials/src/com/earth2me/essentials/EssentialsConf.java b/Essentials/src/com/earth2me/essentials/EssentialsConf.java index 7fdf3baf4..3ce2151ea 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsConf.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsConf.java @@ -31,11 +31,11 @@ import org.bukkit.util.Vector; public class EssentialsConf extends YamlConfiguration { - private static final Logger LOGGER = Logger.getLogger("Essentials"); - private final File configFile; - private String templateName = null; - private Class resourceClass = EssentialsConf.class; - private static final Charset UTF8 = Charset.forName("UTF-8"); + protected static final Logger LOGGER = Logger.getLogger("Essentials"); + protected final File configFile; + protected String templateName = null; + protected static final Charset UTF8 = Charset.forName("UTF-8"); + private Class resourceClass = EssentialsConf.class; private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor(); private final AtomicInteger pendingDiskWrites = new AtomicInteger(0); @@ -95,10 +95,14 @@ public class EssentialsConf extends YamlConfiguration LOGGER.log(Level.SEVERE, null, ex); } } - + if (!configFile.exists()) { - if (templateName != null) + if (legacyFileExists()) + { + convertLegacyFile(); + } + else if (templateName != null) { LOGGER.log(Level.INFO, tl("creatingConfigFromTemplate", configFile.toString())); createFromTemplate(); @@ -166,6 +170,7 @@ public class EssentialsConf extends YamlConfiguration finally { inputStream.close(); + save(); } } catch (IOException ex) @@ -179,6 +184,16 @@ public class EssentialsConf extends YamlConfiguration LOGGER.log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), ex.getCause()); } } + + public boolean legacyFileExists() + { + return false; + } + + public void convertLegacyFile() + { + LOGGER.log(Level.SEVERE, "Unable to import legacy config file."); + } private void createFromTemplate() { diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java index 70943e149..307e4fea3 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java @@ -230,7 +230,7 @@ public class EssentialsPlayerListener implements Listener return; } - user.trackUUID(); + user.setLastAccountName(user.getBase().getName()); user.setLastLogin(currentTime); user.setDisplayNick(); updateCompass(user); diff --git a/Essentials/src/com/earth2me/essentials/EssentialsUpgrade.java b/Essentials/src/com/earth2me/essentials/EssentialsUpgrade.java index fe3f5129d..b94512676 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsUpgrade.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsUpgrade.java @@ -15,9 +15,7 @@ import java.util.logging.Logger; import net.ess3.api.IEssentials; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.inventory.ItemStack; public class EssentialsUpgrade @@ -37,46 +35,6 @@ public class EssentialsUpgrade doneFile.load(); } - private void moveWorthValuesToWorthYml() - { - if (doneFile.getBoolean("moveWorthValuesToWorthYml", false)) - { - return; - } - try - { - final File configFile = new File(ess.getDataFolder(), "config.yml"); - if (!configFile.exists()) - { - return; - } - final EssentialsConf conf = new EssentialsConf(configFile); - conf.load(); - final Worth worth = new Worth(ess.getDataFolder()); - boolean found = false; - for (Material mat : Material.values()) - { - final int id = mat.getId(); - final double value = conf.getDouble("worth-" + id, Double.NaN); - if (!Double.isNaN(value)) - { - found = true; - worth.setPrice(new ItemStack(mat, 1, (short)0, (byte)0), value); - } - } - if (found) - { - removeLinesFromConfig(configFile, "\\s*#?\\s*worth-[0-9]+.*", "# Worth values have been moved to worth.yml"); - } - doneFile.setProperty("moveWorthValuesToWorthYml", true); - doneFile.save(); - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, tl("upgradingFilesError"), e); - } - } - private void moveMotdRulesToFile(String name) { if (doneFile.getBoolean("move" + name + "ToFile", false)) @@ -180,73 +138,6 @@ public class EssentialsUpgrade } } - private void updateUsersToNewDefaultHome() - { - if (doneFile.getBoolean("updateUsersToNewDefaultHome", false)) - { - return; - } - final File userdataFolder = new File(ess.getDataFolder(), "userdata"); - if (!userdataFolder.exists() || !userdataFolder.isDirectory()) - { - return; - } - final File[] userFiles = userdataFolder.listFiles(); - - for (File file : userFiles) - { - if (!file.isFile() || !file.getName().endsWith(".yml")) - { - continue; - } - final EssentialsConf config = new EssentialsConf(file); - try - { - config.load(); - if (config.hasProperty("home") && !config.hasProperty("home.default")) - { - @SuppressWarnings("unchecked") - final List vals = (List)config.getProperty("home"); - if (vals == null) - { - continue; - } - World world = ess.getServer().getWorlds().get(0); - if (vals.size() > 5) - { - world = ess.getServer().getWorld((String)vals.get(5)); - } - if (world != null) - { - final Location loc = new Location( - world, - ((Number)vals.get(0)).doubleValue(), - ((Number)vals.get(1)).doubleValue(), - ((Number)vals.get(2)).doubleValue(), - ((Number)vals.get(3)).floatValue(), - ((Number)vals.get(4)).floatValue()); - - final String worldName = world.getName().toLowerCase(Locale.ENGLISH); - if (worldName != null && !worldName.isEmpty()) - { - config.removeProperty("home"); - config.setProperty("home.default", worldName); - config.setProperty("home.worlds." + worldName, loc); - config.forceSave(); - } - } - } - } - catch (RuntimeException ex) - { - LOGGER.log(Level.INFO, "File: " + file.toString()); - throw ex; - } - } - doneFile.setProperty("updateUsersToNewDefaultHome", true); - doneFile.save(); - } - private void updateUsersPowerToolsFormat() { if (doneFile.getBoolean("updateUsersPowerToolsFormat", false)) @@ -374,195 +265,6 @@ public class EssentialsUpgrade doneFile.save(); } - private void moveUsersDataToUserdataFolder() - { - final File usersFile = new File(ess.getDataFolder(), "users.yml"); - if (!usersFile.exists()) - { - return; - } - final EssentialsConf usersConfig = new EssentialsConf(usersFile); - usersConfig.load(); - for (String username : usersConfig.getKeys(false)) - { - final User user = new User(new OfflinePlayer(username, ess), ess); - final String nickname = usersConfig.getString(username + ".nickname"); - if (nickname != null && !nickname.isEmpty() && !nickname.equals(username)) - { - user.setNickname(nickname); - } - final List mails = usersConfig.getStringList(username + ".mail"); - if (mails != null && !mails.isEmpty()) - { - user.setMails(mails); - } - if (!user.hasHome()) - { - @SuppressWarnings("unchecked") - final List vals = (List)usersConfig.getProperty(username + ".home"); - if (vals != null) - { - World world = ess.getServer().getWorlds().get(0); - if (vals.size() > 5) - { - world = getFakeWorld((String)vals.get(5)); - } - if (world != null) - { - user.setHome("home", new Location(world, - ((Number)vals.get(0)).doubleValue(), - ((Number)vals.get(1)).doubleValue(), - ((Number)vals.get(2)).doubleValue(), - ((Number)vals.get(3)).floatValue(), - ((Number)vals.get(4)).floatValue())); - } - } - } - } - usersFile.renameTo(new File(usersFile.getAbsolutePath() + ".old")); - } - - private void convertWarps() - { - final File warpsFolder = new File(ess.getDataFolder(), "warps"); - if (!warpsFolder.exists()) - { - warpsFolder.mkdirs(); - } - final File[] listOfFiles = warpsFolder.listFiles(); - if (listOfFiles.length >= 1) - { - for (int i = 0; i < listOfFiles.length; i++) - { - final String filename = listOfFiles[i].getName(); - if (listOfFiles[i].isFile() && filename.endsWith(".dat")) - { - try - { - final BufferedReader rx = new BufferedReader(new FileReader(listOfFiles[i])); - double x, y, z; - float yaw, pitch; - String worldName; - try - { - if (!rx.ready()) - { - continue; - } - x = Double.parseDouble(rx.readLine().trim()); - if (!rx.ready()) - { - continue; - } - y = Double.parseDouble(rx.readLine().trim()); - if (!rx.ready()) - { - continue; - } - z = Double.parseDouble(rx.readLine().trim()); - if (!rx.ready()) - { - continue; - } - yaw = Float.parseFloat(rx.readLine().trim()); - if (!rx.ready()) - { - continue; - } - pitch = Float.parseFloat(rx.readLine().trim()); - worldName = rx.readLine(); - } - finally - { - rx.close(); - } - World w = null; - for (World world : ess.getServer().getWorlds()) - { - if (world.getEnvironment() != World.Environment.NETHER) - { - w = world; - break; - } - } - if (worldName != null) - { - worldName = worldName.trim(); - World w1 = null; - w1 = getFakeWorld(worldName); - if (w1 != null) - { - w = w1; - } - } - final Location loc = new Location(w, x, y, z, yaw, pitch); - ess.getWarps().setWarp(filename.substring(0, filename.length() - 4), loc); - if (!listOfFiles[i].renameTo(new File(warpsFolder, filename + ".old"))) - { - throw new Exception(tl("fileRenameError", filename)); - } - } - catch (Exception ex) - { - LOGGER.log(Level.SEVERE, null, ex); - } - } - } - - } - final File warpFile = new File(ess.getDataFolder(), "warps.txt"); - if (warpFile.exists()) - { - try - { - final BufferedReader rx = new BufferedReader(new FileReader(warpFile)); - try - { - for (String[] parts = new String[0]; rx.ready(); parts = rx.readLine().split(":")) - { - if (parts.length < 6) - { - continue; - } - final String name = parts[0]; - final double x = Double.parseDouble(parts[1].trim()); - final double y = Double.parseDouble(parts[2].trim()); - final double z = Double.parseDouble(parts[3].trim()); - final float yaw = Float.parseFloat(parts[4].trim()); - final float pitch = Float.parseFloat(parts[5].trim()); - if (name.isEmpty()) - { - continue; - } - World w = null; - for (World world : ess.getServer().getWorlds()) - { - if (world.getEnvironment() != World.Environment.NETHER) - { - w = world; - break; - } - } - final Location loc = new Location(w, x, y, z, yaw, pitch); - ess.getWarps().setWarp(name, loc); - if (!warpFile.renameTo(new File(ess.getDataFolder(), "warps.txt.old"))) - { - throw new Exception(tl("fileRenameError", "warps.txt")); - } - } - } - finally - { - rx.close(); - } - } - catch (Exception ex) - { - LOGGER.log(Level.SEVERE, null, ex); - } - } - } - private void sanitizeAllUserFilenames() { if (doneFile.getBoolean("sanitizeAllUserFilenames", false)) @@ -791,13 +493,74 @@ public class EssentialsUpgrade doneFile.save(); } + private void uuidFileChange() + { + if (doneFile.getBoolean("uuidFileChange", false)) + { + return; + } + + final File userdir = new File(ess.getDataFolder(), "userdata"); + if (!userdir.exists()) + { + return; + } + for (String string : userdir.list()) + { + if (!string.endsWith(".yml")) + { + continue; + } + final String name = string.substring(0, string.length() - 4); + EssentialsUserConf config; + UUID uuid = null; + try + { + uuid = UUID.fromString(name); + } + catch (IllegalArgumentException ex) + { + File file = new File(userdir, string); + EssentialsConf conf = new EssentialsConf(file); + conf.load(); + conf.setProperty("lastAccountName", name); + conf.forceSave(); + + String uuidString = conf.getString("uuid", null); + + try + { + uuid = UUID.fromString(uuidString); + } + catch (Exception ex2) + { + org.bukkit.OfflinePlayer player = ess.getServer().getOfflinePlayer(name); + uuid = player.getUniqueId(); + } + + if (uuid == null && conf.getBoolean("npc", false)) + { + uuid = UUID.randomUUID(); + } + + if (uuid != null) + { + config = new EssentialsUserConf(name, uuid, new File(userdir, uuid + ".yml")); + config.convertLegacyFile(); + ess.getUserMap().trackUUID(uuid, name); + } + } + } + doneFile.setProperty("uuidFileChange", true); + doneFile.save(); + } + public void beforeSettings() { if (!ess.getDataFolder().exists()) { ess.getDataFolder().mkdirs(); } - moveWorthValuesToWorthYml(); moveMotdRulesToFile("motd"); moveMotdRulesToFile("rules"); } @@ -805,14 +568,12 @@ public class EssentialsUpgrade public void afterSettings() { sanitizeAllUserFilenames(); - updateUsersToNewDefaultHome(); - moveUsersDataToUserdataFolder(); - convertWarps(); updateUsersPowerToolsFormat(); updateUsersHomesFormat(); deleteOldItemsCsv(); updateSpawnsToNewSpawnsConfig(); updateJailsToNewJailsConfig(); + uuidFileChange(); warnMetrics(); } } diff --git a/Essentials/src/com/earth2me/essentials/EssentialsUserConf.java b/Essentials/src/com/earth2me/essentials/EssentialsUserConf.java new file mode 100644 index 000000000..ef5b9f863 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/EssentialsUserConf.java @@ -0,0 +1,45 @@ +package com.earth2me.essentials; + +import com.google.common.io.Files; +import java.io.File; +import java.io.IOException; +import java.util.UUID; +import java.util.logging.Level; +import org.bukkit.Bukkit; + + +public class EssentialsUserConf extends EssentialsConf +{ + final String username; + final UUID uuid; + + public EssentialsUserConf(final String username, final UUID uuid, final File configFile) + { + super(configFile); + this.username = username; + this.uuid = uuid; + } + + @Override + public boolean legacyFileExists() + { + File file = new File(configFile.getParentFile(), username + ".yml"); + return file.exists(); + } + + @Override + public void convertLegacyFile() + { + File file = new File(configFile.getParentFile(), username + ".yml"); + try + { + Files.move(file, new File(configFile.getParentFile(), uuid + ".yml")); + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex); + } + + setProperty("lastAccountName", username); + } +} diff --git a/Essentials/src/com/earth2me/essentials/IEssentials.java b/Essentials/src/com/earth2me/essentials/IEssentials.java index f293dbd6c..ea18fb329 100644 --- a/Essentials/src/com/earth2me/essentials/IEssentials.java +++ b/Essentials/src/com/earth2me/essentials/IEssentials.java @@ -7,6 +7,7 @@ import com.earth2me.essentials.metrics.Metrics; import com.earth2me.essentials.perm.PermissionsHandler; import com.earth2me.essentials.register.payment.Methods; import java.util.List; +import java.util.UUID; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -27,6 +28,8 @@ public interface IEssentials extends Plugin @Deprecated User getUser(Object base); + User getUser(UUID base); + User getUser(String base); User getUser(Player base); diff --git a/Essentials/src/com/earth2me/essentials/OfflinePlayer.java b/Essentials/src/com/earth2me/essentials/OfflinePlayer.java index 5fbdb289d..9e725473d 100644 --- a/Essentials/src/com/earth2me/essentials/OfflinePlayer.java +++ b/Essentials/src/com/earth2me/essentials/OfflinePlayer.java @@ -35,6 +35,13 @@ public class OfflinePlayer implements Player private boolean allowFlight = false; private boolean isFlying = false; + public OfflinePlayer(final UUID uuid, final IEssentials ess) + { + this.ess = ess; + this.world = ess.getServer().getWorlds().get(0); + this.base = ess.getServer().getOfflinePlayer(uuid); + } + public OfflinePlayer(final String name, final IEssentials ess) { this.ess = ess; diff --git a/Essentials/src/com/earth2me/essentials/PlayerExtension.java b/Essentials/src/com/earth2me/essentials/PlayerExtension.java index 0038a3e0f..36c2289e3 100644 --- a/Essentials/src/com/earth2me/essentials/PlayerExtension.java +++ b/Essentials/src/com/earth2me/essentials/PlayerExtension.java @@ -1,6 +1,9 @@ package com.earth2me.essentials; import lombok.Delegate; +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Entity; @@ -13,12 +16,6 @@ import org.bukkit.permissions.ServerOperator; public class PlayerExtension { - @Delegate(types = - { - Player.class, Entity.class, CommandSender.class, ServerOperator.class, - HumanEntity.class, ConfigurationSerializable.class, LivingEntity.class, - Permissible.class - }) protected Player base; public PlayerExtension(final Player base) @@ -35,4 +32,17 @@ public class PlayerExtension { return this.base = base; } + + public Server getServer() + { + return base.getServer(); + } + + public World getWorld() { + return base.getWorld(); + } + + public Location getLocation() { + return base.getLocation(); + } } diff --git a/Essentials/src/com/earth2me/essentials/User.java b/Essentials/src/com/earth2me/essentials/User.java index 8107727d1..c6c81dc84 100644 --- a/Essentials/src/com/earth2me/essentials/User.java +++ b/Essentials/src/com/earth2me/essentials/User.java @@ -135,7 +135,7 @@ public class User extends UserData implements Comparable, IReplyTo, net.es } @Override - public void giveMoney(final BigDecimal value) throws MaxMoneyException + public void giveMoney(final BigDecimal value) throws MaxMoneyException { giveMoney(value, (CommandSource)null); } @@ -225,7 +225,7 @@ public class User extends UserData implements Comparable, IReplyTo, net.es public void dispose() { - this.base = new OfflinePlayer(getName(), ess); + this.base = new OfflinePlayer(base.getUniqueId(), ess); } @Override @@ -493,7 +493,7 @@ public class User extends UserData implements Comparable, IReplyTo, net.es { return; } - + this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") ? true : set); if (set && !isAfk()) { @@ -505,7 +505,7 @@ public class User extends UserData implements Comparable, IReplyTo, net.es } _setAfk(set); } - + public boolean toggleAfk() { setAfk(!isAfk()); diff --git a/Essentials/src/com/earth2me/essentials/UserData.java b/Essentials/src/com/earth2me/essentials/UserData.java index 20734b461..33ce24b9f 100644 --- a/Essentials/src/com/earth2me/essentials/UserData.java +++ b/Essentials/src/com/earth2me/essentials/UserData.java @@ -18,7 +18,7 @@ import org.bukkit.inventory.ItemStack; public abstract class UserData extends PlayerExtension implements IConf { protected final transient IEssentials ess; - private final EssentialsConf config; + private final EssentialsUserConf config; private final File folder; protected UserData(Player base, IEssentials ess) @@ -30,7 +30,20 @@ public abstract class UserData extends PlayerExtension implements IConf { folder.mkdirs(); } - config = new EssentialsConf(new File(folder, StringUtil.sanitizeFileName(base.getName()) + ".yml")); + + String filename; + try + { + filename = base.getUniqueId().toString(); + } + catch (Throwable ex) + { + ess.getLogger().warning("Falling back to old username system for " + base.getName()); + filename = base.getName(); + } + + ess.getLogger().info("Loading yml: " + filename + ".yml"); + config = new EssentialsUserConf(base.getName(), base.getUniqueId(), new File(folder, filename + ".yml")); reloadConfig(); } @@ -71,6 +84,7 @@ public abstract class UserData extends PlayerExtension implements IConf nickname = _getNickname(); ignoredPlayers = _getIgnoredPlayers(); logoutLocation = _getLogoutLocation(); + lastAccountName = _getLastAccountName(); } private BigDecimal money; @@ -799,6 +813,25 @@ public abstract class UserData extends PlayerExtension implements IConf { return isNPC; } + private String lastAccountName = null; + + public String getLastAccountName() + { + return lastAccountName; + } + + public String _getLastAccountName() + { + return config.getString("lastAccountName", null); + } + + public void setLastAccountName(String lastAccountName) + { + this.lastAccountName = lastAccountName; + config.setProperty("lastAccountName", lastAccountName); + config.save(); + ess.getUserMap().trackUUID(base.getUniqueId(), lastAccountName); + } public void setNPC(boolean set) { @@ -873,12 +906,6 @@ public abstract class UserData extends PlayerExtension implements IConf config.save(); } - public void trackUUID() - { - config.setProperty("uuid", base.getUniqueId().toString()); - config.save(); - } - public void setConfigProperty(String node, Object object) { final String prefix = "info."; diff --git a/Essentials/src/com/earth2me/essentials/UserMap.java b/Essentials/src/com/earth2me/essentials/UserMap.java index 2b2f26a1a..7060cbe5a 100644 --- a/Essentials/src/com/earth2me/essentials/UserMap.java +++ b/Essentials/src/com/earth2me/essentials/UserMap.java @@ -4,27 +4,44 @@ import com.earth2me.essentials.utils.StringUtil; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; +import com.google.common.io.Files; import com.google.common.util.concurrent.UncheckedExecutionException; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; import java.util.Collections; +import java.util.Map; import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; import net.ess3.api.IEssentials; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; -public class UserMap extends CacheLoader implements IConf +public class UserMap extends CacheLoader implements IConf { private final transient IEssentials ess; - private final transient Cache users; - private final transient ConcurrentSkipListSet keys = new ConcurrentSkipListSet(); + private final transient Cache users; + private final transient ConcurrentSkipListSet keys = new ConcurrentSkipListSet(); + private final transient ConcurrentSkipListMap names = new ConcurrentSkipListMap(); + private final transient Pattern splitPattern = Pattern.compile(","); + private File userList; public UserMap(final IEssentials ess) { super(); this.ess = ess; - users = CacheBuilder.newBuilder().maximumSize(ess.getSettings().getMaxUserCacheCount()).softValues().build(this); + userList = new File(ess.getDataFolder(), "usermap.csv"); + users = CacheBuilder.newBuilder().maximumSize(ess.getSettings().getMaxUserCacheCount()).softValues().build(this); loadAllUsersAsync(ess); } @@ -41,6 +58,7 @@ public class UserMap extends CacheLoader implements IConf return; } keys.clear(); + names.clear(); users.invalidateAll(); for (String string : userdir.list()) { @@ -49,23 +67,76 @@ public class UserMap extends CacheLoader implements IConf continue; } final String name = string.substring(0, string.length() - 4); - keys.add(StringUtil.sanitizeFileName(name)); + try + { + keys.add(UUID.fromString(name)); + } + catch (IllegalArgumentException ex) + { + //Ignore these users till they rejoin. + } } + + try + { + if (!userList.exists()) + { + userList.createNewFile(); + } + + final BufferedReader reader = new BufferedReader(new FileReader(userList)); + try + { + do + { + final String line = reader.readLine(); + if (line == null) + { + break; + } + else + { + String[] values = splitPattern.split(line); + if (values.length == 2) + { + names.put(values[0], UUID.fromString(values[1])); + } + } + } + while (true); + } + finally + { + reader.close(); + } + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex); + } + } }); } - public boolean userExists(final String name) + public boolean userExists(final UUID uuid) { - return keys.contains(StringUtil.sanitizeFileName(name)); + return keys.contains(uuid); } public User getUser(final String name) { try - { - String sanitizedName = StringUtil.sanitizeFileName(name); - return users.get(sanitizedName); + { + final String sanitizedName = StringUtil.sanitizeFileName(name); + if (names.containsKey(sanitizedName)) + { + ess.getLogger().info("Trying to grab user via string, found matching key."); + final UUID uuid = names.get(sanitizedName); + return users.get(uuid); + } + ess.getLogger().info("Trying to grab user via string, failed, returning null."); + return null; // TODO: THIS IS PROBABLY NOT RIGHT } catch (ExecutionException ex) { @@ -77,24 +148,67 @@ public class UserMap extends CacheLoader implements IConf } } - @Override - public User load(final String sanitizedName) throws Exception + public User getUser(final UUID uuid) { - for (Player player : ess.getServer().getOnlinePlayers()) - { - String sanitizedPlayer = StringUtil.sanitizeFileName(player.getName()); - if (sanitizedPlayer.equalsIgnoreCase(sanitizedName)) - { - keys.add(sanitizedName); - return new User(player, ess); - } + try + { + return users.get(uuid); } - final File userFile = getUserFile2(sanitizedName); + catch (ExecutionException ex) + { + return null; + } + catch (UncheckedExecutionException ex) + { + return null; + } + } + + public void trackUUID(final UUID uuid, final String name) + { + names.put(StringUtil.sanitizeFileName(name), uuid); + writeUUIDMap(); + } + + public void writeUUIDMap() + { + try + { + final File tempFile = File.createTempFile("usermap", ".tmp.yml", ess.getDataFolder()); + final BufferedWriter bWriter = new BufferedWriter(new FileWriter(tempFile)); + + for (Map.Entry entry : names.entrySet()) + { + bWriter.write(entry.getKey() + "," + entry.getValue().toString()); + bWriter.newLine(); + } + + bWriter.close(); + Files.move(tempFile, userList); + } + catch (IOException ex) + { + Logger.getLogger(UserMap.class.getName()).log(Level.SEVERE, null, ex); + } + } + + @Override + public User load(final UUID uuid) throws Exception + { + Player player = ess.getServer().getPlayer(uuid); + if (player != null) + { + return new User(player, ess); + } + + final File userFile = getUserFileFromID(uuid); + if (userFile.exists()) { - keys.add(sanitizedName); - return new User(new OfflinePlayer(sanitizedName, ess), ess); + keys.add(uuid); + return new User(new OfflinePlayer(uuid, ess), ess); } + throw new Exception("User not found!"); } @@ -106,12 +220,14 @@ public class UserMap extends CacheLoader implements IConf public void removeUser(final String name) { - keys.remove(StringUtil.sanitizeFileName(name)); - users.invalidate(StringUtil.sanitizeFileName(name)); - users.invalidate(name); + UUID uuid = names.get(name); + keys.remove(uuid); + users.invalidate(uuid); + names.remove(name); + names.remove(StringUtil.sanitizeFileName(name)); } - public Set getAllUniqueUsers() + public Set getAllUniqueUsers() { return Collections.unmodifiableSet(keys); } @@ -121,14 +237,9 @@ public class UserMap extends CacheLoader implements IConf return keys.size(); } - public File getUserFile(final String name) - { - return getUserFile2(StringUtil.sanitizeFileName(name)); - } - - private File getUserFile2(final String name) + private File getUserFileFromID(final UUID uuid) { final File userFolder = new File(ess.getDataFolder(), "userdata"); - return new File(userFolder, name + ".yml"); + return new File(userFolder, uuid.toString() + ".yml"); } } diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java b/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java index 29f32f8e8..42946fbe2 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java @@ -119,7 +119,7 @@ public class Commandbalancetop extends EssentialsCommand } else { - for (String u : ess.getUserMap().getAllUniqueUsers()) + for (UUID u : ess.getUserMap().getAllUniqueUsers()) { final User user = ess.getUserMap().getUser(u); if (user != null) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java b/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java index 9b6242fab..5d1e3d9b7 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandessentials.java @@ -10,6 +10,7 @@ import com.earth2me.essentials.utils.NumberUtil; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import org.bukkit.Material; import org.bukkit.Server; import org.bukkit.Sound; @@ -269,7 +270,7 @@ public class Commandessentials extends EssentialsCommand public void run() { Long currTime = System.currentTimeMillis(); - for (String u : userMap.getAllUniqueUsers()) + for (UUID u : userMap.getAllUniqueUsers()) { final User user = ess.getUserMap().getUser(u); if (user == null) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandmail.java b/Essentials/src/com/earth2me/essentials/commands/Commandmail.java index 611e2e897..0b7a5a09d 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandmail.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandmail.java @@ -9,6 +9,7 @@ import org.bukkit.Server; import java.util.List; import static com.earth2me.essentials.I18n.tl; +import java.util.UUID; public class Commandmail extends EssentialsCommand @@ -154,9 +155,9 @@ public class Commandmail extends EssentialsCommand @Override public void run() { - for (String username : ess.getUserMap().getAllUniqueUsers()) + for (UUID userid : ess.getUserMap().getAllUniqueUsers()) { - User user = ess.getUserMap().getUser(username); + User user = ess.getUserMap().getUser(userid); if (user != null) { user.addMail(message); diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandseen.java b/Essentials/src/com/earth2me/essentials/commands/Commandseen.java index 38453efc5..ef888381a 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandseen.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandseen.java @@ -9,6 +9,7 @@ import com.earth2me.essentials.utils.FormatUtil; import com.earth2me.essentials.utils.StringUtil; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import org.bukkit.Location; import org.bukkit.Server; @@ -149,7 +150,7 @@ public class Commandseen extends EssentialsCommand public void run() { final List matches = new ArrayList(); - for (final String u : userMap.getAllUniqueUsers()) + for (final UUID u : userMap.getAllUniqueUsers()) { final User user = ess.getUserMap().getUser(u); if (user == null) diff --git a/Essentials/src/com/earth2me/essentials/commands/EssentialsLoopCommand.java b/Essentials/src/com/earth2me/essentials/commands/EssentialsLoopCommand.java index be30cde70..7ac4d0595 100644 --- a/Essentials/src/com/earth2me/essentials/commands/EssentialsLoopCommand.java +++ b/Essentials/src/com/earth2me/essentials/commands/EssentialsLoopCommand.java @@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException; import com.earth2me.essentials.CommandSource; import com.earth2me.essentials.User; import java.util.List; +import java.util.UUID; import net.ess3.api.MaxMoneyException; import org.bukkit.Server; import org.bukkit.entity.Player; @@ -26,7 +27,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand if (matchWildcards && searchTerm.contentEquals("**")) { - for (String sUser : ess.getUserMap().getAllUniqueUsers()) + for (UUID sUser : ess.getUserMap().getAllUniqueUsers()) { final User matchedUser = ess.getUser(sUser); updatePlayer(server, sender, matchedUser, commandArgs);