diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/PlotMain.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/PlotMain.java index 85acc1222..757b0b4a3 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/PlotMain.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/PlotMain.java @@ -40,8 +40,6 @@ import com.intellectualcrafters.plot.util.*; import com.intellectualcrafters.plot.util.Logger.LogLevel; import com.intellectualcrafters.plot.uuid.DefaultUUIDWrapper; import com.intellectualcrafters.plot.uuid.OfflineUUIDWrapper; -import com.intellectualcrafters.plot.uuid.PlotUUIDSaver; -import com.intellectualcrafters.plot.uuid.UUIDSaver; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; @@ -53,6 +51,9 @@ import org.bukkit.command.PluginCommand; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; @@ -74,7 +75,7 @@ import java.util.concurrent.TimeUnit; * @author Citymonstret * @author Empire92 */ -@SuppressWarnings("unused") public class PlotMain extends JavaPlugin { +@SuppressWarnings("unused") public class PlotMain extends JavaPlugin implements Listener { /** * Permission that allows for "everything" */ @@ -157,10 +158,6 @@ import java.util.concurrent.TimeUnit; */ public static boolean useEconomy = false; private static PlotMain main = null; - /** - * The UUID Saver - */ - private static UUIDSaver uuidSaver; /** * MySQL Object */ @@ -254,28 +251,6 @@ import java.util.concurrent.TimeUnit; return true; } - /** - * Get the uuid saver - * - * @return uuid saver - * - * @see com.intellectualcrafters.plot.uuid.UUIDSaver; - */ - public static UUIDSaver getUUIDSaver() { - return uuidSaver; - } - - /** - * Set the uuid saver - * - * @param saver new saver - * - * @see com.intellectualcrafters.plot.uuid.UUIDSaver - */ - public static void setUUIDSaver(final UUIDSaver saver) { - uuidSaver = saver; - } - /** * Check a player for a permission
- Op has all permissions
- checks for '*' nodes * @@ -928,6 +903,13 @@ import java.util.concurrent.TimeUnit; PlotMain.sendConsoleSenderMessage("&c[Warning] PlotSquared failed to save the configuration&7 (settings.yml may differ from the one in memory)\n - To force a save from console use /plots save"); } } + + @EventHandler + public static void worldLoad(WorldLoadEvent event) { + if (!UUIDHandler.CACHED) { + UUIDHandler.cacheAll(); + } + } public static void loadWorld(final String world, final ChunkGenerator generator) { if (getWorldSettings(world) != null) { @@ -1466,6 +1448,8 @@ import java.util.concurrent.TimeUnit; // Main event handler getServer().getPluginManager().registerEvents(new PlayerEvents(), this); + // World load events + getServer().getPluginManager().registerEvents(this, this); // Info Inventory getServer().getPluginManager().registerEvents(new InventoryListener(), this); // Flag runnable @@ -1551,14 +1535,12 @@ import java.util.concurrent.TimeUnit; UUIDHandler.uuidWrapper = new OfflineUUIDWrapper(); Settings.OFFLINE_MODE = true; } - if (Settings.OFFLINE_MODE) { - sendConsoleSenderMessage(C.PREFIX.s()+" &6PlotSquared &cis using Offline Mode UUIDs either because of user preference, or because of the version of the Bukkit API"); + sendConsoleSenderMessage(C.PREFIX.s()+" &6PlotSquared is using Offline Mode UUIDs either because of user preference, or because of the version of the Bukkit API"); + } + else { + sendConsoleSenderMessage(C.PREFIX.s()+" &6PlotSquared is using online UUIDs"); } - - setUUIDSaver(new PlotUUIDSaver()); - // Looks really cool xD - getUUIDSaver().globalPopulate(); } // Now we're finished :D if (C.ENABLED.s().length() > 0) { diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Kick.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Kick.java index dac097866..c853a9503 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Kick.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Kick.java @@ -50,7 +50,7 @@ import org.bukkit.entity.Player; return false; } if (Bukkit.getPlayer(args[0]) == null) { - PlayerFunctions.sendMessage(plr, C.INVALID_PLAYER.s().replaceAll("%player%", args[0])); + PlayerFunctions.sendMessage(plr, C.INVALID_PLAYER, args[0]); return false; } final Player player = Bukkit.getPlayer(args[0]); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/C.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/C.java index 8e1d3bb1a..45b7bf4c8 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/C.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/C.java @@ -173,7 +173,7 @@ public enum C { /* * Player not found */ - INVALID_PLAYER("&cPlayer not found: &6%player%."), + INVALID_PLAYER("&cPlayer not found: &6%s."), /* * */ diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/Settings.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/Settings.java index 32f2bd35c..5c641332f 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/Settings.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/config/Settings.java @@ -32,7 +32,7 @@ public class Settings { * Default UUID_FECTHING: false */ public static boolean UUID_FECTHING = false; - public static boolean UUID_FROM_DISK = false; + public static boolean UUID_FROM_DISK = true; /** * */ diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java index e1d4dca14..b797ce361 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java @@ -157,18 +157,24 @@ import java.util.HashSet; public void run() { if (chunks.size() == 0) { HybridPlotManager.UPDATE = false; - Bukkit.getScheduler().cancelTask(task); PlotMain.sendConsoleSenderMessage(C.PREFIX.s() + "Finished road conversion"); + Bukkit.getScheduler().cancelTask(task); return; } else { - ChunkLoc loc = chunks.get(0); - - PlotMain.sendConsoleSenderMessage("Updating .mcr: " + loc.x + ", "+loc.z + " (aprrox 256 chunks)"); - PlotMain.sendConsoleSenderMessage("Remaining regions: "+chunks.size()); - - regenerateChunkChunk(world, loc); - chunks.remove(0); + try { + ChunkLoc loc = chunks.get(0); + PlotMain.sendConsoleSenderMessage("Updating .mcr: " + loc.x + ", "+loc.z + " (aprrox 256 chunks)"); + PlotMain.sendConsoleSenderMessage("Remaining regions: "+chunks.size()); + regenerateChunkChunk(world, loc); + chunks.remove(0); + } + catch (Exception e) { + ChunkLoc loc = chunks.get(0); + PlotMain.sendConsoleSenderMessage("&c[ERROR]&7 Could not update '"+world.getName() + "/region/r." + loc.x + "." + loc.z + ".mca' (Corrupt chunk?)"); + PlotMain.sendConsoleSenderMessage("&d - Potentially skipping 256 chunks"); + PlotMain.sendConsoleSenderMessage("&d - TODO: recommend chunkster if corrupt"); + } } } }, 20, 20); @@ -194,7 +200,7 @@ import java.util.HashSet; ChunkLoc loc = new ChunkLoc(x, z); chunks.add(loc); } - catch (Exception e) { } + catch (Exception e) { } } } @@ -227,13 +233,31 @@ import java.util.HashSet; PlotId id1 = getPlotId(plotworld, bot); PlotId id2 = getPlotId(plotworld, top); + + boolean toCheck = false; + if (id1 == null || id2 == null || id1 != id2) { boolean result = chunk.load(false); if (result) { - int size = plotworld.SIZE; + while (!chunk.isLoaded()) { + chunk.load(false); + } + if (id1 != null) { + Plot p1 = PlotHelper.getPlot(world, id1); + if (p1 != null && p1.hasOwner() && p1.settings.isMerged()) { + toCheck = true; + } + } + if (id2 != null && !toCheck) { + Plot p2 = PlotHelper.getPlot(world, id2); + if (p2 != null && p2.hasOwner() && p2.settings.isMerged()) { + toCheck = true; + } + } + int size = plotworld.SIZE; for (int X = 0; X < 16; X++) { for (int Z = 0; Z < 16; Z++) { @@ -249,11 +273,17 @@ import java.util.HashSet; boolean gx = absX > plotworld.PATH_WIDTH_LOWER; boolean gz = absZ > plotworld.PATH_WIDTH_LOWER; - boolean lx = absX < plotworld.PATH_WIDTH_UPPER; boolean lz = absZ < plotworld.PATH_WIDTH_UPPER; + boolean condition; - if (!gx || !gz || !lx || !lz) { + if (toCheck) { + Location l = new Location(world, x + X, 1, z + Z); + condition = getPlotId(plotworld, l) == null; + } + else { condition = (!gx || !gz || !lx || !lz); } + + if (condition) { int sy = plotworld.ROAD_HEIGHT + plotworld.OFFSET; ChunkLoc loc = new ChunkLoc(absX, absZ); HashMap blocks = plotworld.G_SCH.get(loc); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java index 7521d2598..3badd0a2f 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java @@ -192,9 +192,7 @@ public class HybridPlotWorld extends PlotWorld { this.PATH_WIDTH_UPPER = (short) (this.PATH_WIDTH_LOWER + this.PLOT_WIDTH + 1); try { - if (true) { - setupSchematics(); - } + setupSchematics(); } catch (Exception e) { PlotMain.sendConsoleSenderMessage("&c - road schematics are disabled for this world."); @@ -213,7 +211,7 @@ public class HybridPlotWorld extends PlotWorld { Schematic schem2 = SchematicHandler.getSchematic(schem2Str); if (schem1 == null || schem2 == null || this.ROAD_WIDTH == 0) { - PlotMain.sendConsoleSenderMessage(C.PREFIX.s() + "&cInvalid generator schematic for world '" + worldname + "'"); + PlotMain.sendConsoleSenderMessage(C.PREFIX.s() + "&3 - schematic: &7false"); return; } @@ -262,6 +260,8 @@ public class HybridPlotWorld extends PlotWorld { } } } + + this.ROAD_SCHEMATIC_ENABLED = true; } public void addOverlayBlock(short x, short y, short z, short id, byte data) { diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java index 3390505f9..62070fe67 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/PlayerEvents.java @@ -29,6 +29,8 @@ import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.object.*; import com.intellectualcrafters.plot.util.PlayerFunctions; import com.intellectualcrafters.plot.util.PlotHelper; +import com.intellectualcrafters.plot.util.UUIDHandler; + import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -53,6 +55,7 @@ import org.bukkit.event.world.WorldLoadEvent; import java.util.List; import java.util.Set; +import java.util.UUID; /** * Player Events involving plots @@ -69,9 +72,17 @@ import java.util.Set; @EventHandler public static void onJoin(final PlayerJoinEvent event) { - if (!event.getPlayer().hasPlayedBefore()) { - event.getPlayer().saveData(); + Player player = event.getPlayer(); + if (!player.hasPlayedBefore()) { + player.saveData(); } + + // UUID stuff + String username = player.getName(); + StringWrapper name = new StringWrapper(username); + UUID uuid = UUIDHandler.getUUID(player); + UUIDHandler.add(name, uuid); + // textures(event.getPlayer()); if (isInPlot(event.getPlayer().getLocation())) { if (Settings.TELEPORT_ON_LOGIN) { diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/StringWrapper.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/StringWrapper.java index 619816a99..ebcbbc701 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/StringWrapper.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/StringWrapper.java @@ -60,9 +60,6 @@ public class StringWrapper { if (other.value == null || this.value == null) { return false; } - if (Settings.OFFLINE_MODE) { - return other.value.equals(this.value); - } return other.value.toLowerCase().equals(this.value.toLowerCase()); } @@ -86,9 +83,6 @@ public class StringWrapper { if (this.value == null) { return 0; } - if (Settings.OFFLINE_MODE) { - return this.value.hashCode(); - } return this.value.toLowerCase().hashCode(); } } diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/UUIDHandler.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/UUIDHandler.java index 6bd190c29..4e2ca2297 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/UUIDHandler.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/UUIDHandler.java @@ -1,65 +1,33 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////// -// PlotSquared - A plot manager and world generator for the Bukkit API / -// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / -// / -// This program is free software; you can redistribute it and/or modify / -// it under the terms of the GNU General Public License as published by / -// the Free Software Foundation; either version 3 of the License, or / -// (at your option) any later version. / -// / -// This program is distributed in the hope that it will be useful, / -// but WITHOUT ANY WARRANTY; without even the implied warranty of / -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / -// GNU General Public License for more details. / -// / -// You should have received a copy of the GNU General Public License / -// along with this program; if not, write to the Free Software Foundation, / -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / -// / -// You can contact us via: support@intellectualsites.com / -//////////////////////////////////////////////////////////////////////////////////////////////////// - package com.intellectualcrafters.plot.util; -import com.google.common.base.Charsets; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.intellectualcrafters.plot.PlotMain; -import com.intellectualcrafters.plot.config.Settings; -import com.intellectualcrafters.plot.object.StringWrapper; -import com.intellectualcrafters.plot.uuid.*; +import java.io.File; +import java.io.FilenameFilter; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.UUID; + import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import java.util.Arrays; -import java.util.HashMap; -import java.util.UUID; - -/** - * This class can be used to efficiently translate UUIDs and names back and forth. It uses three primary methods of - * achieving this: - Read From Cache - Read from OfflinePlayer objects - Read from (if onlinemode: mojang api) (else: - * playername hashing) All UUIDs/Usernames will be stored in a map (cache) until the server is restarted. - *

- * You can use getUuidMap() to save the uuids/names to a file (SQLite db for example). Primary methods: getUUID(String - * name) & getName(UUID uuid) <-- You should ONLY use these. Call startFetch(JavaPlugin plugin) in your onEnable(). - *

- * Originally created by: - * - * @author Citymonstret - * @author Empire92 for PlotSquared. - */ -@SuppressWarnings("unused") public class UUIDHandler { +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.intellectualcrafters.plot.PlotMain; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.uuid.DefaultUUIDWrapper; +import com.intellectualcrafters.plot.uuid.UUIDWrapper; +import com.intellectualcrafters.plot.uuid.OfflineUUIDWrapper; +public class UUIDHandler { + + public static boolean CACHED = false; public static UUIDWrapper uuidWrapper = null; - - /** - * Online mode - * - * @see org.bukkit.Server#getOnlineMode() - */ - private final static boolean online = Bukkit.getServer().getOnlineMode() && !Settings.OFFLINE_MODE; - + /** * Map containing names and UUIDs * @@ -67,6 +35,15 @@ import java.util.UUID; */ private final static BiMap uuidMap = HashBiMap.create(new HashMap()); + public static void add(final StringWrapper name, final UUID uuid) { + if (uuid == null || name == null) { + return; + } + if (!uuidMap.containsKey(name) && !uuidMap.inverse().containsKey(uuid)) { + uuidMap.put(name, uuid); + } + } + /** * Get the map containing all names/uuids * @@ -77,7 +54,7 @@ import java.util.UUID; public static BiMap getUuidMap() { return uuidMap; } - + /** * Check if a uuid is cached * @@ -103,253 +80,129 @@ import java.util.UUID; public static boolean nameExists(final StringWrapper name) { return uuidMap.containsKey(name); } + + public static void cacheAll() { + + UUIDHandler.CACHED = true; + HashSet players = new HashSet<>(); + HashSet worlds = new HashSet<>(); + worlds.add(Bukkit.getWorlds().get(0).getName()); + worlds.add("world"); - /** - * Add a set to the cache - * - * @param name to cache - * @param uuid to cache - */ - public static void add(final StringWrapper name, final UUID uuid) { - if (uuid == null || name == null) { - return; - } - if (!uuidMap.containsKey(name) && !uuidMap.inverse().containsKey(uuid)) { - uuidMap.put(name, uuid); - } - } - - /** - * @param name to use as key - * - * @return uuid - */ - public static UUID getUUID(final String name) { - final StringWrapper nameWrap = new StringWrapper(name); - if (uuidMap.containsKey(nameWrap)) { - return uuidMap.get(nameWrap); - } - @SuppressWarnings("deprecation") final Player player = Bukkit.getPlayer(name); - if (player != null) { - final UUID uuid = getUUID(player); - add(nameWrap, uuid); - return uuid; - } - UUID uuid; - if (online) { - if (Settings.CUSTOM_API) { - if ((uuid = getUuidOnlinePlayer(nameWrap)) != null) { - return uuid; + HashSet uuids = new HashSet<>(); + HashSet names = new HashSet<>(); + + for (String worldname : worlds) { + // Getting UUIDs + File playerdataFolder = new File(worldname + File.separator + "playerdata"); + String[] dat = playerdataFolder.list(new FilenameFilter() { + public boolean accept(File f, String s) { + return s.endsWith(".dat"); } + }); + for (String current : dat) { + String s = current.replaceAll(".dat$", ""); try { - return PlotMain.getUUIDSaver().mojangUUID(name); - } catch (final Exception e) { - try { - final UUIDFetcher fetcher = new UUIDFetcher(Arrays.asList(name)); - uuid = fetcher.call().get(name); - add(nameWrap, uuid); - } catch (final Exception ex) { - ex.printStackTrace(); - } + UUID uuid = UUID.fromString(s); + uuids.add(uuid); } - } else { - try { - final UUIDFetcher fetcher = new UUIDFetcher(Arrays.asList(name)); - uuid = fetcher.call().get(name); - add(nameWrap, uuid); - } catch (final Exception ex) { - ex.printStackTrace(); + catch (Exception e) { + PlotMain.sendConsoleSenderMessage(C.PREFIX.s() + "Invalid playerdata: "+current); } } - } else { - return getUuidOfflineMode(nameWrap); + + // Getting names + File playersFolder = new File(worldname + File.separator + "players"); + dat = playersFolder.list(new FilenameFilter() { + public boolean accept(File f, String s) { + return s.endsWith(".dat"); + } + }); + for (String current : dat) { + names.add(current.replaceAll(".dat$", "")); + } } + + + UUIDWrapper wrapper = null; + for (UUID uuid : uuids) { + try { + OfflinePlayer player = wrapper.getOfflinePlayer(uuid); + uuid = UUIDHandler.uuidWrapper.getUUID(player); + StringWrapper name = new StringWrapper(player.getName()); + add(name, uuid); + } + catch (Throwable e) { + PlotMain.sendConsoleSenderMessage(C.PREFIX.s() + "&6Invalid playerdata: "+uuid.toString() + ".dat"); + } + } + for (String name : names) { + OfflinePlayer player = Bukkit.getOfflinePlayer(name); + UUID uuid = UUIDHandler.uuidWrapper.getUUID(player); + StringWrapper nameWrap = new StringWrapper(name); + System.out.print(nameWrap); + add(nameWrap, uuid); + } + + PlotMain.sendConsoleSenderMessage("C.PREFIX.s() + &6Cached a total of: " + UUIDHandler.uuidMap.size() + " UUIDs"); + } + + public static UUID getUUID(Player player) { + return UUIDHandler.uuidWrapper.getUUID(player); + } + + public static UUID getUUID(OfflinePlayer player) { + return UUIDHandler.uuidWrapper.getUUID(player); + } + + public static String getName(UUID uuid) { + // check online + for (Player player : Bukkit.getOnlinePlayers()) { + UUID u2 = UUIDHandler.uuidWrapper.getUUID(player); + if (uuid.equals(u2)) { + return player.getName(); + } + } + + // check cache + StringWrapper name = UUIDHandler.uuidMap.inverse().get(uuid); + if (name != null) { + return name.value; + } + + // check drive + if (Settings.UUID_FROM_DISK) { + OfflinePlayer op = UUIDHandler.uuidWrapper.getOfflinePlayer(uuid); + String string = op.getName(); + StringWrapper sw = new StringWrapper(string); + add(sw, uuid); + return string; + } + return null; } - /** - * @param uuid to use as key - * - * @return name (cache) - */ - private static StringWrapper loopSearch(final UUID uuid) { - return uuidMap.inverse().get(uuid); - } - - /** - * @param uuid to use as key - * - * @return Name - */ - public static String getName(final UUID uuid) { - if (uuidExists(uuid)) { - return loopSearch(uuid).value; - } - String name; - if ((name = getNameOnlinePlayer(uuid)) != null) { - return name; + public static UUID getUUID(final String name) { + // check online + Player player = Bukkit.getPlayer(name); + if (player != null) { + UUID uuid = UUIDHandler.uuidWrapper.getUUID(player); + add(new StringWrapper(name), uuid); + return uuid; } - if (!Settings.UUID_FROM_DISK) { - return null; + // check cache + UUID uuid = UUIDHandler.uuidMap.get(name); + if (uuid != null) { + return uuid; } - if ((name = getNameOfflinePlayer(uuid)) != null) { - return name; - } - if (online && !Settings.OFFLINE_MODE) { - if (!Settings.UUID_FECTHING) { - name = getNameOfflineFromOnlineUUID(uuid); - return name; - } - if (!Settings.CUSTOM_API) { - try { - final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); - name = fetcher.call().get(uuid); - add(new StringWrapper(name), uuid); - return name; - } catch (final Exception ex) { - ex.printStackTrace(); - } - } else { - try { - return PlotMain.getUUIDSaver().mojangName(uuid); - } catch (final Exception e) { - try { - final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); - name = fetcher.call().get(uuid); - add(new StringWrapper(name), uuid); - return name; - } catch (final Exception ex) { - e.printStackTrace(); - } - } - } - try { - return PlotMain.getUUIDSaver().mojangName(uuid); - } catch (final Exception e) { - try { - final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); - name = fetcher.call().get(uuid); - add(new StringWrapper(name), uuid); - return name; - } catch (final Exception ex) { - ex.printStackTrace(); - } - } - } else { - return "unknown"; - } - return ""; - } - - /** - * @param name to use as key - * - * @return UUID (name hash) - */ - private static UUID getUuidOfflineMode(final StringWrapper name) { - final UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)); - add(name, uuid); - return uuid; - } - - /** - * @param uuid to use as key - * - * @return String - name - */ - private static String getNameOnlinePlayer(final UUID uuid) { - final Player player = uuidWrapper.getPlayer(uuid); - if ((player == null) || !player.isOnline()) { - return null; - } - final String name = player.getName(); - add(new StringWrapper(name), uuid); - return name; - } - - /** - * @param uuid to use as key - * - * @return String - name - */ - private static String getNameOfflinePlayer(final UUID uuid) { - final OfflinePlayer player = uuidWrapper.getOfflinePlayer(uuid); - if ((player == null) || !player.hasPlayedBefore()) { - return null; - } - final String name = player.getName(); - add(new StringWrapper(name), uuid); - return name; - } - - private static UUID getUuidOnlineFromOfflinePlayer(final StringWrapper name) { - return getUUID(Bukkit.getOfflinePlayer(name.toString())); - } - - private static String getNameOfflineFromOnlineUUID(final UUID uuid) { - return uuidWrapper.getOfflinePlayer(uuid).getName(); - } - - /** - * @param name to use as key - * - * @return UUID - */ - private static UUID getUuidOnlinePlayer(final StringWrapper name) { - @SuppressWarnings("deprecation") final Player player = Bukkit.getPlayer(name.value); - if (player == null) { - return null; - } - final UUID uuid = getUUID(player); - add(name, uuid); - return uuid; - } - - /** - * Handle saving of uuids - * - * @see com.intellectualcrafters.plot.uuid.UUIDSaver#globalSave(com.google.common.collect.BiMap) - */ - @SuppressWarnings("unused") - public static void handleSaving() { - final UUIDSaver saver = PlotMain.getUUIDSaver(); - saver.globalSave(getUuidMap()); - } - - public static UUID getUUID(final Player player) { - if (uuidWrapper == null) { - try { - getUUID(player); - uuidWrapper = new DefaultUUIDWrapper(); - } catch (final Throwable e) { - uuidWrapper = new OfflineUUIDWrapper(); - } - } - return uuidWrapper.getUUID(player); - } - - /** - * Safely provide the correct UUID provider. Ignores user preference if not possible rather than break the plugin. - */ - public static UUID getUUID(final OfflinePlayer player) { - if (uuidWrapper == null) { - if (Settings.OFFLINE_MODE) { - uuidWrapper = new OfflineUUIDWrapper(); - } else { - try { - getUUID(player); - uuidWrapper = new DefaultUUIDWrapper(); - } catch (final Throwable e) { - uuidWrapper = new OfflineUUIDWrapper(); - } - } - } - try { - return uuidWrapper.getUUID(player); - } catch (final Throwable e) { - uuidWrapper = new OfflineUUIDWrapper(); - return uuidWrapper.getUUID(player); + + // Read from disk + if (Settings.UUID_FROM_DISK) { + OfflinePlayer op = Bukkit.getOfflinePlayer(name); + return UUIDHandler.uuidWrapper.getUUID(op); } + + return null; } } diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/DefaultUUIDWrapper.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/DefaultUUIDWrapper.java new file mode 100644 index 000000000..c8fc3a7a3 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/DefaultUUIDWrapper.java @@ -0,0 +1,31 @@ +package com.intellectualcrafters.unused; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class DefaultUUIDWrapper extends UUIDWrapper { + + @Override + public UUID getUUID(final Player player) { + return player.getUniqueId(); + } + + @Override + public UUID getUUID(final OfflinePlayer player) { + return player.getUniqueId(); + } + + @Override + public OfflinePlayer getOfflinePlayer(final UUID uuid) { + return Bukkit.getOfflinePlayer(uuid); + } + + @Override + public Player getPlayer(final UUID uuid) { + return Bukkit.getPlayer(uuid); + } + +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/EntityListener.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/EntityListener.java new file mode 100644 index 000000000..ae529138d --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/EntityListener.java @@ -0,0 +1,215 @@ +package com.intellectualcrafters.unused; + +import com.intellectualcrafters.plot.PlotMain; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.util.PlayerFunctions; +import com.intellectualcrafters.plot.util.PlotHelper; + +import org.bukkit.*; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.scheduler.BukkitScheduler; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; + +/** + * @author Empire92 + */ +@SuppressWarnings({"unused", "deprecation"}) public class EntityListener implements Listener { + + public final static HashMap>> entityMap = new HashMap<>(); + + public EntityListener() { + final BukkitScheduler scheduler = Bukkit.getServer().getScheduler(); + scheduler.scheduleSyncRepeatingTask(PlotMain.getMain(), new Runnable() { + @Override + public void run() { + final Iterator>>> worldIt = entityMap.entrySet().iterator(); + + final Set plots = PlotMain.getPlots(); + + while (worldIt.hasNext()) { + final Entry>> entry = worldIt.next(); + final String worldname = entry.getKey(); + if (!PlotMain.isPlotWorld(worldname)) { + worldIt.remove(); + continue; + } + final World world = Bukkit.getWorld(worldname); + if ((world == null) || (entry.getValue().size() == 0)) { + worldIt.remove(); + continue; + } + final Iterator>> it = entry.getValue().entrySet().iterator(); + while (it.hasNext()) { + final Entry> plotEntry = it.next(); + final Plot plot = plotEntry.getKey(); + if (!plots.contains(plot)) { + it.remove(); + continue; + } + + boolean loaded = false; + + final Location pos1 = PlotHelper.getPlotBottomLoc(world, plot.id).add(1, 0, 1); + final Location pos2 = PlotHelper.getPlotTopLoc(world, plot.id); + try { + loops: + for (int i = (pos1.getBlockX() / 16) * 16; i < (16 + ((pos2.getBlockX() / 16) * 16)); i += 16) { + for (int j = (pos1.getBlockZ() / 16) * 16; j < (16 + ((pos2.getBlockZ() / 16) * 16)); j += 16) { + final Chunk chunk = world.getChunkAt(i, j); + if (chunk.isLoaded()) { + loaded = true; + break loops; + } + } + } + } catch (final Exception e) { + it.remove(); + continue; + } + if (!loaded) { + it.remove(); + } + } + } + } + }, 24000L, 48000L); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public static void onPlayerInteract(final PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { + final Player p = e.getPlayer(); + final World w = p.getWorld(); + final String n = w.getName(); + if ((e.getMaterial() == Material.MONSTER_EGG) || (e.getMaterial() == Material.MONSTER_EGGS)) { + if (entityMap.containsKey(n)) { + final Location l = e.getClickedBlock().getLocation(); + final Plot plot = PlotHelper.getCurrentPlot(l); + if ((plot != null) && plot.hasRights(p)) { + int mobs; + if (entityMap.get(n).containsKey(plot)) { + mobs = entityMap.get(n).get(plot).size(); + } else { + mobs = 0; + } + if (!(PlotMain.hasPermissionRange(p, "plots.mobcap", Settings.MOB_CAP) > mobs)) { + PlayerFunctions.sendMessage(p, C.NO_PERMISSION, "plots.mobcap." + (mobs + 1)); + e.setCancelled(true); + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public static void onCreatureSpawn(final CreatureSpawnEvent e) { + final Location l = e.getLocation(); + final String w = l.getWorld().getName(); + if (PlotMain.isPlotWorld(w)) { + final Plot plot = PlotHelper.getCurrentPlot(l); + if ((plot != null) && plot.hasOwner()) { + addEntity(e.getEntity(), plot); + } + } + } + + @EventHandler + public static void onChunkLoad(final ChunkLoadEvent e) { + if (PlotMain.isPlotWorld(e.getWorld())) { + for (final Entity entity : e.getChunk().getEntities()) { + if (entity instanceof LivingEntity) { + if (!(entity instanceof Player)) { + final Plot plot = PlotHelper.getCurrentPlot(entity.getLocation()); + if (plot != null) { + if (plot.hasOwner()) { + addEntity(entity, plot); + } + } + } + } + } + } + } + + public static void addEntity(final Entity entity, final Plot plot) { + if (!entityMap.containsKey(plot.world)) { + entityMap.put(plot.world, new HashMap>()); + } + if (!entityMap.containsKey(plot.world)) { + entityMap.put(plot.world, new HashMap>()); + } + final HashMap> section = entityMap.get(plot.world); + if (!section.containsKey(plot)) { + section.put(plot, new HashSet()); + } + section.get(plot).add(entity.getEntityId()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public static void onEntityDeath(final EntityDeathEvent e) { + final Entity entity = e.getEntity(); + final Location l = entity.getLocation(); + final String w = l.getWorld().getName(); + remove(w, entity); + } + + public static void remove(String w, Entity entity) { + if (entityMap.containsKey(w)) { + final int id = entity.getEntityId(); + final Plot plot = PlotHelper.getCurrentPlot(entity.getLocation()); + if (plot != null) { + if (entityMap.get(w).containsKey(plot)) { + entityMap.get(w).get(plot).remove(id); + } + } else { + for (final Entry> n : entityMap.get(w).entrySet()) { + n.getValue().remove(id); + } + } + } + } + + @EventHandler + public static void onChunkDespawn(final ChunkUnloadEvent e) { + final String w = e.getWorld().getName(); + if (entityMap.containsKey(w)) { + for (final Entity entity : e.getChunk().getEntities()) { + if (entity instanceof LivingEntity) { + if (!(entity instanceof Player)) { + final Plot plot = PlotHelper.getCurrentPlot(entity.getLocation()); + if (plot != null) { + if (plot.hasOwner()) { + if (entityMap.get(w).containsKey(plot)) { + if (entityMap.get(w).get(plot).size() == 1) { + entityMap.get(w).remove(plot); + } else { + entityMap.get(w).get(plot).remove(entity.getEntityId()); + } + } + } + } + } + } + } + } + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/NameFetcher.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/NameFetcher.java new file mode 100644 index 000000000..276572840 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/NameFetcher.java @@ -0,0 +1,71 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import com.google.common.collect.ImmutableList; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.InputStreamReader; +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.concurrent.Callable; + +/** + * Name Fetcher Class From Bukkit + */ +public class NameFetcher implements Callable> { + private static final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/"; + private final JSONParser jsonParser = new JSONParser(); + private final List uuids; + + public NameFetcher(final List uuids) { + this.uuids = ImmutableList.copyOf(uuids); + } + + @Override + public Map call() throws Exception { + final Map uuidStringMap = new HashMap<>(); + for (final UUID uuid : this.uuids) { + if (uuidStringMap.containsKey(uuid)) { + continue; + } + final HttpURLConnection connection = (HttpURLConnection) new URL(PROFILE_URL + uuid.toString().replace("-", "")).openConnection(); + final JSONObject response = (JSONObject) this.jsonParser.parse(new InputStreamReader(connection.getInputStream())); + final String name = (String) response.get("name"); + if (name == null) { + continue; + } + final String cause = (String) response.get("cause"); + final String errorMessage = (String) response.get("errorMessage"); + if ((cause != null) && (cause.length() > 0)) { + throw new IllegalStateException(errorMessage); + } + uuidStringMap.put(uuid, name); + } + return uuidStringMap; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/OfflineUUIDWrapper.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/OfflineUUIDWrapper.java new file mode 100644 index 000000000..9248a3930 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/OfflineUUIDWrapper.java @@ -0,0 +1,56 @@ +package com.intellectualcrafters.unused; + +import com.google.common.base.Charsets; +import com.google.common.collect.BiMap; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.util.UUIDHandler; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class OfflineUUIDWrapper extends UUIDWrapper { + + @Override + public UUID getUUID(final Player player) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); + } + + @Override + public UUID getUUID(final OfflinePlayer player) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); + } + + @Override + public OfflinePlayer getOfflinePlayer(final UUID uuid) { + final BiMap map = UUIDHandler.getUuidMap().inverse(); + String name; + try { + name = map.get(uuid).value; + } catch (NullPointerException e) { + name = null; + } + if (name != null) { + return Bukkit.getOfflinePlayer(name); + } else { + for (final OfflinePlayer player : Bukkit.getOfflinePlayers()) { + if (getUUID(player).equals(uuid)) { + return player; + } + } + } + return Bukkit.getOfflinePlayer(uuid.toString()); + } + + @Override + public Player getPlayer(final UUID uuid) { + for (final Player player : Bukkit.getOnlinePlayers()) { + if (getUUID(player).equals(uuid)) { + return player; + } + } + return null; + } + +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/PlotUUIDSaver.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/PlotUUIDSaver.java new file mode 100644 index 000000000..bbb3fc287 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/PlotUUIDSaver.java @@ -0,0 +1,120 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import com.google.common.collect.BiMap; +import com.intellectualcrafters.json.JSONObject; +import com.intellectualcrafters.json.JSONTokener; +import com.intellectualcrafters.plot.PlotMain; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.util.UUIDHandler; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; + +import java.net.URL; +import java.net.URLConnection; +import java.util.UUID; + +/** + * Plot UUID Saver/Fetcher + * + * @author Citymonstret + * @author Empire92 + */ +public class PlotUUIDSaver implements UUIDSaver { + + @Override + public void globalPopulate() { + Bukkit.getServer().getScheduler().runTaskAsynchronously(PlotMain.getMain(), new Runnable() { + @Override + public void run() { + final OfflinePlayer[] offlinePlayers = Bukkit.getOfflinePlayers(); + final int length = offlinePlayers.length; + final long start = System.currentTimeMillis(); + + String name; + UUID uuid; + for (final OfflinePlayer player : offlinePlayers) { + uuid = UUIDHandler.getUUID(player); + if (!UUIDHandler.uuidExists(uuid)) { + name = player.getName(); + if (name != null) { + UUIDHandler.add(new StringWrapper(name), uuid); + } + } + } + + final long time = System.currentTimeMillis() - start; + final int size = UUIDHandler.getUuidMap().size(); + double ups; + if ((time == 0l) || (size == 0)) { + ups = size; + } else { + ups = size / time; + } + + // Plot Squared Only... + PlotMain.sendConsoleSenderMessage("&cFinished caching of offline player UUIDs! Took &6" + time + "&cms (&6" + ups + "&c per millisecond), &6" + length + " &cUUIDs were cached" + " and there is now a grand total of &6" + size + " &ccached."); + } + }); + } + + @Override + public void globalSave(final BiMap map) { + + } + + @Override + public void save(final UUIDSet set) { + + } + + @Override + public UUID mojangUUID(final String name) throws Exception { + final URLConnection connection = new URL(Settings.API_URL + "?user=" + name).openConnection(); + connection.addRequestProperty("User-Agent", "Mozilla/4.0"); + final JSONTokener tokener = new JSONTokener(connection.getInputStream()); + final JSONObject root = new JSONObject(tokener); + final String uuid = root.getJSONObject(name).getString("dashed"); + return UUID.fromString(uuid); + } + + @Override + public String mojangName(final UUID uuid) throws Exception { + final URLConnection connection = new URL(Settings.API_URL + "?user=" + uuid.toString().replace("-", "")).openConnection(); + connection.addRequestProperty("User-Agent", "Mozilla/4.0"); + final JSONTokener tokener = new JSONTokener(connection.getInputStream()); + final JSONObject root = new JSONObject(tokener); + return root.getJSONObject(uuid.toString().replace("-", "")).getString("username"); + } + + @Override + public UUIDSet get(final String name) { + return null; + } + + @Override + public UUIDSet get(final UUID uuid) { + return null; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDFetcher.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDFetcher.java new file mode 100644 index 000000000..1b7567218 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDFetcher.java @@ -0,0 +1,124 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import com.google.common.collect.ImmutableList; +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; + +/** + * UUID Fetcher From Bukkit + */ +public class UUIDFetcher implements Callable> { + 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 names; + private final boolean rateLimiting; + + public UUIDFetcher(final List names, final boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } + + public UUIDFetcher(final List names) { + this(names, true); + } + + private static void writeBody(final HttpURLConnection connection, final String body) throws Exception { + final OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } + + private static HttpURLConnection createConnection() throws Exception { + final URL url = new URL(PROFILE_URL); + final 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; + } + + public static UUID getUUID(final 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)); + } + + @SuppressWarnings("unused") + public static byte[] toBytes(final UUID uuid) { + final ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } + + @SuppressWarnings("unused") + public static UUID fromBytes(final byte[] array) { + if (array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + final ByteBuffer byteBuffer = ByteBuffer.wrap(array); + final long mostSignificant = byteBuffer.getLong(); + final long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } + + @SuppressWarnings("unused") + public static UUID getUUIDOf(final String name) throws Exception { + return new UUIDFetcher(Arrays.asList(name)).call().get(name); + } + + @Override + public Map call() throws Exception { + final Map uuidMap = new HashMap<>(); + final int requests = (int) Math.ceil(this.names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + final HttpURLConnection connection = createConnection(); + final String body = JSONArray.toJSONString(this.names.subList(i * 100, Math.min((i + 1) * 100, this.names.size()))); + writeBody(connection, body); + final JSONArray array = (JSONArray) this.jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (final Object profile : array) { + final JSONObject jsonProfile = (JSONObject) profile; + final String id = (String) jsonProfile.get("id"); + final String name = (String) jsonProfile.get("name"); + final UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + if (this.rateLimiting && (i != (requests - 1))) { + Thread.sleep(100L); + } + } + return uuidMap; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDHandler.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDHandler.java new file mode 100644 index 000000000..cc98d6471 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDHandler.java @@ -0,0 +1,355 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import com.google.common.base.Charsets; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.intellectualcrafters.plot.PlotMain; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.uuid.*; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.UUID; + +/** + * This class can be used to efficiently translate UUIDs and names back and forth. It uses three primary methods of + * achieving this: - Read From Cache - Read from OfflinePlayer objects - Read from (if onlinemode: mojang api) (else: + * playername hashing) All UUIDs/Usernames will be stored in a map (cache) until the server is restarted. + *

+ * You can use getUuidMap() to save the uuids/names to a file (SQLite db for example). Primary methods: getUUID(String + * name) & getName(UUID uuid) <-- You should ONLY use these. Call startFetch(JavaPlugin plugin) in your onEnable(). + *

+ * Originally created by: + * + * @author Citymonstret + * @author Empire92 for PlotSquared. + */ +@SuppressWarnings("unused") public class UUIDHandler { + + public static UUIDWrapper uuidWrapper = null; + + /** + * Online mode + * + * @see org.bukkit.Server#getOnlineMode() + */ + private final static boolean online = Bukkit.getServer().getOnlineMode() && !Settings.OFFLINE_MODE; + + /** + * Map containing names and UUIDs + * + * @see com.google.common.collect.BiMap + */ + private final static BiMap uuidMap = HashBiMap.create(new HashMap()); + + /** + * Get the map containing all names/uuids + * + * @return map with names + uuids + * + * @see com.google.common.collect.BiMap + */ + public static BiMap getUuidMap() { + return uuidMap; + } + + /** + * Check if a uuid is cached + * + * @param uuid to check + * + * @return true of the uuid is cached + * + * @see com.google.common.collect.BiMap#containsValue(Object) + */ + public static boolean uuidExists(final UUID uuid) { + return uuidMap.containsValue(uuid); + } + + /** + * Check if a name is cached + * + * @param name to check + * + * @return true of the name is cached + * + * @see com.google.common.collect.BiMap#containsKey(Object) + */ + public static boolean nameExists(final StringWrapper name) { + return uuidMap.containsKey(name); + } + + /** + * Add a set to the cache + * + * @param name to cache + * @param uuid to cache + */ + public static void add(final StringWrapper name, final UUID uuid) { + if (uuid == null || name == null) { + return; + } + if (!uuidMap.containsKey(name) && !uuidMap.inverse().containsKey(uuid)) { + uuidMap.put(name, uuid); + } + } + + /** + * @param name to use as key + * + * @return uuid + */ + public static UUID getUUID(final String name) { + final StringWrapper nameWrap = new StringWrapper(name); + if (uuidMap.containsKey(nameWrap)) { + return uuidMap.get(nameWrap); + } + @SuppressWarnings("deprecation") final Player player = Bukkit.getPlayer(name); + if (player != null) { + final UUID uuid = getUUID(player); + add(nameWrap, uuid); + return uuid; + } + UUID uuid; + if (online) { + if (Settings.CUSTOM_API) { + if ((uuid = getUuidOnlinePlayer(nameWrap)) != null) { + return uuid; + } + try { + return PlotMain.getUUIDSaver().mojangUUID(name); + } catch (final Exception e) { + try { + final UUIDFetcher fetcher = new UUIDFetcher(Arrays.asList(name)); + uuid = fetcher.call().get(name); + add(nameWrap, uuid); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } else { + try { + final UUIDFetcher fetcher = new UUIDFetcher(Arrays.asList(name)); + uuid = fetcher.call().get(name); + add(nameWrap, uuid); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } else { + return getUuidOfflineMode(nameWrap); + } + return null; + } + + /** + * @param uuid to use as key + * + * @return name (cache) + */ + private static StringWrapper loopSearch(final UUID uuid) { + return uuidMap.inverse().get(uuid); + } + + /** + * @param uuid to use as key + * + * @return Name + */ + public static String getName(final UUID uuid) { + if (uuidExists(uuid)) { + return loopSearch(uuid).value; + } + String name; + if ((name = getNameOnlinePlayer(uuid)) != null) { + return name; + } + + if (!Settings.UUID_FROM_DISK) { + return null; + } + if ((name = getNameOfflinePlayer(uuid)) != null) { + return name; + } + if (online && !Settings.OFFLINE_MODE) { + if (!Settings.UUID_FECTHING) { + name = getNameOfflineFromOnlineUUID(uuid); + return name; + } + if (!Settings.CUSTOM_API) { + try { + final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); + name = fetcher.call().get(uuid); + add(new StringWrapper(name), uuid); + return name; + } catch (final Exception ex) { + ex.printStackTrace(); + } + } else { + try { + return PlotMain.getUUIDSaver().mojangName(uuid); + } catch (final Exception e) { + try { + final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); + name = fetcher.call().get(uuid); + add(new StringWrapper(name), uuid); + return name; + } catch (final Exception ex) { + e.printStackTrace(); + } + } + } + try { + return PlotMain.getUUIDSaver().mojangName(uuid); + } catch (final Exception e) { + try { + final NameFetcher fetcher = new NameFetcher(Arrays.asList(uuid)); + name = fetcher.call().get(uuid); + add(new StringWrapper(name), uuid); + return name; + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } else { + return "unknown"; + } + return ""; + } + + /** + * @param name to use as key + * + * @return UUID (name hash) + */ + private static UUID getUuidOfflineMode(final StringWrapper name) { + final UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)); + add(name, uuid); + return uuid; + } + + /** + * @param uuid to use as key + * + * @return String - name + */ + private static String getNameOnlinePlayer(final UUID uuid) { + final Player player = uuidWrapper.getPlayer(uuid); + if ((player == null) || !player.isOnline()) { + return null; + } + final String name = player.getName(); + add(new StringWrapper(name), uuid); + return name; + } + + /** + * @param uuid to use as key + * + * @return String - name + */ + private static String getNameOfflinePlayer(final UUID uuid) { + final OfflinePlayer player = uuidWrapper.getOfflinePlayer(uuid); + if ((player == null) || !player.hasPlayedBefore()) { + return null; + } + final String name = player.getName(); + add(new StringWrapper(name), uuid); + return name; + } + + private static UUID getUuidOnlineFromOfflinePlayer(final StringWrapper name) { + return getUUID(Bukkit.getOfflinePlayer(name.toString())); + } + + private static String getNameOfflineFromOnlineUUID(final UUID uuid) { + return uuidWrapper.getOfflinePlayer(uuid).getName(); + } + + /** + * @param name to use as key + * + * @return UUID + */ + private static UUID getUuidOnlinePlayer(final StringWrapper name) { + @SuppressWarnings("deprecation") final Player player = Bukkit.getPlayer(name.value); + if (player == null) { + return null; + } + final UUID uuid = getUUID(player); + add(name, uuid); + return uuid; + } + + /** + * Handle saving of uuids + * + * @see com.intellectualcrafters.plot.uuid.UUIDSaver#globalSave(com.google.common.collect.BiMap) + */ + @SuppressWarnings("unused") + public static void handleSaving() { + final UUIDSaver saver = PlotMain.getUUIDSaver(); + saver.globalSave(getUuidMap()); + } + + public static UUID getUUID(final Player player) { + if (uuidWrapper == null) { + try { + getUUID(player); + uuidWrapper = new DefaultUUIDWrapper(); + } catch (final Throwable e) { + uuidWrapper = new OfflineUUIDWrapper(); + } + } + return uuidWrapper.getUUID(player); + } + + /** + * Safely provide the correct UUID provider. Ignores user preference if not possible rather than break the plugin. + */ + public static UUID getUUID(final OfflinePlayer player) { + if (uuidWrapper == null) { + if (Settings.OFFLINE_MODE) { + uuidWrapper = new OfflineUUIDWrapper(); + } else { + try { + getUUID(player); + uuidWrapper = new DefaultUUIDWrapper(); + } catch (final Throwable e) { + uuidWrapper = new OfflineUUIDWrapper(); + } + } + } + try { + return uuidWrapper.getUUID(player); + } catch (final Throwable e) { + uuidWrapper = new OfflineUUIDWrapper(); + return uuidWrapper.getUUID(player); + } + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSaver.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSaver.java new file mode 100644 index 000000000..94605066a --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSaver.java @@ -0,0 +1,92 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import com.google.common.collect.BiMap; +import com.intellectualcrafters.plot.object.StringWrapper; + +import java.util.UUID; + +/** + * @author Citymonstret + */ +public interface UUIDSaver { + + /** + * Populate the default list + */ + public void globalPopulate(); + + /** + * Save the UUIDs + * + * @param biMap Map containing names and UUIDs + */ + public void globalSave(final BiMap biMap); + + /** + * Save a single UUIDSet + * + * @param set Set to save + */ + public void save(final UUIDSet set); + + /** + * Get a single UUIDSet + * + * @param name Username + * + * @return UUID Set + */ + public UUIDSet get(final String name); + + /** + * Get a single UUIDSet + * + * @param uuid UUID + * + * @return UUID Set + */ + public UUIDSet get(final UUID uuid); + + /** + * Fetch uuid from mojang servers + * + * @param name Username + * + * @return uuid + * + * @throws Exception + */ + public UUID mojangUUID(final String name) throws Exception; + + /** + * Fetch username from mojang servers + * + * @param uuid UUID + * + * @return username + * + * @throws Exception + */ + public String mojangName(final UUID uuid) throws Exception; +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSet.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSet.java new file mode 100644 index 000000000..0abfef7b0 --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDSet.java @@ -0,0 +1,69 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PlotSquared - A plot manager and world generator for the Bukkit API / +// Copyright (c) 2014 IntellectualSites/IntellectualCrafters / +// / +// This program is free software; you can redistribute it and/or modify / +// it under the terms of the GNU General Public License as published by / +// the Free Software Foundation; either version 3 of the License, or / +// (at your option) any later version. / +// / +// This program is distributed in the hope that it will be useful, / +// but WITHOUT ANY WARRANTY; without even the implied warranty of / +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / +// GNU General Public License for more details. / +// / +// You should have received a copy of the GNU General Public License / +// along with this program; if not, write to the Free Software Foundation, / +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / +// / +// You can contact us via: support@intellectualsites.com / +//////////////////////////////////////////////////////////////////////////////////////////////////// + +package com.intellectualcrafters.unused; + +import java.util.UUID; + +/** + * @author Citymonstret + */ +public class UUIDSet { + + /** + * Player Name + */ + private final String name; + + /** + * Player UUID + */ + private final UUID uuid; + + /** + * Constructor + * + * @param name Username + * @param uuid UUID + */ + public UUIDSet(final String name, final UUID uuid) { + this.name = name; + this.uuid = uuid; + } + + @Override + public String toString() { + return getName(); + } + + /** + * Return the name + * + * @return Name + */ + public String getName() { + return this.name; + } + + public UUID getUUID() { + return this.uuid; + } +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDWrapper.java b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDWrapper.java new file mode 100644 index 000000000..a897a40bd --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/unused/UUIDWrapper.java @@ -0,0 +1,16 @@ +package com.intellectualcrafters.unused; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public abstract class UUIDWrapper { + public abstract UUID getUUID(Player player); + + public abstract UUID getUUID(OfflinePlayer player); + + public abstract OfflinePlayer getOfflinePlayer(UUID uuid); + + public abstract Player getPlayer(UUID uuid); +}